0% found this document useful (0 votes)
4K views600 pages

Do417 2.8 Student Guide

RedHat - Do417 2.8 Student Guide

Uploaded by

Ruben
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4K views600 pages

Do417 2.8 Student Guide

RedHat - Do417 2.8 Student Guide

Uploaded by

Ruben
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 600

Student Workbook (ROLE)

Red Hat Ansible Engine 2.8 DO417


Microsoft Windows Automation with Red
Hat Ansible
Edition 1

DO417-RHAE2.8-en-1-20200106 Copyright ©2020 Red Hat, Inc.


Microsoft Windows
Automation with
Red Hat Ansible

DO417-RHAE2.8-en-1-20200106 Copyright ©2020 Red Hat, Inc.


Red Hat Ansible Engine 2.8 DO417
Microsoft Windows Automation with Red Hat Ansible
Edition 1 20200106
Publication date 20200106

Authors: Razique Mahroua, Chris Caillouet, Joel Birchler, Artur Glogowski,


Morgan Weetman, Rajat Agrawal
Editor: Steven Bonneville, David O'Brien, Nicole Muller

Copyright © 2019 Red Hat, Inc.

The contents of this course and all its modules and related materials, including handouts to
audience members, are Copyright © 2019 Red Hat, Inc.

No part of this publication may be stored in a retrieval system, transmitted or reproduced in


any way, including, but not limited to, photocopy, photograph, magnetic, electronic or other
record, without the prior written permission of Red Hat, Inc.

This instructional program, including all material provided herein, is supplied without any
guarantees from Red Hat, Inc. Red Hat, Inc. assumes no liability for damages or legal action
arising from the use or misuse of contents or details contained herein.

If you believe Red Hat training materials are being used, copied, or otherwise improperly
distributed please e-mail training@redhat.com or phone toll-free (USA) +1 (866) 626-2994
or +1 (919) 754-3700.

Red Hat, Red Hat Enterprise Linux, the Shadowman logo, JBoss, Hibernate, Fedora, the
Infinity Logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and
other countries.

Linux® is the registered trademark of Linus Torvalds in the United States and other countries.

Java® is a registered trademark of Oracle and/or its affiliates.

XFS® is a registered trademark of Silicon Graphics International Corp. or its subsidiaries in


the United States and/or other countries.

The OpenStack® Word Mark and OpenStack Logo are either registered trademarks/service
marks or trademarks/service marks of the OpenStack Foundation, in the United States
and other countries and are used with the OpenStack Foundation's permission. We are not
affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack
community.

All other trademarks are the property of their respective owners.


Document Conventions ix

Introduction xi
Microsoft Windows Automation with Red Hat Ansible ................................................... xi
Orientation to the Classroom Environment ................................................................. xii

1. Introducing Red Hat Ansible Automation 1


Introducing Red Hat Ansible Automation ..................................................................... 2
Quiz: Introducing Red Hat Ansible Automation ............................................................. 8
Architecture of Windows Automation with Red Hat Ansible Tower ................................. 10
Guided Exercise: Architecture of Windows Automation with Red Hat Ansible Tower .......... 18
Managing Files in Git with Visual Studio Code ............................................................ 25
Guided Exercise: Managing Files in Git with Visual Studio Code ................................... 34
Lab: Introducing Red Hat Ansible Automation ............................................................ 38
Summary ............................................................................................................... 47

2. Running Simple Automation Commands 49


Preparing Microsoft Windows Hosts for Automation ................................................... 50
Quiz: Preparing Microsoft Windows Hosts for Automation ........................................... 55
Preparing Red Hat Ansible Tower to Manage Hosts ..................................................... 57
Guided Exercise: Preparing Red Hat Ansible Tower to Manage Hosts ............................ 64
Running Ad Hoc Commands .................................................................................... 69
Guided Exercise: Running Ad Hoc Commands ............................................................ 77
Lab: Running Simple Automation Commands ............................................................. 83
Summary ............................................................................................................... 98

3. Implementing Ansible Playbooks 99


Writing Playbooks ................................................................................................. 100
Guided Exercise: Writing Playbooks ......................................................................... 104
Running Playbooks in Red Hat Ansible Tower ............................................................ 108
Guided Exercise: Running Playbooks in Red Hat Ansible Tower ..................................... 119
Implementing Multiple Plays ................................................................................... 125
Guided Exercise: Implementing Multiple Plays ............................................................ 131
Lab: Implementing Ansible Playbooks ...................................................................... 139
Summary .............................................................................................................. 149

4. Managing Variables and Facts 151


Managing Variables ................................................................................................ 152
Guided Exercise: Managing Variables ........................................................................ 161
Managing Secrets .................................................................................................. 172
Quiz: Managing Secrets ......................................................................................... 178
Managing Facts .................................................................................................... 180
Guided Exercise: Managing Facts ............................................................................ 187
Lab: Managing Variables and Facts .......................................................................... 193
Summary .............................................................................................................. 199

5. Installing and Updating Software 201


Installing and Updating Software ............................................................................ 202
Guided Exercise: Installing and Updating Software .................................................... 207
Editing the Registry ............................................................................................... 222
Guided Exercise: Editing the Registry ...................................................................... 226
Lab: Installing and Updating Software ...................................................................... 231
Summary ............................................................................................................. 245

6. Implementing Task Control 247


Writing Loops and Conditional Tasks ...................................................................... 248
Guided Exercise: Writing Loops and Conditional Tasks .............................................. 259
Implementing Handlers ......................................................................................... 264

DO417-RHAE2.8-en-1-20200106 v
Guided Exercise: Implementing Handlers ................................................................. 267
Handling Task Failure ............................................................................................. 271
Guided Exercise: Handling Task Failure .................................................................... 276
Lab: Implementing Task Control .............................................................................. 281
Summary ............................................................................................................. 288
7. Deploying Files to Managed Hosts 289
Modifying and Transferring Files on Hosts ............................................................... 290
Guided Exercise: Modifying and Transferring Files on Hosts ....................................... 296
Templating Files with Jinja2 .................................................................................... 313
Guided Exercise: Templating Files with Jinja2 ........................................................... 318
Lab: Deploying Files to Managed Hosts .................................................................. 326
Summary ............................................................................................................. 336
8. Interacting with Users and Domains 337
Managing Local User Accounts .............................................................................. 338
Guided Exercise: Managing Local User Accounts ...................................................... 343
Managing Active Directory Domains ....................................................................... 346
Guided Exercise: Managing Active Directory Domains ............................................... 353
Generating Dynamic Inventories from Active Directory ............................................... 361
Guided Exercise: Generating Dynamic Inventories from Active Directory ..................... 368
Lab: Interacting with Users and Domains ................................................................. 373
Summary .............................................................................................................. 381
9. Automating Windows Administration Tasks 383
Running Commands and Scheduling Tasks on Hosts ................................................. 384
Guided Exercise: Running Commands and Scheduling Tasks on Hosts ......................... 399
Configuring and Managing Storage ......................................................................... 416
Guided Exercise: Configuring and Managing Storage ................................................ 420
Lab: Automating Windows Administration Tasks ....................................................... 425
Summary ............................................................................................................. 433
10. Managing Large Projects 435
Including and Importing Files ................................................................................. 436
Guided Exercise: Including and Importing Files .......................................................... 441
Creating Roles ..................................................................................................... 446
Guided Exercise: Creating Roles ............................................................................. 456
Deploying Roles with Ansible Galaxy ....................................................................... 462
Guided Exercise: Deploying Roles with Ansible Galaxy .............................................. 466
Integrating Ansible with Desired State Configuration Resources ................................. 474
Guided Exercise: Integrating Ansible with Desired State Configuration Resources ......... 478
Lab: Managing Large Projects ................................................................................ 481
Summary ............................................................................................................. 489
11. Constructing Ansible Tower Workflows 491
Creating and Managing Ansible Tower Users ............................................................ 492
Guided Exercise: Managing Users and Teams ........................................................... 502
Creating and Using Surveys ................................................................................... 509
Guided Exercise: Creating and Using Surveys ........................................................... 514
Scheduling Job Launches ...................................................................................... 519
Guided Exercise: Scheduling Job Launches .............................................................. 521
Running Complex Workflows .................................................................................. 524
Guided Exercise: Running Complex Workflows ......................................................... 530
Lab: Constructing Ansible Tower Workflows ............................................................. 535
Summary ............................................................................................................. 546
12. Comprehensive Review 547
Comprehensive Review ......................................................................................... 548

vi DO417-RHAE2.8-en-1-20200106
Lab: Comprehensive Review Lab 1 ........................................................................... 551
Lab: Comprehensive Review Lab 2 .......................................................................... 557
Lab: Comprehensive Review Lab 3 ......................................................................... 563
Lab: Comprehensive Review Lab 4 ......................................................................... 567
A. Supplementary Topics 575
Managing Red Hat Ansible Tower User Roles ........................................................... 576
B. Legal Notices 583
arillso.chocolatey Role License ............................................................................... 584

DO417-RHAE2.8-en-1-20200106 vii
viii DO417-RHAE2.8-en-1-20200106
Document Conventions

References
"References" describe where to find external documentation relevant to a subject.

Note
"Notes" are tips, shortcuts or alternative approaches to the task at hand. Ignoring a
note should have no negative consequences, but you might miss out on a trick that
makes your life easier.

Important
"Important" boxes detail things that are easily missed: configuration changes that
only apply to the current session, or services that need restarting before an update
will apply. Ignoring a box labeled "Important" will not cause data loss, but may cause
irritation and frustration.

Warning
"Warnings" should not be ignored. Ignoring warnings will most likely cause data loss.

DO417-RHAE2.8-en-1-20200106 ix
x DO417-RHAE2.8-en-1-20200106
Introduction

Microsoft Windows Automation with Red Hat


Ansible
Microsoft Windows Automation with Red Hat Ansible (DO417) is designed for
Windows Server professionals who want to use Ansible to write automation
playbooks to perform common system administration tasks, reproducibly and
at scale, for Microsoft Windows systems. You will use Red Hat Ansible Tower
to securely manage and run your Ansible Playbooks from a central web-
based user interface.

Course • Students will write and run Microsoft Windows


Objectives automation tasks using Red Hat Ansible
Automation in a Microsoft Windows
environment. They will perform common
administrative tasks, write Ansible projects from
their Microsoft Windows workstation, store the
history of all changes in a Git-based version
control system, and run and troubleshoot
those tasks from the web interface of Red Hat
Ansible Tower.

Audience • Microsoft Windows Server administrators who


are interested in automating management tasks
and using automation tools to implement a
DevOps workflow.

Prerequisites • Students are expected to have experience


as a Microsoft Windows Server administrator.
No previous experience with Red Hat Ansible
Automation or Linux is required.

DO417-RHAE2.8-en-1-20200106 xi
Introduction

Orientation to the Classroom


Environment

Figure 0.1: Classroom environment

In this course, the main computer system used for hands-on learning activities is workstation.
The credentials to access this system are displayed in your Red Hat Online Learning (ROL)
interface, under the Online Lab tab. This course uses a set of six virtual machines running in a
remote cloud environment:

All systems are connected to a private subnet, 172.25.250.0/24. IPs are generated during
provisioning and remain static during throughout the environment life cycle.

• workstation is the main system that you will use interactively in this course. You will connect
to this host using Remote Desktop Protocol (RDP) from your own computer or laptop.
Instructions for making these connections is covered in detail later in this introduction.

xii DO417-RHAE2.8-en-1-20200106
Introduction

The workstation system is the only system that is directly connected to the Internet. It is also
connected to a private network used by all other classroom systems.

• windc is the Microsoft Active Directory domain controller for the example.com domain.

• win1 and win2 are the two Ansible managed hosts.

• tower provides the Red Hat Ansible Tower service that you will use to run your automation
code.

• gitlab provides a GitLab CE service that provides the Git version control repositories, in which
your code and other exercise materials are stored.

Summary of Classroom Machines

Machine name Role

workstation.example.com Windows Server host used as a workstation

windc.example.com Active Directory domain controller for the


example.com domain

win1.example.com First Windows Server host managed by Ansible

win2.example.com Second Windows Server host managed by Ansible

tower.example.com Red Hat Ansible Tower server

gitlab.example.com GitLab server

The following list describes the user accounts that are available:

• On workstation, you will use the training user as your standard user account. The
password for this account is automatically generated and is available in the online learning
platform (ROL), under the Online Lab tab.

The local Administrator account on this system uses the same password.

• On windc, the local user account Administrator uses RedHat123@! as a password. This is
also the password for the example.com domain administrator account.

• On win1 and win2, the user devops is used by Red Hat Ansible Tower for management and
automation purposes.

This account uses RedHat123@! as a password.

• The URL http://tower.example.com provides access to the web-based user interface


of Red Hat Ansible Tower. You can log in through the web interface as the admin user, with
RedHat123@! as the password.

• The URL https://gitlab.example.com provides access to the web-based user interface


of GitLab CE in your classroom environment. You can log in as the student user, with
RedHat123@! as the password.

DO417-RHAE2.8-en-1-20200106 xiii
Introduction

Controlling Your Systems


The computers that you will use for activities are in a remote Red Hat Online Learning classroom.
You can control them using a web application hosted at http://rol.redhat.com. You should log in to
this site using your Red Hat Customer Portal user credentials.

In order to access the remote classroom, you will need a computer with Internet access and an
RDP client. That device should have a screen resolution of at least 1280x800 pixels. We assume
that you will provide your own computer for this training course.

Important
If you are attending an instructor-led training session and do not have your own
computer with you, or have difficulty with your RDP client, then please ask the
instructor for assistance.

Installing an RDP Client


If your computer does not have an RDP client installed, then you must be able to install the
software on it. The following table lists some suggested RDP clients for the most common
operating systems.

Recommended RDP Clients

Operating System Client Name Installation

Windows 2000 or later Microsoft Remote Installed on all Windows system, Windows
Desktop 2000 or later

macOS 10.12 or later, 64- Microsoft Remote Install from https://apps.apple.com/us/


bit processor Desktop app/microsoft-remote-desktop-10/
id1295203466, or directly from the Mac App
Store.

Linux distributions, Remmina Fedora provides Remmina in the


including Fedora, distribution. Install with sudo dnf
Red Hat Enterprise install remmina.
Linux, Ubuntu, and
Debian Instructions for other Linux distributions are
available at https://remmina.org/how-to-
install-remmina/. On those distributions,
make sure that both the program, and its
RDP plug-in for Remmina, are installed.

Remmina has some feature advantages over


xfreerdp.

xiv DO417-RHAE2.8-en-1-20200106
Introduction

Operating System Client Name Installation

Red Hat Enterprise xfreerdp Provided by the distribution. Install with


Linux 7 or later sudo yum install freerdp.

You must also make sure the required plug-


ins for Windows RDP support are installed
(freerdp-plugins for RHEL 7, and freerdp-
libs for RHEL 8).

This client has fewer features than


Remmina but is easy to install on Red Hat
Enterprise Linux.

Controlling the Virtual Machines


The virtual machines in the classroom environment are controlled through a web page. The state
of each virtual machine in the classroom is displayed on the page under the Online Lab tab.

Machine States

Virtual Machine Description


State

STARTING The virtual machine is in the process of booting.

STARTED The virtual machine is running and available (or, when booting, soon
will be).

STOPPING The virtual machine is in the process of shutting down.

STOPPED The virtual machine is completely shut down. Upon starting, the virtual
machine boots into the same state as when it was shut down (the disk
will have been preserved).

PUBLISHING The initial creation of the virtual machine is being performed.

WAITING_TO_START The virtual machine is waiting for other virtual machines to start.

Depending on the state of a machine, a selection of the following actions is available.

Classroom/Machine Actions

Button or Action Description

PROVISION LAB Create the ROL classroom. Creates all of the virtual machines needed
for the classroom and starts them. Can take up to an hour to complete.

DELETE LAB Delete the ROL classroom. Destroys all virtual machines in the
classroom. Caution: Any work generated on the disks is lost.

START LAB Start all virtual machines in the classroom.

SHUTDOWN LAB Stop all virtual machines in the classroom.

DO417-RHAE2.8-en-1-20200106 xv
Introduction

Button or Action Description

ACTION → Start Start (power on) the virtual machine.

ACTION → Gracefully shut down the virtual machine, preserving the contents of
Shutdown its disk.

ACTION → Power Forcefully shut down the virtual machine, preserving the contents of its
Off disk. This is equivalent to removing the power from a physical machine.

At the start of an exercise, if instructed to reset a single virtual machine node, click ACTION →
Reset for only the specific virtual machine you wish to reset.

At the start of an exercise, if instructed to reset all virtual machines, click ACTION → Reset

If you want to return the classroom environment to its original state at the start of the course, click
DELETE LAB to remove the entire classroom environment. After the lab has been deleted, you
can click PROVISION LAB to provision a new set of classroom systems.

Warning
The DELETE LAB operation cannot be undone. Any work you have completed in
the classroom environment up to that point is lost.

The Autostop Timer


The Red Hat Online Learning enrollment entitles students to a certain amount of computer time.
To help conserve allotted computer time, the ROL classroom has an associated countdown timer,
which shuts down the classroom environment when the timer expires.

To adjust the timer, click MODIFY to display the New Autostop Time window. Set the number
of hours until the classroom should automatically stop. Note that there is a maximum time of ten
hours. Click ADJUST TIME to apply this change to the timer settings.

Classroom Life Cycle


The Red Hat Online Learning enrollment limits the life cycle of this class to ninety (90) days. After
90 days, the environment is decommissioned and all data is lost; however, you can provision a
new environment if needed. If necessary, follow the aforementioned instructions to provision the
environment.

Upon provisioning, the Online Lab tab displays the connection information for the environment.
This includes the list of systems that are provisioned, and the various credentials that you will use
throughout the course.

xvi DO417-RHAE2.8-en-1-20200106
Chapter 1

Introducing Red Hat Ansible


Automation
Goal Describe the purpose and benefits of automating
Windows server administration tasks, and the basic
architecture of a solution based on Red Hat Ansible
Automation.

Objectives • Describe fundamental concepts of automation


with Red Hat Ansible Automation, its basic
design, and common use cases.
• Describe the architecture of a Windows
automation implementation using Red Hat
Ansible Tower and a Git repository as a central
point of control.
• Retrieve, manage, edit, and store files in a
remote Git version control system, such as
GitHub or GitLab, using Visual Studio Code.

Sections • Introducing Red Hat Ansible Automation (and


Quiz)
• Describing the architecture of Windows
Automation with Red Hat Ansible Tower (and
Guided Exercise)
• Managing Files in Git with Visual Studio Code
(and Guided Exercise)

Lab Introducing Red Hat Ansible Automation

DO417-RHAE2.8-en-1-20200106 1
Chapter 1 | Introducing Red Hat Ansible Automation

Introducing Red Hat Ansible Automation

Objectives
After completing this section, you should be able to describe the fundamental concepts of
automation with Red Hat Ansible Automation, its basic design, and common use cases.

Introducing Automation and Windows System


Administration
For many years, most system administration and infrastructure management have relied on manual
tasks performed through graphical or command-line user interfaces. System administrators often
work from checklists, documentation, or a memorized routine to perform standard tasks.

However, this approach is error-prone; it is easy for a system administrator to skip a step or
perform a step incorrectly. Often, there is limited verification that the steps were performed
properly, or that they result in the expected outcome.

Furthermore, by managing each server manually and independently, it is very easy for many
servers that should be identical in configuration are different in minor (or major) ways. This
inconsistency can make maintenance more difficult and introduce errors or instability in the IT
environment.

Automation can help avoid the problems caused by manual system administration and
infrastructure management. As a system administrator, use automation to ensure that all your
systems are quickly and correctly deployed and configured. Automation frees you from running
repetitive tasks in your daily schedule, freeing up your time and allowing you to focus on more
critical things. For your organization, this means you can more quickly roll out the next version of
an application or updates to a service.

Infrastructure-as-Code
A good automation system allows you to implement Infrastructure-as-Code (IaC) practices. IaC
means using a machine-readable automation language to define and describe the state in which
you want your IT infrastructure. Ideally, this automation language is easy for humans to read,
because then you can easily understand what the state is and make changes to it. This code is
then applied to your infrastructure to ensure that it is actually in that state.

If the automation language is represented as simple text files, then you can manage it in a version
control system, such as Git, the same way you would manage software code. The advantage is
that every change can be checked into the version control system so that you have a history of the
changes you make over time. If you want to revert to an earlier, known good configuration, then
you can check out that version of the code and apply it to your infrastructure.

By managing your infrastructure as code, you can ensure that your staging and production
environments are consistent. This also enables you to implement continuous integration (CI) and
continuous delivery (CD) practices. You can integrate tools such as linters and unit tests to check
the code that defines the configuration of your infrastructure before committing your changes
Using these tools can help improve the overall quality of your code and enforce compliance
standards, building a foundation to support DevOps best practices.

2 DO417-RHAE2.8-en-1-20200106
Chapter 1 | Introducing Red Hat Ansible Automation

Developers can define their desired configuration in the automation language. Operators
can review those changes more easily to provide feedback, and can use this automation to
reproducibly ensure that systems are in the state expected by the developers. Finally, it helps you
to establish best practices, and to ensure that they are in line with various teams implementations.

Mitigating Human Error


By reducing the tasks performed manually on servers using automation of tasks and IaC practices
your servers will have consistent configurations more often. This means that you must become
accustomed to making changes by updating automation code, rather than manually applying them
to your servers. Otherwise, you run the risk of losing manually applied changes the next time you
apply changes through your automation.

Automation enables code review by multiple subject matter experts, and supports automated
documentation of the review process to reduce operational risks.

Ultimately, you can enforce that changes to your IT infrastructure must be made through
automation to mitigate human error.

What is Ansible?
Ansible is an open source automation platform and a simple automation language that can
describe IT application infrastructure in Ansible Playbooks. It is also an automation engine that runs
Ansible Playbooks.

Ansible can manage powerful automation tasks and can adapt to many different workflows and
environments. At the same time, new users of Ansible can use it to quickly become productive.

Ansible Is Simple
Ansible Playbooks provide human-readable automation. This means that playbooks are
automation tools that are also easy for humans to read, comprehend, and change. No special
coding skills are required to write them. Playbooks execute tasks in order. The simplicity of
playbook design makes them usable by every team, which allows people new to Ansible to rapidly
become productive.

Ansible Is Powerful
You can use Ansible for deploy applications, for configuration management, for workflow
automation, and for network automation. Thus, Ansible can be used to orchestrate the entire
application life cycle.

Ansible Is Agentless
Ansible is built around an agentless architecture. Typically, Ansible connects to the hosts it
manages using OpenSSH, Windows Remote Management (WinRM), or PowerShell Remoting
Protocol (PSRP) and then runs tasks, often by pushing out small programs called Ansible modules
to those hosts. These programs are used to put the system in a specific desired state. Any
modules that are pushed are removed when Ansible is finished with its tasks. You can start using
Ansible almost immediately, because no special agents need to be approved for use and then
deployed to the managed hosts. Because there are no agents and no additional custom security
infrastructure, Ansible is more efficient and more secure than other alternatives.

Ansible has a number of important strengths:

• Cross platform support: Ansible provides agentless support for Linux, Windows, UNIX, and
network devices, in physical, virtual, cloud, and container environments.

DO417-RHAE2.8-en-1-20200106 3
Chapter 1 | Introducing Red Hat Ansible Automation

• Human-readable automation: Ansible Playbooks, written as YAML text files, are easy to read and
help ensure that everyone understands what they will do.

• Perfect description of applications: Every change can be made by Ansible Playbooks, and every
aspect of your application environment can be described and documented.

• Easy to manage in version control: Ansible Playbooks and projects are plain text. They can be
treated like source code and placed in your existing version control system.

• Support for dynamic inventories: The list of machines that Ansible manages can be dynamically
updated from external sources to capture the correct, current list of all managed servers all the
time, regardless of infrastructure or location.

• Orchestration that integrates easily with other systems: HP Server Automation (HPSA), Puppet,
Jenkins, Red Hat Satellite, and other systems that exist in your environment can be used and
integrated into your Ansible workflow.

Ansible: The Language of DevOps

Figure 1.1: Ansible across the application life cycle

Communication is the key to DevOps. Ansible is the first automation language that can be read
and written across systems without prior programming knowledge.

The Ansible Way


Ansible describes your infrastructure in a simple way that does not require advanced programming
language skills. It is designed with simplicity and efficiency in mind.

Complexity Kills Productivity


Simpler is better. Ansible is designed so that its tools are simple to use and automation is
simple to write and read. Take advantage of this simplicity to strive for simplification in how
you create your automation.

Optimize For Readability


The Ansible automation language is built around simple, declarative, text-based files that
are easy for humans to read. Written properly, Ansible Playbooks can clearly document your
workflow automation.

Think Declaratively
Ansible is a desired-state engine. It approaches the problem of how to automate IT
deployments by expressing them in terms of the desired system state. Ansible puts your
systems into the desired state by only making necessary changes. Ansible is not a scripting
language and should not be treated as one.

4 DO417-RHAE2.8-en-1-20200106
Chapter 1 | Introducing Red Hat Ansible Automation

Figure 1.2: Ansible provides complete automation

Ansible Concepts and Architecture


There are two types of machines in the Ansible architecture: control nodes and managed hosts.
Ansible is installed and run from a control node, which is a single machine that has copies of
the Ansible project files. A control node that runs on Linux could be an administrator's laptop,
a system shared by several administrators, a Linux virtual machine, or a server running Red Hat
Ansible Tower.

Managed hosts are listed in an inventory, which also organizes those systems into groups for
easier collective management. The inventory can be defined in a static text file, or dynamically
determined by scripts that get information from external sources.

Instead of writing complex scripts, Ansible users create high-level plays to ensure a host or group
of hosts are in a particular state. A play performs a series of tasks on the hosts, in the order
specified by the play. These plays are expressed in YAML format in a text file. A file that contains
one or more plays is called a playbook.

Each task runs a module, a small piece of code (written in Python, PowerShell, or some other
language), with specific arguments. Ansible ships with many useful modules that can perform a
wide variety of automation tasks. Each module is essentially a tool in your toolkit. Modules can act
on system files, install services or users, or interact with PowerShell DSC configurations.

When used in a task, a module generally ensures that some particular aspect of the machine is
in a particular state. For example, a task using one module may ensure that a file exists and has
particular permissions and contents, while a task using a different module may make certain that a
particular file system is mounted. If the system is not in that state, the task will put it in that state. If

DO417-RHAE2.8-en-1-20200106 5
Chapter 1 | Introducing Red Hat Ansible Automation

the system is already in that state, it does nothing. If a task fails, then by default Ansible will abort
the rest of the playbook for those hosts that failed.

Tasks, plays, and playbooks are designed to be idempotent. This means that you can safely run
a playbook on the same host multiple times. When your systems are in the correct state, the
playbook makes no changes when run. Therefore, running a playbook multiple times on the same
host is safe. There are a handful of modules that you can use to run arbitrary commands. However,
you must use those modules with care to ensure that they run in an idempotent way.

As discussed previously, the Ansible architecture is agentless. Therefore, when you run an Ansible
Playbook or an ad hoc command, the control node connects to the managed host, using SSH (the
default configuration) or WinRM (for most Windows hosts). Clients need only a WinRM listener
installed on hosts, rather than an Ansible-specific agent, and therefore, need not permit special
network traffic to a nonstandard port.

Figure 1.3: Ansible architecture

Red Hat Ansible Tower is an enterprise framework to help you control, secure, and manage your
Ansible automation at scale. It acts as the control node to run your Ansible Playbooks. It provides
a web-based user interface and a RESTful API. Linux administrators can use command-line tools
included with Ansible to run playbooks, but Red Hat Ansible Tower provides a centralized graphical
interface that helps you use Ansible more effectively with a team or at large scale. It allows users
with no Linux experience to easily run Ansible automation, while also providing a central point of
authorization, management, and logging of automation activities.

Use Cases
Unlike some other tools, Ansible combines and unites orchestration with configuration
management, provisioning, and application deployment in one easy-to-use platform.

Some use cases for Ansible include:

6 DO417-RHAE2.8-en-1-20200106
Chapter 1 | Introducing Red Hat Ansible Automation

Configuration Management
Centralizing configuration file management and deployment is a common use case for
Ansible, and is how many power users are first introduced to the Ansible automation platform.

Application Deployment
When you define your application with Ansible, and manage the deployment with Red Hat
Ansible Tower, teams can effectively manage the entire application life cycle from
development to production.

Provisioning
Applications must be deployed or installed on systems. Ansible and Red Hat Ansible Tower can
streamline the process of provisioning systems, whether you are using a Preboot Execution
Environment (PXE) with Kickstart installation on bare-metal servers or virtual machines, or
creating virtual machines or cloud instances from templates.

Continuous Delivery
Creating a CI/CD pipeline requires coordination and buy-in from numerous teams. You cannot
do it without a simple automation platform that everyone in your organization can use. Ansible
Playbooks keep your applications properly deployed (and managed) throughout their entire
life cycle.

Security and Compliance


When your security policy is defined in Ansible Playbooks, scanning and remediation of site-
wide security policies can be integrated into other automated processes. Instead of being an
afterthought, it is an integral part of everything that is deployed.

Orchestration
Configurations alone do not define your environment. You must also define how multiple
configurations interact, and ensure the disparate pieces can be managed as a whole.

References
Ansible
https://www.ansible.com

How Ansible Works


https://www.ansible.com/how-ansible-works

DO417-RHAE2.8-en-1-20200106 7
Chapter 1 | Introducing Red Hat Ansible Automation

Quiz

Introducing Red Hat Ansible Automation


Choose the correct answers to the following questions:

1. Which of the following terms best describes the Ansible architecture?


a. Agentless
b. Client/Server
c. Event-driven
d. Stateless

2. Which two of the following protocols does Ansible use to communicate with managed
Windows nodes? (Choose two.)
a. HTTP
b. HTTPS
c. WinRM
d. WinSCP
e. PowerShell remote protocol

3. Which of the following files defines the actions that Ansible performs on managed
nodes?
a. Host inventory
b. Manifest
c. Playbook
d. Script

4. What syntax is used to define Ansible Playbooks?


a. Bash
b. Perl
c. Python
d. YAML

8 DO417-RHAE2.8-en-1-20200106
Chapter 1 | Introducing Red Hat Ansible Automation

Solution

Introducing Red Hat Ansible Automation


Choose the correct answers to the following questions:

1. Which of the following terms best describes the Ansible architecture?


a. Agentless
b. Client/Server
c. Event-driven
d. Stateless

2. Which two of the following protocols does Ansible use to communicate with managed
Windows nodes? (Choose two.)
a. HTTP
b. HTTPS
c. WinRM
d. WinSCP
e. PowerShell remote protocol

3. Which of the following files defines the actions that Ansible performs on managed
nodes?
a. Host inventory
b. Manifest
c. Playbook
d. Script

4. What syntax is used to define Ansible Playbooks?


a. Bash
b. Perl
c. Python
d. YAML

DO417-RHAE2.8-en-1-20200106 9
Chapter 1 | Introducing Red Hat Ansible Automation

Architecture of Windows Automation


with Red Hat Ansible Tower

Objectives
After completing this section, you should be able to describe the architecture of a Windows
automation implementation using Red Hat Ansible Tower and a Git repository as a central point of
control.

Integrating Ansible in a Microsoft Windows


Environment
There are a number of methods that you can use to implement Ansible automation in an
environment wholly or primarily consisting of Microsoft Windows-based managed hosts. Red Hat
has worked with a wide variety of customers and based on our experience, we recommend the
following architectural model:

• Use Red Hat Ansible Tower as the control node to run Ansible Playbooks.

• Store Ansible Playbooks and other materials in a distributed version control system, preferably
one based on Git.

• Use Windows-native source code editors that can directly work with files in your version control
system to edit Ansible Playbooks and other materials.

One advantage of this solution is that most of your Windows administrators do not need to use
the Linux command line in order to use Ansible. Instead, they can work through the Red Hat
Ansible Tower graphical, web-based user interface, or its REST API. This reduces the Ansible
learning curve for administrators, and also provides valuable capabilities from Ansible Tower, such
as event scheduling, logging, and secrets management.

Using a version control system to manage your code is a recommended practice, even if you are
not using Ansible Tower. This gives you the ability to track the people responsible for making
specific changes to the code, and the ability to roll back to older revisions, if needed. When using
Ansible to define something that is as important as your Infrastructure-as-Code, it is important
that you have solid practices to manage that code.

One reason why we recommend Git is because Git skills are common, and there are powerful
services that provide Git repository management for use in both the cloud, and as an on-site
installation. These include GitHub, GitLab, and Bitbucket, among others. In this course, we will use
a local installation of GitLab, rather than one of the cloud services, but these function similarly.

In addition, many Windows-based programming editors provide direct integration between


the text editing environment, and the Git repositories that store project files. One popular
environment is Visual Studio Code, which is used for this course.

The next section provides a quick overview of how to work with a Git repository using Visual Studio
Code. In the remainder of this section, you will learn more about Red Hat Ansible Tower.

Introducing Red Hat Ansible Tower


Sharing an existing Ansible infrastructure to scale IT automation across an enterprise can present
some challenges. Although you can use properly written Ansible Playbooks across teams, Ansible

10 DO417-RHAE2.8-en-1-20200106
Chapter 1 | Introducing Red Hat Ansible Automation

does not provide any facilities for managing shared access. Additionally, although playbooks may
allow for the delegation of complex tasks, executing those tasks may require highly privileged and
guarded administrator credentials. Red Hat Ansible Tower mitigates these challenges, providing a
framework for running and managing Ansible efficiently on an enterprise scale.

Ansible Tower eases the administration involved with sharing an Ansible infrastructure, while
maintaining organization security, by introducing features such as a centralized web UI for
playbook management, role-based access control (RBAC), and centralized logging and auditing.

The REST API enables you to integrate Ansible Tower with existing organizational workflows and
tool sets. The Ansible Tower API and notification features make it particularly easy to associate
Ansible Playbooks with other tools, such as Jenkins, Red Hat CloudForms, or Red Hat Satellite,
to enable continuous integration and deployment. It provides mechanisms to enable centralized
use and control of machine credentials and other secrets, without exposing them to end users of
Ansible Tower.

The Red Hat Ansible Automation subscription offers support for both Red Hat Ansible Tower
and Red Hat Ansible Engine. More information is available at https://www.redhat.com/en/
technologies/management/ansible.

Red Hat Ansible Tower Architecture


Red Hat Ansible Tower is a Django web application, designed to run on a Linux server as an on-
premise, self-hosted solution that layers on top of an existing enterprise Ansible infrastructure.

Figure 1.4: Ansible Tower architecture

You can interact with the underlying Ansible infrastructure for the enterprise using either the
Ansible Tower web UI or RESTful API. The Ansible Tower web UI is a graphical interface that
performs actions by executing calls against the Ansible Tower API. Any action available through
the Ansible Tower web UI can also be performed using the Ansible Tower RESTful API. The
RESTful API is essential for those users looking to integrate Ansible with existing software tools
and processes.

DO417-RHAE2.8-en-1-20200106 11
Chapter 1 | Introducing Red Hat Ansible Automation

Ansible Tower stores its data in a PostgreSQL back-end database, and makes use of the
RabbitMQ messaging system. Versions of Ansible Tower before version 3.0 also relied on a
MongoDB database. This dependency has since been removed, and data is now stored solely in a
PostgreSQL database.

Depending on the needs of your enterprise, Ansible Tower can be implemented using one of the
following architectures:

• Single machine with integrated database

• Single machine with remote database

• High availability multimachine cluster

• OpenShift pod with remote database

Note
This course focuses on the most straightforward architecture to deploy; that is, a
single Red Hat Ansible Tower server with an integrated database.

Red Hat Ansible Tower Features


The following are some features offered by Red Hat Ansible Tower for controlling, securing, and
managing Ansible in an enterprise environment:

External Credentials Vaults


Ansible Tower 3.5 supports external credentials vaults. This allows you to manage credentials
for a variety of vendors, including HashiCorp Vault, CyberArk AIM and CyberArk Conjur, and
Microsoft Azure Key Vault.

Visual Dashboard
The Ansible Tower web UI displays a dashboard that provides a summary view of the entire
Ansible environment for the enterprise. The Ansible Tower dashboard allows you to easily see
the current status of hosts and inventories, as well as the results of recent job executions.

12 DO417-RHAE2.8-en-1-20200106
Chapter 1 | Introducing Red Hat Ansible Automation

Figure 1.5: The Ansible Tower dashboard

Role-based Access Control


Ansible Tower uses a Role-based Access Control (RBAC) system, which maintains security
while streamlining user access management. This system simplifies the delegation of user
access to Ansible Tower objects, such as organizations, projects, and inventories.

Graphical Inventory Management


Use the Ansible Tower web UI to create inventory groups and add inventory hosts. Update
inventories from an external inventory source, such as public cloud providers, local
virtualization environments, and an organization's custom configuration management database
(CMDB).

Job Scheduling
Use Ansible Tower to schedule playbook execution and updates from external data sources,
either on a one-time basis or at recurring intervals. This allows you to perform unattended
routine tasks, and is especially useful for tasks such as backup routines, which are ideally
executed during operational off-hours.

Real-time and Historical Job Status Reporting


When you initiate a playbook execution in Ansible Tower, the web UI displays the playbook's
output and execution results in real-time. The results of previously executed jobs and
scheduled job runs are also available in Ansible Tower.

DO417-RHAE2.8-en-1-20200106 13
Chapter 1 | Introducing Red Hat Ansible Automation

Figure 1.6: Managing jobs with Ansible Tower

User-triggered Automation
Ansible simplifies IT automation, and Ansible Tower takes it a step further by enabling user
self-service. The Ansible Tower streamlined web UI, coupled with the flexibility of its RBAC
system, allows you to reduce complex tasks to simple routines that are easy to use.

Remote Command Execution


Ansible Tower makes the on-demand flexibility of Ansible ad hoc commands available through
its remote command execution feature. User permissions for remote command execution are
enforced using the Ansible Tower RBAC system.

Credential Management
Ansible Tower centrally manages authentication credentials. This means that you can run
Ansible plays on managed hosts, synchronize information from dynamic inventory sources,
and import Ansible project content from version control systems. Ansible Tower encrypts the
passwords or keys provided so that they cannot be retrieved by Ansible Tower users. You can
grant users the ability to use or replace these credentials without actually exposing them to
the user.

Ansible supports more than 15 different credential types, which includes major providers such
as Google Compute Engine, Microsoft Azure, and VMware.

14 DO417-RHAE2.8-en-1-20200106
Chapter 1 | Introducing Red Hat Ansible Automation

Figure 1.7: Managing Ansible Tower credentials

Centralized Logging and Auditing


Ansible Tower logs all playbook and remote command execution. This allows you to audit when
each job was executed and by whom. In addition, Ansible Tower offers the ability to integrate
its log data into third-party logging aggregation solutions, such as Splunk and Sumologic.

Integrated Notifications
Ansible Tower notifies you when job executions succeed or fail. Ansible Tower can deliver
notifications using many applications, including email, Slack, and HipChat.

Multiplaybook Workflows
Complex operations often involve the serial execution of multiple playbooks. Ansible Tower
multi-playbook workflows allow users to chain together multiple playbooks to facilitate
the execution of complex routines involving provisioning, configuration, deployment, and
orchestration. An intuitive workflow editor also simplifies the modeling of multi-playbook
workflows.

RESTful API
The Ansible Tower RESTful API exposes every Ansible Tower feature available through the
web UI. The API's browsable format makes it self-documenting, and simplifies the lookup of
API usage information.

DO417-RHAE2.8-en-1-20200106 15
Chapter 1 | Introducing Red Hat Ansible Automation

Figure 1.8: Interacting with Ansible Tower API

Interacting with Git Repositories


Ansible Tower projects can retrieve your playbooks from a version control system such as Git, SVN,
or Mercurial and run them. For a Git repository, you can pull code from a specific branch, tag, or
commit, and run that version of the code. You can also configure Ansible Tower to provide any
authentication information it needs to access the repository.

Figure 1.9: Managing VCS with Ansible Tower

16 DO417-RHAE2.8-en-1-20200106
Chapter 1 | Introducing Red Hat Ansible Automation

With this flexible approach you can test your changes from a development branch against a set
of test servers. Based on the results, you can then decide whether to merge your changes to the
main branch to use them in the production environment.

References
For more information, refer to the Ansible Tower Administration Guide at
https://docs.ansible.com/ansible-tower/latest/html/administration/

Manage Windows like Linux with Ansible


https://www.redhat.com/en/about/videos/summit-2018-manage-windows-linux-
ansible

Integration: Ansible and Windows


https://www.ansible.com/integrations/infrastructure/windows

Windows PowerShell Desired State Configuration Overview


https://docs.microsoft.com/en-us/powershell/dsc/overview/overview

DO417-RHAE2.8-en-1-20200106 17
Chapter 1 | Introducing Red Hat Ansible Automation

Guided Exercise

Architecture of Windows Automation


with Red Hat Ansible Tower
In this exercise, you will log in to a Red Hat Ansible Tower server, explore and familiarize
yourself with its web-based user interface, and use it to launch an existing automation
template.

Outcomes
You should be able to log into the Ansible Tower web UI, explore the control panel, and
launch a template from the console.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. Access the Ansible Tower web UI.

1.1. Double click the desktop shortcut labeled Ansible Tower and authenticate with the
user admin and RedHat123@! as the password.

2. Review Ansible Tower configuration.

2.1. From the dashboard, click Users in the sidebar to view the accounts available within
Ansible Tower.

18 DO417-RHAE2.8-en-1-20200106
Chapter 1 | Introducing Red Hat Ansible Automation

This menu displays the accounts available, including the admin account currently in
use.

2.2. Click Settings at the bottom of the console sidebar to access the Ansible Tower
configuration.

2.3. Click Authentication to view the current configuration.

From this panel, you can configure authentication from various applications and
providers, such as GitHub or LDAP. Click the LDAP button to view the current
configuration for your instance.
In a production configuration, configure the authentication implementation that is
appropriate for your environment.

DO417-RHAE2.8-en-1-20200106 19
Chapter 1 | Introducing Red Hat Ansible Automation

2.4. Return to the Settings page, and then click License to view the licensing information
for Ansible Tower.

From this panel, you can peruse the licensing information for this instance of Ansible
Tower, as well as upload a new license file.

3. Access and execute job templates.

3.1. From the console sidebar, click Templates to access the available templates or
configure new ones. Templates are a set of instructions that execute Ansible Playbooks
and perform tasks using Ansible modules.

3.2. From the Templates list, select the Run architecture project template.

Note
To select a project for editing, click its name.

3.3. Select the create_desktop_file.yml playbook from the PLAYBOOK list, and
then click Save to update the job template.
The playbook instructs Ansible to create an ansible.txt text file on the devops'
desktop of the win1.example.com server.
Select LAUNCH to begin execution.

20 DO417-RHAE2.8-en-1-20200106
Chapter 1 | Introducing Red Hat Ansible Automation

3.4. While the job is running, Ansible Tower displays the output of the tasks as they execute.
Ansible retrieves information about the system, and then runs the tasks. A task with a
state of changed indicates that the file was not present and that the task creates it.

The output also displays job statistics, such as the start time and information from the
template in use.

3.5. Once completed, the status changes from Running to Successful. If the job
encounters any issues, this status changes to Failed and the output contains
information regarding the errors.

DO417-RHAE2.8-en-1-20200106 21
Chapter 1 | Introducing Red Hat Ansible Automation

Select an entry from the output to access more information about the execution result.

4. Access the ansible.txt text file.

4.1. To ensure that the file is present on win1.example.com, access the Remote
Desktop Connection client available from the Start menu. The client is accessible
from the Windows Server applications list.
Access win1 using devops as the user name. Click Connect to initiate the
connection. When prompted, use a password of RedHat123@!, and then click OK.

22 DO417-RHAE2.8-en-1-20200106
Chapter 1 | Introducing Red Hat Ansible Automation

4.2. Accept the self-signed certificate by selecting Yes.

4.3. Ensure that the ansible.txt text file is present on the desktop.

DO417-RHAE2.8-en-1-20200106 23
Chapter 1 | Introducing Red Hat Ansible Automation

This concludes the guided exercise.

24 DO417-RHAE2.8-en-1-20200106
Chapter 1 | Introducing Red Hat Ansible Automation

Managing Files in Git with Visual Studio


Code

Objectives
After completing this section, you should be able to retrieve, manage, edit, and store files in a
remote Git version control system such as GitHub or GitLab, using Visual Studio Code.

Infrastructure-as-Code
One key DevOps concept is the idea of Infrastructure-as-Code (IaC), previously discussed in
this chapter. Instead of managing your infrastructure manually, you define and build your systems
by running your automation code. Red Hat Ansible Automation is a key tool that can help you
implement this approach.

If Ansible projects are the code which is used to define the infrastructure, then a version control
system such as Git should be used to track and control changes to the code.

Version control also allows you to implement a life cycle for the different stages of your
infrastructure code, such as development, QA, and production. You can commit your changes to
a branch, and then test those changes in noncritical development and QA environments. Once
you are confident in the changes, you can merge them to the main production code and apply the
changes to your production infrastructure.

Introducing Git
Git is a distributed version control system (DVCS) that allows you to manage changes to files in a
project in a collaborative manner. Each revision of a file is committed to the system. Old versions
of files can be restored, and a log of who made the changes is maintained.

Version control systems provide many benefits, including:

• The ability to review and restore old versions of files.

• The ability to compare two versions of the same file to identify changes.

• A record or log of who made what changes, and when those changes were made.

• Mechanisms for multiple users to collaboratively modify files, resolve conflicting changes, and
merge the changes together.

Each developer can start by cloning an existing shared project from a remote repository. Cloning
a project creates a complete copy of the original remote repository as a local repository. This is
a local copy of the entire history of the files in the version control system, and not just the latest
snapshot of the project files.

The developer makes edits in a working tree, which is a working area for new and modified files.
A set of related changes are then staged and committed to the local repository. At this point, no
changes have been made to the shared remote repository.

When the developer is ready to share their work, they push changes to the remote repository.
Alternatively, if the local repository is accessible from the network, the owner of the remote
repository can pull the changes from the developer's local repository to the remote repository.

DO417-RHAE2.8-en-1-20200106 25
Chapter 1 | Introducing Red Hat Ansible Automation

Likewise, when a developer is ready to update their local repository with the latest changes in the
remote repository, they can pull the changes, which fetches them from the remote repository and
merges them into the local repository.

To use Git effectively, a user must be aware of the three possible states of a file in the working
tree: modified, staged, or committed.

• Modified: the copy of the file in the working tree has been edited and is different from the latest
version in the repository.

• Staged: the modified file has been added to a list of changed files to commit as a set, but has
not yet been committed.

• Committed: the modified file has been committed to the local repository.

Once the file is committed to the local repository, the commit can be pushed to or pulled by a
remote repository.

Figure 1.23: The four areas where Git manages files

A link to detailed information on Git can be found in the references at the end of this section.

Introducing Visual Studio Code


Visual Studio Code is a multiplatform, lightweight Integrated Development Environment (IDE),
for editing and debugging code. The project itself is mostly developed under an open source
MIT license, at https://github.com/microsoft/vscode, but official builds include some
customizations released under a proprietary Microsoft license. Scripts to build fully open source
binaries based on that project, with all proprietary code removed, are maintained at https://
github.com/VSCodium/vscodium.

In this course, you will use Visual Studio Code as your primary editor for Ansible files and tool for
working with Git repositories.

There are other text editors available on Windows with support for Git, including Atom and
Sublime Text.

Installing Git on Microsoft Windows


Git for Windows is available at https://git-scm.com/download/win. The installation is
straightforward. If you are using Git with Visual Studio Code, you should select Visual Studio Code
as the default editor when prompted.

26 DO417-RHAE2.8-en-1-20200106
Chapter 1 | Introducing Red Hat Ansible Automation

Figure 1.24: The default editor for Git

After installing Git, run the Git GUI program accessible from the quick start menu. After cloning
a repository, you can configure the user name and email address settings for the repository, or
globally.

Figure 1.25: Accessing Git GUI

DO417-RHAE2.8-en-1-20200106 27
Chapter 1 | Introducing Red Hat Ansible Automation

Figure 1.26: Managing default Git options using Git GUI

Configuring Visual Studio Code


Most of the integration between Visual Studio Code and Git is performed within Visual Studio
Code. Navigate to File → Preferences → Settings, expand Extensions, and then select Git.
Scroll to the Path setting, and then select the Edit in settings.json link in the main window. This
opens the JSON file that stores the settings.

Figure 1.27: Configure Git settings with Visual Studio Code

Add the Path option with the value being the absolute path to the Git executable.

28 DO417-RHAE2.8-en-1-20200106
Chapter 1 | Introducing Red Hat Ansible Automation

Note
Make sure to escape any backslashes with an extra backslash, as shown in the
following figure.

Figure 1.28: Configure the path to the Git executable

Because you are working with Ansible Playbooks, which are in YAML format, install the YAML
extension by navigating to View → Extensions, and then search for or scroll down to the YAML
extension. Click Install.

Figure 1.29: Install the YAML extension

You can clone a Git repository in Visual Studio Code by accessing the Command Palette, which
is accessible by selecting View → Command Palette or by pressing Ctrl+Shift+P on the
keyboard. Type Git: Clone to access the Git clone feature.

The command palette prompts you for the URL of the remote repository, and the intended parent
directory for the local repository.

DO417-RHAE2.8-en-1-20200106 29
Chapter 1 | Introducing Red Hat Ansible Automation

Figure 1.30: Cloning Git repositories using the command palette

Managing Playbooks in Visual Studio Code


For the purposes of this example, assume that you have cloned a repository from a central Git
server. Navigate to File → Open Folder..., select the location of the cloned repository, and then
click Select Folder. The Explorer view should be active, showing the contents of the cloned
repository.

Figure 1.31: Explorer view

Note the version control status icons at the lower left of the screen. They currently indicate that
there have been no changes.

30 DO417-RHAE2.8-en-1-20200106
Chapter 1 | Introducing Red Hat Ansible Automation

Figure 1.32: Version control status icons

Adding a new site.yml file results in a notification being added to the Source Control icon,
as well as a U being displayed next to site.yml. The U indicates that site.yml is untracked,
meaning that Git is not watching it for changes. If you navigate to the Source Control view, you
will see site.yml listed underneath Changes.

Figure 1.33: A new file is created

DO417-RHAE2.8-en-1-20200106 31
Chapter 1 | Introducing Red Hat Ansible Automation

Figure 1.34: The new file listed under Changes in Source Control view

Some of the common codes for changed files are as follows:

Indicator Description

U (Untracked) This file is not under version control yet.

M (Modified) This file is tracked by git and has been modified.

A (Added) This file has been added to the index and will be included in the next commit.

D (Deleted) This file has been deleted. The file will no longer appear in the Explorer view,
only in the Source Control view. The deletion of the file will be included in the
next commit.

Click + next to site.yml to add the file to Git, and then enter a commit message describing
your changes. Ideally, your commit message will be succinct enough to fit on a single line. Press
Ctrl+Enter to commit your changes.

Figure 1.35: Commit changes

Now that a local change has been committed, the local repository is ahead of the remote
repository in terms of changes. Note the status icon at the lower left, which shows that one change
can be pushed to the remote repository.

32 DO417-RHAE2.8-en-1-20200106
Chapter 1 | Introducing Red Hat Ansible Automation

Figure 1.36: The local repository is ahead of the remote repository

The status icons displayed in the lower left corner of the editor indicate that there are changes
ready to push to the remote Git repository. Click Synchronize Changes to push your local changes
to the remote repository, and retrieve any new changes from the repository.

Figure 1.37: A push to the remote repository is required

The repositories are now synchronized again, and the next piece of work can begin.

References
Pro Git by Scott Chacon and Ben Straub (free book)
https://git-scm.com/book/en/v2

Visual Studio Code


https://code.visualstudio.com/

How to Write a Git Commit Message


https://chris.beams.io/posts/git-commit/

DO417-RHAE2.8-en-1-20200106 33
Chapter 1 | Introducing Red Hat Ansible Automation

Guided Exercise

Managing Files in Git with Visual Studio


Code
In this exercise you will edit files in a local copy of a remote Git repository, commit your
changes, and then push those changes to the remote repository.

Outcomes
You should be able to configure Git settings, and edit files stored in an existing Git
repository.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. Launch the Visual Studio Code editor and clone the architecture repository to your
workstation instance.

1.1. Click Search Windows, type code as the term for which to search, and then open
Visual Studio Code.

34 DO417-RHAE2.8-en-1-20200106
Chapter 1 | Introducing Red Hat Ansible Automation

1.2. Open the command palette by navigating to View → Command Palette or by typing
Ctrl+Shift+P.
Type clone and select Git: Clone to clone a repository.
Use a repository URL of https://gitlab.example.com/student/
architecture.git. When prompted, select the Documents folder in the home
directory of the training user as the repository location, and then click Select
Repository Location. This clones the remote repository into the architecture
folder.
Optionally, view the files by selecting Open from the window that displays after
cloning.

DO417-RHAE2.8-en-1-20200106 35
Chapter 1 | Introducing Red Hat Ansible Automation

2. Open the c:\Users\student\Documents\architecture directory by navigating


to File → Open Folder, and then select the c:\Users\student\Documents
\architecture folder.

3. Edit the site.yml file, and then commit your changes.

3.1. Select the site.yml file, and then change the task name and the name of the
managed Windows service from W32Time to Spooler.

...output omitted...
- name: Spooler service is enabled and running
win_service:
name: Spooler
start_mode: auto
state: running

3.2. Click Save. Note the status icons in the lower left. There is an asterisk next to Master,
indicating that changes have been made.

3.3. Change to the Source Control view, and then select +, next to site.yml, to stage
the changes.

3.4. Enter a commit message, and then press Ctrl+Enter to commit the changes.

4. Edit the README.md file, commit your changes, and then synchronize your local repository
with the remote one.

4.1. Select the Explorer view, and then the README.md file.

4.2. Change the service name in the description from W32Time to Spooler.

This is a sample README for the Managing Files in Git exercise in DO417

### Description: Manages the Spooler service


...output omitted...

4.3. Click Save. Note the status icons in the lower left. There is an asterisk next to master
again, indicating that changes have been made.

4.4. Change to the Source Control view, and then select + next to README.md to stage
the changes.

4.5. Enter a commit message, and then press Ctrl+Enter to commit the changes.

4.6. The status icons displayed in the lower left corner of the editor indicate that there
are changes ready to push to the remote Git repository. Click Synchronize Changes,
represented by a circular arrow at the bottom of the editor, to push your local changes
to the remote repository, and retrieve any new changes from the repository.

36 DO417-RHAE2.8-en-1-20200106
Chapter 1 | Introducing Red Hat Ansible Automation

Click Yes or Ask Me Later when prompted.

This concludes the guided exercise.

DO417-RHAE2.8-en-1-20200106 37
Chapter 1 | Introducing Red Hat Ansible Automation

Lab

Introducing Red Hat Ansible Automation


Performance Checklist
In this lab, you will use Visual Studio Code to clone a Git repository from a remote server,
make changes to your local repository and commit them, and push the changes to the
remote repository.

Outcomes
You should be able to:

• Access the GitLab web console and inspect repositories.

• Clone a remote repository using Visual Studio Code.

• Update an Ansible Playbook.

• Commit and push your changes to a remote Git repository.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. From workstation, access your GitLab instance available at https://


gitlab.example.com. Connect as the student user and RedHat123@! as the password.
Access the architecture repository in the student namespace, and ensure that the
review.yml playbook exists. Inspect the content of the playbook.
2. From workstation, access Visual Studio Code. If you did not already clone the
architecture repository, available at https://gitlab.example.com/student/
architecture.git, clone it to C:\Users\student\Documents\architecture.
Add the architecture folder to the Visual Studio Code workspace.
3. Use Visual Studio Code to edit the file review.yml in the architecture project. These
edits will change an Ansible Playbook. For now, do not worry about what these changes do, as
this exercise is intended to give you a chance to practice using Visual Studio Code with Git.
Read the file and make the following changes:

• On the hosts: line, insert a space and the text win1.example.com after the colon.

• For the first task, that is, the line that reads - name: Install service, replace "Install
service" with IIS Web Server is installed.

38 DO417-RHAE2.8-en-1-20200106
Chapter 1 | Introducing Red Hat Ansible Automation

• For the second task (- name: Start service), change the line name: W3Svc to
name: IIS Web Server is started. Do not change the indentation of this line.

Save your changes.


4. Add your changes to the Git index, and then commit your changes using a message of Use
more descriptive task names and target the correct host.
Commit and push your changes back to the master branch.
5. Access the GitLab web console and review the review.yml playbook in the
architecture repository to ensure that the changes are available on the remote server.

This concludes the lab.

DO417-RHAE2.8-en-1-20200106 39
Chapter 1 | Introducing Red Hat Ansible Automation

Solution

Introducing Red Hat Ansible Automation


Performance Checklist
In this lab, you will use Visual Studio Code to clone a Git repository from a remote server,
make changes to your local repository and commit them, and push the changes to the
remote repository.

Outcomes
You should be able to:

• Access the GitLab web console and inspect repositories.

• Clone a remote repository using Visual Studio Code.

• Update an Ansible Playbook.

• Commit and push your changes to a remote Git repository.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. From workstation, access your GitLab instance available at https://


gitlab.example.com. Connect as the student user and RedHat123@! as the password.
Access the architecture repository in the student namespace, and ensure that the
review.yml playbook exists. Inspect the content of the playbook.

1.1. From workstation, double-click the GitLab icon on your Desktop to access your
GitLab instance located at https://gitlab.example.com.

1.2. Log in to GitLab using student as the user name and RedHat123@! as the password.
Make sure that LDAP is selected and click Sign In.

40 DO417-RHAE2.8-en-1-20200106
Chapter 1 | Introducing Red Hat Ansible Automation

1.3. The page redirects you to the list of projects for the student user. From the Your
projects tab select the architecture project to view the contents of the repository.

1.4. The page lists all the files in the repository. Click review.yml to inspect the playbook.

1.5. The playbook invokes the win_feature module to install the IIS web server on
your managed hosts. After installation, the playbook starts the service by using the
win_service module.

DO417-RHAE2.8-en-1-20200106 41
Chapter 1 | Introducing Red Hat Ansible Automation

2. From workstation, access Visual Studio Code. If you did not already clone the
architecture repository, available at https://gitlab.example.com/student/
architecture.git, clone it to C:\Users\student\Documents\architecture.
Add the architecture folder to the Visual Studio Code workspace.

2.1. Click Search Windows, and then type code to search for, and then open, Visual Studio
Code.

2.2. To clone the architecture repository, open the command palette by navigating to
View → Command Palette or by typing Ctrl+Shift+P.
Type clone and select Git: Clone to clone a repository.
Use a repository URL of https://gitlab.example.com/student/
architecture.git. When prompted, select the Documents folder in the home
directory of the training user as the repository location, and click Select Repository
Location. This clones the remote repository into the architecture folder.
Optionally, to view the files select Open from the window that displays after cloning.

2.3. To add the architecture folder to your workspace, navigate to File → Open Folder.

42 DO417-RHAE2.8-en-1-20200106
Chapter 1 | Introducing Red Hat Ansible Automation

From the Windows Explorer, navigate to Local Disk (C:) → Users → student →
architecture and then click Select Folder.

3. Use Visual Studio Code to edit the file review.yml in the architecture project. These
edits will change an Ansible Playbook. For now, do not worry about what these changes do, as
this exercise is intended to give you a chance to practice using Visual Studio Code with Git.
Read the file and make the following changes:

• On the hosts: line, insert a space and the text win1.example.com after the colon.

• For the first task, that is, the line that reads - name: Install service, replace "Install
service" with IIS Web Server is installed.

• For the second task (- name: Start service), change the line name: W3Svc to
name: IIS Web Server is started. Do not change the indentation of this line.

Save your changes.

3.1. From Visual Studio Code, open the review.yml playbook in the architecture folder.
On the hosts: line, insert a space and the text win1.example.com after the colon.

---
- name: Install the IIS web server on managed hosts
hosts: win1.example.com
...output omitted...

3.2. For the first task, that is, the line that reads - name: Install service, replace
"Install service" with IIS Web Server is installed.

DO417-RHAE2.8-en-1-20200106 43
Chapter 1 | Introducing Red Hat Ansible Automation

...output omitted...
tasks:
- name: IIS Web Server is installed
win_feature:
name: Web-Server
state: present
...output omitted...

3.3. For the second task (- name: Start service), change the line name: W3Svc to
name: IIS Web Server is started.

...output omitted...
- name: IIS Web Server is started
win_service:
name: W3Svc
state: started

3.4. Save your file. After your updates, the file should display as follows:

---
- name: Install the IIS web server on managed hosts
hosts: win1.example.com
tasks:
- name: IIS Web Server is installed
win_feature:
name: Web-Server
state: present

- name: IIS Web Server is started


win_service:
name: W3Svc
state: started

Note
The completed solution file is available at solutions/review.sol in the
architecture project.

4. Add your changes to the Git index, and then commit your changes using a message of Use
more descriptive task names and target the correct host.
Commit and push your changes back to the master branch.

4.1. From the Visual Studio Code side bar, select Source Control to access the list of
changes.

44 DO417-RHAE2.8-en-1-20200106
Chapter 1 | Introducing Red Hat Ansible Automation

4.2. Hover over review.yml to access the available options for the file. Click Stage
Changes to add your changes to the index.

4.3. In the Message text file, enter a message of Use more descriptive task names
and target the correct host

4.4. Click Commit to commit the changes to your local repository.

DO417-RHAE2.8-en-1-20200106 45
Chapter 1 | Introducing Red Hat Ansible Automation

4.5. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to push
your local changes to the remote repository, and retrieve any new changes from the
repository.

5. Access the GitLab web console and review the review.yml playbook in the
architecture repository to ensure that the changes are available on the remote server.

5.1. From workstation, refresh your browser or navigate to Student → Personal


projects → student / architecture to access the repository.
Select the review.yml playbook. The output should display your changes.

This concludes the lab.

46 DO417-RHAE2.8-en-1-20200106
Chapter 1 | Introducing Red Hat Ansible Automation

Summary
In this chapter, you learned:

• Infrastructure as Code (IaC) allows you to use a machine-readable automation language to


define and describe the state you want your IT infrastructure to be in.

• Ansible is an open source automation platform and a simple automation language that can
describe IT application infrastructure.

• Ansible is installed and run from a control node, that runs playbooks against managed hosts..

• Ansible Tower provides native tools and features for managing Microsoft Windows
environments.

• Git is a distributed version control system (DVCS) that allows you to manage changes to files in
a project in a collaborative manner.

DO417-RHAE2.8-en-1-20200106 47
48 DO417-RHAE2.8-en-1-20200106
Chapter 2

Running Simple Automation


Commands
Goal Prepare Microsoft Windows hosts for automation
and Red Hat Ansible Tower as a central automation
control system, and run one-off automation tasks
on those hosts from Ansible Tower.

Objectives • Configure Microsoft Windows systems


to provide the prerequisites and access
needed for management by Red Hat Ansible
Automation.
• Configure Red Hat Ansible Tower with an
inventory of Windows hosts to manage, and
credentials needed to authenticate and
connect to those hosts.
• Describe what an Ansible module is, and run
a single operation on managed hosts as an ad
hoc command using Red Hat Ansible Tower.

Sections • Preparing Microsoft Windows Hosts for


Automation (and Quiz)
• Preparing Red Hat Ansible Tower to Manage
Hosts (and Guided Exercise)
• Running Ad Hoc Commands (and Guided
Exercise)

Lab Running Simple Automation Commands

DO417-RHAE2.8-en-1-20200106 49
Chapter 2 | Running Simple Automation Commands

Preparing Microsoft Windows Hosts for


Automation

Objectives
After completing this section, you should be able to configure Microsoft Windows systems to
provide the prerequisites and access needed for management by Red Hat Ansible Automation.

Managed Hosts
One of the benefits of Ansible is that managed hosts do not need to have a special agent installed.
The Ansible control node connects to managed hosts using a standard network protocol to ensure
that the systems are in the specified state. On Windows systems, Ansible connects to the Windows
Remote Management (WinRM) service and its listener.

Minimum Requirements
Before getting started, verify that the minimum host operating system requirements are met.

You can use Ansible to manage all versions of Windows that are under Microsoft mainstream
and extended support. Older versions of Windows, such as Windows Server 2008 or Windows 7,
require PowerShell and .NET Framework updates. Always apply the latest security patches.

Managed hosts need the following minimum base requirements:

• Windows Server (2008, 2008 R2, 2012, 2012 R2, 2016, or 2019) or Windows 7, 8.1, or 10

• PowerShell 3.0 or newer

• .NET Framework 4.0 or newer

Windows versions since Windows Server 2012 and Windows 8 ship with the minimum required .NET
and PowerShell dependencies. Versions of Windows prior to this require download and installation
of the latest service pack, .NET framework, and PowerShell.

These are the basic requirements for Ansible to work in general. However, some Ansible modules
may have additional requirements that will be listed in the documentation for those modules at
https://docs.ansible.com/ansible/latest/user_guide/modules.html.

Important
Due to a WinRM memory issue, PowerShell 3.0 requires a hotfix. Refer to the
Microsoft support article available at https://support.microsoft.com/en-us/
help/2842230/out-of-memory-error-on-a-computer-that-has-a-customized-
maxmemorypersh for more information.

Install the latest stable updates to keep your systems secure and reliable.

Configuring Windows for Ansible Access


Ansible communicates with Windows hosts using Windows Remote Management. WinRM is a
Microsoft implementation of the SOAP-based WS-Management standard protocol and provides a
noninteractive login to control a remote system.

50 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

WinRM is enabled by default since Windows Server 2012. However, you still need to configure a
WinRM listener, the corresponding firewall rules, and the authentication mechanism.

Ansible uses the PowerShell Remoting Protocol (PSRP) on top of WinRM to execute PowerShell
commands on a target. PSRP provides a faster direct connection to PowerShell.

Since the Ansible connection normally depends on both WinRM and PowerShell, Ansible cannot
interact directly with WinRM listeners or upgrade PowerShell.

Note
Ansible 2.8 provides an experimental feature that allows you to use SSH instead of
WinRM to connect to Windows hosts. It is not yet supported and might change in
future versions of Ansible. This course uses the standard WinRM protocol to connect
to Windows-based managed hosts.

Configuring for Development Environments


The Ansible project provides an example PowerShell script for configuring Windows managed
hosts for remote access. This script is designed for use in lab and development environments
where high levels of security are not a concern. Ansible does not recommend using the example
script in production environments due to the potential weakening of the authentication
mechanism.

Find the script in the official repository https://github.com/ansible/ansible/blob/


devel/examples/scripts/ConfigureRemotingForAnsible.ps1.

The ConfigureRemotingForAnsible.ps1 script performs the following actions:

1. Confirms PowerShell version 3 or higher is installed.

2. Runs the WinRM service, if not already running, and configures it to automatically start on
boot.

3. Enables PowerShell Remoting and an SSL listener.

4. Sets the LocalAccountTokenFilterPolicy registry key to 1.

5. Optionally configures basic authentication or CredSSP. This is discussed in detail below.

6. Configures the Windows firewall for WinRM connections over both HTTP and HTTPS.

Run ConfigureRemotingForAnsible.ps1 as an Administrator with the appropriate options


for your environment. This course uses the -DisableBasicAuth and -EnableCredSSP options
as a security preference.

ConfigureRemotingForAnsible.ps1 also creates a self-signed certificate for HTTPS


communication. Several options exist to customize the SSL certificate or force the creation of a
new one.

The following list describes the list of arguments that you can use with the PowerShell script:

ConfigureRemotingForAnsible.ps1 Argument List

-EnableCredSSP
Enables the CredSSP authentication protocol.

DO417-RHAE2.8-en-1-20200106 51
Chapter 2 | Running Simple Automation Commands

-DisableBasicAuth
Disables Basic authentication. This option is recommended since Basic authentication is the
least secure WinRM authentication method.

-CertValidityDays
Specifies the expiration of the self-signed SSL certificate created for HTTPS. The default
validity is 1095 days (3 years).

-ForceNewSSLCert
Forces the creation of a new SSL certificate.

-SubjectName
Specifies the CN (Common Name) of the SSL certificate. Defaults to the host name.

-SkipNetworkProfileCheck
Allows for enabling PS Remoting without checking the network profile.

-Verbose
Enables verbose output. This option is useful for debugging.

Configuring for Production Environments


Running ConfigureRemotingForAnsible.ps1 quickly bootstraps systems for lab and
development environments, but it is not intended for robust production systems. Use the script as
a starting point, and then tailor it to adhere to your security requirements.

To avoid inconsistencies across systems and reduce manual steps, integrate the script as part
of an automated host provisioning process. Specific methods for achieving this vary across
environments and are outside of the scope of this course.

Authentication
Ansible can use a variety of protocols to authenticate its connection with Windows hosts. These
are: Basic, Certificate, CredSSP, NTLM, and Kerberos. You must configure the managed host to
accept the protocol best suited for your environment.

Option Local Accounts Active Credentials HTTP


Directory Delegation Encryption
Accounts

Basic Yes No No No

Certificate Yes No No No

Kerberos No Yes Yes Yes

NTLM Yes Yes No Yes

CredSSP Yes Yes Yes Yes

Warning
Basic and certificate authentication strategies are unencrypted. It is strongly
advised to only allow these protocols over trusted HTTPS connections.

52 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

Basic and certificate authentication protocols are simple but less secure. Additionally, these
options can only use local accounts. Most production configurations require a protocol designed
for domain accounts.

CredSSP, NTLM, and Kerberos support domain accounts. CredSSP and Kerberos are preferred
due to their security, speed, and support for credential delegation.

CredSSP
Credential Security Support Provider (CredSSP) supports authentication for both local and
domain accounts.

Unlike Basic authentication, CredSSP encrypts credentials prior to transmitting them to the target
host. Encrypted messages may be sent over HTTP.

Note
This course uses CredSSP for the classroom environment.

A primary feature of CredSSP is credential delegation. This allows your target server to
authenticate to a second server using your credentials.

Important
Only use CredSSP credential delegation with trusted hosts. User credentials are
passed directly to the servers.

Run the ConfigureRemotingForAnsible.ps1 command with the -EnableCredSSP


option to enable CredSSP authentication. This executes the PowerShell command Enable-
WSManCredSSP -role server -Force.

New Technology Local-Area Network Manager


NT (New Technology) LAN (Local-Area Network) Manager (NTLM) is a one-way hash
authentication protocol.

The NTLM protocol requires no additional setup and the WinRM service enables it by default.

NTLM is widely used for legacy compatibility, however it is not preferred for production
applications due to security weaknesses and known vulnerabilities. Kerberos has superseded
NTLM as the recommended authentication protocol.

Kerberos
Kerberos is the default Microsoft network authentication protocol and provides a more
sophisticated authentication option, which is recommended for use with domain accounts.

Kerberos is designed to securely authenticate entities in an untrusted network, such as the


Internet. It uses symmetric key cryptography and a trusted third party to generate and validate a
system of exchanged tickets.

Clients authenticate with a Kerberos Key Distribution Center (KDC) to retrieve a session ticket. The
Active Directory domain controller can provide the role of the KDC. Shared secrets are used to
encrypt and decrypt messages between entities.

DO417-RHAE2.8-en-1-20200106 53
Chapter 2 | Running Simple Automation Commands

Unlike CredSSP and NTLM, Kerberos does not support local accounts.

Configuring Active Directory and Kerberos authentication is discussed in Chapter 8, Interacting


with Users and Domains.

References
Ansible Windows Guides — Ansible Documentation
https://docs.ansible.com/ansible/latest/user_guide/windows.html

Windows Remote Management


https://docs.microsoft.com/en-us/windows/win32/winrm/portal

54 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

Quiz

Preparing Microsoft Windows Hosts for


Automation
Choose the correct answers to the following questions:

1. Which two technologies are required on Windows managed hosts? (Choose two.)
a. OpenSSH 8.0
b. .NET Framework 4.0
c. Visual Studio 2019
d. PowerShell 3.0

2. What are two limitations of the Ansible WinRM connection? (Choose two.)
a. Ansible cannot execute commands that require administrator access.
b. Ansible cannot interact with the WinRM listener.
c. Ansible cannot upgrade PowerShell.
d. Ansible cannot reboot the host.

3. What is the purpose of the ConfigureRemotingForAnsible.ps1 example PowerShell


script provided by Ansible?
a. To quickly configure managed hosts for remote access.
b. To demonstrate best practices for production deployments.
c. To configure Ansible Tower for remote operation.
d. To remotely install the latest software updates on managed hosts.

4. What feature makes CredSSP more secure than Basic authentication?


a. CredSSP does not transmit credentials during a second server hop.
b. CredSSP does not support local accounts.
c. A trusted third party provides an encrypted exchange of tickets.
d. CredSSP encrypts credentials prior to sending them to the target host.

5. Which three features make Kerberos the preferred option for production
environments? (Choose three.)
a. Kerberos is the default Microsoft network authentication protocol.
b. Kerberos supports Active Directory domain accounts.
c. Kerberos uses symmetric key cryptography and a system of tickets instead of passing
account credentials directly to the target host.
d. Kerberos cannot be operated securely in untrusted networks.

DO417-RHAE2.8-en-1-20200106 55
Chapter 2 | Running Simple Automation Commands

Solution

Preparing Microsoft Windows Hosts for


Automation
Choose the correct answers to the following questions:

1. Which two technologies are required on Windows managed hosts? (Choose two.)
a. OpenSSH 8.0
b. .NET Framework 4.0
c. Visual Studio 2019
d. PowerShell 3.0

2. What are two limitations of the Ansible WinRM connection? (Choose two.)
a. Ansible cannot execute commands that require administrator access.
b. Ansible cannot interact with the WinRM listener.
c. Ansible cannot upgrade PowerShell.
d. Ansible cannot reboot the host.

3. What is the purpose of the ConfigureRemotingForAnsible.ps1 example PowerShell


script provided by Ansible?
a. To quickly configure managed hosts for remote access.
b. To demonstrate best practices for production deployments.
c. To configure Ansible Tower for remote operation.
d. To remotely install the latest software updates on managed hosts.

4. What feature makes CredSSP more secure than Basic authentication?


a. CredSSP does not transmit credentials during a second server hop.
b. CredSSP does not support local accounts.
c. A trusted third party provides an encrypted exchange of tickets.
d. CredSSP encrypts credentials prior to sending them to the target host.

5. Which three features make Kerberos the preferred option for production
environments? (Choose three.)
a. Kerberos is the default Microsoft network authentication protocol.
b. Kerberos supports Active Directory domain accounts.
c. Kerberos uses symmetric key cryptography and a system of tickets instead of passing
account credentials directly to the target host.
d. Kerberos cannot be operated securely in untrusted networks.

56 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

Preparing Red Hat Ansible Tower to


Manage Hosts

Objectives
After completing this section, you should be able to configure Red Hat Ansible Tower with an
inventory of Windows hosts to manage, and credentials needed to authenticate and connect to
those hosts.

Managing Windows Systems with Ansible Tower


Red Hat Ansible Tower can be a central control panel to manage your Microsoft Windows systems.
It can protect the security of authentication credentials, add and organzie host machines into
groups, and control user access to those projects and credentials.

Specifying Managed Hosts in Ansible Tower


Ansible Tower gets lists of hosts to manage from inventories. An inventory describes a collection of
individual hosts or host groups on which automation jobs can be run.

You can set other information through inventory variables on individual hosts, host groups, or all
members of a particular inventory. Inventory variables can modify how Ansible Tower interacts with
or connects to hosts, and automation jobs can use them to determine what to do.

You can configure more than one inventory in Ansible Tower, and use different inventories for
different purposes. Manually specify hosts and host groups in an inventory, or dynamically
generate inventory settings from a remote source of information, such as Microsoft Azure
Resource Manager or Amazon Web Services EC2.

Creating an Inventory in the Ansible Tower Web UI


Inventories describe a collection of hosts against which jobs are run. Inventories are divided into
groups and these groups contain the hosts. You can use an IP address, a host name, or regular
expressions when host names use a naming pattern. Groups are similar to categories that describe
a set of similar hosts, for example, a development group would contain all of your development
servers.

You can create inventories manually or dynamically provision them. Inventories require a name and
must be assigned to an organization.

The following example outlines the procedure to manually create an inventory in the web-based
user interface:

1. Log in to the Ansible Tower web-based user interface.

2. Click the Inventories in the navigation pane.

3. On the INVENTORIES window, click the + button.


Choose Inventory from the list.
On the NEW INVENTORY window, enter the NAME of the inventory and its
ORGANIZATION. Click the magnifying glass icon for the ORGANIZATION box to get a list
of the available organizations.

DO417-RHAE2.8-en-1-20200106 57
Chapter 2 | Running Simple Automation Commands

Click SAVE.

Figure 2.1: Creating new inventories in Ansible Tower

Once the inventory exists, you can add hosts to it, assign those hosts to groups, and set values for
inventory variables.

There are two main ways to add hosts to inventories. Static inventories are managed manually.
Dynamic inventories are dynamically updated the with hosts and groups in the inventory by
retrieving a list from some central source of information, such as Microsoft Azure Resource
Manager, Amazon EC2, or VMware vCenter. It is often easier and more efficient to set up a
dynamic inventory that gets up to date information from an accurate central source.

Managing Hosts in an Inventory


Ansible hosts define the systems to manage. To add a host to a static inventory:

1. In the Ansible Tower web-based user interface, click the Inventories in the navigation pane,
and then click the name of the inventory to which you want to add a host.

2. On the inventory detail window, click the HOSTS button. Then, click the + button, which
displays the tooltip "Create a new host."

3. In the HOST NAME field, enter the host name or IP address for the host which automation
tools use to manage that host.

4. You may define values for Ansible inventory variables that only apply to this host in the
VARIABLES box, in either YAML or JSON format. More detail on variables and their usage
will be covered later in this course. For Windows-based hosts, you may need to set variables
that control how Ansible Tower will connect to that host for management purposes. These
variables are discussed later in this section.

5. Click SAVE.

58 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

Figure 2.2: Managing hosts in Ansible inventories

Note
To set up a dynamic inventory instead, select the SOURCES button from the
inventory interface. Click the + button to add a source, and then give the source a
name, select the source type you are using, and fill in other necessary information
for that source type. More information is available in the documentation for
Ansible Tower at https://docs.ansible.com.

Organizing Hosts into Groups


Use groups to organize hosts for collective management. For example, you can create a
development group for development servers, and run an automation task on all hosts in that
group. You could also create production group for production servers.

Hosts can be placed in multiple groups simultaneously. For example, you could create a set of
groups for development, testing, and production systems. You could also create groups based
on the physical location or data center in which a host is located. You could set up groups based
on the purpose or application on those systems. Then, you could create a final set of groups
based on whether a system is running Windows Server 2016, Windows Server 2019, or Red Hat
Enterprise Linux 8. You can even nest groups, so an us group could have the us-west-1 and us-
east-1 groups as members. By using groups like this, you can more easily apply automation tasks
to many hosts of the same type without using complex conditional tests in the Ansible Playbooks.

To create a group and assign hosts to it:

1. In the Ansible Tower web-based user interface, click the Inventories in the navigation pane,
and then click the name of the inventory to which you want to add a group.

2. On the inventory's detail screen, click the GROUPS button. Then, click the + button, which
displays the tooltip "Create a new group.""

3. In the NAME field, enter the name to use for the group.

4. You may define values for Ansible inventory variables that apply to all members of this group
in the VARIABLES box, in either YAML or JSON format. If both a group variable and a
host variable set a value for the same variable name, the value of the host variable takes
precedence.

5. Click SAVE.

6. Nested groups are created, and hosts added to the group, in the same way as for top-level
inventory groups. In the detail screen for the group, click the GROUPS button to create a

DO417-RHAE2.8-en-1-20200106 59
Chapter 2 | Running Simple Automation Commands

nested group for this inventory, thereby adding the hosts included in each nested group to
the new group. Alternatively, click the HOSTS button to add hosts to the group.

You can define any variables in the VARIABLES field. Ansible Playbooks read these variables
and apply their value to the hosts in that group. This is useful if some values depend on the
environment, for example, a different path between a development environment and a production
environment.

The following screenshot shows how to use group variables to define the root directory of a web
server in a staging environment.

Figure 2.3: Managing group variables

Inventory Variables and Microsoft Windows Hosts


When managing Microsoft Windows hosts, a few inventory variables must be set for the Windows
hosts, so that Ansible Tower knows how to connect to them. There are four key settings:

Connection Variables for Microsoft Windows Systems

Variable Purpose

ansible_connection Protocol to use to connect to the


host

ansible_port Network port to use with that


protocol

ansible_winrm_transport The authentication method to use


with WinRM connections

ansible_winrm_server_cert_validation Whether to validate the TLS


certificate for WinRM connections

Although you can define these variables for each host, it is useful and more practical to define
them for the inventory, or for a group, especially if all the hosts in the inventory are hosts that
should have the same settings. If you have a mix of Windows hosts and other operating systems
and devices in the inventory, then you can create a group for the Windows hosts and apply the
settings to all hosts in that group.

These settings must be made in the appropriate Variables frame. The following example
demonstrates setting them for the entire inventory.

60 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

Figure 2.4: Managing connection variables in an inventory

1. Instructs Ansible Tower to utilize a different connection method for a Windows host, in this
case, WinRM. By default, Ansible uses the SSH protocol to connect to any host.

2. Instructs Ansible to use port 5986 for TLS-encrypted WinRM traffic.

3. Instructs Ansible to ignore the Certificate Authority (CA) signature on the WinRM certificate
presented by the server, and simply accept it. This setting is necessary if the WinRM
certificate is self-signed. Set the option to validate if you use WinRM certificates signed by
a valid CA.

Note
If your WinRM certificate is signed by a public CA, then it should validate. If you are
using a custom CA certificate to sign the WinRM certificate, then add the custom
CA certificate to your Ansible Tower installation. Details on how to configure this
certificate validation are beyond the scope of this course, but you can find more
information in the Ansible User Guide in the section "HTTPS Certificate Validation"
[https://docs.ansible.com/ansible/latest/user_guide/windows_winrm.html#https-
certificate-validation].

For more information on WinRM certificates, follow the How To: Configure WINRM
for HTTPS link listed in the references section.

4. Instructs Windows Ansible to use the CredSSP transport method, which is discussed in
Preparing Microsoft Windows Hosts for Automation. Windows has various authentication
methods that you can use to connect to your servers.

The following diagram shows how Ansible Tower uses credentials stored in its database to connect
to Windows hosts through the transport method that you define. It uses the connection to run
playbooks or ad hoc modules.

DO417-RHAE2.8-en-1-20200106 61
Chapter 2 | Running Simple Automation Commands

Figure 2.5: Connecting to Windows hosts

Authenticating Access to Managed Hosts


In order for Ansible Tower to access managed hosts in your inventory, it must provide
authentication credentials to those hosts. Ansible Tower credentials securely store sensitive data,
such as authentication credentials for managed hosts, sources of dynamic inventory information,
and Git repositories. These credentials are stored in encrypted format and can be set up so that
Ansible Tower users can use them but cannot view what they are.

There are many types of credentials supported by Ansible Tower. Use machine credentials to
authenticate to your inventory hosts. This credential type must contain credentials that your
connection method can use to authenticate. For example, it can contain a username and a
password for a user on your Windows systems that has administrator privileges, so that Ansible
Tower can manage components. After creating the credential, the password is encrypted so that
no one can read it, but Ansible Tower can decrypt and use it.

To create a machine credential:

1. In the Ansible Tower web-based user interface, click the Credentials in the navigation pane.

2. Create a new credential. On the CREDENTIALS window, click the + button, which displays
the tooltip "Create a new credential."

3. On the NEW CREDENTIAL window, enter a name for the credential. In the CREDENTIAL
TYPE field, click the magnifying glass icon and select the Machine credential type. It may be
on the second page of the search results. Click the SELECT button.
Alternatively, you can type the word Machine in the field.

4. For password-based authentication, add a user name and a password in the TYPE DETAILS
fields that display. If you leave the PASSWORD field blank, then you can also select the
Prompt on launch check box. If this check box is selected, then Ansible Tower prompts the
user to enter the password when running automation tasks that use this credential.

Figure 2.6: Creating machine credentials in Ansible Tower

62 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

5. Click SAVE.

The following screenshot shows how the password field is displayed after the machine credential is
created.

Figure 2.7: Viewing machine credentials in Ansible Tower

References
Window Support — Ansible Documentation
https://docs.ansible.com/ansible/2.3/intro_windows.html

Credential Types — Ansible Documentation


https://docs.ansible.com/ansible-tower/latest/html/userguide/
credentials.html#credential-types

How To: Configure WINRM for HTTPS


https://support.microsoft.com/en-ca/help/2019527/how-to-configure-winrm-for-
https

DO417-RHAE2.8-en-1-20200106 63
Chapter 2 | Running Simple Automation Commands

Guided Exercise

Preparing Red Hat Ansible Tower to


Manage Hosts
In this exercise, you will configure Red Hat Ansible Tower with an inventory of Windows hosts
to manage, and credentials needed to authenticate and connect to those hosts.

Outcomes
You should be able to:

• Manage inventories and inventory variables in Ansible Tower.

• Create groups and hosts in Ansible Tower.

• Authenticate against hosts using machine credentials.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. From workstation, click the Ansible Tower icon on your desktop to access Ansible Tower.
Log in to the web console as admin and RedHat123@! as the password.

2. Before you can interact with the hosts, you must create an inventory and define the
connection information. In the following steps, you create the group and add a host.

2.1. Navigate to Inventories to manage inventories. Click Create a new inventory, and
then select Inventory to create a new static inventory.

64 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

2.2. Create a new inventory using the following information:

Field Value

Name Dev

Description Development Environment

Organization Default

Leave all other fields with the default value.

2.3. Define some inventory variables so that all hosts in the inventory inherit the settings.
Enter the following variables in the Variables area and click SAVE to create the
inventory.

ansible_connection: winrm
ansible_port: 5986
ansible_winrm_server_cert_validation: ignore
ansible_winrm_transport: credssp

By default, Ansible uses the SSH protocol to connect to any host. Your Windows
servers are configured with a WinRM listener instead, so you must use this variable
to instruct Ansible to use the WinRM connection method.
This variable instructs Ansible to use the encrypted WinRM TLS port 5986.
This variable instructs Ansible to ignore the validation of the WinRM certificate, as
the environment uses self-signed certificates.
This variable instructs Ansible to authenticate using CredSSP for authentication.

Note
YAML uses three dashes (---) to separate directives in a YAML file. This also serves
to signal the start of a document if no directives are present. Removing or leaving
the dashes in this case does not make any difference.

2.4. Create a group for this development inventory by selecting GROUPS, and then
clicking the + button, which displays the tooltip Create a new group.

DO417-RHAE2.8-en-1-20200106 65
Chapter 2 | Running Simple Automation Commands

Name the group dev_servers, and then click SAVE to create the group.

2.5. Create a new host for the dev_servers group by selecting HOSTS. Click the +
button, which displays the tooltip Add a host, and then select New Host from the
menu displayed.

Use the HOST NAME field to name the new host win2.example.com. Because the
inventory defines the connection information, you do not need to specify it in the host
definition.
Click SAVE to create the host.

66 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

Note
The breadcrumb trail at the top of the page displays the inventory structure.

2.6. Review all hosts in the inventory from the page displayed when the new host is saved.
This page provides access to the following operations:

• Including or excluding hosts from jobs; this is indicated by the ON/OFF switch. All
hosts that are created are included by default.
• Editing hosts, including renaming them or deleting them.
• Executing commands by invoking ad hoc modules.
• Managing groups, including renaming them or deleting them.

3. Review the machine credentials that are provided in the environment.

3.1. To review the credentials that Ansible Tower uses to connect to your hosts, select
Credentials from the main menu.
Notice that the Windows domain controller has a devops user that belongs to the
Domain Admins group.
Click the Edit credential pencil icon for the DevOps credential to review its credential
information.

DO417-RHAE2.8-en-1-20200106 67
Chapter 2 | Running Simple Automation Commands

This credential uses a type of Machine, which is used for connecting directly to
servers. Notice the user name that matches the name of the user in Active Directory.
The password is encrypted and unreadable. Extra fields are available to configure
authentication, however, the connection method we are using for Windows systems in
these activities do not use them.
Click CANCEL to return to the CREDENTIALS page, and then log out.

This concludes the guided exercise.

68 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

Running Ad Hoc Commands

Objectives
After completing this section, you should be able to describe what an Ansible module is, and run a
single operation on managed hosts as an ad hoc command, using Red Hat Ansible Tower.

Running One-Off Automation Tasks


An ad hoc command is a way of quickly executing a single Ansible task that you do not need
to save to run again later. They are simple, online operations that you can run without writing a
playbook.

Ad hoc commands are useful for quick tests and changes. For example, you can use an ad hoc
command to make sure that a certain line exists in the %SystemRoot%\System32\drivers
\etc\hosts file on a group of servers. You could use another ad hoc command to efficiently
restart a service on many different machines, or to ensure that a particular software package is
up-to-date.

However, ad hoc commands cannot perform complex or repetitive tasks; use Ansible Playbooks to
realize the full power of Ansible for repeatable automation.

Note
Ad hoc commands interact with Ansible modules, which are small programs or
scripts that are executed on managed hosts to implement an automation task. Every
module has a particular use, such as creating a user, installing a package, executing a
PowerShell script, or creating a scheduled task.

Ansible ships with many modules for managing Windows environment. Chapter 3,
Implementing Ansible Playbooks, discusses modules in detail.

Running an Ad Hoc Command in Ansible Tower


To run an ad hoc command against a set of managed nodes:

1. Navigate to the Inventories view, and then select an inventory.

2. Select the check boxes next to the hosts on which you want to run the command.

3. Click RUN COMMANDS.

DO417-RHAE2.8-en-1-20200106 69
Chapter 2 | Running Simple Automation Commands

Figure 2.14: Using the Run Commands feature

4. In the EXECUTE COMMAND window, select a module from the MODULE list. In the
ARGUMENTS field, specify any arguments required by the selected module. Although not all
modules require additional arguments, many do.

In the MACHINE CREDENTIAL field, select the machine credential needed to authenticate
to the managed hosts on which you will run this ad hoc command. Use the magnifying glass
icon to see a list of available machine credentials.

The win_ping module in the following example needs no arguments, and checks to see if the
hosts it runs on can run Ansible automation.

Figure 2.15: Running commands against hosts

The question mark of the ARGUMENTS field is dynamic. After selecting a module, clicking
the icon shows some text that contains a link; that link points to the module documentation.
This is a useful feature for quickly determining the module capabilities and how to use it.

70 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

Figure 2.16: Accessing Modules Documentation

5. Click LAUNCH to run the ad hoc command.

Figure 2.17: Ansible Tower ad hoc commands result

6. Ansible Tower displays a new screen in your web browser for the job you just started. As the
job runs, the DETAILS pane continuously updates with information on the status of the job.
The pane on the right displays the name of the module running, and the output from the
Ansible ad hoc command. This output provides more information about job successes and
failures, warnings, and other useful details resulting from the Ansible command.

Performing Tasks with Ansible Modules


Modules are the tools that Ansible uses to perform tasks. Ansible provides hundreds of modules
that do different things. You can usually find a tested, special-purpose module which does what
you need as part of the standard installation.

DO417-RHAE2.8-en-1-20200106 71
Chapter 2 | Running Simple Automation Commands

Note
By default, a limited subset of modules can be used in ad hoc commands run
by Ansible Tower. However, any available module can be included in an Ansible
Playbook that is run by Ansible Tower.

An Ansible module is PowerShell (for modules which are used on Windows) or Python code that
performs a specific task, such as installing software or configuring a service. The core Ansible
product includes many modules, and the following table lists several of the Windows specific ones.

Selected Ansible Modules for Windows

Name Description

win_command Enables executing a command on managed nodes, as a specific user,


or with privilege escalation to an administrative account. Because of its
simplicity and flexibility, the module is not idempotent, so care should be
taken when using it.

win_shell Enables executing PowerShell scripts on managed nodes.

win_package Enables installation of Microsoft Software Installation (MSI) files or


executable software packages.

win_feature Manages system Roles or Features for Windows systems.

win_update Manages Windows updates.

win_reboot Handles reboots for Windows systems, for example, after win_update has
applied system updates.

win_partition Manages partitioning of disks.

win_format Ensures volumes are formatted.

win_hostname Controls the system machine name.

Important
For a complete list of available modules and documentation on how to use them,
see Windows Modules — Ansible Documentation [https://docs.ansible.com/ansible/
latest/modules/list_of_windows_modules.html].

Most modules require arguments to control their operation. A list of the arguments available
for a module is available in the module documentation. When you run a module in an ad hoc
command through Ansible Tower, specify any arguments in the ARGUMENTS field on the
EXECUTE COMMAND page. This field accepts arguments entered as a space separated list of
argument=value items.

For example, to start the spooler service on selected managed hosts with an ad hoc command,
select the win_service module and then put the text name=spooler state=started in the
ARGUMENTS field.

72 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

This instructs Ansible to manage the spooler service to ensure that it is running. This is
accomplished by the the usage of two arguments: name, and state.

Figure 2.18: Running ad hoc commands in Ansible

Most modules are idempotent, which means that you can run them safely multiple times, and if the
system is already in the correct state, they do nothing. For example, if you run the previous ad hoc
command again, it should report no change since the spooler service is already running. This is
shown as a change of the text color.

Figure 2.19: Rerunning ad hoc commands in Ansible

Managing Ansible Modules for Ad Hoc Commands


In Ansible Tower, you can manage the list of modules to use for ad hoc commands. The option is
available in Settings → Jobs. The ANSIBLE MODULES ALLOWED FOR AD HOC JOBS area
lists all the modules that you can use for ad hoc commands. From that list, you can add or remove

DO417-RHAE2.8-en-1-20200106 73
Chapter 2 | Running Simple Automation Commands

a module: to delete a module, click the delete icon next to the module name, and to add a module,
type its name and type ENTER. To delete a module, you can also click the field to bring a list that
shows all the active modules and select a module from that list.

The following screenshot shows how to add the win_scheduled_task module to the list.

Figure 2.20: Managing Ansible Modules for Ad Hoc Jobs

After adding it, the module is available for running ad hoc commands:

Figure 2.21: Listing Ansible Modules for Ad Hoc Jobs

Running Arbitrary Commands on Managed Hosts


The win_command module allows you to run arbitrary commands on managed hosts. The
command to run is passed to the module as an argument. For example, to run the hostname
command on the managed hosts as an ad hoc command, you would simply put hostname in the
ARGUMENTS box.

74 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

Figure 2.22: Retrieving host names with ad hoc commands

Note
If a module is missing from the list of modules that you can use for ad hoc
commands, navigate to Settings → Jobs and add the module to the MODULE
area.

The win_command module allows you to quickly execute remote commands on managed hosts.
These commands are not processed by the shell on the managed hosts. As such, they cannot
access environment variables or perform shell operations such as <, >, | and ;.

For situations where commands require shell processing, administrators can use the win_shell
module. Like the win_command module, you pass the commands to be executed as arguments to
the module in an ad hoc command. Ansible then executes the command remotely on the managed
hosts. Unlike the win_command module, the commands are processed through a shell (by default,
PowerShell) on the managed hosts. Therefore, environment variables are accessible and shell
operations are also available for use.

DO417-RHAE2.8-en-1-20200106 75
Chapter 2 | Running Simple Automation Commands

Important
In most circumstances, it is a recommended practice to avoid the win_command
and win_shell "run command" modules if you can use other modules to
accomplish the same thing.

Most other modules are idempotent and can perform change tracking automatically.
They can test the state of systems and do nothing if those systems are already in
the correct state. By contrast, it is much more complicated to use "run command"
modules in a way that is idempotent. Depending upon them makes it more difficult
to ensure that rerunning an ad hoc command or playbook will not cause an
unexpected failure.

When the win_shell or win_command module runs, it typically reports a CHANGED


status because these modules cannot detect whether the machine is already in
the correct state. An idempotent module can detect whether the machine is in the
correct state, do nothing, and report OK.

There are times when "run command" modules are valuable tools and a good
solution to a problem. If you do need to use them, it is best to try the win_command
module first, resorting to win_shell module only if you need its special features.

Comparing Ad Hoc Commands and Ansible Playbooks


Ad hoc commands are useful when you need to run a task only once, it is very simple, and you
never plan to run the task again. However, ad hoc commands have some disadvantages.

One limitation of ad hoc commands is that you can only use a single module as a single task. An
Ansible Playbook allows you to write more complex automation that executes a sequence of tasks.

Another limitation is that an ad hoc command is authored and executed as needed. That is, you
invent it "on the fly" and do not save the command after it runs. Version control systems normally
manage Ansible Playbooks so that you can easily reuse them.

Finally, Ansible Tower normally only provides a limited set of modules for use as ad hoc commands.
The Ansible Tower server administrator can change these settings in Settings → Jobs, but it is
still less flexible than simply writing and using a playbook.

The next chapter of this course teaches you how to write and use Ansible Playbooks.

References
Control with Ansible Tower, Part 2
https://www.ansible.com/blog/control-with-ansible-tower-part-2

Windows Modules — Ansible Documentation


https://docs.ansible.com/ansible/latest/modules/list_of_windows_modules.html

76 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

Guided Exercise

Running Ad Hoc Commands


In this exercise, you will you will run a single operation on a managed host as an ad hoc
command within Red Hat Ansible Tower.

Outcomes
You should be able to execute ad hoc commands on a managed host from within Ansible
Tower.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. From workstation, access the Ansible Tower instance available at http://


tower.example.com. Connect as the student user and RedHat123@! as the password.
Browse to the Default inventory page within the Inventories area of the Ansible
Tower control panel, and then open the ad hoc command execution screen for the
win1.example.com host.

1.1. From workstation, double-click the Ansible Tower shortcut icon on your Desktop
to access your Ansible Tower instance located at http://tower.example.com.

1.2. Log in to Ansible Tower using student as the user name and RedHat123@! as the
password.

DO417-RHAE2.8-en-1-20200106 77
Chapter 2 | Running Simple Automation Commands

1.3. From the main dashboard page, select Inventories from the sidebar and choose
Default inventory from the inventories listed.

1.4. From the Default inventory page, click HOSTS, and then select the
win1.example.com host entry.

1.5. After checking win1.example.com, click RUN COMMANDS to enter the ad hoc
command execution screen.

78 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

2. Using the win_ping module, verify that the win1.example.com server is running and
reachable by Ansible.

2.1. On the RUN COMMAND page, select the module win_ping from the MODULE list

2.2. Click the question mark icon of the ARGUMENTS field. This shows a windows that
contains a link that points to the win_ping documentation.

2.3. Click LAUNCH to run the ad hoc command.

2.4. Review the output to verify that the module ran successfully, confirming that Ansible
successfully communicated with the server.

3. Navigate back to the RUN COMMANDS page for the win1.example.com server.
Using the setup module, gather the Ansible facts for the win1.example.com server. You
will explore the usage of this output information, and use these facts available to Ansible, in
subsequent chapters and exercises.

DO417-RHAE2.8-en-1-20200106 79
Chapter 2 | Running Simple Automation Commands

3.1. Navigate back to the RUN COMMANDS page for the win1.example.com server.
On the RUN COMMAND page, select the setup module from the MODULE list, and
then click LAUNCH.

3.2. Review the output to verify that the module ran successfully, confirming that Ansible
contacted the system and profiled various aspects of the environment. Take note of
the various facts Ansible gathers, as you will use these in subsequent chapter exercises.

4. Using the win_reboot module, restart the win1.example.com server.

80 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

4.1. On the RUN COMMAND page, select the module win_reboot from the MODULE
list, and then click LAUNCH.

4.2. Review the output to verify that the module ran successfully and that Ansible restarted
the server.

5. Using the win_ping module, verify that the win1.example.com server is running and
reachable by Ansible.

5.1. On the RUN COMMAND page, select the module win_ping from the MODULE list,
and then click LAUNCH.

DO417-RHAE2.8-en-1-20200106 81
Chapter 2 | Running Simple Automation Commands

5.2. Review the output to verify that the module ran successfully, that the system is running
after the reboot, and that Ansible can successfully communicate with it.

This concludes the guided exercise.

82 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

Lab

Running Simple Automation Commands


Performance Checklist
In this lab, you will use Ansible Tower to run several ad hoc commands against a Windows
host in your inventory.

Outcomes
You should be able to:

• Access the Ansible Tower web console and inspect the default inventory.

• Select a host for the execution of ad hoc commands.

• Execute several ad hoc commands on the target host.

• Log into the target host to verify the success of ad hoc commands.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. From workstation, access your Ansible Tower instance available at http://


tower.example.com. Connect as the student user and RedHat123@! as the password.
Browse to the Default inventory window within the Inventories area of the Ansible
Tower control panel, and then open the ad hoc command execution screen for the
win1.example.com host.
2. Using the win_ping module, verify that the win1.example.com server is running and
reachable by Ansible.
3. Return to the EXECUTE COMMAND window for the win1.example.com server.
Using the setup module, gather the Ansible facts for the win1.example.com server. You
will explore the usage of this output information and utilize these facts available to Ansible in
subsequent chapters and exercises.
4. Return to the EXECUTE COMMAND window for the win1.example.com server.
Using the win_feature module, install the Web-Server feature on the
win1.example.com server.
5. Return to the EXECUTE COMMAND window for the win1.example.com server.
Using the win_service module, start the W3Svc web server service on the
win1.example.com server.

DO417-RHAE2.8-en-1-20200106 83
Chapter 2 | Running Simple Automation Commands

6. Log into the win1.example.com server to verify the installation of the web service, and
that it is currently running.
After verifying that Ansible successfully installed the web server feature and started the
service, disconnect from win1.example.com.
7. Use additional Ansible ad hoc commands to revert your the changes made to the
environment. Return to the EXECUTE COMMAND window for the win1.example.com
server.
Using the win_service module, stop the W3Svc web server on the win1.example.com
server.
8. Return to the EXECUTE COMMAND window for the win1.example.com server.
Using the win_feature module, uninstall the web server feature on the
win1.example.com server.
9. Using the win_reboot module, restart the win1.example.com server.
10. Using the win_ping module, verify that the win1.example.com server is running and
reachable by Ansible.

This concludes the lab.

84 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

Solution

Running Simple Automation Commands


Performance Checklist
In this lab, you will use Ansible Tower to run several ad hoc commands against a Windows
host in your inventory.

Outcomes
You should be able to:

• Access the Ansible Tower web console and inspect the default inventory.

• Select a host for the execution of ad hoc commands.

• Execute several ad hoc commands on the target host.

• Log into the target host to verify the success of ad hoc commands.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. From workstation, access your Ansible Tower instance available at http://


tower.example.com. Connect as the student user and RedHat123@! as the password.
Browse to the Default inventory window within the Inventories area of the Ansible
Tower control panel, and then open the ad hoc command execution screen for the
win1.example.com host.

1.1. From workstation, double-click the Ansible Tower shortcut icon on your Desktop
to access your Ansible Tower instance, located at http://tower.example.com.

1.2. Log in to Ansible Tower using student as the user name and RedHat123@! as the
password.

DO417-RHAE2.8-en-1-20200106 85
Chapter 2 | Running Simple Automation Commands

1.3. From the main dashboard window, select Inventories from the sidebar and choose
Default inventory from the inventories listed.

1.4. From the Default inventory window, select the HOSTS button and select the check
box next to the win1.example.com host entry.

86 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

1.5. After selecting win1.example.com, click RUN COMMANDS to enter the EXECUTE
COMMAND window for running ad hoc commands..

2. Using the win_ping module, verify that the win1.example.com server is running and
reachable by Ansible.

2.1. On the EXECUTE COMMAND window, select the module win_ping from the
MODULE list, and then click LAUNCH.

DO417-RHAE2.8-en-1-20200106 87
Chapter 2 | Running Simple Automation Commands

2.2. Review the output to verify that the module ran successfully, confirming that Ansible
could successfully communicate with the server.

3. Return to the EXECUTE COMMAND window for the win1.example.com server.


Using the setup module, gather the Ansible facts for the win1.example.com server. You
will explore the usage of this output information and utilize these facts available to Ansible in
subsequent chapters and exercises.

3.1. Return to the EXECUTE COMMAND window for the win1.example.com server.
On the EXECUTE COMMAND window, select the module setup from the MODULE
list, and then click LAUNCH.

88 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

3.2. Review the output to verify that the module ran successfully, and that Ansible contacted
the system and profiled various aspects of the environment. Take note of the various
facts Ansible gathers, as you will use these in subsequent chapter exercises.

4. Return to the EXECUTE COMMAND window for the win1.example.com server.

DO417-RHAE2.8-en-1-20200106 89
Chapter 2 | Running Simple Automation Commands

Using the win_feature module, install the Web-Server feature on the


win1.example.com server.

4.1. Return to the EXECUTE COMMAND window for the win1.example.com server.
On the EXECUTE COMMAND window, select the win_feature module from the
MODULE list. In the ARGUMENTS field, supply the arguments name=Web-Server
state=present, and then click LAUNCH.

4.2. Review the output to verify that the module ran successfully and that Ansible has added
the feature.

5. Return to the EXECUTE COMMAND window for the win1.example.com server.


Using the win_service module, start the W3Svc web server service on the
win1.example.com server.

5.1. Return to the EXECUTE COMMAND window for the win1.example.com server.

90 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

On the EXECUTE COMMAND window, select the win_service module from the
MODULE list. In the ARGUMENTS field, supply the arguments name=W3Svc
state=started, and then click LAUNCH.

5.2. Review the output to verify that the module ran successfully and that Ansible has started
the service.

6. Log into the win1.example.com server to verify the installation of the web service, and
that it is currently running.
After verifying that Ansible successfully installed the web server feature and started the
service, disconnect from win1.example.com.

6.1. Launch an RDP client on the workstation.example.com system to connect to


the win1.example.com server. Use the example domain, student username, and
RedHat123@! password.

DO417-RHAE2.8-en-1-20200106 91
Chapter 2 | Running Simple Automation Commands

Once you connect to the win1.example.com server, open the Server Manager by
selecting it from the Start Menu.

6.2. Select IIS from the menu to verify that the web service is installed and running.

7. Use additional Ansible ad hoc commands to revert your the changes made to the
environment. Return to the EXECUTE COMMAND window for the win1.example.com
server.
Using the win_service module, stop the W3Svc web server on the win1.example.com
server.

7.1. Return to the EXECUTE COMMANDS window for the win1.example.com server.
On the EXECUTE COMMAND window, select the win_service module from the
MODULE list. In the ARGUMENTS field, supply the arguments name=W3Svc
state=stopped, and then click LAUNCH.

92 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

7.2. Review the output to verify that the module ran successfully and that Ansible has
stopped the service.

8. Return to the EXECUTE COMMAND window for the win1.example.com server.

DO417-RHAE2.8-en-1-20200106 93
Chapter 2 | Running Simple Automation Commands

Using the win_feature module, uninstall the web server feature on the
win1.example.com server.

8.1. Return to the EXECUTE COMMAND window for the win1.example.com server.
On the EXECUTE COMMAND window, select the win_feature module from the
MODULE list. In the ARGUMENTS field, supply the arguments name=Web-Server
state=absent, and then click LAUNCH.

8.2. Review the output to verify that the module ran successfully and that Ansible has
removed the feature.

94 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

9. Using the win_reboot module, restart the win1.example.com server.

9.1. On the EXECUTE COMMAND window, select the win_reboot module from the
MODULE list, and then click LAUNCH.

DO417-RHAE2.8-en-1-20200106 95
Chapter 2 | Running Simple Automation Commands

9.2. Review the output to verify that the module ran successfully and that Ansible restarted
the server.

10. Using the win_ping module, verify that the win1.example.com server is running and
reachable by Ansible.

10.1. On the EXECUTE COMMAND window, select the win_ping module from the
MODULE list, and then click LAUNCH.

10.2.Review the output to verify that the module ran successfully, that the system is running
after the reboot, and that Ansible can successfully communicate with it.

96 DO417-RHAE2.8-en-1-20200106
Chapter 2 | Running Simple Automation Commands

This concludes the lab.

DO417-RHAE2.8-en-1-20200106 97
Chapter 2 | Running Simple Automation Commands

Summary
In this chapter, you learned:

• Ansible communicates with Windows hosts using Windows Remote Management (WinRM),
which is enabled by default since Windows Server 2012.

• You can define connection settings for your Windows-based hosts in inventory variables at the
inventory level, for specific groups, or on a host-by-host basis.

• Ansible Tower credentials allow you to store sensitive authentication data such as passwords or
authentication information used to access source code repositories.

• Ad hoc commands allow you to execute an Ansible module as a one-time task on a managed
host, or on a selection of hosts in an inventory.

98 DO417-RHAE2.8-en-1-20200106
Chapter 3

Implementing Ansible
Playbooks
Goal Write a simple playbook to automate tasks on
multiple Microsoft Windows-based hosts, and then
use Red Hat Ansible Tower to run it.

Objectives • Write a basic playbook and store it in a Git


repository.
• Configure a job template for a playbook in
Red Hat Ansible Tower, and then use it to run
the playbook on managed hosts.
• Write a playbook that includes multiple plays,
and then use per-play privilege escalation to
perform tasks as particular users.

Sections • Writing Playbooks (and Guided Exercise)


• Running Playbooks in Red Hat Ansible Tower
(and Guided Exercise)
• Implementing Multiple Plays (and Guided
Exercise)

Lab Implementing Ansible Playbooks

DO417-RHAE2.8-en-1-20200106 99
Chapter 3 | Implementing Ansible Playbooks

Writing Playbooks

Objectives
After completing this section, you should be able to write a basic Ansible Playbook and store it in a
Git repository.

Ansible Playbooks and Ad Hoc Commands


Ad hoc commands can run a single, simple task against a set of targeted hosts as a one-time
command. The real power of Ansible, however, is in learning to use playbooks to run multiple,
complex tasks against a set of targeted hosts in an easily repeatable manner.

A play is an ordered set of tasks run against hosts selected from your inventory. A playbook is a
text file containing a list of one or more plays to run in a specific order.

Plays allow you to change a lengthy, complex set of manual administrative tasks into an easily
repeatable routine with predictable and successful outcomes. In a playbook, you can save the
sequence of tasks in a play in a human-readable and immediately runnable form. Playbooks may
be authored in either YAML or JSON formats. Because of the way in which they are written, the
tasks themselves document the steps needed to deploy your application or infrastructure.

Formatting an Ansible Playbook


To better understand how to write a simple Ansible Playbook, consider how you run ad hoc
commands in Red Hat Ansible Tower. Figure 3.1 illustrates a user of Ansible Tower launching an
ad hoc command, which runs the win_service module with the arguments name=spooler
state=started on the host win1.example.com.

Figure 3.1: Example ad hoc command run in Ansible Tower

Any ad hoc command can be rewritten as a single task play, and then saved in a playbook for use
and later reuse.

100 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

A playbook is a text file written in YAML format, and normally is saved using the standard file
extension .yml. The playbook uses indentation with space characters to indicate the structure
of its data. YAML does not place strict requirements on how many spaces are used for the
indentation, but there are two basic rules:

• Data elements at the same level in the hierarchy (such as items in the same list) must have the
same indentation.

• Items that are children of another item must be indented more than their parents.

The ad hoc command from Figure 3.1 could be converted into the Ansible Playbook as illustrated:

---
- name: Converted ad hoc command example
hosts: win1.example.com
tasks:
- name: Make sure the spooler service is started
win_service:
name: spooler
state: started

A name for the play to help document its intended purpose.


Hosts from the inventory on which the tasks will run.
The beginning of a list of the tasks in the play. There is one task in this play.
Clear descriptive names for each task that help document what this task does. As reflected in
the name, this task ensures that the spooler service is configured correctly on each host.
Each task utilizes one Ansible Module to perform the work, in this case win_service.
This line is an argument for the win_service module.
This line is indented the same amount as the previous line, so it is also an argument for the
module.

You can also add blank lines for readability.

Important
Only the space character can be used for indentation; tab characters are not
allowed. Specifically, a two space indentation is standard in YAML files written for
Ansible.

In this course, you use Visual Studio Code as your text editor. However, there are
many other options to consider when you are working with Ansible in a production
environment. Visual Studio Code has extensions that allow customizations for
various languages and preferences, including syntax assistance for YAML. Each
editor has settings that you can adjust to make it easier to edit your YAML
playbooks.

A playbook begins with a line consisting of three dashes (---) as the start of a document marker.
It may end with three dots (...) as the end of a document marker, although in practice these are
often omitted.

In between those markers, the playbook is defined as a list of plays. An item in a YAML list starts
with a single dash followed by a space. For example, a YAML list might appear as follows:

DO417-RHAE2.8-en-1-20200106 101
Chapter 3 | Implementing Ansible Playbooks

- apple
- orange
- grape

In the example playbook, the line after --- begins with a dash, and starts the first (and only) play
in the list of plays.

The play itself is a collection of key-value pairs. Keys in the same play should have the same
indentation. The following example shows a YAML snippet with three keys. The first two keys have
simple values. The third key has a list of three items as a value.

- name: just an example


hosts: webservers
tasks:
- first
- second
- third

The original example play has three keys, name, hosts, and tasks; these keys all have the same
indentation.

The first line of the example play starts with a dash and space, indicating that the play is the first
item in a list, followed by the first key, which is the name attribute. The name key associates an
arbitrary string with the play as a label. This label identifies the purpose of the play. The name key
is optional, but is recommended because it helps to document your playbook. This is especially
useful when a playbook contains multiple plays.

- name: Converted ad hoc command example

The second key in the play is a hosts attribute, which specifies the hosts against which tasks in
the play are run. Like the argument for the ansible command, the hosts attribute takes a host
pattern as a value, such as the names of managed hosts or of groups in the inventory.

hosts: win1.example.com

Finally, the last key in the play is the tasks attribute, whose value specifies a list of tasks to run
for this play. This example has a single task that runs the win_service module with specific
arguments, to ensure that the spooler service has been started.

tasks:
- name: Make sure the spooler service is started
win_service:
name: spooler
state: started

The tasks attribute is the part of the play that actually lists, in order, the tasks to be run on the
managed hosts. Each task in the list is itself a collection of key-value pairs.

In the preceding example, the only task in the play has two keys:

• name is an optional label that documents the purpose of the task. It is a good idea to name
all your tasks to document the purpose of each step of the automation process. This label is

102 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

intended to be human readable, and is shown in the output during the play execution, as Ansible
performs each task.

• win_service is the module to run for this task. Arguments are passed as a collection of key-
value pairs, which are children of the module (name and state).

The following is another example of a tasks attribute with multiple tasks, using the
win_service module to ensure that several network services are configured to start at boot: the
win_regedit module to delete a registry key, and the win_region module to set the region
format to United States English:

tasks:
- name: Ensure that WinRM is started when the system has settled
win_service:
name: WinRM
start_mode: delayed

- name: Registry path MyClassroom and its entries are absent


win_regedit:
path: HKCU:\Software\MyClassroom
state: absent
delete_key: yes

- name: Region format is set to English (United States)


win_region:
format: en-US

Important
The order in which the plays and tasks are listed in a playbook is important, because
Ansible runs them in the same order.

The playbooks you have seen so far are basic examples; more sophisticated examples of plays
and tasks are presented later in this course. Information on the various modules provided
with Ansible is available on the web at https://docs.ansible.com/ansible/latest/modules/
modules_by_category.html, but a number of frequently useful modules will be introduced in
upcoming sections.

References
Intro to Playbooks — Ansible Documentation
https://docs.ansible.com/ansible/latest/user_guide/playbooks_intro.html

Working With Playbooks — Ansible Documentation


https://docs.ansible.com/ansible/latest/user_guide/playbooks.html

Module Index — Ansible Documentation


https://docs.ansible.com/ansible/latest/modules/modules_by_category.html

DO417-RHAE2.8-en-1-20200106 103
Chapter 3 | Implementing Ansible Playbooks

Guided Exercise

Writing Playbooks
In this exercise, you will write a basic Ansible Playbook and store it in a remote Git repository.

Outcomes
You should be able to use Visual Studio Code to write a simple Ansible Playbook and store it
in a Git repository.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. Launch Visual Studio Code and install the Red Hat YAML extension.

1.1. Double-click Visual Studio Code on the desktop.

1.2. Change to the Extensions view, and search the extensions marketplace for yaml.

1.3. Select the YAML extension at the top of the list and click Install.

2. Clone the playbooks repository to your workstation instance.

2.1. Click View → Command Palette or type Ctrl+Shift+P to open the command
palette.
Type clone, and then select Git: Clone to clone a repository.

2.2. Use a repository URL of https://gitlab.example.com/student/


playbooks.git. When prompted, select the Documents folder in the home

104 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

directory of the training user as the repository location, and then click Select
Repository Location. This clones the remote repository into the playbooks folder.

2.3. From the dialog that appears after cloning select Open to view the files.

3. Click the icon next to PLAYBOOKS to create a new file, and then name that file install-
iis.yml.

4. In the new file, begin your playbook with three dashes.

---

5. Add the name of the playbook, and the hosts to be targeted by its execution.

---
- name: Install the IIS web service
hosts: win1.example.com

6. Begin the tasks section with a two space indentation.

---
- name: Install the IIS web service
hosts: win1.example.com

tasks:

DO417-RHAE2.8-en-1-20200106 105
Chapter 3 | Implementing Ansible Playbooks

7. Add a task to install the Web-Server feature on the target server. Use the win_feature
Ansible module to accomplish this installation.

---
- name: Install the IIS web service
hosts: win1.example.com

tasks:

- name: IIS service installed


win_feature:
name: Web-Server
state: present

8. Add a task to start the W3Svc service on the target server. Use the win_service Ansible
module to accomplish this management task.

---
- name: Install the IIS web service
hosts: win1.example.com

tasks:

- name: IIS service installed


win_feature:
name: Web-Server
state: present

- name: IIS service started


win_service:
name: W3Svc
state: started

9. Add a final task to place a simple index.html file on the target server that contains
the phrase, "Hello World!" Use the win_copy Ansible module to accomplish this content
addition.

---
- name: Install the IIS web service
hosts: win1.example.com

tasks:

- name: IIS service installed


win_feature:
name: Web-Server
state: present

- name: IIS service started


win_service:
name: W3Svc
state: started

106 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

- name: Website index.html created


win_copy:
content: "Hello World!"
dest: C:\Inetpub\wwwroot\index.html

Note
The completed file is available in the write.sol file in the solutions directory.

10. Click Save. Note the status icons at the bottom. An asterisk appears next to Master,
indicating that changes have been made.

11. Gp to the Source Control view, and then click + for the install-iis.yml file to stage
the changes.

12. Enter a commit message that describes the work you have done, and then press
Ctrl+Enter to commit the changes.

13. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to push
your local changes to the remote repository, and retrieve any new changes from the
repository.
Click Yes or Ask Me Later when prompted.

This concludes the guided exercise.

DO417-RHAE2.8-en-1-20200106 107
Chapter 3 | Implementing Ansible Playbooks

Running Playbooks in Red Hat Ansible


Tower

Objectives
After completing this section, you should be able to configure a job template for a playbook in
Red Hat Ansible Tower, and use it to run the playbook on managed hosts.

Preparing Ansible Tower and Running Playbooks


Red Hat Ansible Tower provides an easy way to manage and run your Ansible Playbooks from
a central web interface. As an administrator of the Ansible Tower server, or as an Ansible Tower
user set up with appropriate permissions (called roles), you can run playbooks, see the results of
previous runs, and automatically update a playbook from your version control system.

Before you can run a playbook in Ansible Tower, you must first set up a job template specifying
where Ansible Tower can find the playbook, the inventory and credentials to use, and any special
settings controlling how you want the playbook to run. Creating a job template requires that you
perform the following steps, which will be covered in more detail later in this section:

• Create an SCM credential that Ansible Tower can use to authenticate to your version control
system.

• Create a project that specifies the location of the playbook repository in your version control
system, the credential to access the version control system, and how to update the copy of the
repository used by Ansible Tower.

• Create a job template that specifies how you want the playbook to run, and that the playbook
can be reused in the same way again and again.

Generally, you only perform these steps once. Then, you "launch" the job template to run your
playbook, and the results are reported in the Ansible Tower interface. Each run of the playbook is
recorded as a job.

The remainder of this section will review these steps in detail, and discuss how to review the output
of your playbook run.

Note
Some of the instructions mention the role (permissions) a user needs to perform
specific steps. The admin user has all permissions and can perform all steps. Other
users created by the admin may have fewer permissions.

Most Ansible Tower installations have a single organization configured to organize


users, inventories, playbooks, and so on. Ansible Tower installations can have more
than one organization defined. However, even if you have only one configured
organization, you may need to specify it in the user interface during setup.

Creating an SCM Credential


In a previous section of this course, you learned how to use machine credentials, which store
the authentication information that playbooks use to connect to managed hosts and perform

108 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

authentication tasks on them. Source Control Credentials, also called SCM Credentials, store
authentication information that Ansible Tower uses to access project materials stored in a version
control system like Git. SCM Credentials store the user name and the password or private key (and
private key passphrase, if any) required to authenticate access to the source control repository.

This is an outline of the procedure used create an SCM credential, so that Ansible Tower can
retrieve playbooks, roles, or other materials from a Git repository.

1. Log in as a user with the appropriate role assignment:

a. If creating a private SCM Credential, then there are no specific role requirements.

b. If creating an SCM Credential belonging to an organization, then log in as a user with the
Admin role for that organization.

2. Click Credentials to enter the credentials management interface.

In the CREDENTIAL pane, click + to create a new credential.

3. In the CREATE CREDENTIAL pane, enter the required information for the new credential.

a. Enter a unique name for the Credential.

If creating an organization credential, click the magnifying glass next to the


ORGANIZATION field, and select the organization. Skip this step if you are creating a
private credential.

b. In the CREDENTIAL TYPE list, select Source Control.

4. After selecting the Source Control credential type, the appropriate fields display in the
TYPE DETAILS section.

Enter authentication data in the respective fields. For example, you may need to specify a
user name. If a password is needed, you must enter that in the password field. If you are using
an SSH private key to authenticate, either copy and paste or drag and drop your private key
into the SCM PRIVATE KEY field. That key can be a passphrase encrypted SSH private
key, in which case you can provide the passphrase to Ansible Tower in the PRIVATE KEY
PASSPHRASE field.

DO417-RHAE2.8-en-1-20200106 109
Chapter 3 | Implementing Ansible Playbooks

Figure 3.5: Creating a new SCM credential in Ansible Tower

Creating a Project
In Ansible Tower, the project resource represents a repository that is available in a version control
system (also referred to by Ansible Tower as a source control management or SCM system), and
has at least one playbook and its associated resources, such as files and templates. In this course,
you are using Git to manage these files. The design of Ansible Tower assumes that most Ansible
projects are in a version control system, and it can automatically retrieve updated materials for a
project from several commonly used version control systems.

Ansible Tower supports the ability to download and automatically get updates of project materials
from SCMs using Git, Subversion, or Mercurial.

The following procedure shows how to create a project in Tower that connects to an existing Git
repository, which contains Ansible Playbooks.

1. Log in to the Ansible Tower web interface as a user that has the Admin role.

2. Select Projects to go to the list of projects. Click + to create the new project.

3. Enter a unique name for your project.

Optionally, enter a description for your project.

4. To assign the project to a specific organization, click the magnifying glass icon for the
ORGANIZATION field, and then select an organization.

5. From the SCM TYPE list, select the Git item to instruct Ansible Tower to retrieve a Git
repository.

6. Enter the location of the Git repository in the SCM URL field.

Optionally, in the SCM BRANCH/TAG/COMMIT field, specify the branch, tag or commit of
the repository from which to obtain the contents.

110 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

If the repository server requires authentication, select a new credential in the SCM
CREDENTIAL field.

7. Finally, configure how the project gets updates from the version control system (SCM).
Available settings are Clean, Delete on Update, and Update Revision on Launch.

Figure 3.6: Creating new projects in Ansible Tower

Clean
This SCM update option removes local modifications to project materials on Ansible Tower
before getting the latest revision from the source control repository.

Delete on Update
This SCM option completely removes the local project repository on Ansible Tower before
retrieving the latest revision from the source control repository. For large repositories, this
operation takes longer than Clean.

Update on Launch
This SCM option automatically updates the project from the source control repository each
time you use the project to launch a job. Ansible Tower tracks this update as a separate job. If
this option is not selected, you must update the project manually.

If you do not want to use these automatic settings, then you can manually update a project to
the latest version in the source control repository. The following procedure outlines the steps for
manually updating a project from an SCM source.

1. Log in as a user that has the Update role for the project.

2. Click Projects to enter the project management interface.

3. A synchronize icon is visible under the ACTIONS column if the user has the Update role for a
given project. Click the icon to trigger an immediate update of a project.

DO417-RHAE2.8-en-1-20200106 111
Chapter 3 | Implementing Ansible Playbooks

Figure 3.7: Updating an SCM project

Creating a Job Template


A job template is used to run your playbook. It combines the project containing your playbook
with an inventory, the machine credentials for authenticating to the hosts in your inventory, and
parameters that control how your playbook runs.

Once you create a job template in Ansible Tower, you can reuse it to run the playbook
again, as often as needed. This allows you to rerun the playbook to correct any unexpected
misconfigurations or changes that have been made to your servers, or to prepare additional
servers that have been added to the inventory. Therefore, you normally set up the job template
only once, but you run it whenever you update your playbook, or periodically to ensure expected
host configuration. The Launch button, or icon, for a job template is used to run its playbook.

The following procedure details how to create a job template for running a playbook:

1. Log in to the Ansible Tower web interface as a user who has the Use role for an inventory, a
project, and a machine credential.

2. Click Templates to go to the template management interface.

Click +, and then select Job Template to create a new job template.

3. Enter a name for the job template, and then select Run as the job type.

4. Click the magnifying glass icon for the INVENTORY field, and then select the desired
inventory to specify the managed hosts against which the job will execute.

5. Click the magnifying glass icon for the PROJECT field, and then select the project containing
the playbook that the job will execute.

6. Specify the playbook that the job will execute by selecting a playbook from the PLAYBOOK
list. The list shows all the playbooks that exist in the project.

7. Specify the credential to use for authenticating against the managed hosts.

a. Click the magnifying glass icon for the CREDENTIAL field.

b. Select the credential that the job template uses.

8. Select a desired setting from the VERBOSITY list. This selection determines the level of
detail that is generated in the output of the job run.

112 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

Figure 3.8: Creating job templates in Ansible Tower

Note
For more information on the various fields, consult the Job Templates — Ansible
Documentation link provided in the references section.

Prompting for Job Parameters on Launch


Ansible Tower provides some flexibility by allowing certain parameters in job templates to prompt
for input at the time the job executes. This Prompt on launch option is available for a number of job
parameters.

The flexibility to change job parameters at the time the job executes encourages playbook reuse.
For example, rather than creating multiple job templates to run the same playbook on different
sets of managed hosts, create a single job template and select Prompt on launch for the
inventory field. When the job runs, you can specify the inventory for the play. Users can only select
Inventories on which they have the Use role.

DO417-RHAE2.8-en-1-20200106 113
Chapter 3 | Implementing Ansible Playbooks

Figure 3.9: A job template prompting for inventory when launching a job

Launching Jobs
Most of the time, you will already have your job template and all its components configured. All you
will usually do is to run your playbook by launching a job from an existing job template.

The following describes how to use an existing job template to run a playbook:

1. Log in as a user that has the Execute role for the job template.

2. Click Templates to access the list of templates.

3. Locate the job template to run from the list of templates, and then click the rocket icon
beneath the ACTIONS column to launch the job.

4. If you have enabled the Prompt on launch option for any of the fields, Tower prompts
you for input before executing the job. Enter the inputs for the parameter, and then click
LAUNCH to launch the job, as shown in Figure 3.10.

114 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

Figure 3.10: Launching a job

Evaluating Job Results


After running a job, Tower redirects you to the detail page for the job. You can also navigate to the
details page by selecting Jobs, and then selecting the job whose details you wish to view.

The job detail page is divided into two panes. The DETAILS pane displays details of the job
parameters, whereas the job output pane displays the output of the playbook run by the job.

Across the top of the job output pane is a summary detailing the number of plays and tasks that
were executed, the count of hosts that Tower used for executing the job, and also the time it took
for the job to execute. Additionally, you can use controls to maximize this pane to full-screen size,
or to download the output of the job execution.

Along the left side of the output section, you can use the + and - controls to expand or collapse
the output for each task in the playbook. Controls in the output section enable scrolling through
the output, as well as jumping to the beginning and end of the output, as shown in Figure 3.11.

DO417-RHAE2.8-en-1-20200106 115
Chapter 3 | Implementing Ansible Playbooks

Figure 3.11: Accessing job run results

To better understand how to interpret the output of the playbook run in the job record, consider
the following playbook:

---
- name: Converted ad hoc command example
hosts: win1.example.com
tasks:
- name: Make sure the spooler service is started
win_service:
name: spooler
state: started

A successful run of the playbook might result in the following job output:

PLAY [Converted ad hoc command example] ****************************************

TASK [Gathering Facts] *********************************************************


ok: [win1.example.com]

TASK [Make sure the spooler service is started] ********************************


changed: [win1.example.com]

PLAY RECAP *********************************************************************


win1.example.com : ok=2 changed=1 unreachable=0 failed=0
skipped=0 rescued=0 ignored=0

A line is printed that displays the name of the play, and the name of each task in the play. Note
that the "Gathering Facts" task is a special task that normally runs by default and uses the setup
module automatically to set some machine-specific variables at the start of a play. Facts and fact
gathering will be covered later in the course.

Each task lists all the hosts on which the task ran, as well as the outcome of the task:

• ok means the task did not make any changes to the host.

116 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

• changed means that the task made a change to the system, and now the system is OK.

• fatal means there was a fatal error of some sort when running this task on this host. Ansible
will normally stop trying to run the playbook on that host for this job. Additional information
about the fatal error is included in the output.

• skipping means the playbook task was skipped for this host, probably due to conditional
execution, which will be discussed later in this course.

At the end of the play is a play recap that has a line for each host in the play, and how many tasks
matched certain outcomes for that host. If a task reported changed, then it will be also counted as
ok in the play recap. Besides ok, changed, and skipped, there are a number of other outcomes
reported in the play recap:

• unreachable is counted if the host could not be contacted over the network, or there was
some fatal error.

• failed counts tasks that failed, stopping execution of the playbook for that host.

• rescued counts tasks that failed, but were recovered by block rescue handling, which is covered
later in this course.

• ignored counts tasks that failed, but for which playbook execution was allowed to continue on
failure. This must be configured by the author of the playbook.

For more information, see Job Details — Playbook Run [https://docs.ansible.com/ansible-tower/


latest/html/userguide/jobs.html#job-details-playbook-run] in the Ansible Tower User Guide.

In general, Ansible Playbooks are idempotent and it is safe to run a playbook multiple times. If the
targeted managed hosts are already in the correct state, then no changes should be made. For
example, assume that the playbook from the previous example is run again:

PLAY [Converted ad hoc command example] ****************************************

TASK [Gathering Facts] *********************************************************


ok: [win1.example.com]

TASK [Make sure the spooler service is started] ********************************


ok: [win1.example.com]

PLAY RECAP *********************************************************************


win1.example.com : ok=2 changed=0 unreachable=0 failed=0
skipped=0 rescued=0 ignored=0

This time, all tasks passed with status ok and no changes were reported.

DO417-RHAE2.8-en-1-20200106 117
Chapter 3 | Implementing Ansible Playbooks

References
Ansible Tower User Guide
http://docs.ansible.com/ansible-tower/latest/html/userguide/index.html

Credentials — Ansible Tower User Guide


https://docs.ansible.com/ansible-tower/latest/html/userguide/credentials.html

Projects — Ansible Tower User Guide


https://docs.ansible.com/ansible-tower/latest/html/userguide/projects.html

Job Templates — Ansible Tower User Guide


https://docs.ansible.com/ansible-tower/latest/html/userguide/job_templates.html

118 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

Guided Exercise

Running Playbooks in Red Hat Ansible


Tower
In this exercise, you will configure Red Hat Ansible Tower with a project and job template for
an existing playbook, and use the job template to run the playbook.

Outcomes
You should be able to create a project and a job template, and to launch a job from the
Ansible Tower web interface.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

Complete the section called "Guided Exercise: Writing Playbooks" presented earlier in this
chapter.

1. Click the Ansible Tower shortcut on your desktop, or navigate to https://


tower.example.com to open the Ansible Tower web interface. Log in using the admin
account and RedHat123@! as the password.

2. Create a new Source Control credential. The project that you create at a later step will use
this credential.

2.1. Click Credentials to manage credentials.

2.2. Click + to add a new credential.

2.3. In the next window, fill in the details as follows:

DO417-RHAE2.8-en-1-20200106 119
Chapter 3 | Implementing Ansible Playbooks

Field Value

NAME Run Practice Git

DESCRIPTION Student Git credential

ORGANIZATION Default

TYPE Source Control

USERNAME student

PASSWORD RedHat123@!

Leave the SCM PRIVATE KEY and PRIVATE KEY PASSPHRASE fields blank.

2.4. Click SAVE to create the credential.

3. Create a new project called Run Practice.

3.1. Click Projects.

3.2. Click + to add a new project.

3.3. In the next window, fill in the details as follows:

Field Value

NAME Run Practice

DESCRIPTION Single playbook practice project

ORGANIZATION Default

SCM TYPE Git

SCM URL https://gitlab.example.com/student/playbooks.git

SCM CREDENTIAL Run Practice Git

SCM UPDATE OPTIONS Select CLEAN and UPDATE REVISION ON


LAUNCH

120 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

3.4. Click SAVE to create the project. This automatically triggers the SCM update of the
project.
The CLEAN and UPDATE REVISION ON LAUNCH options ensure that the Ansible
Job refreshes the playbook from Git prior to running the job. Ansible Tower uses the
values provided in the SCM URL and SCM CREDENTIAL fields to retrieve a local
copy of the repository.

4. Observe the automatic SCM update of the Run Practice project.

4.1. Scroll down the page and wait for a few seconds. In the list of projects, there is a status
icon to the left of the project, Run Practice. This icon is white at the start, red with
an exclamation mark when it fails, and green when it succeeds.

4.2. Click the status icon to show the detailed status page for the SCM update job. As
you can see in the DETAILS window, the SCM update job runs like any other Ansible
Playbook.

4.3. Verify that the status of the job in the DETAILS section shows Successful.

5. Create a new job template called Install IIS.

5.1. Click Templates.

5.2. Click + to create a new job template.

5.3. Select Job Template from the list.

5.4. On the next window, fill in the details as follows:

Field Value

NAME Install IIS

DESCRIPTION Installs and starts IIS

JOB TYPE Run

INVENTORY Default Inventory

PROJECT Run Practice

DO417-RHAE2.8-en-1-20200106 121
Chapter 3 | Implementing Ansible Playbooks

Field Value

PLAYBOOK install-iis.yml

CREDENTIAL DevOps

Important
A solutions/install-iis.sol solution file is available in the playbooks git
repository.

5.5. Leave the other fields untouched and click SAVE to create the job template.

6. Launch a job using the Install IIS job template.

6.1. Click Templates.

6.2. On the same line as the job template Install IIS, click the rocket icon on the right
to launch the job. This redirects you to a detailed status page for the running job.

Figure 3.16: Launching a job

6.3. Observe the live output of the running job for a moment.

122 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

6.4. Verify that the status of the job in the DETAILS pane displays Successful.

6.5. Read the output log to ensure that all tasks completed successfully. The play recap
at the bottom of the log should indicate that three tasks resulted in changes to the
win1.example.com host.

SSH password:
PLAY [The IIS web service is started] ******************************************

TASK [Gathering Facts] *********************************************************


ok: [win1.example.com]

TASK [IIS is installed] ********************************************************


changed: [win1.example.com]

TASK [IIS service is started] **************************************************


changed: [win1.example.com]

TASK [Website index.html is created] *******************************************


changed: [win1.example.com]

PLAY RECAP *********************************************************************


win1.example.com : ok=4 changed=3 unreachable=0 failed=0
skipped=0 rescued=0 ignored=0

DO417-RHAE2.8-en-1-20200106 123
Chapter 3 | Implementing Ansible Playbooks

Note
If a playbook is improperly formatted, Ansible displays a status of FAILED and a red
exclamation mark. The error message in the log output can assist in debugging the
issue, and may point you directly to the problematic line.

You may also compare your playbook with the solution playbook solutions/
install-iis.sol in the playbooks git repository to complete this guided
exercise.

7. Confirm the IIS server is up and running on win1.example.com.

7.1. In Chrome, open a new tab and navigate to http://win1.example.com/. You


should see the following output:

Hello, World!

8. View previously executed jobs.

8.1. Return to the Tower interface, and click Jobs. You will see a list of jobs that have
already run.

8.2. Click the top job in the list. This is the job that you just executed.

This concludes the guided exercise.

124 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

Implementing Multiple Plays

Objectives
After completing this section, you should be able to write a playbook that uses multiple plays, and
per-play privilege escalation, to perform tasks as particular users.

Writing Multiple Plays


A playbook is a YAML file containing a list of one or more plays. Remember that a single play is an
ordered list of tasks to execute against hosts selected from the inventory. Therefore, if a playbook
contains multiple plays, each play may apply its tasks to a separate set of hosts.

This can be very useful when orchestrating a complex deployment, which may involve different
tasks on different hosts. You can write a playbook that runs one play against one set of hosts, and
when that finishes, runs another play against another set of hosts.

Writing a playbook that contains multiple plays is very straightforward. Each play in the playbook is
written as a top-level list item in the playbook, and each list item follows the same play syntax.

The following example shows a playbook with two plays. The first play runs against web hosts, and
the second play runs against app hosts.

---
# This is a playbook with two plays

- name: first play


hosts: web
tasks:
- name: Web server is installed
win_feature:
name: Web-Server
status: present

- name: second play


hosts: app
tasks:
- name: App server is installed
win_feature:
name: Application-Server
status: present

Begin each play with - name: and no indentation.


The second play is identical in structure to the first, and contains name, hosts, and tasks
parameters.

DO417-RHAE2.8-en-1-20200106 125
Chapter 3 | Implementing Ansible Playbooks

Remote Users and Privilege Escalation in Plays


Parameters set in the play can override the default Ansible user, specifying a custom user for
remote connection or task execution. These parameters must be placed at the same level as the
hosts and tasks keywords.

Privilege Escalation Attributes


Occasionally, you may want to run a play or specific tasks in the play as a different user than the
one you use to connect to your managed hosts. For example, you might want to run a command as
if you used a tool like runas to gain administrative privileges.

You can enable privilege escalation for an entire playbook by selecting the ENABLE PRIVILEGE
ESCALATION check box for your job template. The privilege escalation method to use, the
alternative user to run, and the password for that user, are usually provided as part of your machine
credential.

You can use special keywords in your playbook to specify privilege escalation settings for a play, or
specific tasks in the play, that are different from those specified in your machine credential. These
keywords override the ENABLE PRIVILEGE ESCALATION selection for that play or task.

Use the become keyword to enable or disable privilege escalation, regardless of how it is defined
in the Ansible configuration file. Use the values yes or true to enable privilege escalation, and no
or false to disable it.

become: true

If you enable privilege escalation, then you can use the become_method keyword to define the
privilege escalation method to use during a specific play. The example below illustrates that runas
be used for privilege escalation.

become_method: runas

Additionally, you can use the become_user keyword to define the user account to execute tasks
for a specific play.

become_user: privileged_user

The following example demonstrates the use of these keywords in a play:

- name: Escalate privilege


hosts: datacenter-west
become: yes
become_method: runas
become_user: System
tasks:
- name: Display information about the System user
win_whoami:

The next example demonstrates this playbook specifying that privilege escalation must be used
for one task, and the default settings used for another, with privilege escalation details defined by
the play:

126 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

- name: Selected privilege escalation example


hosts: datacenter-west
become_method: runas
become_user: System
tasks:
- name: Display information about the privilege escalation user
win_whoami:
become: yes

- name: Display user information (using current default "become" settings)


win_whoami:

Using Module Documentation to Find Modules


The large number of modules packaged with Ansible provides administrators with many tools
for common administrative tasks. Earlier in this course, we discussed the Ansible documentation
website at http://docs.ansible.com. The Module Index on the website is an easy way to browse the
list of modules shipped with Ansible. For example, modules for user and service management can
be found in Systems Modules, and modules for database administration can be found in Database
Modules.

For each module, the Ansible documentation website provides a summary of functions and
instructions, detailing how each specific function can be invoked with options to the module. The
documentation also provides useful examples that show you how to use each module, and how to
set their keywords in a task.

In subsequent sections, this course will introduce many modules specifically useful for
Microsoft Windows automation tasks.

Discussing Playbook Syntax Variations


The last part of this chapter investigates some variations of YAML or Ansible Playbook syntax that
you might encounter.

YAML Comments
Use comments to aid playbook readability. In YAML, everything to the right of the number or hash
symbol (#) is a comment. If there is content to the left of the comment, precede the number
symbol with a space.

# This is a YAML comment

some data # This is also a YAML comment

YAML Strings
Quotation marks around strings are not required, even if the string contains spaces. Optionally, you
can enclose strings in either double quotes or single quotes.

this is a string
'this is another string'
"this is yet another a string"

DO417-RHAE2.8-en-1-20200106 127
Chapter 3 | Implementing Ansible Playbooks

Double-quoted strings parse escape sequences identified by a prefixed backslash character. Use
escape sequences to insert special characters such as \t for tab or \b for backspace. If a string
contains a backslash character \ that is not used to start an escape sequence, enclose the string in
single quotes to prevent parsing. Variables embedded in strings that are enclosed in single quotes
will still work correctly.

There are two ways to write multiline strings. You can use the vertical bar (|) character to denote
that newline characters within the string are to be preserved.

include_newlines: |
Example Company
123 Main Street
Atlanta, GA 30303

You can also write multiline strings using the greater than (>) symbol to indicate that newline
characters should be converted to spaces, and that leading white spaces in the lines should be
removed. This method is often used to break long strings at space characters, so that they can
span multiple lines for better readability.

fold_newlines: >
This is an example
of a long string,
that will become
a single sentence once folded.

Strip the ending newline from the multiline string by appending the minus (-) symbol to the > or |
indicators.

no_newlines: >-
This example will
contain no newlines
at all.

YAML Dictionaries
You are familiar with collections of key-value pairs written as an indented block, as follows:

name: svcrole
svcservice: W3Svc
svcport: 80

You may be familiar with dictionaries written in a condensed format and enclosed in curly braces,
as follows:

{name: svcrole, svcservice: W3Svc, svcport: 80}

In most cases, you should avoid the condensed format because it is harder to read and identify
changes in diff tools.

128 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

YAML Lists
You are familiar with lists that are written with the normal single dash syntax:

hosts:
- servera
- serverb
- serverc

Lists also have a condensed format enclosed in square braces, as follows:

hosts: [servera, serverb, serverc]

As with dictionaries, avoid the condensed inline syntax for readability.

Obsolete key=value Playbook Shorthand


Some playbooks may use an older shorthand method to define tasks, which puts the key-value
pairs for the module on the same line as the module name. For example, you might see this syntax:

tasks:
- name: shorthand form
service: name=W3Svc enabled=true state=started

Write the same task as follows:

tasks:
- name: preferred expanded form
service:
name: W3Svc
enabled: true
state: started

Avoid the shorthand form, and use the expanded form with one key-value pair per line.

The expanded form has more lines, but it is easier to work with. The keywords for the task are
stacked vertically, and are easier to differentiate. Your eyes can run straight down the play, with
less shifting from left to right. Also, the expanded syntax is native YAML, whereas, the shorthand
form is not. Syntax highlighting tools in modern text editors work more effectively if you use the
expanded format, rather than the shorthand format.

DO417-RHAE2.8-en-1-20200106 129
Chapter 3 | Implementing Ansible Playbooks

References
Intro to Playbooks — Ansible Documentation
https://docs.ansible.com/ansible/latest/user_guide/playbooks_intro.html

Working With Playbooks — Ansible Documentation


https://docs.ansible.com/ansible/latest/user_guide/playbooks.html

YAML Syntax — Ansible Documentation


https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html

Using Ansible and Windows: YAML Style — Ansible Documentation


https://docs.ansible.com/ansible/latest/user_guide/windows_usage.html#yaml-
style

130 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

Guided Exercise

Implementing Multiple Plays


In this exercise, you will create a playbook containing multiple plays, and then use it to ensure
that managed hosts are properly configured.

Outcomes
You should be able to construct and execute a playbook to manage configuration, and
perform administration, on a managed host.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. Launch the Visual Studio Code editor and, if you have not already cloned the playbooks
repository, clone it to your workstation.

1.1. Click Search Windows, search for code, and then open Visual Studio Code.

1.2. Open the command palette by navigating to View → Command Palette or by


pressing Ctrl+Shift+P.
Type clone, and then select Git: Clone to clone a repository.

1.3. When prompted, provide a repository URL of https://gitlab.example.com/


student/playbooks.git, and select the Documents folder in the home directory
of the training user as the repository location. This clones the remote repository
into the playbooks folder on the workstation instance.

DO417-RHAE2.8-en-1-20200106 131
Chapter 3 | Implementing Ansible Playbooks

1.4. A prompt to open the project displays. Click Open.

2. Create a new playbook, name it multi.yml, and then add the lines needed to start the
first play. The play creates a Windows file share on win1.example.com.

2.1. Navigating to File → New File or press Ctrl+N to create a new file.

2.2. Add a line to the beginning of the file consisting of three dashes. This indicates the
start of the YAML document.

---

2.3. Add the following line to provide a name for the play that describes the desired state.

- name: Backup directory is shared on win1

2.4. Add the following line to specify that the play applies to the win1.example.com
managed host. Indent the line with two spaces (aligning with the name keyword above
it) to include it as part of the first play.

hosts: win1.example.com

2.5. Add the following line to define the beginning of the tasks list. Indent the line with
two spaces (aligning with the keywords above it) to include it as part of the first play.

tasks:

2.6. Save the file by navigating to File → Save or by pressing Ctrl+S. Name the playbook
multi.yml, and then save it in the playbooks repository that you created in the
Documents folder.

132 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

3. The first task in the play checks for the existence of a C:\shares\backup directory on
win1.example.com. If the directory does not exist, Ansible will create it.
Indent the first line of the task with four spaces. Under the tasks keyword in the first play,
add the following lines.

- name: Backup directory exists


win_file:
path: C:\shares\backup
state: directory

Provide a descriptive declarative name for the task.


The second line is indented an additional two spaces and calls the win_file module.
The win_file module is used to create and modify files and directories on Windows
hosts.
Indent two more spaces and provide the path of the required directory.
Directly under the path option, specify that a directory should exist at the provided
path using the state parameter.

4. Add a task in the play that uses the win_share module to ensure that the C:\shares
\backup directory is shared on the network. Add the following lines to the playbook,
beneath the preceding task. Be sure to indent the first line with four spaces so that both
tasks are aligned vertically.

- name: Share is present


win_share:
name: backup
description: Critical backup files
path: C:\shares\backup
full: devops
state: present

Provide a descriptive declarative name for the task.


Indent the second line an additional two spaces, and invoke the win_share module.
The remaining lines are indented two spaces further, and provide parameters to the
win_share module.
Ansible will ensure that a file share named backup exists on the managed host.
The path parameter specifies the directory to share.
The user devops will have full access.

5. Start a new play within the same playbook to configure the win2.example.com host to
copy a file to the win1.example.com share for backup.

5.1. Add the following line without indentation to create a second play.

- name: File is backed up from win2

5.2. Specify win2.example.com as the target host for the play. Use two spaces in front of
hosts, so that hosts aligns horizontally with name directly above it.

hosts: win2.example.com

5.3. Add the following line to define the beginning of the tasks list for the second play.

DO417-RHAE2.8-en-1-20200106 133
Chapter 3 | Implementing Ansible Playbooks

tasks:

6. Create a task that copies example content into a file on win2.example.com for backup.
Indent the first line of the task with four spaces. Under the tasks keyword in the second
play, add the following lines.

- name: Example file created for backup


win_copy:
content: Hello. This is an example.
dest: C:\Users\devops\Documents\logs.txt

Provide a descriptive declarative name for the task.


Use the win_copy module to copy or create files on Windows systems.
Set the contents of the file to a literal string, using the content parameter.
Specify the destination file path for the content using the dest parameter.

7. Add a final task to the playbook that copies the file to the win1 file share. Indent the task
declaration in line with the previous task.

- name: Logs copied to backup share


win_copy:
src: C:\Users\devops\Documents\logs.txt
dest: \\WIN1\backup\logs.txt
remote_src: yes

Provide a descriptive declarative name for the task.


Invoke the win_copy module used previously however in this instance copy the log
from a source file instead of literal content.
Specify the source file with the src parameter.
Specify the destination file with the dest parameter.
Set remote_src to yes so that Ansible locates the source file on the
win2.example.com managed host.

8. Verify that the final multi.yml playbook matches the following structured content.

---
- name: Backup directory is shared on win1
hosts: win1.example.com
tasks:
- name: Backup directory exists
win_file:
path: C:\shares\backup
state: directory
- name: Share is present
win_share:
name: backup
description: Critical backup files
path: C:\shares\backup
full: devops
state: present

134 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

- name: File is backed up from win2


hosts: win2.example.com
tasks:
- name: Example file created for backup
win_copy:
content: Hello. This is an example.
dest: C:\Users\devops\Documents\logs.txt
- name: Logs copied to backup share
win_copy:
src: C:\Users\devops\Documents\logs.txt
dest: \\WIN1\backup\logs.txt
remote_src: yes

9. Commit the changes to your local Git repository, and then push them to the remote
repository.

9.1. Click File → Save or press Ctrl+S to save the file.


9.2. Navigate to the Source Control pane, and then click + for the multi.yml file to
stage the changes.

9.3. Enter a brief commit message, and then press Ctrl+Enter to commit the changes.

9.4. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to
push your local changes to the remote repository, and retrieve any new changes from
the repository.

10. From workstation, access your Ansible Tower instance available at http://
tower.example.com. Connect as the student user and RedHat123@! as the password.

11. Add win2.example.com to the Default inventory.

11.1. Click Inventories in the navigation pane.

11.2. Click Default inventory from the INVENTORIES page.

11.3. Click the GROUPS tab then select the Windows group.

DO417-RHAE2.8-en-1-20200106 135
Chapter 3 | Implementing Ansible Playbooks

11.4. Click the HOSTS tab to access the list of hosts in the group.

11.5. Click + and select New host to add a new host to the group.

11.6. On the next screen, fill in the details as follows:

Field Value

HOST NAME win2.example.com

11.7. Click SAVE to add the new host.

11.8. Verify the presence of both win1.example.com and win2.example.com hosts.

12. In the navigation pane, click Projects. Click the refresh icon next to the project name to
ensure the playbooks repository project fetches the new file.

13. Create a new job template called Backup win2 Log.

13.1. Click Templates.

13.2. Click + to create a new job template, and then select Job Template.

13.3. Fill in the new job template form as follows:

Field Value

NAME Backup win2 Log

DESCRIPTION Copies log from win2 to win1 file share

JOB TYPE Run

INVENTORY Default Inventory

PROJECT playbooks repository

PLAYBOOK multi.yml

CREDENTIAL DevOps

136 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

13.4. Click SAVE to create the job template.

14. Click LAUNCH to launch the Backup win2 log job.

15. Observe the output and ensure that the STATUS of the job in the DETAILS pane displays
Successful. Read the output log to verify that both the Backup directory is
shared on win1 and the File is backed up from win2 plays executed.

16. Connect to the win1.example.com managed host to verify that the file has been copied
from win2.example.com.

16.1. Click Search Windows, search for remote, and then open Remote Desktop
Connection.

16.2. Enter win1.example.com for Computer and EXAMPLE\student for User Name
and RedHat123@! as the password.

16.3.Click Search Windows in the win1.example.com Remote Desktop Connection


window, search for C:\shares\backup\logs.txt, and then open the logs file in
Notepad.

DO417-RHAE2.8-en-1-20200106 137
Chapter 3 | Implementing Ansible Playbooks

This concludes the guided exercise.

138 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

Lab

Implementing Ansible Playbooks


Performance Checklist
In this lab, you will write and run a playbook to ensure that your managed hosts are properly
configured.

Outcomes
You should be able to:

• Inspect Ansible Playbooks using Gitlab.

• Run multi-play playbooks using Ansible Tower.

• Update playbooks using Visual Studio Code.

• Add hosts to inventories.

• Access web pages to ensure that playbooks successfully run.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. In a previous activity, you installed and started the web server. Run the remove-iis.yml
playbook to remove the service and the web page. To run this playbook, access Ansible Tower
from workstation, accessible at https://tower.lab.example.com, or by double-
clicking the Ansible Tower desktop icon.
Log in to Ansible Tower using admin as the user name and RedHat123@! as the password.
Update the Run playbooks project job template by selecting the remove-iis.yml
playbook.
Run the job template.
2. From workstation, access your GitLab instance at https://gitlab.example.com. You
can either use the desktop icon, or use Chrome to access the URL. Log in using student as
user name and RedHat123@! as the password. Make sure to select the LDAP authentication
method.
Access the playbooks repository and review the install-review.yml playbook. The
playbook installs the Web-Server service, starts the associated service, and create a custom
index.html file.
3. From workstation, access Visual Studio Code and clone the Git repository, accessible at
https://gitlab.example.com/student/playbooks.git, to C:\Users\student
\Documents\playbooks.

DO417-RHAE2.8-en-1-20200106 139
Chapter 3 | Implementing Ansible Playbooks

Add the playbooks folder to your workspace, and then make the following changes to the
install-review.yml playbook. Comments in the playbook indicate the changes to make.

• Give the first play (which reads - name: Install web service) a name of The IIS
web server is deployed and running.

• Rename the first task (which reads - name: Install service) to IIS service is
installed.

• Rename the second task (which reads - name: Start service) to IIS service is
running.

• Update the content of the index.html HTML file for the two tasks that target the two
different hosts by updating the content parameter. Give the modules a value of The
win1 web server has been provisioned by Ansible and The win2 web
server has been provisioned by Ansible.
4. Save your changes, commit the file using a message of Add better description to
playbook, and push your changes to the remote repository.
5. From Ansible Tower, update the Default inventory inventory by adding
win2.example.com as a host in the Windows group of that same inventory.
6. From Ansible Tower, update the Run playbooks project job template by instructing it to
use install-review.yml as the playbook.
Run the job template, and then review the job output; the output of the job indicates that
Ansible installs and configures the web server on the two hosts of the default inventory, and
then customizes the web page for each host.
7. From workstation open Chrome and access http://win1.example.com. Ensure that
the home page reads as follows:

The win1 web server has been provisioned by Ansible

From workstation open Chrome and access http://win2.example.com. Ensure that


the home page reads the following:

The win2 web server has been provisioned by Ansible

This concludes the lab.

140 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

Solution

Implementing Ansible Playbooks


Performance Checklist
In this lab, you will write and run a playbook to ensure that your managed hosts are properly
configured.

Outcomes
You should be able to:

• Inspect Ansible Playbooks using Gitlab.

• Run multi-play playbooks using Ansible Tower.

• Update playbooks using Visual Studio Code.

• Add hosts to inventories.

• Access web pages to ensure that playbooks successfully run.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. In a previous activity, you installed and started the web server. Run the remove-iis.yml
playbook to remove the service and the web page. To run this playbook, access Ansible Tower
from workstation, accessible at https://tower.lab.example.com, or by double-
clicking the Ansible Tower desktop icon.
Log in to Ansible Tower using admin as the user name and RedHat123@! as the password.
Update the Run playbooks project job template by selecting the remove-iis.yml
playbook.
Run the job template.

1.1. From workstation double-click the Ansible Tower desktop icon to open the web
console.
Log in to Ansible Tower using admin as the user name and RedHat123@! as the
password.

1.2. Access the Run playbooks project job template, accessible from the Templates
link. Click the job template to edit it.

1.3. Select the remove-iis.yml in the PLAYBOOKS field, and then click SAVE to save
your changes.

DO417-RHAE2.8-en-1-20200106 141
Chapter 3 | Implementing Ansible Playbooks

1.4. To run the job template, click either the rocket icon or the LAUNCH button that is
available after saving your changes.

1.5. The output indicates that Ansible removes the index.html file, stops the web server
service, and removes the IIS service (Web-Server) from win1.example.com.

2. From workstation, access your GitLab instance at https://gitlab.example.com. You


can either use the desktop icon, or use Chrome to access the URL. Log in using student as
user name and RedHat123@! as the password. Make sure to select the LDAP authentication
method.
Access the playbooks repository and review the install-review.yml playbook. The
playbook installs the Web-Server service, starts the associated service, and create a custom
index.html file.

2.1. Double-click the GitLab desktop icon, and then log in to GitLab using student as the
user name and RedHat123@! as the password.
Review the install-review.yml playbook in the playbooks repository. To do so
navigate to Projects → Your projects and select student / playbooks. Click

142 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

install-review.yml to display the playbook. The comments in the playbooks


indicate the changes that you will make in a later step.

3. From workstation, access Visual Studio Code and clone the Git repository, accessible at
https://gitlab.example.com/student/playbooks.git, to C:\Users\student
\Documents\playbooks.
Add the playbooks folder to your workspace, and then make the following changes to the
install-review.yml playbook. Comments in the playbook indicate the changes to make.

• Give the first play (which reads - name: Install web service) a name of The IIS
web server is deployed and running.

• Rename the first task (which reads - name: Install service) to IIS service is
installed.

• Rename the second task (which reads - name: Start service) to IIS service is
running.

• Update the content of the index.html HTML file for the two tasks that target the two
different hosts by updating the content parameter. Give the modules a value of The
win1 web server has been provisioned by Ansible and The win2 web
server has been provisioned by Ansible.

3.1. From workstation, access Visual Studio Code by double-clicking the Desktop
shortcut.

3.2. Clone the playbooks repository by opening the command palette. To do so, navigate
to View → Command Palette or press Ctrl+Shift+P.
Type clone, and then select Git: Clone to clone a repository.

3.3. Use a repository URL of https://gitlab.example.com/student/


playbooks.git. When prompted, select the Documents folder in the home directory
of the training user as the repository location, and then Select Repository
Location. This clones the remote repository in to the playbooks folder.

DO417-RHAE2.8-en-1-20200106 143
Chapter 3 | Implementing Ansible Playbooks

Optionally, select Open from the window that displays after cloning to open the folder.

3.4. To add the playbooks folder to your workspace, navigate to File → Open Folder.
From the Windows Explorer, navigate to Local Disk (C:) → Users → student →
playbooks, and then click Select Folder.

3.5. Open the install-review.yml playbook in the architecture project. Make the
following changes:

• Give the first play a name of The IIS web server is deployed and running.

---
# Update the name of the play
- name: The IIS web server is deployed and running
hosts: all
...output omitted...

• Rename the first task to IIS service is installed.

...output omitted...
# Change the name of this task
- name: IIS service is installed
win_feature:
name: Web-Server
state: present
...output omitted...

• Rename the second task to IIS service is started.

...output omitted...
# Change the name of this task
- name: IIS service is started
win_service:
name: W3Svc
state: started
...output omitted...

• Update the content of the index.html HTML file for the two tasks that target the
two different hosts by updating the content parameter. Give the modules a value of
The win1 web server has been provisioned by Ansible and The win2
web server has been provisioned by Ansible

...output omitted...
- name: The default web page is created on win1
hosts: win1.example.com
tasks:
# Change the content of the file
- name: Index file is created
win_copy:
content: "The win1 web server has been provisioned by Ansible"
dest: C:\Inetpub\wwwroot\index.html

144 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

- name: The default web page is created on win2


hosts: win2.example.com
tasks:
# Change the content of the file
- name: Index file is created
win_copy:
content: "The win2 web server has been provisioned by Ansible"
dest: C:\Inetpub\wwwroot\index.html

After these changes are complete, the file should look like the following. The output
intentionally omits the comments.

---
- name: Web server is installed and running
hosts: all
tasks:
- name: IIS service is installed
win_feature:
name: Web-Server
state: present

- name: IIS service is started


win_service:
name: W3Svc
state: started

- name: Default web page is created on win1


hosts: win1.example.com
tasks:
- name: Index file is created
win_copy:
content: "The win1 web server has been provisioned by Ansible"
dest: C:\Inetpub\wwwroot\index.html

- name: Default web page is created on win2


hosts: win2.example.com
tasks:
- name: Index file is created
win_copy:
content: "The win2 web server has been provisioned by Ansible"
dest: C:\Inetpub\wwwroot\index.html

Note
The completed solution file is available at solutions/install-review.sol of
the playbooks project.

4. Save your changes, commit the file using a message of Add better description to
playbook, and push your changes to the remote repository.

4.1. Save your changes.

4.2. From the Visual Studio Code side bar, select Source Control to access the list of
changes.

DO417-RHAE2.8-en-1-20200106 145
Chapter 3 | Implementing Ansible Playbooks

4.3. Hover over install-review.yml to access the available options for this file. Click
Stage Changes to add your changes to the index.

4.4. In the Message text file, enter a message of Add better description to the
install playbook.

4.5. Click Commit to commit the changes to your local repository.

4.6. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to push
your local changes to the remote repository, and retrieve any new changes from the
repository.

146 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

5. From Ansible Tower, update the Default inventory inventory by adding


win2.example.com as a host in the Windows group of that same inventory.

5.1. From Ansible Tower, click Inventories in the navigation pane to access the Default
inventory inventory.
Click the Default inventory to edit it.

5.2. Click GROUPS to list all groups in the inventory.

5.3. Click the Windows inventory to access its content, and then select HOSTS to access
the hosts list.

5.4. Click the green plus sign, and then select Existing Host to add the previously created
win2.example.com host.

5.5. Select the win2.example.com check box and click SAVE.

6. From Ansible Tower, update the Run playbooks project job template by instructing it to
use install-review.yml as the playbook.
Run the job template, and then review the job output; the output of the job indicates that
Ansible installs and configures the web server on the two hosts of the default inventory, and
then customizes the web page for each host.

6.1. From Ansible Tower, click Templates in the navigation pane to access the Run
playbooks project job template.

6.2. Click the job template to edit it. Select install-review.yml for the PLAYBOOK
field, and then click SAVE to update the job template.

6.3. Click LAUNCH to run the job template.

6.4. This action redirects you to the job output. The output indicates that Ansible is able to
install and start the web server on win1 and win2, and create the custom index.html
HTML page on each server.

DO417-RHAE2.8-en-1-20200106 147
Chapter 3 | Implementing Ansible Playbooks

7. From workstation open Chrome and access http://win1.example.com. Ensure that


the home page reads as follows:

The win1 web server has been provisioned by Ansible

From workstation open Chrome and access http://win2.example.com. Ensure that


the home page reads the following:

The win2 web server has been provisioned by Ansible

7.1. To ensure that the web server is running and that the web page is available on the server,
open a new tab in Chrome and access http://win2.example.com.

7.2. The default web page should read as follows:

The win1 web server has been provisioned by Ansible

7.3. Open a new tab and access http://win2.example.com. The default web page
should read as follows:

The win2 web server has been provisioned by Ansible

This concludes the lab.

148 DO417-RHAE2.8-en-1-20200106
Chapter 3 | Implementing Ansible Playbooks

Summary
In this chapter, you learned:

• A play is an ordered set of tasks run against hosts selected from your inventory.

• A playbook is a text file that contains a list of one or more plays to run in a specific order.

• Multiple plays can be very useful when orchestrating a complex deployment, which may involve
different tasks on different hosts.

• In Red Hat Ansible Tower, a project represents a repository that is available in a version control
system, and which holds at least one playbook.

• In Red Hat Ansible Tower, a job template represents a saved command that can be repeatedly
used to run a playbook from a project with a particular inventory, credentials, and configuration
settings.

DO417-RHAE2.8-en-1-20200106 149
150 DO417-RHAE2.8-en-1-20200106
Chapter 4

Managing Variables and Facts


Goal Write playbooks that use variables to simplify
management of the playbook and facts to
reference information about managed hosts.

Objectives • Create and reference variables that affect


specific hosts or host groups, the play, or the
global environment, and describe how variable
precedence works.
• Encrypt sensitive variables using Ansible
Vault, and run playbooks that reference Vault-
encrypted variables.
• Reference data specific to particular managed
hosts using Ansible facts.

Sections • Managing Variables (and Guided Exercise)


• Managing Secrets (and Guided Exercise)
• Getting System Information with Facts (and
Guided Exercise)

Lab Managing Variables and Facts

DO417-RHAE2.8-en-1-20200106 151
Chapter 4 | Managing Variables and Facts

Managing Variables

Objectives
After completing this section, you should be able to define and reference variables that affect
specific hosts or host groups, the play, or the global environment, and describe how variable
precedence works.

Introduction to Ansible Variables


Ansible supports variables that you can use to store values that you can then reuse throughout
files in an Ansible project. This can simplify the creation and maintenance of a project and reduce
the number of errors.

Variables provide a convenient way to manage dynamic values for a given environment in your
Ansible project. Examples of values that variables might contain include:

• Users to create, modify, or delete.

• Software to install or uninstall.

• Services to stop, start, or restart.

• Files to create, modify, or remove.

• Archives to retrieve from the Internet, or extract.

Naming Variables
Variable names must start with a letter, and they can only contain letters, numbers, and
underscores.

The following table illustrates the difference between invalid and valid variable names.

Examples of Invalid and Valid Ansible Variable Names

Invalid variable names Valid variable names

web server web_server

web-server

remote.file remote_file

1st file file_1

1st_file file1

remoteserver$1 remote_server_1

remote_server1

152 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

Defining Variables
You can define variables in a variety of places in an Ansible project. However, this can be simplified
to three basic scope levels:

Variable Scope

Global scope
Variables set from the command line or Ansible configuration.

Play scope
Variables set in the play and related structures.

Host scope
Variables set on host groups and individual hosts by the inventory, fact gathering, or
registered tasks.

If you define the same variable name at more than one level, the level with the highest precedence
wins. A narrow scope takes precedence over a wider scope; variables that you define in an
inventory are overridden by variables that you define by the playbook, which are overridden by
variables defined on the command line.

A detailed discussion of variable precedence is available in the Ansible documentation, a link to


which is provided in the References at the end of this section.

Managing Variables in Playbooks


Variables play an important role in Ansible playbooks because they ease the management of
variable data.

Defining Variables in Plays


When writing playbooks, you can define your own variables and then invoke those values in a task.

You can define play variables in multiple ways. One common method is to place a variable in a
vars block at the beginning of a play:

- hosts: all
vars:
user_name: joe
user_state: present

It is also possible to define play variables in external files. In this case, instead of using a vars
block in a play in the play, you can use the vars_files directive, followed by a list of names for
external variable files relative to the location of the playbook:

- hosts: all
vars_files:
- vars/users.yml

You then define the playbook variables in YAML format in those external variable files:

user_name: joe
user_state: present

DO417-RHAE2.8-en-1-20200106 153
Chapter 4 | Managing Variables and Facts

Using Variables in Plays


After declaring variables, you can use the variables in tasks. You reference variables by placing
the variable name in double braces ({{ }}). Ansible substitutes the variable with its value when it
executes the task.

- name: Example play


hosts: all
vars:
user_name: joe

tasks:
# This line will read: Creates the user joe
- name: Creates the user {{ user_name }}
win_user:
# This line will create the user named Joe
name: "{{ user_name }}"

Important
When you use a variable as the first element to start a value, quotes are mandatory.
This prevents Ansible from interpreting the variable reference as starting a YAML
dictionary. The following message appears if quotes are missing:

win_service:
name: {{ service }}
^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:

with_items:
- {{ foo }}

Should be written as:

with_items:
- "{{ foo }}"

Describing Host Variables and Group Variables


Inventory variables that apply directly to hosts fall into two broad categories: host variables apply
to a specific host, and group variables apply to all hosts in a host group or in a group of host
groups. Host variables take precedence over group variables, but variables that you define in a
playbook take precedence over both.

Setting Host and Group Variables in the Inventory


One way to define host variables and group variables is to define them in the inventory. Hosts,
groups, and the inventory as a whole have a VARIABLES text box that you can use to define
variables.

154 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

Figure 4.1 illustrates setting the ansible_user variable to devops for the win1.example.com
inventory host:

Figure 4.1: Setting inventory variables in Ansible Tower

This approach has advantages and disadvantages. The advantage is that inventory variables
stored in Ansible Tower are consistent for all job templates that use that inventory. The
disadvantage is that you might find it easier to manage host-specific and group-specific variables
for a particular project by using playbook variable directories or by defining the variables in the
playbook. This section covers those approaches next.

Using Directories to Populate Host and Group Variables


Another approach for defining variables for hosts and host groups is to create two directories,
group_vars and host_vars, in the Ansible base directory. These directories contain files
defining group variables and host variables, respectively.

To define group variables for the servers group, you would create a YAML file named
group_vars/servers, and then the contents of that file would set variables to values using the
same syntax as in a playbook:

user_name: joe

Likewise, to define host variables for a particular host, create a file with a name matching the host
in the host_vars directory to contain the host variables.

The following examples illustrate this approach in more detail. Consider a scenario where there are
two data centers to manage and the data center hosts are defined in the inventory:

• The datacenter1 group consists of the demo1.example.com and demo2.example.com


hosts.

• The datacenter2 group consists of the demo3.example.com and demo4.example.com


hosts.

• The datacenters group consists of the datacenter1 and datacenter2 groups; all four
hosts which are members of those groups are members of the datacenters group.

With this inventory, you can configure host_vars and group_vars files to set variables for
different hosts or groups. You do not have to have a file for a host or a group if it would be empty.
If you wanted to make settings for each host or group individually, you might have a directory
structure like this for your project:

DO417-RHAE2.8-en-1-20200106 155
Chapter 4 | Managing Variables and Facts

project
├── group_vars
│ ├── all
│ ├── datacenters
│ ├── datacenters1
│ └── datacenters2
├── host_vars
│ ├── demo1.example.com
│ ├── demo2.example.com
│ ├── demo3.example.com
│ └── demo4.example.com
└── playbook.yml

Some things that you might do with this structure include:

Setting a value for all servers


If you need to define a general value for all servers in both data centers, set a group variable
for the datacenters host group in the group_vars/datacenters file:

time_server: 192.168.1.254

Alternatively, you could use the all host group to affect all hosts in the inventory.

Setting different values for each data center


If the value to define varies for each data center, set a group variable for each data center
host group. In group_vars/datacenter1:

time_server: 192.168.1.254

In group_vars/datacenter2:

time_server: 192.168.2.254

Setting different values for each host


If the value to be defined varies for each host in every data center, then define the variables
in separate host variable files. As an example, set a variable for demo1.example.com in the
host_vars/demo1.example.com file:

smtp_relay: 192.168.1.20

156 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

Note
The Ansible Tower documentation recommends defining inventory variables in the
inventory itself instead of using directories (at https://docs.ansible.com/ansible-
tower/latest/html/userguide/best_practices.html). No reason is specified.

The authors of this course believe that there are some disadvantages to that
approach. For example, there is no version control tracking changes to the inventory
fields for objects in Ansible Tower, and checking settings can involve a lot of clicking
through the user interface.

However, it is true that by setting the variable settings in the inventory itself, the
variables will be consistent between multiple projects that share the same inventory.

Overriding Variables from the Job Template


You can use playbook variables to override inventory variables. Job template variables override
all other variables. These are called extra variables. The values of extra variables override all other
settings for that variable.

In the following example, the variable prototype_server is being set to true as an extra
variable in a job template.

Figure 4.2: Setting extra variables in a job template

Extra variables can be useful when you need to override the defined value for a variable for a one-
off run of a playbook.

Using Arrays as Variables


Instead of assigning configuration data that relates to the same element (a list of services, a list
of users, and so on), to multiple variables, you can use arrays. One benefit of using arrays is that
Ansible can browse them.

Consider the following snippet:

DO417-RHAE2.8-en-1-20200106 157
Chapter 4 | Managing Variables and Facts

user1_first_name: Bob
user1_last_name: Jones
user1_full_name: Robert Richard Jones
user2_first_name: Anne
user2_last_name: Cook
user2_full_name: Anne Marie Cook

This could be rewritten as an array called users, where each user is an element in the array. Each
user is a hash, meaning that it contains a set of key-value pairs. This means that users is an array
of hashes.

users:
bjones:
first_name: Bob
last_name: Jones
full_name: Robert Richard Jones
acook:
first_name: Anne
last_name: Cook
full_name: Anne Marie Cook

You can then use the following variables to access user data:

# Returns 'Bob'
users.bjones.first_name

# Returns 'Anne Marie Cook'


users.acook.full_name

Because the variable is defined as a Python dictionary, an alternative syntax is available.

# Returns 'Bob'
users['bjones']['first_name']

# Returns 'Anne Marie Cook'


users['acook']['full_name']

Important
The dot notation can cause problems if the key names are the same as names of
Python methods or attributes, such as discard, copy, add, and so on. Using the
bracket notation can help avoid conflicts and errors.

Both syntaxes are valid, but to make troubleshooting easier, Red Hat recommends
that you use one syntax consistently in all files throughout any given Ansible project.

Capturing Task Results with Registered Variables


You can use the register statement to capture the results of a task. The output is saved into
a temporary variable that can be used later in the playbook for either debugging purposes or to
achieve something else, such as a particular configuration based on a task's results.

158 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

The following playbook demonstrates how to capture the results of a task for debugging purposes:

---
- name: Installs a package and prints the result
hosts: demo.example.com

tasks:
- name: Copy install package
win_copy:
src: files/7z1900-x64.exe
dest: C:\7z1900-x64.exe

- name: Install the package


win_package:
path: c:\7z1900-x64.exe
state: present
product_id: 7-Zip
arguments: /S
register: install_result

- debug:
var: install_result

When you run the playbook, Ansible uses the debug module to display the value of the
install_result registered variable.

PLAY [Installs a package and prints the result] ********************************

TASK [Gathering Facts] *********************************************************


ok: [demo.example.com]

TASK [Copy install package] ****************************************************


changed: [demo.example.com]

TASK [Install the package] *****************************************************


changed: [demo.example.com]

TASK [debug] *******************************************************************


ok: [demo.example.com] => {
"install_result": {
"changed": true,
"failed": false,
"rc": 0,
"reboot_required": false
}
}

PLAY RECAP *********************************************************************


demo.example.com: ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0
ignored=0

DO417-RHAE2.8-en-1-20200106 159
Chapter 4 | Managing Variables and Facts

References
Inventory — Ansible Documentation
https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html

Variables — Ansible Documentation


https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html

Variable Precedence: Where Should I Put A Variable?


https://docs.ansible.com/ansible/latest/user_guide/
playbooks_variables.html#variable-precedence-where-should-i-put-a-variable

YAML Syntax — Ansible Documentation


https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html

160 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

Guided Exercise

Managing Variables
In this exercise, you will define variables and use them in a playbook.

Outcomes
You should be able to:

• Define group variables in Ansible.

• Refactor an Ansible Playbook to use variables.

• Run Jobs in Ansible Tower.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

Ensure that the win2.example.com host is listed in Default inventory.

Note
This activity requires win2.example.com in the Default inventory
inventory. You added the host in a previous exercise. If the host is not present,
follow the instructions in the Implementing Multiple Plays guided exercise to
create it.

In the following activity, you will refactor an Ansible Playbook to use variables. The playbook
installs and configures the IIS service with a site on both hosts. A default index.html
file is transferred to the servers. The default web page is accessible at https://
gitlab.example.com/student/variables/blob/master/files/index.html.

1. From your Windows workstation, access your GitLab instance at https://


gitlab.example.com and review the content of the variables repository.
Inspect the manage.yml playbook to review the tasks that you will update at a later step.

1.1. On workstation, double-click the GitLab icon on the desktop to access your GitLab
instance.

1.2. Log in to GitLab via LDAP using student as the user name and RedHat123@! as the
password.
To access the variables repository, click student / variables in the list of projects.

DO417-RHAE2.8-en-1-20200106 161
Chapter 4 | Managing Variables and Facts

1.3. Click the manage.yml playbook to review it. The playbook installs and configures IIS.

2. On workstation, open Visual Studio Code and clone the https://


gitlab.example.com/student/variables.git repository to C:\Users\student
\Documents\variables.

2.1. Double-click the Visual Studio Code icon on the desktop to open the Visual Studio
Code editor.

2.2. Click View → Command Palette or press Ctrl+Shift+P to open the command
palette.
Type Git: Clone to clone a repository.

2.3. Use a repository URL of https://gitlab.example.com/student/


variables.git and press ENTER.
Select the Documents folder and click Select Repository Location to clone the
variables repository to the variables folder.

162 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

2.4. Click Open to add the folder to the workspace.

3. In this step, you will create a new folder for group variables and add a variables file for the
Windows group that defines the following variables:

• The iis_packages_name variable is a list, defining the features to install. It will contain
the following three entries:
• Web-Server
• NET-Framework-Core
• Web-Asp-Net45

• The iis_site_path variable specifies the root directory of your IIS site. Give the
variable a value of C:\sites\variables.

• The iis_site_name variable specifies the name of the IIS site (DO417-variables).

• The iis_site_port variable specifies the port that the site listens on (8080).

3.1. Create a new folder C:\Users\student\Documents\variables\group_vars.


To do so, right-click and select New Folder from the editor tree on the left side.

3.2. Right-click the group_vars folder to create a new Windows file within it.

DO417-RHAE2.8-en-1-20200106 163
Chapter 4 | Managing Variables and Facts

3.3. In the Windows file, define the iis_packages_name variable as a list to indicate to
Ansible the list of features to install as the following:

iis_packages_name:
- Web-Server
- NET-Framework-Core
- Web-Asp-Net45

3.4. Define the iis_site_path variable, which specifies the root directory of your IIS site.
Give the variable a value of C:\sites\variables.

...output omitted...
iis_site_path: C:\sites\variables

3.5. Define the iis_site_name variable with a value of DO417-variables:

...output omitted...
iis_site_name: "DO417-variables"

3.6. Define the iis_site_port variable with a value of 8080:

...output omitted...
iis_site_port: 8080

3.7. Save your changes.

The completed file should appear as follows:

164 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

iis_packages_name:
- Web-Server
- NET-Framework-Core
- Web-Asp-Net45
iis_site_path: C:\sites\variables
iis_site_name: "DO417-variables"
iis_site_port: 8080

Note
The completed variables file is accessible at solutions/group_vars/Windows.

4. In the following steps, you will use Visual Studio Code to edit the manage.yml playbook
and make the following changes:

• Use the iis_packages_name variable to update the win_feature module.

• Use the iis_site_path variable to update the win_file module.

• Use the iis_site_path variable to update the win_copy module.

The content requires both the iis_site_path variable and index.html since the
variable does not define the HTML file to install.

• Update the win_iis_website module as follows:

Variables for the win_iis_website Module

Parameter Variable

name iis_site_name

port iis_site_port

hostname inventory_hostname

physical_path iis_site_path

• Use the inventory_hostname variable to update the win_firewall_rule module.

4.1. Click the manage.yml playbook to open it.


For the win_feature module, move the list of features (listed in the name entry) to a
list and instruct Ansible to use the iis_packages_name variable instead:

...output omitted...
- name: IIS and .Net 4.5 are installed
win_feature:
name: "{{ iis_packages_name }}"
include_management_tools: True
state: present

4.2. For the win_file module used in the Site directory is created task, replace
the value of the path parameter with the iis_site_path variable.

DO417-RHAE2.8-en-1-20200106 165
Chapter 4 | Managing Variables and Facts

...output omitted...
- name: Site directory is created
win_file:
path: "{{ iis_site_path }}"
state: directory

4.3. For the win_copy module, replace the path of the dest parameter with the
iis_site_path variable.
The content should use both the variable and index.html, as the variable does not
define the HTML file to install.

Important
Use single quotes to ensure the backslash is not interpreted as an escape sequence.

...output omitted...
- name: Index page for site is installed
# Reuse the variable for the site path
win_copy:
src: files/index.html
dest: '{{ iis_site_path }}\index.html'

4.4. For the win_iis_website module, replace the module variables as follows:

Variables for the win_iis_website Module

Parameter Variable

name iis_site_name

port iis_site_port

hostname inventory_hostname

physical_path iis_site_path

The content should match the following:

...output omitted...
- name: IIS site is created
win_iis_website:
name: "{{ iis_site_name }}"
state: started
port: "{{ iis_site_port }}"
ip: "*"
hostname: "{{ inventory_hostname }}"
application_pool: DefaultAppPool
physical_path: "{{ iis_site_path }}"
parameters: logfile.directory:C:\sites\logs

166 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

4.5. For the win_firewall_rule module, replace the value of the localport
parameter with the iis_site_port variable. The content should match the following:

...output omitted...
- name: Firewall rule is enabled
win_firewall_rule:
name: HTTP
localport: "{{ iis_site_port }}"
action: allow
direction: in
protocol: tcp
state: present
enabled: yes

The final file should look like the following:

- name: Install and Configure an IIS site


hosts: all
tasks:

- name: IIS and .Net 4.5 are installed


win_feature:
name: "{{ iis_packages_name }}"
include_management_tools: True
state: present

- name: Logs directory is created


win_file:
path: C:\sites\logs
state: directory

- name: Site directory is created


win_file:
path: "{{ iis_site_path }}"
state: directory

- name: Index page for site is installed


win_copy:
src: files/index.html
dest: '{{ iis_site_path }}\index.html'

- name: IIS site is created


win_iis_website:
name: "{{ iis_site_name }}"
state: started
port: "{{ iis_site_port }}"
ip: "*"
hostname: "{{ inventory_hostname }}"
application_pool: DefaultAppPool
physical_path: "{{ iis_site_path }}"
parameters: logfile.directory:C:\sites\logs

- name: Firewall rule is enabled

DO417-RHAE2.8-en-1-20200106 167
Chapter 4 | Managing Variables and Facts

win_firewall_rule:
name: HTTP
localport: "{{ iis_site_port }}"
action: allow
direction: in
protocol: tcp
state: present
enabled: yes

5. Save your changes, commit the file using a message of Define variables for the
manage.yml playbook and push your changes to the remote repository.

5.1. Save your changes.

5.2. From the Visual Studio Code side bar, select Source Control to access the list of
changes.

5.3. Hover over the manage.yml playbook to access the available options for the file. Click
Stage Changes to add your changes to the index.

5.4. Repeat the same step for the Windows file.

5.5. In the Message text file, enter a message of Define variables for the
manage.yml playbook.

5.6. Click Commit to commit the changes to your local repository.

5.7. To push your local changes to the remote repository, click the synchronize button
at the bottom of the editor. This instructs Visual Studio Code to synchronize your
repository with the remote copy.

6. In Ansible Tower, edit the Run variables project job template, to use manage.yml as
the playbook.

168 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

After updating the job template, run it and review the job output. The output of the job
indicates that Ansible installed and configured the web server on the two hosts of the
default inventory. It then customized the web page for each host.

6.1. Access Ansible Tower by double-clicking Ansible Tower from your desktop. Log in to
Ansible Tower using admin as the user name and RedHat123@! as the password.

6.2. In Ansible Tower, click Templates then Run variables project job template on
the side menu.

6.3. Click the job template to edit it. Select manage.yml for the PLAYBOOK field and
click SAVE to update the job template.

6.4. Click LAUNCH to run a job from the job template.

6.5. The action redirects you to the job output. The output indicates that Ansible is able
to install and start the web server on win1 and win2, and create the custom DO417-
variables site on each server.
The play also opens the firewall to allow connections on port 8080.

DO417-RHAE2.8-en-1-20200106 169
Chapter 4 | Managing Variables and Facts

7. On workstation, open Chrome and access http://win1.example.com:8080. Ensure


that the home page matches the following:

8. On workstation, open Chrome and access http://win2.example.com:8080 and


ensure that the web page matches the one returned by win1.example.com.

Note
If you are not able to access the web pages and need to clean the resources on the
hosts, run the remove-iis.yml Ansible Playbook available in the variables
project directory. The playbook removes the IIS site and the firewall rule.

After cleaning the resources, make changes to your playbook and rerun it.

170 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

This concludes the guided exercise.

DO417-RHAE2.8-en-1-20200106 171
Chapter 4 | Managing Variables and Facts

Managing Secrets

Objectives
After completing this section, you should be able to describe approaches to protecting sensitive
data used by playbooks.

Protecting Sensitive Data


Ansible may need access to sensitive data such as passwords or API keys in order to configure
managed hosts. Normally, you might store this information as plain text in inventory variables or
other Ansible files. In that case, however, any user with access to the Ansible files or a version
control system that stores the Ansible files would have access to this sensitive data. This poses an
obvious security risk.

There are a number of ways in which you can address this risk. Each has its own advantages and
disadvantages. Some approaches include:

• Protect structured files with the Ansible Vault tool included with Ansible on a Linux system or
container.

• Protect structured files with the Ansible Vault tool included with Ansible on a Windows system
that is installed with Windows Subsystem for Linux (WSL).

• Protect structured files with Ansible Vault by using Jordan Borean's unofficial PowerShell
cmdlets on a Windows system.

• Use an Ansible Tower custom credential.

• Use a third-party secret management system.

Protecting Secrets with Ansible Vault on Linux


Ansible Vault, which is included within the Ansible command-line tools, can be used to encrypt and
decrypt any structured data file used by Ansible. This includes host and group variable files and
variables loaded by include_vars or vars_files directives. Some Ansible modules, including
template, can accept an Ansible Vault-encrypted file as a value for its src directive and will
decrypt the file before placing it at the destination on the target host.

The main limitation of Ansible Vault is that the Ansible command-line tools are not currently
supported on Microsoft Windows operating systems. This means it can be a challenge to prepare
the encrypted file with Ansible Vault if you are working on a Windows-based workstation. When
you have an encrypted file, however, Ansible Tower can decrypt it when you run the job as long as
you provide the correct Vault credential as one of the credentials in the job template.

Important
Ansible Vault does not implement its own cryptographic functions but rather uses
an external Python toolkit. Files are protected with symmetric encryption using
AES256 with a password as the secret key. Note that the way this is done has not
been formally audited by a third party.

172 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

Encrypting Files on the Linux Command Line


To encrypt files with Ansible Vault on a Linux system, you need a Linux server or virtual machine
installed with the Ansible command-line tools. Information on how to do this can be found at
https://docs.ansible.com/ansible/latest/installation_guide/index.html. You also need to clone the
Git repository that contains your Ansible project to the Linux system.

To encrypt an existing file, you can use the ansible-vault encrypt command:

[student@demo project]$ ansible-vault encrypt secret.yml


New Vault password:
Confirm New Vault password:
Encryption successful
[student@demo project]$

You can use the ansible-vault rekey command to change the password on the file, and the
ansible-vault decrypt command to permanently decrypt the file.

The disadvantage of this approach in a Windows-centric environment is that you need to edit your
secret files on a Linux workstation.

Running Jobs with Ansible Vault-protected Files


On Ansible Tower, to decrypt an Ansible Vault-protected file when you launch a job, the job
template must include the passwords for the Ansible Vault-protected files as one or more Vault
credentials.

A Vault credential is created in Ansible Tower the same way as a machine credential, except that
you select Vault for the credential type and provide the Vault password to the credential.

Figure 4.11: A Vault credential

Include the Vault credentials and the machine credentials in the job template:

DO417-RHAE2.8-en-1-20200106 173
Chapter 4 | Managing Variables and Facts

Figure 4.12: A job template that uses a Vault credential

Recommended Practices for Managing Variable Files


To simplify management, it makes sense to set up your Ansible project so that sensitive variables
and all other variables are kept in separate files. You can protect the files containing sensitive
variables with the ansible-vault command.

Remember that the preferred way to manage group variables and host variables is to create
directories at the playbook level. The group_vars directory normally contains variable files
with names that match the host groups to which they apply. The host_vars directory normally
contains variable files with names that match the host names of the managed hosts to which they
apply.

However, instead of using files in group_vars or host_vars, you can also use directories for
each host group or managed host. These directories can then contain multiple variable files, all of
which are used by the host group or managed host. For example, in the following project directory
for playbook.yml, members of the webservers host group use variables in the group_vars/
webservers/vars file, and demo.example.com uses the variables in both host_vars/
demo.example.com/vars and host_vars/demo.example.com/vault:

.
├── ansible.cfg
├── group_vars
│ └── webservers
│ └── vars
├── host_vars
│ └── demo.example.com
│ ├── vars
│ └── vault
├── inventory
└── playbook.yml

In this scenario, the advantage is that you can place most variables for demo.example.com in
the vars file, but you can protect sensitive variables by placing them separately in the vault file.
Then you can use ansible-vault to encrypt the vault file and leave the vars file as plain text.

There is nothing special about the file names being used in this example inside the host_vars/
demo.example.com directory. That directory could contain more files, some encrypted by
Ansible Vault and some which are not.

174 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

You can also protect playbook variables (as opposed to inventory variables) with Ansible Vault.
You can place sensitive playbook variables in a separate file encrypted by Ansible Vault and which
is included in the playbook through a vars_files directive. This can be useful because playbook
variables take precedence over inventory variables.

If you are using multiple vault passwords with your playbook, make sure that each encrypted file
is assigned a vault ID, and that you enter the matching password with that vault ID when running
the playbook. This ensures that the correct password is selected first when decrypting the vault-
encrypted file, which is faster than forcing Ansible to try all the vault passwords you provided until
it finds the right one.

Using Ansible Vault on Windows


The ansible-vault tool is only supported on Linux. However, there are some unsupported
options for Windows.

You could install the Ansible tools under the Windows Subsystem for Linux (WSL) environment on
a Windows workstation. This might work, but is unsupported and not recommended by Red Hat.

One of the Ansible developers, Jordan Borean, has written some unofficial PowerShell cmdlets
that you could use to encrypt and decrypt Ansible Vault files. The GitHub repository for his code
is at https://github.com/jborean93/PowerShell-AnsibleVault. This is code written by a member of
the open source community and is also not supported by Red Hat.

Important
Neither of these options are supported by Red Hat, but we are providing information
about them for your reference.

Links to further reading are available in the References section below.

Storing Sensitive Information in Custom Credentials


A new feature in Ansible Tower 3.2 is custom credential types. You can use this feature to create
custom credential types, instances of which are stored encrypted in the Ansible Tower database.

Custom credentials are composed of inputs and injectors. Inputs define the fields that the
credential contains, such as a user name, or a token. Injectors define how the information is made
available for use in playbooks.

Even though these are called credentials, you are not restricted to using them for authentication
purposes. For example, you could store purchased software details such as a license key, serial
number, or activation code. The following images show a simple custom credential used to store a
username and password for proxy authentication.

DO417-RHAE2.8-en-1-20200106 175
Chapter 4 | Managing Variables and Facts

Figure 4.13: Creating a new custom credential type

Figure 4.14: Creating a new credential using a custom type

Integrating Third-party Secret Management Systems


Many organizations already have a centralized secret management system in place. Ansible
Tower 3.5 and later can integrate with several secret management systems through credential
plug-ins.

Supported Secret Management Systems

• CyberArk Application Identity Manager

• CyberArk Conjur

• HashiCorp Vault Key-Value Store

• HashiCorp Vault SSH Secrets Engine

• Microsoft Azure Key Management System

One of the benefits of a centralized secret service is that sensitive information is available to
members of the organization without requiring access to Ansible Tower.

176 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

The following image shows an example of the additional fields required when creating a credential
mapping to an external secret service.

Figure 4.15: Creating a new credential mapped to an external secret service

Ansible retrieves the credentials just before the playbook runs.

References
Vault — Ansible Documentation
https://docs.ansible.com/ansible/latest/user_guide/playbooks_vault.html

Variables and Vaults — Ansible Documentation


https://docs.ansible.com/ansible/latest/user_guide/
playbooks_best_practices.html#best-practices-for-variables-and-vaults

PowerShell-AnsibleVault
https://github.com/jborean93/PowerShell-AnsibleVault

Can Ansible run on windows? — Ansible Documentation


https://docs.ansible.com/ansible/latest/user_guide/windows_faq.html#can-
ansible-run-on-windows

Secret Management System — Ansible Documentation


https://docs.ansible.com/ansible-tower/latest/html/userguide/
credential_plugins.html#ug-credential-plugins

Ansible Tower Feature Spotlight: Custom Credentials


https://www.ansible.com/blog/ansible-tower-feature-spotlight-custom-credentials

DO417-RHAE2.8-en-1-20200106 177
Chapter 4 | Managing Variables and Facts

Quiz

Managing Secrets
Choose the correct answers to the following questions:

1. Which two of the following methods are unsupported ways of running Ansible Vault on
Windows? (Choose two.)
a. Ansible PyInstaller
b. Ansible PowerShell module
c. AnsiblePE
d. Bash for Windows
e. Windows Subsystem for Linux

2. Which encryption cipher does Ansible Vault use?


a. Blowfish
b. 3DES
c. RC4
d. AES256
e. SHA512

3. Which two groups of information are required for a custom credential type? (Choose
two.)
a. Inputs
b. Pipes
c. Extractors
d. Exports
e. Injectors

4. Which five of the following secret management systems are supported by Ansible
Tower? (Choose five.)
a. Microsoft Azure Key Management System
b. HashiCorp Vault Key-Value Store
c. Cloudflare Red October
d. CyberArk Conjur
e. Lyft Confidant
f. CyberArk Application Identity Manager
g. HashiCorp Vault SSH Secrets Engine
h. Pinterest Knox

178 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

Solution

Managing Secrets
Choose the correct answers to the following questions:

1. Which two of the following methods are unsupported ways of running Ansible Vault on
Windows? (Choose two.)
a. Ansible PyInstaller
b. Ansible PowerShell module
c. AnsiblePE
d. Bash for Windows
e. Windows Subsystem for Linux

2. Which encryption cipher does Ansible Vault use?


a. Blowfish
b. 3DES
c. RC4
d. AES256
e. SHA512

3. Which two groups of information are required for a custom credential type? (Choose
two.)
a. Inputs
b. Pipes
c. Extractors
d. Exports
e. Injectors

4. Which five of the following secret management systems are supported by Ansible
Tower? (Choose five.)
a. Microsoft Azure Key Management System
b. HashiCorp Vault Key-Value Store
c. Cloudflare Red October
d. CyberArk Conjur
e. Lyft Confidant
f. CyberArk Application Identity Manager
g. HashiCorp Vault SSH Secrets Engine
h. Pinterest Knox

DO417-RHAE2.8-en-1-20200106 179
Chapter 4 | Managing Variables and Facts

Managing Facts

Objectives
After completing this section, you should be able to reference data about managed hosts using
Ansible facts, and configure custom facts on managed hosts.

Describing Ansible Facts


Ansible facts are variables that Ansible automatically discovers on a managed host. Facts contain
host-specific information that you can use just like regular variables in plays, conditionals, loops, or
any other statement that depends on a value collected from a managed host.

Facts gathered from managed hosts can include:

• The host name.

• Network interface names.

• The IP addresses.

• The version of the operating system.

• Various environment variables.

• The number of CPUs.

• The total or free memory.

• The available disk space.

Facts are a convenient way to retrieve the state of a managed host and to determine what action
to take based on that state. For example:

• You can decide to restart a server via a conditional task, which runs or not based on a fact
containing the managed host's current kernel version.

• You can customize a database based on the available memory reported by a fact.

• You can set the IPv4 address based on the value of a fact.

Usually, every play automatically runs the setup module before the first task to gather facts.
This is reported as the Gathering Facts task in Ansible 2.3 and later, or simply as setup in
earlier versions of Ansible. By default, you do not need to have a task to run setup in your play. It is
normally run automatically for you.

To see which facts Ansible gathers for your managed hosts, you can run a short playbook that
gathers facts and uses the debug module to print the value of the ansible_facts variable.

180 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

- name: Fact dump


hosts: all
tasks:
- name: Print all facts
debug:
var: ansible_facts

When you run the playbook, the job output displays the facts:

PLAY [Fact dump] ***************************************************************

TASK [Gathering Facts] *********************************************************


ok: [win1.example.com]

TASK [Print all facts] *********************************************************


ok: [win1.example.com] => {
"ansible_facts": {
"lastboot": "2019-08-21 03:14:00Z",
"owner_contact": "",
"domain": "example.com",
"distribution_major_version": "10",
"swaptotal_mb": 0,
"kernel": "10.0.17763.0",
"windows_domain_member": true,
"system_vendor": "Amazon EC2",
"module_setup": true,
"processor_count": 1,
"_facts_gathered": true,
"gather_subset": [
"interfaces": [
{
"macaddress": "06:77:83:A2:D5:29",
"default_gateway": "172.25.250.1",
"interface_name": "Amazon Elastic Network Adapter",
"connection_name": "Ethernet 3",
"dns_domain": "us-west-1.compute.internal",
"interface_index": 5
}
],
"memtotal_mb": 4036,
"windows_domain": "example.com",
"os_family": "Windows",
"processor_cores": 1,
...output omitted...

The playbook displays the contents of the ansible_facts variable in JSON format as a hash
(dictionary) of variables. You can browse the output to see what facts are gathered, and to find
facts that you might want to use in your playbooks.

The following table shows some facts which Ansible might gather from a managed host and may
be useful in a playbook:

DO417-RHAE2.8-en-1-20200106 181
Chapter 4 | Managing Variables and Facts

Examples of Ansible Facts

Fact Variable

Short host name ansible_facts['hostname']

Fully qualified domain name ansible_facts['fqdn']

Number of processors ansible_facts['processor_count']

Names of all network ansible_facts['interfaces']


interfaces

Total system memory ansible_facts['memtotal_mb']

Version of the currently ansible_facts['kernel']


running kernel

Note
Remember that when a variable's value is a hash, you can use either of two syntaxes
to retrieve the value. To take two examples from the preceding table:

• ansible_facts['date_time']['month'] can also be written


ansible_facts.date_time.month

• ansible_facts['env']['SystemDrive'] can also be written


ansible_facts.env.SystemDrive

When using facts in a playbook, Ansible dynamically substitutes the variable name for the fact with
its corresponding value:

---
- name: Fact usage
hosts: all
tasks:
- name: Prints various Ansible facts
debug:
msg: >
The current time on {{ ansible_facts['fqdn'] }}
is {{ ansible_facts['date_time']['time'] }}

The following output shows how Ansible is able to query the managed node and dynamically use
the system information to update the variable. You can also use facts to create dynamic groups of
hosts that match particular criteria.

PLAY ***********************************************************************

TASK [Gathering Facts] *****************************************************


ok: [win1.example.com]

TASK [Prints various Ansible facts] ****************************************


ok: [win1.example.com] => {
"msg": "The current time on win1.example.com is 13:16:45"

182 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

PLAY RECAP *****************************************************************


win1.example.com : ok=2 changed=0 unreachable=0 failed=0

Managing Ansible Facts Injected as Variables


Before Ansible 2.5, facts were injected as individual variables prefixed with the string
ansible_ instead of being part of the ansible_facts variable. For example, the
ansible_facts['distribution'] fact would have been called ansible_distribution.

Many older playbooks still use facts injected as variables, instead of the new syntax where they
appear under the ansible_facts variable.

The following table compares the old and new fact names.

Comparison of Selected Ansible Fact Names

ansible_facts form Old fact variable form

ansible_facts['hostname'] ansible_hostname

ansible_facts['fqdn'] ansible_fqdn

ansible_facts['interfaces'] ansible_interfaces

ansible_facts['kernel'] ansible_kernel

Important
Currently, Ansible recognizes both the new fact naming system (using
ansible_facts) and the old pre-2.5 “facts injected as separate variables” naming
system.

The default value of inject_facts_as_vars will probably change to false


in a future version of Ansible. If it is set to false, you can only reference Ansible
facts using the new ansible_facts.* naming system. In that case, attempts to
reference facts using the old namespace will result in the following error:

...output omitted...
TASK [Show me the facts] *************************************************
fatal: [demo.example.com]: FAILED! => {"msg": "The task includes an option
with an \
undefined variable. The error was: 'ansible_distribution' is undefined\n\n
The error appears to have been in '/home/student/demo/playbook.yml': line 5, \
column 7, but may\nbe elsewhere in the file depending on the exact syntax
problem.\n
\nThe offending line appears to be:\n\n tasks:\n
- name: Show me the facts\n
^ here\n"}
...output omitted...

DO417-RHAE2.8-en-1-20200106 183
Chapter 4 | Managing Variables and Facts

Turning off Fact Gathering


Sometimes, you do not want to gather facts for your play. There are a couple of reasons why this
might be the case. In some cases you might not want to gather facts for your play, for example
if you are not using them and want to speed up the play or reduce load on the managed hosts.
Perhaps the managed hosts cannot run the setup module for some reason, or need to install
some prerequisite software before gathering facts.

To disable fact gathering for a play, set the gather_facts keyword to no or false:

---
- name: This play gathers no facts automatically
hosts: large_farm
gather_facts: no

Even if gather_facts: no is set for a play, you can manually gather facts at any time by running
a task that uses the setup module:

tasks:
- name: Manually gather facts
setup:
...output omitted...

Obtaining Information Using Magic Variables


Some variables are not facts or configured through the setup module, but are automatically
set by Ansible. These magic variables can also be used to get information specific to a particular
managed host.

Four of the most useful are:

hostvars
Contains the variables for managed hosts, and can be used to get the values for another
managed host's variables. It does not include the managed host's facts if Ansible does not
gather them for that host.

group_names
Lists all groups the current managed host is in.

groups
Lists all groups and hosts in the inventory.

inventory_hostname
Contains the host name for the currently managed host as configured in the inventory. This
may be different from the host name reported by facts for various reasons.

There are a number of other “magic variables” as well. For more information, see Variable
Precedence — Ansible Documentation in the references section below. One way to get insight into
their values is to use the debug module to report on the contents of the hostvars variable for a
particular host:

...output omitted...
{
"hostvars[inventory_hostname]": {
"awx_job_template_name": "Run test-playbook project",

184 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

"ansible_windows_domain_member": true,
"tower_user_last_name": "student",
"ansible_os_product_type": "server",
"awx_user_email": "student@example.com",
"module_setup": true,
"tower_job_launch_type": "manual",
"awx_job_template_id": 9,
"gather_subset": [
"all"
],
"playbook_dir": "/var/lib/awx/projects/_7__test_playbook_repository",
"ansible_distribution_version": "10.0.17763.0",
"ansible_playbook_python": "/usr/bin/python2",
"ansible_forks": 10,
"ansible_owner_contact": "",
"ansible_facts": {
"lastboot": "2019-08-21 03:13:53Z",
"owner_contact": "",
"domain": "example.com",
"distribution_major_version": "10",
"swaptotal_mb": 0,
"kernel": "10.0.17763.0",
...output omitted...
},
"tower_user_email": "student@example.com",
"ansible_windows_domain": "example.com",
"awx_job_id": 32,
"ansible_distribution_major_version": "10",
"groups": {
"ungrouped": [
"win1.example.com"
],
"Windows": [],
"all": [
"win1.example.com"
]
},
"ansible_bios_date": "10/16/2017",
"inventory_hostname_short": "win1",
"tower_project_revision": "273396b95ae1d2724f38e4024fc4e1f7907f098f",
"omit": "__omit_place_holder__1594b921bbf58cfd665e07686cdff4ae5d1a7125",
"ansible_user_gecos": "",
"ansible_diff_mode": false,
"ansible_processor_threads_per_core": 2,
"ansible_win_rm_certificate_expires": "2022-08-19 03:00:51",
"ansible_product_name": "t3.medium",
"ansible_user_sid": "S-1-5-21-2938333969-4197073335-1435044025-500",
"ansible_run_tags": [
"all"
],
"awx_user_last_name": "student"
},
"changed": false,

DO417-RHAE2.8-en-1-20200106 185
Chapter 4 | Managing Variables and Facts

"_ansible_verbose_always": true,
"_ansible_no_log": false
}

References
setup - Gathers facts about remote hosts — Ansible Documentation
https://docs.ansible.com/ansible/latest/modules/setup_module.html

186 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

Guided Exercise

Managing Facts
In this exercise, you will gather Ansible facts from your managed hosts and use them in plays.

Outcomes
You should be able to:

• Gather facts from managed hosts using the setup, win_product_facts, and
win_disk_facts modules.

• Create tasks that use the gathered facts.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. Launch the Visual Studio Code editor. If you have not previously cloned the variables
repository, clone it to your workstation instance.

1.1. Click Search Windows and type code to search for and open Visual Studio Code.

1.2. Click View → Command Palette or press Ctrl+Shift+P to open the command
palette.
Type clone and select Git: Clone to clone a repository.
Use a repository URL of https://gitlab.example.com/student/
variables.git. When prompted, select the Documents folder as the repository
location. This clones the remote repository in to the C:\Users\student
\Documents\variables folder.

2. Click File → Open Folder then select the c:\Users\student\Documents


\variables directory.

3. Open the facts.yml playbook to add tasks that gather system facts and create a
summary text file.

4. Modify the task named Product facts are collected to invoke the
win_product_facts module to gather Windows product and license information.

- name: Product facts are collected


win_product_facts:

DO417-RHAE2.8-en-1-20200106 187
Chapter 4 | Managing Variables and Facts

5. Modify the task named Disk facts are collected to invoke the win_disk_facts
module to collect information about attached disks.

- name: Disk facts are collected


win_disk_facts:

6. Modify the Summary is written task to write a selection of the facts in a summary text
file on the managed host's Desktop.

- name: Summary is written


win_copy:
content: |
OS: {{ ansible_facts['os_name'] }}
Machine ID: {{ ansible_facts['machine_id'] }}
Last Boot: {{ ansible_facts['lastboot'] }}
License Status: {{ ansible_facts['os_license_status'] }}
Disk Size: {{ ansible_facts['disks'][0]['size'] }}
dest: "{{ ansible_facts['user_dir'] }}\\Desktop\\summary-
{{ ansible_facts['hostname'] }}.txt"

Use the win_copy module's content parameter to write simple content to a file.
Insert variables and facts into text using double braces {{ variable }}.
Access array values using numeric keys, as in myArray[index].
Identify the target file location with the dest parameter. Like other values,
filenames can also include dynamic variable substitution. Ansible resolves
ansible_facts['user_dir'] to C:\Users\devops.

7. Verify that the final facts.yml matches the following playbook.

---
- name: System summary is compiled
hosts: all
tasks:
- name: Product facts are collected
win_product_facts:

- name: Disk facts are collected


win_disk_facts:

- name: Summary is written


win_copy:
content: |
OS: {{ ansible_facts['os_name'] }}
Machine ID: {{ ansible_facts['machine_id'] }}
Last Boot: {{ ansible_facts['lastboot'] }}
License Status: {{ ansible_facts['os_license_status'] }}
Disk Size: {{ ansible_facts['disks'][0]['size'] }}
dest: "{{ ansible_facts['user_dir'] }}\\Desktop\\summary-
{{ ansible_facts['hostname'] }}.txt"

188 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

8. Save and commit the changes to your local Git repository and then push them to the
remote repository.

8.1. Click File → Save or press Ctrl+S to save the file.

8.2. Navigate to the Source Control pane and click + next to facts.yml to stage the
changes.

8.3. Enter a brief commit message, then press Ctrl+Enter to commit the changes.

8.4. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to
push your local changes to the remote repository, and retrieve any new changes from
the repository.

9. From workstation, access your Ansible Tower instance available at http://


tower.example.com. Connect as the student user and RedHat123@! as the password.

10. Edit the Run variables project job template to test your playbook.

10.1. In the navigation pane, click Templates.

10.2.Click Run variables project job template to edit it.

10.3.Select the facts.yml playbook from the PLAYBOOK list.

10.4.Click SAVE to update the template, and then click LAUNCH to run the job.

11. Verify that the playbook completed successfully and review the log output.

11.1. When all tasks have completed, verify that the status in the DETAILS section
shows Successful. If the job was not successful, compare your playbook with the
solutions/facts.sol solution file in the variables Git repository.

DO417-RHAE2.8-en-1-20200106 189
Chapter 4 | Managing Variables and Facts

11.2. In the console output panel, click ok: [win1.example.com] under TASK [Gathering
Facts]. Observe the "ansible_facts" JSON dictionary in the modal window text
area.

11.3. In the console output panel, click ok: [win2.example.com] under TASK [Product
facts are collected]. Observe the "ansible_facts" JSON dictionary in the
modal window text area.

190 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

11.4. In the console output panel, click ok: [win1.example.com] under TASK [Disk
facts are collected]. Observe the "ansible_facts" JSON dictionary in the
modal window text area.

12. Connect to the win1.example.com managed host, and view the system summary file
that has been written to the desktop.

12.1. Click Search Windows and type remote to search for and open Remote Desktop
Connection.

12.2. Enter win1.example.com for Computer and devops for User Name and
RedHat123@! as the password. Note that devops is a local user, not a domain user, so
do not include the EXAMPLE domain.

DO417-RHAE2.8-en-1-20200106 191
Chapter 4 | Managing Variables and Facts

12.3. Double-click the summary-WIN1.txt text document on the win1.example.com


desktop to review its contents.

13. Connect to the win2.example.com managed host, and view the system summary file
that has been written to the desktop.

13.1. Click Search Windows and type remote to search for and open Remote Desktop
Connection.

13.2. Enter win2.example.com for Computer and devops for User Name and
RedHat123@! as the password.

13.3. Double-click the summary-WIN2.txt text document on the win2.example.com


desktop to review its contents.

This concludes the guided exercise.

192 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

Lab

Managing Variables and Facts


Performance Checklist
In this lab, you will write and run a playbook that uses variables and facts.

Outcomes
You should be able to:

• Define group variables in Ansible.

• Refactor an Ansible Playbook to use variables and facts.

• Run a job in Ansible Tower.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

Note
This activity requires win2.example.com in the Default inventory
inventory. You added the host in a previous exercise. If the host is not present,
follow the instructions in the Implementing Multiple Plays guided exercise to
create it.

In this lab you will refactor a playbook to use group and registered variables, and to display page
file and memory information.
1. From workstation open Visual Studio Code and clone the variables repository
accessible at https://gitlab.example.com/student/variables.git to C:\Users
\student\Documents\variables, then open the folder.
2. Create a new folder for group variables if it does not exist, and a subfolder for the Windows
group. If a file named Windows exists already, then delete it first. Create a file named
vars.yml under the Windows folder that defines the pagefile variable. This variable
contains the following list of variables that control the win_pagefile module:

• remove: yes
• auto: no
3. Open review.yml for editing. Locate the task named Obtain page file
information. This task uses the win_pagefile module with no arguments to query the

DO417-RHAE2.8-en-1-20200106 193
Chapter 4 | Managing Variables and Facts

current configuration. Complete the Show original page file information task
using the debug module to display the value of the orig_pagefile_info registered
variable. Edit the Manage page files on virtual machines task to include the use
of the pagefile variables. Complete the Show new page file information task
using the debug module to display the new_pagefile_info registered variable. Complete
the Show current memory information task using the debug module to display the
ansible_facts['memtotal_mb'] fact.
4. Save the file and then commit and push your changes to the remote variables repository.
5. Open the Ansible Tower web UI and test your playbook using the Run variables
project job template. Review the job output and note the differences between the original
and new page file configuration.
6. Edit the Run variables project job template to use the review_finish.yml
playbook, then launch it to revert your changes.

This concludes the lab.

194 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

Solution

Managing Variables and Facts


Performance Checklist
In this lab, you will write and run a playbook that uses variables and facts.

Outcomes
You should be able to:

• Define group variables in Ansible.

• Refactor an Ansible Playbook to use variables and facts.

• Run a job in Ansible Tower.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

Note
This activity requires win2.example.com in the Default inventory
inventory. You added the host in a previous exercise. If the host is not present,
follow the instructions in the Implementing Multiple Plays guided exercise to
create it.

In this lab you will refactor a playbook to use group and registered variables, and to display page
file and memory information.
1. From workstation open Visual Studio Code and clone the variables repository
accessible at https://gitlab.example.com/student/variables.git to C:\Users
\student\Documents\variables, then open the folder.

1.1. Double-click the Visual Studio Code icon on the desktop.

1.2. Click View → Command Palette or press Ctrl+Shift+P to open the command
palette.
Type Git: Clone to clone a repository.

1.3. Use a repository URL of https://gitlab.example.com/student/


variables.git and type ENTER.

DO417-RHAE2.8-en-1-20200106 195
Chapter 4 | Managing Variables and Facts

Select the Documents folder and click Select Repository Location to clone the
variables repository to the variables folder.

1.4. Click Open to add the folder to the workspace.

2. Create a new folder for group variables if it does not exist, and a subfolder for the Windows
group. If a file named Windows exists already, then delete it first. Create a file named
vars.yml under the Windows folder that defines the pagefile variable. This variable
contains the following list of variables that control the win_pagefile module:

• remove: yes
• auto: no

2.1. Create a new group_vars folder at the top level of the project if it does not already
exist. To do so, right-click and select New Folder from the editor tree on the left side.

2.2. Create a new Windows folder in the group_vars folder. If a file named Windows exists
already, then delete it first.

2.3. Create a new file group_vars/Windows/vars.yml.

2.4. In the vars.yml file, define the pagefile variable with its content being parameters
for the win_pagefile module.

---
pagefile:
remove: yes
auto: no

2.5. Save your changes.

3. Open review.yml for editing. Locate the task named Obtain page file
information. This task uses the win_pagefile module with no arguments to query the
current configuration. Complete the Show original page file information task
using the debug module to display the value of the orig_pagefile_info registered
variable. Edit the Manage page files on virtual machines task to include the use
of the pagefile variables. Complete the Show new page file information task
using the debug module to display the new_pagefile_info registered variable. Complete
the Show current memory information task using the debug module to display the
ansible_facts['memtotal_mb'] fact.

3.1. Locate the task named Obtain page file information. This task uses the
win_pagefile module with no arguments to query the current configuration.

- name: Obtain page file information


win_pagefile:
register: orig_pagefile_info

3.2. Complete the Show original page file information task using the debug
module to display the value of the orig_pagefile_info registered variable.

- name: Show original page file information


debug:
var: orig_pagefile_info

196 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

3.3. Locate the task named Manage page files on virtual machines. Replace the
instances of CHANGE_ME with the relevant pagefile variables. This task will make
changes to the page file configuration.

- name: Manage page files on virtual machines


win_pagefile:
remove_all: "{{ pagefile['remove'] }}"
automatic: "{{ pagefile['auto'] }}"
register: new_pagefile_info

3.4. Complete the Show new page file information task using the debug module to
display the value of the pagefile_info registered variable.

- name: Show new page file information


debug:
var: new_pagefile_info

3.5. Complete the Show current memory information task using the debug module
to display the value of the ansible_facts['memtotal_mb'] fact.

- name: Show current memory information


debug:
var: ansible_facts['memtotal_mb']

3.6. The completed playbook should look like this:

---
- name: Manage page files
hosts: Windows

tasks:
- name: Obtain page file information
win_pagefile:
register: orig_pagefile_info

- name: Show original page file information


debug:
var: orig_pagefile_info

- name: Manage page files on virtual machines


win_pagefile:
remove_all: "{{ pagefile['remove'] }}"
automatic: "{{ pagefile['auto'] }}"
register: new_pagefile_info

- name: Show new page file information


debug:
var: new_pagefile_info

- name: Show current memory information


debug:
var: ansible_facts['memtotal_mb']

DO417-RHAE2.8-en-1-20200106 197
Chapter 4 | Managing Variables and Facts

4. Save the file and then commit and push your changes to the remote variables repository.

4.1. Save your changes to the review.yml file.

4.2. From the Visual Studio Code side bar, select Source Control to access the list of
changes.

4.3. Hover over the review.yml playbook to access the available options for the file. Click +
to add your changes to the index.

4.4. In the Message field, enter a concise commit message and then press Ctrl+Enter.

4.5. To push your local changes to the remote repository, click the Synchronize Changes
button at the bottom of the editor. This instructs Visual Studio Code to synchronize your
repository with the remote copy.

5. Open the Ansible Tower web UI and test your playbook using the Run variables
project job template. Review the job output and note the differences between the original
and new page file configuration.

5.1. In the navigation pane, click Templates.

5.2. Click the name of the Run variables project job template.

5.3. Select the review.yml playbook from the PLAYBOOK list.

5.4. Click SAVE to update the template and then click LAUNCH to run the job.

5.5. Review the output from the Show current page file information task to
confirm that the changes were successful.

...output omitted...
"orig_pagefile_info": {
"failed": false,
"automatic_managed_pagefiles": true,
"changed": false,
"pagefiles": []
}
...output omitted...
"new_pagefile_info": {
"failed": false,
"automatic_managed_pagefiles": false,
"changed": true,
"pagefiles": [
{
"caption": "C:\\ 'pagefile.sys'",
"maximum_size": 0,
"initial_size": 0,
"description": "'pagefile.sys' @ C:\\",
"name": "C:\\pagefile.sys"
}

6. Edit the Run variables project job template to use the review_finish.yml
playbook, then launch it to revert your changes.

This concludes the lab.

198 DO417-RHAE2.8-en-1-20200106
Chapter 4 | Managing Variables and Facts

Summary
In this chapter, you learned:

• Variables, which have a global, play, or host scope, allow plays to be more flexible, providing
default values that can be overridden at various levels.

• When using variables in a play, you must quote them if they start the line. Unquoted variables at
the start of the line prevent the playbook from parsing.

• There are many methods for managing sensitive information in Ansible Tower Custom credential
types allow you to store non-standard credentials and keys, that are encrypted in the database.

• Ansible Tower supports integration with several centralized secret storage services from
CyberArk, HashiCorp, and Microsoft.

• Ansible Vault manages encryption of secrets and is included with Ansible, however it is only
supported on Linux. There are unsupported methods of managing Ansible Vault encrypted files
on Windows.

• Facts are pieces of information about a managed host, collected by the setup module. You can
use facts in conditional statements.

DO417-RHAE2.8-en-1-20200106 199
200 DO417-RHAE2.8-en-1-20200106
Chapter 5

Installing and Updating


Software
Goal Install, manage, and ensure software is up to date
using Ansible Playbooks.

Objectives • Ensure software is installed and up to date on


Microsoft Windows systems.
• Inspect the Windows Registry and ensure that
registry keys are correctly configured.

Sections • Installing and Updating Software (and Guided


Exercise)
• Editing the Registry (and Guided Exercise)

Lab Installing and Updating Software

DO417-RHAE2.8-en-1-20200106 201
Chapter 5 | Installing and Updating Software

Installing and Updating Software

Objectives
After completing this section, you should be able to ensure software is installed and up to date on
Microsoft Windows systems.

Installing Software on Windows Systems


There are many types of software installation that you may want to perform on a Windows host,
such as adding Windows Roles and Features, installing MSI or executable packages, and applying
hotfixes or Windows updates. There are different Ansible modules available to support these
various installation methods. Some of the most common are described below.

Software Installation Modules

win_package
The original module for installing MSI or executable packages, which can be available locally
or remotely from a URL. There are several methods for determining whether the package
is already installed, such as creates_path and create_service, which check for the
presence of directories and services respectively. You can also specify the product_id
argument to check the registry for the installed product.

win_chocolatey
Chocolatey is a package manager for Windows, allowing you to search, install, and uninstall
packages from the Chocolatey repository. The win_chocolatey module, and its associated
sub-modules, support Chocolatey package management functions from Ansible.

win_feature
On a Windows server, roles and features are functions that you can add to a server, and that
are provided as part of the operating system. For example, to make a server provide the DHCP
service, use the Add Roles and Features wizard. The win_feature module allows you to
automate the addition and removal of roles and features.

The following example shows the win_chocolatey module installing several packages at once,
and specifies a proxy server to use with the proxy_url option.

- name: Install developer packages


win_chocolatey:
name:
- firefox
- git
- jdk8
state: present
proxy_url: http://192.168.0.254:3128

Unlike win_feature, the win_chocolatey module does not support feedback on whether
a reboot is required. However, you can review the output of the command by capturing it with a
registered variable.

202 DO417-RHAE2.8-en-1-20200106
Chapter 5 | Installing and Updating Software

The following example shows how to install a DHCP server using the win_feature module. It
uses a registered variable to trigger the win_reboot module, if a reboot is required.

- name: Install DHCP server


win_feature:
name: DHCP
state: present
include_management_tools: yes
register: dhcp_feature

- name: Reboot if required by DHCP feature


win_reboot:
when: dhcp_feature.reboot_required

When a win_feature task succeeds, further information is available in the


feature_result variable, such as a list of KB articles that apply to the feature. You
can use a registered variable as shown in the preceding example, and then display the
registered_variable.feature_result variable using the debug module.

You can obtain a list of all feature names available on a system by running the Get-
WindowsFeature PowerShell command. Any features that have sub-features are listed in a tree
layout, with the sub-features indented beneath the main feature.

DO417-RHAE2.8-en-1-20200106 203
Chapter 5 | Installing and Updating Software

Figure 5.1: Listing Windows feature names

The following example shows how to install an MSI package using the win_package module. It
uses the creates_path parameter to test whether the package is already installed.

- name: Install Registry Cleaner


win_package:
path: C:\temp\susregclean.msi
state: present
creates_path: C:\Program Files\Suspicious Registry Cleaner

Tasks using win_package can provide any of the creates_[path,service,version]


parameters, to test whether a package is installed.

204 DO417-RHAE2.8-en-1-20200106
Chapter 5 | Installing and Updating Software

Updating Software on Windows Systems


Like software installation, there are several methods for updating software. The installation
modules support updating packages to a newer version, however, they do not handle Windows
updates or hotfixes. Modules to handle hotfixes and Windows updates are listed below.

Software Update Modules

win_updates
This module works with the Windows Update service to automate the download and
installation of Windows updates. You may restrict the available categories from which to install
updates by providing the category_names argument. If required, this module can reboot the
system and continue installing updates, thus avoiding calls to the win_reboot module.

win_hotfix
This module manages the installation of hotfix .msu files. The package can be verified against
the identifier or the KB article, however, a mismatch on either one will prevent installation.

win_reboot
Use this module to control when a reboot occurs. For example, you could use the notify
option in a win_hotfix task to initiate a reboot handler task.

The following example shows the win_updates module. It is configured to only install critical
updates, to reboot the system if required, and to use a scheduled task instead of the become
method to escalate privileges.

- name: Install any critical updates, reboot if required


win_updates:
category_names:
- CriticalUpdates
use_scheduled_task: yes
reboot: yes
reboot_timeout: 600

This example shows the win_hotfix module. This module also supports notification of whether a
reboot is required.

- name: Install hotfix for SAP printing


win_hotfix:
hotfix_kb: KB7654321
source: C:\temp\hotfix.msu
state: present
register: sap_hotfix

- name: Reboot if required for SAP printing hotfix


win_reboot:
when: sap_hotfix.reboot_required

The win_hotfix module can verify a hotfix package against the hotfix identifier, or the hotfix KB
article number. If verification fails, then the installation of the hotfix is aborted.

These primary modules are unlikely to be used on their own in a play. There are many other
modules that perform ancillary tasks, such as restarting services (win_service), unzipping
archives (win_unzip), or making configuration changes in the registry (win_regedit). The
modules that you require will depend on the complexity of the software being installed or updated.

DO417-RHAE2.8-en-1-20200106 205
Chapter 5 | Installing and Updating Software

References
Windows modules — Ansible Documentation
https://docs.ansible.com/ansible/latest/modules/list_of_windows_modules.html

Chocolatey - The Package Manager for Windows


https://chocolatey.org/

206 DO417-RHAE2.8-en-1-20200106
Chapter 5 | Installing and Updating Software

Guided Exercise

Installing and Updating Software


In this exercise, you will use a variety of modules to ensure that software is installed and up to
date on Microsoft Windows-based managed hosts.

Outcomes
You should be able to:

• Generate a GitLab token.

• Clone a Git repository.

• Write two plays in an Ansible Playbook.

• Update Ansible Tower job templates.

• Review installed packages on managed hosts.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. From workstation, access your GitLab instance and review the updates repository.

1.1. From workstation, double-click the GitLab icon on your desktop to access your
GitLab instance.
Log in to GitLab using student as the user name, and RedHat123@! as the
password. Make sure to select LDAP as the authentication method.

1.2. The main page lists the available repositories. Select the updates repository for the
student namespace.

DO417-RHAE2.8-en-1-20200106 207
Chapter 5 | Installing and Updating Software

1.3. This repository contains a top-level updates.yml Ansible Playbook. In this playbook,
you will create two plays: one that manages the updates on your servers, and one that
runs Chocolatey for installing packages.
Click the file to inspect it.

2. Open the Visual Studio Code editor and clone the updates repository to your
workstation.

2.1. From workstation, open the Visual Studio Code editor by double-clicking the icon
on the desktop.

2.2. Open the command palette by navigating to View → Command Palette or by


pressing Ctrl+Shift+P.
Type clone, and then select Git: Clone to clone a repository.

2.3. When prompted, provide a repository URL of https://gitlab.example.com/


student/updates.git and select the Documents folder in the home directory of
the training user as the repository location. This clones the remote repository into
the updates folder on the workstation instance.

208 DO417-RHAE2.8-en-1-20200106
Chapter 5 | Installing and Updating Software

2.4. When prompted to open a project, click Open.

3. In Visual Studio Code, open the updates.yml playbook. Write the first play for managing
updates on your systems, as described in the following steps.

3.1. Update the first play by giving it a name of Manage updates on systems.

- name: Manage updates on systems

3.2. Instruct Ansible to target all hosts by using a value of all for the hosts directive
below the play name.

- name: Manage updates on systems


hosts: all

3.3. To support reusability, create three new variables: log_file, KB, and access_token.
The log_file variable points to a text file that contains the list of available updates.
Use a value of C:\Windows\Temp\ansible_available_updates.txt.
The KB variable contains the knowledge base number of the update that the playbook
installs. Give it a value of KB4465065.
Leave the access_token variable with an empty value. In a later step, you will
generate and pass this access token to the variable in Ansible Tower.

- name: Manage Updates on Systems


hosts: all
vars:
log_file: C:\Windows\Temp\ansible_available_updates.txt
KB: 'KB4465065'
access_token: ""

DO417-RHAE2.8-en-1-20200106 209
Chapter 5 | Installing and Updating Software

3.4. In the tasks section of the play, create the initial task using the win_updates module.
This initial module queries Microsoft update servers to determine if there are available
security updates. However, the task does not install them.
Name this task Microsoft update servers are queried. Use the
win_updates module with the following settings:

• Define category_names for SecurityUpdates to only look for security updates.

• Use a state of searched to search for new updates, but skip installation.

• Save the output to the C:\Windows\Temp\ansible_available_updates.txt


text file by using the log_file variable in the log_path parameter.

The task should look like the following:

...output omitted...
tasks:
- name: Microsoft update servers are queried
win_updates:
category_names: SecurityUpdates
state: searched
log_path: "{{ log_file }}"

3.5. To display the file contents, create a new task using the win_shell module to run the
type command. The type command displays the contents of a file.
Name this task Available security updates are captured,
and use the log_file variable so that the command accesses the
ansible_available_updates.txt file.
Use the register statement to capture the output in the file_output variable. The
content of the variable is displayed in the next step.

Note
Notice the indentation. The register statement and the win_shell module are
both indented by two spaces, beneath the name of the task.

...output omitted...
- name: Available security updates are captured
win_shell: "type {{ log_file }}"
register: file_output

3.6. Create a task that uses the debug module. This module can display a message or
the content of a variable if there are available updates. The module uses the when
statement to parse the file and look for the Adding update string. Name this task
Available updates are displayed.

Note
The when statement is indented at the same level as the debug module.

210 DO417-RHAE2.8-en-1-20200106
Chapter 5 | Installing and Updating Software

...output omitted...
- name: Available security updates are captured
win_shell: "type {{ log_file }}"
register: file_output

- name: Available updates found


debug:
msg: "Available updates found!"
when: "'Adding update' in file_output.stdout"

3.7. The updates Git repository provides an .MSU file, which is an update for your servers.
The file is accessible at https://gitlab.example.com/student/updates/
raw/master/files/KB4465065.msu.
Create a task that uses the win_uri module to retrieve the file and save it to
C:\Windows\Temp\KB4465065.msu. Give it a name of MSU package is
retrieved on hosts.
Since the URL is protected by a password, use the headers parameter to pass the
access token to the request as a header. The force_basic_auth: yes variable
instructs Ansible to add a Basic authentication header to the initial request.
Reuse the KB variable, which contains the name of the file, as the src parameter.

Note
The validate_certs: no statement instructs Ansible to accept insecure
certificates. Since this is a development environment, it is acceptable to skip the
certificate verification, but is not recommended to bypass this verification in
production environments.

...output omitted...
- name: MSU package is retrieved on hosts
win_uri:
url: >
https://gitlab.example.com/student/updates/raw/master/files/{{ KB }}.msu
dest: C:\Windows\Temp\{{ KB }}.msu
validate_certs: no
force_basic_auth: yes
method: GET
headers:
PRIVATE-TOKEN: "{{ access_token }}"

3.8. The next step installs the package that the previous module retrieved. To begin,
create a new task that uses the win_hotfix module. Pass the path of the MSU file
to the module and the KB identifier (reuse the KB variable). The state: present
parameter instructs Ansible to install the package.
Name this task MSU package is installed.

DO417-RHAE2.8-en-1-20200106 211
Chapter 5 | Installing and Updating Software

...output omitted...
- name: MSU package is installed
win_hotfix:
hotfix_kb: "{{ KB }}"
source: C:\Windows\Temp\{{ KB }}.msu
state: present

3.9. Another way to install updates is the usage of the win_updates module. Create a new
task that invokes this module; name this task Security updates are applied.
The module will validate the packages to install, based on a category that is defined by
the category_name and whitelist parameters.
Add the KB4494174 and KB4346084 KB numbers to the whitelist parameter. The
module returns a Boolean in the reboot_required variable that indicates whether or
not the updates require a restart of the server.
Save the output to the updates_status variable.

...output omitted...
- name: Security updates are applied
win_updates:
category_name:
- Updates
whitelist:
- KB4494174
- KB4346084
register: updates_status

3.10.Finally, if the updates require a restart, then add a task that reboots the server. Use
a conditional based on the output of the updates_status.reboot_required
variable.
Name this task Server is rebooted.

...output omitted...
- name: Server is rebooted
win_reboot:
when: updates_status.reboot_required

After completion, the first play should look like the following:

- name: Manage Updates on Systems


hosts: all
vars:
log_file: C:\Windows\Temp\ansible_available_updates.txt
KB: 'KB4465065'
access_token: ""

tasks:
- name: Microsoft update servers are queried
win_updates:
category_names: SecurityUpdates
state: searched

212 DO417-RHAE2.8-en-1-20200106
Chapter 5 | Installing and Updating Software

log_path: "{{ log_file }}"

- name: Available security updates are captured


win_shell: "type {{ log_file }}"
register: file_output

- name: Available updates found


debug:
msg: "Available updates found!"
when: "'Adding update' in file_output.stdout"

- name: MSU package is retrieved on hosts


win_uri:
url: >
https://gitlab.example.com/student/updates/raw/master/files/{{ KB }}.msu
dest: C:\Windows\Temp\{{ KB }}.msu
validate_certs: no
force_basic_auth: true
method: GET
headers:
PRIVATE-TOKEN: "{{ access_token }}"

- name: MSU package is installed


win_hotfix:
hotfix_kb: "{{ KB }}"
source: C:\Windows\Temp\{{ KB }}.msu
state: present

- name: Security updates are applied


win_updates:
category_name:
- Updates
whitelist:
- KB4494174
- KB4346084
register: updates_status

- name: Server is rebooted


win_reboot:
when: updates_status.reboot_required

Note
The completed file is available in the updates.sol file, in the solutions
directory.

4. Save the file before proceeding to the next step.

5. In this second play, you will use Chocolatey to install two packages on the managed hosts.

5.1. Update the second play in the file by giving it a name of Install packages on
systems and targeting all hosts for the play. To do so, add the hosts: all directive.

DO417-RHAE2.8-en-1-20200106 213
Chapter 5 | Installing and Updating Software

Note
Make sure to indent the hosts directive by two spaces.

...output omitted...
- name: Install packages on systems
hosts: all

5.2. Add a vars directive, and create a packages list that contains to two packages to
install:

• Putty
• Wireshark

...output omitted...
- name: Install packages on systems
hosts: all
vars:
packages:
- Putty
- Wireshark

5.3. Create a tasks block below the hosts directive.

...output omitted...
- name: Install packages on systems
hosts: all
vars:
packages:
- Putty
- Wireshark

tasks:

5.4. Create a task that invokes the win_chocolatey module. This module can install
Chocolatey, if not already present.
Name this task Chocolatey is installed.

...output omitted...
tasks:
- name: Chocolatey is installed
win_chocolatey:
name: chocolatey
state: present

5.5. Create a new task that installs the two packages in the packages list. Use the
win_chocolatey module, passing the variable to the module. The pinned
parameter instructs Chocolatey to suppress upgrades for the packages.
Name this task Packages are installed.

214 DO417-RHAE2.8-en-1-20200106
Chapter 5 | Installing and Updating Software

...output omitted...
- name: Packages are installed
win_chocolatey:
name: "{{ packages }}"
state: present
pinned: true
register: install_result

5.6. Finally, add a task to reboot the server, if needed. This task invokes the win_reboot
module and uses the when statement to determine whether to reboot or not, based
on Chocolatey return codes. The return code 3010 indicates that the server requires a
reboot.
Name this task Server is rebooted.

...output omitted...
- name: Server is rebooted
win_reboot:
when: install_result.changed and install_result.rc == 3010

5.7. Save the file.

After completion, the second play should look like the following:

- name: Install packages on systems


hosts: all
vars:
packages:
- Putty
- Wireshark

tasks:
- name: Chocolatey is installed
win_chocolatey:
name: chocolatey
state: present

- name: Packages are installed


win_chocolatey:
name: "{{ packages }}"
state: present
pinned: true
register: install_result

- name: Server is rebooted


win_reboot:
when: install_result.changed and install_result.rc == 3010

Note
The completed file is available in the updates.sol file, in the solutions
directory.

DO417-RHAE2.8-en-1-20200106 215
Chapter 5 | Installing and Updating Software

6. Commit and push your changes.

6.1. From the Visual Studio Code editor, stage the updates.yml playbook. To do so, click
the Source Control icon.
Click the + symbol for the updates.yml file to stage your changes.

6.2. In the commit message field, enter a commit message of Define updates and
Chocolatey tasks, and then click the commit button.

6.3. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to
push your local changes to the remote repository, and retrieve any new changes from
the repository.

7. Create a GitLab access token that Ansible will use to retrieve a file.

7.1. In GitLab, click the icon in the upper right and select Settings to access your account
settings.

7.2. Click Access Tokens. Give the token a name of WindowsUpdates, and then select
api. Access your API as the scope. Click Create personal access token to create
the token.
The action generates a token and displays it in the Your New Personal Access Token
field. Leave this page open for now, in a later step, you will use the token.

216 DO417-RHAE2.8-en-1-20200106
Chapter 5 | Installing and Updating Software

8. Update and run the Run updates project job template in Ansible Tower.

8.1. From workstation, double-click the Ansible Tower icon on your desktop to
access Ansible Tower. Log in to Ansible Tower using admin as the user name and
RedHat123@! as the password.

8.2. Click Templates to access the Run updates project job template.
Click the template to edit it.

8.3. Update the template by selecting updates.yml in the PLAYBOOK field.


In the EXTRA VARIABLES frame, define the access_token variable. To find
this value, view the Chrome page that shows the access token that you created in a
previous step.

---
access_token: cBSC6VAe351E7J3rLz13

Click SAVE to update the job template.

DO417-RHAE2.8-en-1-20200106 217
Chapter 5 | Installing and Updating Software

8.4. Click LAUNCH to launch a job from the job template. Ansible Tower redirects you to
the job output.
Inspect the output as Ansible Tower runs the first play that retrieves the list of available
security updates, installs the MSU package, and install the two KBs. The second play
installs Chocolatey and the two packages. Notice the warning that if Chocolatey is not
present on the system, then Ansible installs it.
Ansible may skip the tasks that reboot the servers, which is expected if a package or an
update is already present.

9. Review the changes on the managed hosts.

9.1. From workstation, open the remote desktop client. Select Show Options to display
extra options. Use a computer name of win1.example.com and a user name of
devops.
When prompted, accept the self-signed certificate, and use RedHat123@! as the
password.

218 DO417-RHAE2.8-en-1-20200106
Chapter 5 | Installing and Updating Software

9.2. Open File Explorer and navigate to C:\Windows\Temp. From the warning that
displays, click Continue to access the protected Temp directory. Open the
ansible_available_updates.txt text file, created by Ansible. This file contains
the list of available security updates.

DO417-RHAE2.8-en-1-20200106 219
Chapter 5 | Installing and Updating Software

9.3. Navigate to Start → Control Panel → Programs → Programs and Features to


list all installed programs.
Select View installed updates on the side of the window to list Windows updates.
Locate the update named KB4465065, which the is the one that Ansible installed.

9.4. Close the RDP session to win1.example.com, and rerun the RDP client. Use a
computer name of win2.example.com and a user name of devops.
When prompted, accept the self-signed certificate, and use RedHat123@! as the
password.

9.5. To ensure that Putty is installed, click the magnifying glass icon and type Putty. The
search returns one result that confirms that Putty has been successfully installed.

Note
If the package is not visible in the search results, then restart the server.

220 DO417-RHAE2.8-en-1-20200106
Chapter 5 | Installing and Updating Software

9.6. Repeat the same steps for the Wireshark package. The search returns one result.

This concludes the guided exercise.

DO417-RHAE2.8-en-1-20200106 221
Chapter 5 | Installing and Updating Software

Editing the Registry

Objectives
After completing this section, you should be able to inspect the Windows Registry and ensure that
registry keys are correctly configured.

Reviewing Windows Registry Terminology


The Windows Registry is a hierarchical database, designed to enforce atomic updates. Atomic
updates ensure that simultaneous updates cannot interfere with each other.

The registry is used to store configuration information for the operating system and most software
packages. Although it is not a requirement that software stores its configuration in the registry,
it is recommended. In the Windows Registry, you can also find information such as service
configuration and start mode, software license state, information specific to the current user and
all users, and configuration and handlers for various file types.

The following lists describes some of the Windows Registry terminology.

Registry Terms

Hive
The registry is physically stored in several files called hives. A hive is used for data that is
related, for example software installed on the local machine.

Key
Keys provide the hierarchy, as a key can contain values or other keys. You can equate keys to
directories in a file system.

Value
A value has a name and a type. The type defines how the data it contains will be interpreted.
The following list describes the possible data types.
• String: a series of characters
• Binary: true or false, yes or no, 1 or 0
• Dword or Qword: 32 or 64 bit values
• Multi-String: a value that may contain data with multiple lines of strings
• Expandable String: the same as a multi-string but can contain variables which are expanded,
such as environment variables like %HOMEPATH%

The registry hives are stored under C:\Windows\System32\Config, assuming that Windows
is installed on the first drive. The files are named for the type of configuration they hold, such as
SOFTWARE, SYSTEM, SAM, SECURITY, and DEFAULT. In the preceding list, SAM is short for the
Security Account Manager, and this hive holds user account information.

222 DO417-RHAE2.8-en-1-20200106
Chapter 5 | Installing and Updating Software

Figure 5.14: Windows Registry hive files

Editing the Windows Registry


As Windows stores most program configuration within the registry, the ability to alter program
configuration likely requires modules that can interact with the registry.

Windows provides the regedit tool for editing the registry. In earlier versions of Windows there
was a tool called regedt32 which was the first 32 bit version, this has now been deprecated and
simply launches regedit instead.

Figure 5.15: Windows Registry editor

Some of the common tasks are to verify that a key exists, or to return the sub-keys and values for
the key, or to return a specific value. The win_reg_stat module is designed for this purpose, and
performs a similar function to the stat module.

Reading Registry Keys and Values


The win_reg_stat module may be used to read and verify the data contained by a registry
value, or to confirm that a registry key exists.

The following example shows the use of win_reg_stat to obtain licensing information. The
registered variable allows any following tasks to be performed conditionally.

DO417-RHAE2.8-en-1-20200106 223
Chapter 5 | Installing and Updating Software

- name: Obtain myapp license information


win_reg_stat:
path: HKLM:\SOFTWARE\MySoft\MyApp\Licensing
name: LicenseType
register: myapp_license_type

Modifying Registry Keys and Values


The win_regedit module may be used to create a key, to add a value, or to edit the data
contained by a value.

Following on from the previous example, the application is registered based on the value stored in
myapp_license_type.

- name: Set myapp registration type


win_regedit:
path: HKLM:\SOFTWARE\MySoft\MyApp\Licensing
name: LicenseType
data: "FULL"
type: string
when: myapp_license_type.value == "EVAL"

- name: Add myapp registration key


win_regedit:
path: HKLM:\SOFTWARE\MySoft\MyApp\Licensing
name: LicenseKey
data: "{{ myapp_key }}"
type: dword
when: myapp_license_type.value == "EVAL"

If there are too many registry values to manage individually, then it may be simpler to export a
registry key from a system in the desired state and then merge it into the registry of other systems.

Using the win_regmerge module


The win_regmerge module may be used to merge a group of keys and values into the registry of
a managed host.

Note
Be aware that files exported using regedit may contain a Byte Order Mark as
the first character. A Byte Order Mark at the start of a file indicates the Unicode
encoding and endianness for the file. This character will need to be deleted to use
the exported file as a template.

This module does not force registry settings to match the exported file. You must delete the
affected key first as shown in the following example.

224 DO417-RHAE2.8-en-1-20200106
Chapter 5 | Installing and Updating Software

- name: Remove myapp licensing key


win_regedit:
path: HKLM:\SOFTWARE\MySoft\MyApp\Licensing
state: absent

- name: Register myapp


win_regmerge:
path: files/myapp-license.reg

References
win_reg_stat – Get information about Windows registry keys — Ansible
Documentation
https://docs.ansible.com/ansible/latest/modules/win_reg_stat_module.html#win-
reg-stat-module

win_regedit – Add, change, or remove registry keys and values — Ansible


Documentation
https://docs.ansible.com/ansible/latest/modules/win_regedit_module.html#win-
regedit-module

win_regmerge – Merges the contents of a registry file into the windows registry
— Ansible Documentation
https://docs.ansible.com/ansible/latest/modules/win_regmerge_module.html#win-
regmerge-module

DO417-RHAE2.8-en-1-20200106 225
Chapter 5 | Installing and Updating Software

Guided Exercise

Editing the Registry


In this exercise, you will determine whether a Windows registry key exists, and ensure that a
specific registry key or keys are set correctly.

Outcomes
You should be able to inspect the Windows Registry and ensure that registry keys are
correctly configured.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

Note
In this exercise, you will configure the Windows Time service to synchronize
to an external time source. Configuring the Windows Time service to
synchronize to an external time source is not usually performed on a machine
that is a domain member. Domain members normally synchronize time to a
Domain Controller automatically, which prevents authentication issues.

1. Connect to win1.example.com to verify the current configuration for the W32Time


service.

1.1. Click Search Windows, search for mstsc, and then open Remote Desktop
Connection.

Note
The Remote Desktop Connection program is also known as the Microsoft Terminal
Services Client (mstsc.exe).

1.2. To connect to the Remote Desktop, enter win1.example.com for the Computer
and devops for the User Name, and RedHat123@! as the password. Note that
devops is a local user, not a domain user, so do not include the EXAMPLE domain in the
username field.
When prompted, access the insecure certificate.

1.3. Click Search Windows, and then type regedit. Open the registry editor. When
prompted, click Yes to open the registry editor.

226 DO417-RHAE2.8-en-1-20200106
Chapter 5 | Installing and Updating Software

1.4. Navigate to the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services


\W32Time key. Note that the Start value is currently 2.
The following table contains the possible values for drivers and services.

Service/Driver Start Values

Value Start Mode Description

0 Boot The device driver is loaded at boot time, and


if no errors occur then it is started during
kernel initialization.

1 System The device driver is started during kernel


initialization, after boot time device drivers.

2 Automatic The service is started automatically by the


Service Control Manager (SCM).

3 Manual The service must be started manually by an


administrator.

4 Disabled The service cannot be started by the SCM


or an administrator.

An administrator can also set a service to Delayed Start using the Services applet,
or by editing the registry.
Verify that the value of Parameters\NtpServer references a 169.254.x.x address,
Parameters\Type is AllSync, Config\AnnounceFlags is 0xa or 10 decimal, and
Config\MaxPosPhaseCorrection is set to the maximum possible value for 32 bits.

1.5. Close the registry editor and disconnect the remote session.

2. Launch the Visual Studio Code editor. If you have not previously cloned the updates
repository, clone it to your workstation instance.

2.1. Click Search Windows, search for code, and then open Visual Studio Code.

2.2. Open the command palette by navigating to View → Command Palette or by


pressing Ctrl+Shift+P.
Type clone, and then select Git: Clone to clone a repository.
Use a repository URL of https://gitlab.example.com/student/
updates.git. When prompted, select the Documents folder in the home directory
of the training user as the repository location, and then click Select Repository
Location. This clones the remote repository into the updates folder.
Click Open from the window that displays after cloning to view the files, then skip the
next step.

3. Open the c:\Users\student\Documents\updates directory by navigating to File →


Open Folder, and then select the C:\Users\student\Documents\updates folder.

4. Open the time.yml playbook, and then complete the tasks in the file. Note the variable
time_key has been set for you.

DO417-RHAE2.8-en-1-20200106 227
Chapter 5 | Installing and Updating Software

4.1. Modify the task named Configure time server type to set the server type to
NTP. This modifies the Parameters\Type value in the W32Time key.

- name: Configure time server type


win_regedit:
path: '{{ time_key }}\Parameters'
name: Type
data: NTP
type: string
notify: Restart windows time service

4.2. Modify the task named Configure AnnounceFlags to set the value to 5. This
modifies the Config\AnnounceFlags value in the W32Time key.

- name: Configure AnnounceFlags


win_regedit:
path: '{{ time_key }}\Config'
name: AnnounceFlags
data: 5
type: dword
notify: Restart windows time service

4.3. Modify the task named Enable NTP time provider to enable the NTP provider.
This modifies the TimeProviders\NtpServer\Enabled value in the W32Time key.

- name: Enable NTP time provider


win_regedit:
path: '{{ time_key }}\TimeProviders\NtpServer'
name: Enabled
data: 1
type: dword
notify: Restart windows time service

4.4. Modify the task named Configure upstream servers to set


0.rhel.pool.ntp.org as the upstream NTP server. This modifies the Parameters
\NtpServer value in the W32Time key.

- name: Configure upstream servers


win_regedit:
path: '{{ time_key }}\Parameters'
name: NtpServer
data: 0.rhel.pool.ntp.org,0x1
type: string
notify: Restart windows time service

4.5. Modify the tasks named Configure positive time correction and
Configure negative time correction to set the maximum time correction to
3600 seconds. This modifies the Config\MaxPosPhaseCorrection and Config
\MaxPosPhaseCorrection values in the W32Time key.

228 DO417-RHAE2.8-en-1-20200106
Chapter 5 | Installing and Updating Software

- name: Configure positive time correction


win_regedit:
path: '{{ time_key }}\Config'
name: MaxPosPhaseCorrection
data: 3600
type: dword
notify: Restart windows time service

- name: Configure negative time correction


win_regedit:
path: '{{ time_key }}\Config'
name: MaxNegPhaseCorrection
data: 3600
type: dword
notify: Restart windows time service

5. Save and commit the changes to your local Git repository, and then push them to the
remote repository.

5.1. Click File → Save or press Ctrl+S to save the file.

5.2. Navigate to the Source Control pane, and then click + for the time.yml file to stage
the changes.

5.3. Enter a brief commit message, and then press Ctrl+Enter to commit the changes.

5.4. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to
push your local changes to the remote repository, and retrieve any new changes from
the repository.

6. From workstation, access your Ansible Tower instance available at http://


tower.example.com. Connect as the student user and RedHat123@! as the password.

7. Test your playbook by using the Run updates project job template.

7.1. In the navigation pane, click Templates.

7.2. Click the Run updates project job template to edit it.

7.3. Select the time.yml playbook from the PLAYBOOK list.

7.4. Click SAVE to update the template, and then click LAUNCH to run the job.

8. Once all tasks have completed, verify that the STATUS in the DETAILS section shows
Successful. If the job is not successful, compare your playbook with the solutions/
time.sol solution file in the updates Git repository.

9. Connect to the win1.example.com managed host and verify the changes to the
W32Time service.

9.1. Click Search Windows, search for mstsc, and then open the Remote Desktop
Connection.

DO417-RHAE2.8-en-1-20200106 229
Chapter 5 | Installing and Updating Software

9.2. Enter win1.example.com for the Computer and devops for User Name, and
RedHat123@! as the password. Note that devops is a local user, not a domain user, so
do not include the EXAMPLE domain.

9.3. Launch the registry editor then navigate to the W32Time key. Note that the values
viewed at the start of the exercise have changed, as a result of the tasks in the
time.yml playbook file. Close the registry editor.

9.4. Click Search Windows, search for cmd, and then open the command shell.

9.5. Run the W32tm /query /peers command to view time synchronization status.

C:\Users\devops>W32tm /query /peers


##Peers: 2

Peer: windc.example.com
State: Active
Time Remaining: 28.3535922s
Mode: 1 (Symmetric Active)
Stratum: 3 (secondary reference - syncd by (S)NTP)
PeerPoll Interval: 17 (out of valid range)
HostPoll Interval: 6 (64s)

Peer: 0.rhel.pool.ntp.org,0x1
State: Active
Time Remaining: 748.3535922s
Mode: 1 (Symmetric Active)
Stratum: 3 (secondary reference - syncd by (S)NTP)
PeerPoll Interval: 17 (out of valid range)
HostPoll Interval: 6 (64s)

9.6. Exit the command shell, and then disconnect from win1.example.com

10. Switch back to the Ansible Tower web UI. Revert your changes by updating the Run
updates project job template.

Note
This step is required to prevent possible authentication issues in future exercises.

10.1. In the navigation pane, click Templates.

10.2.Click the Run updates project job template to edit it.

10.3.Select the revert_time.yml playbook from the PLAYBOOK list.

10.4.Click SAVE to update the template, and then click LAUNCH to run the job.

This concludes the guided exercise.

230 DO417-RHAE2.8-en-1-20200106
Chapter 5 | Installing and Updating Software

Lab

Installing and Updating Software


Performance Checklist
In this lab, you will ensure that specific software packages are installed and up to date, and
that specific registry keys are configured.

Outcomes
You should be able to:

• Write an Ansible Playbook that installs Chocolatey packages and merges data into the
Windows registry.

• Generate a GitLab API access token.

• Pass Ansible Tower variables to playbooks.

• Access the Windows registry to review changes.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. From the Windows workstation, open the Visual Studio Code editor and clone
the updates repository, available at https://gitlab.example.com/student/
updates.git, to C:\Users\student\Documents\updates if the folder is not already
present.
2. Add the updates folder to Visual Studio Code workspace, and make the following changes
to the review.yml playbook:

• Define the package_name variable with a value of Atom. This is the name of the
Chocolatey package for installing the Atom text editor.

• Define the package_url variable with a value of https://chocolatey.org/api/v2/


package/Atom/1.39.1. This URL specifies the location of the Atom source package in
version 1.39.1

• Define the package_local_path variable with a value of C:\Windows\Temp


\atom.nupkg. This path specifies where to save the package file.

• Create a task that retrieves the Atom source package, as defined by the package_url
variable. Use the package_local_path for the path where the package is saved.

Give the task a name of Atom package is retrieved on managed hosts.

DO417-RHAE2.8-en-1-20200106 231
Chapter 5 | Installing and Updating Software

• Create a task that invokes the win_chocolatey module to install the Atom package.
Configure the task so that it uses the package_name variable as the name of the package
to install, and package_local_path as the package location.

Name the task Atom is installed from a local source.

• Create a task that uses the win_uri module to retrieve the RedHatTraining.reg
registry file, available at https://gitlab.example.com/student/updates/
blob/master/files/RedHatTraining.reg. Name the task Registry file is
retrieved.

Since the URL is protected by a password, use the headers parameter to pass the
PRIVATE-TOKEN header with the access_token Ansible variable. In a later step, you will
generate this token.

Save the file to C:\Windows\Temp\RedHatTraining.reg.

• Create a task that invokes the win_regmerge module to update the registry by merging
the values specified in the registry file.

Give the task a name of Registry is updated.

Note
The completed file is available at solutions/review.sol in the updates folder.

3. Save your changes, and then commit the file with the Configure Atom on managed
hosts message.
Push your changes to the master branch of the updates repository.
4. Access your GitLab instance at https://gitlab.example.com, and then log in using
student and RedHat123@! as the password.
Generate a token for student that has API access. Name the token UpdatesReview.
5. From your workstation, access Ansible Tower at https://tower.example.com. Log in
using admin as the user name and RedHat123@! as the password.
Update the Run updates project job template as follows:

• Select review.yml as the playbook.

• Limit the play to win1.example.com.

• Pass the access_token as an extra variable. Give it the value of the GitLab token that
you generated during the previous step.
6. Run the Run updates project job template and ensure that is runs successfully.
7. From workstation, open your RDP client and connect to win1.example.com using
devops as the user name and RedHat123@! as the password. When prompted, accept the
insecure certificate.
Ensure that Atom is installed. You can look for the desktop icon.
Access the registry to ensure that the RedHat key is available in HKCU:\Software.

This concludes the lab.

232 DO417-RHAE2.8-en-1-20200106
Chapter 5 | Installing and Updating Software

Solution

Installing and Updating Software


Performance Checklist
In this lab, you will ensure that specific software packages are installed and up to date, and
that specific registry keys are configured.

Outcomes
You should be able to:

• Write an Ansible Playbook that installs Chocolatey packages and merges data into the
Windows registry.

• Generate a GitLab API access token.

• Pass Ansible Tower variables to playbooks.

• Access the Windows registry to review changes.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. From the Windows workstation, open the Visual Studio Code editor and clone
the updates repository, available at https://gitlab.example.com/student/
updates.git, to C:\Users\student\Documents\updates if the folder is not already
present.

Note
The following steps describe how to clone the updates repository. If you already
cloned the repository in a previous step, you can skip these steps.

1.1. From the Windows workstation, open Visual Studio Code by double-clicking the
desktop.

1.2. To clone the updates repository, open the command palette by navigating to View →
Command Palette or by pressing Ctrl+Shift+P.
Type clone and select Git: Clone to clone a repository.
Use a repository URL of https://gitlab.example.com/student/updates.git.
When prompted, select the Documents folder in the home directory of the training
user as the repository location. This clones the remote repository into the updates
folder.

DO417-RHAE2.8-en-1-20200106 233
Chapter 5 | Installing and Updating Software

Click Open from the window that displays after cloning.

2. Add the updates folder to Visual Studio Code workspace, and make the following changes
to the review.yml playbook:

• Define the package_name variable with a value of Atom. This is the name of the
Chocolatey package for installing the Atom text editor.

• Define the package_url variable with a value of https://chocolatey.org/api/v2/


package/Atom/1.39.1. This URL specifies the location of the Atom source package in
version 1.39.1

• Define the package_local_path variable with a value of C:\Windows\Temp


\atom.nupkg. This path specifies where to save the package file.

• Create a task that retrieves the Atom source package, as defined by the package_url
variable. Use the package_local_path for the path where the package is saved.

Give the task a name of Atom package is retrieved on managed hosts.

• Create a task that invokes the win_chocolatey module to install the Atom package.
Configure the task so that it uses the package_name variable as the name of the package
to install, and package_local_path as the package location.

Name the task Atom is installed from a local source.

• Create a task that uses the win_uri module to retrieve the RedHatTraining.reg
registry file, available at https://gitlab.example.com/student/updates/
blob/master/files/RedHatTraining.reg. Name the task Registry file is
retrieved.

Since the URL is protected by a password, use the headers parameter to pass the
PRIVATE-TOKEN header with the access_token Ansible variable. In a later step, you will
generate this token.

Save the file to C:\Windows\Temp\RedHatTraining.reg.

• Create a task that invokes the win_regmerge module to update the registry by merging
the values specified in the registry file.

Give the task a name of Registry is updated.

2.1. In Visual Studio Code, open the review.yml playbook and make the following changes:

1. Define the package_name variable with a value of Atom, as follows:

---
- name: Install Atom using Chocolatey and update the registry
hosts: all
vars:
package_name: Atom
...output omitted...

2. Define the package_url variable with a value of https://chocolatey.org/


api/v2/package/Atom/1.39.1. This URL specifies the location of the Atom
.nupkg source package.

234 DO417-RHAE2.8-en-1-20200106
Chapter 5 | Installing and Updating Software

---
- name: Install Atom using Chocolatey and update the registry
hosts: all
vars:
package_name: Atom
package_url: https://chocolatey.org/api/v2/package/Atom/1.39.1
...output omitted...

3. Define the package_local_path variable with a value of C:\Windows\Temp


\atom.nupkg. This path specifies where to save the file.

---
- name: Install Atom using Chocolatey and update the registry
hosts: all
vars:
package_name: Atom
package_url: https://chocolatey.org/api/v2/package/Atom/1.39.1
package_local_path: C:\Windows\Temp\atom.nupkg
...output omitted...

4. Create a task that retrieves the Atom source package, as defined by the
package_url variable, using the win_uri module. Save the package to the path
defined by the package_local_path variable.
Give the task a name of Atom package is retrieved on managed hosts.

---
- name: Install Atom using Chocolatey and update the registry
hosts: all
vars:
package_name: Atom
package_url: https://chocolatey.org/api/v2/package/Atom/1.39.1

DO417-RHAE2.8-en-1-20200106 235
Chapter 5 | Installing and Updating Software

package_local_path: C:\Windows\Temp\atom.nupkg

tasks:
- name: Atom package is retrieved on managed hosts
win_uri:
url: "{{ package_url }}"
dest: "{{ package_local_path }}"
method: GET

5. Create a task that invokes the win_chocolatey module to install the Atom
package, from the file that you retrieved. Name the task Atom is installed
from a local source.
Configure the task so that it uses the package_name variable as the name of
the package to install, and the package_local_path variable as the package
location.

Note
If you need to reinstall the package, pass the force: yes parameter to the
win_chocolatey module.

The playbook should look like the following:

---
- name: Install Atom using Chocolatey and update the registry
hosts: all
vars:
package_name: Atom
package_url: https://chocolatey.org/api/v2/package/Atom/1.39.1
package_local_path: C:\Windows\Temp\atom.nupkg

tasks:
- name: Atom package is retrieved on managed hosts
win_uri:
url: "{{ package_url }}"
dest: "{{ package_local_path }}"
method: GET

- name: Atom is installed from a local source


win_chocolatey:
name: "{{ package_name }}"
source: "{{ package_local_path }}"
state: present

6. Create a task that uses the win_uri module to retrieve the


RedHatTraining.reg registry file, available at https://

236 DO417-RHAE2.8-en-1-20200106
Chapter 5 | Installing and Updating Software

gitlab.example.com/student/updates/blob/master/files/
RedHatTraining.reg. Name the task Registry file is retrieved.
Since the URL is protected by a password, use the headers parameter to pass the
PRIVATE-TOKEN header with the access_token Ansible variable. In a later step,
you will generate this token.
Save the file to C:\Windows\Temp\RedHatTraining.reg.

Note
Notice the extra indentation of the header data.

...output omitted...
- name: Registry file is retrieved
win_uri:
url: >
https://gitlab.example.com/student/updates/blob/master/files/
RedHatTraining.reg
dest: C:\Windows\Temp\RedHatTraining.reg
validate_certs: no
force_basic_auth: yes
method: GET
headers:
PRIVATE-TOKEN: "{{ access_token }}"

7. Create a task that invokes the win_regmerge module to update the registry, by
merging the values specified in the registry file.
Give the task a name of Registry is updated.
The task should look like the following:

...output omitted...
- name: Registry file is retrieved
win_uri:
url: >
https://gitlab.example.com/student/updates/blob/master/files/
RedHatTraining.reg
dest: C:\Windows\Temp\RedHatTraining.reg
validate_certs: no
force_basic_auth: yes
method: GET

DO417-RHAE2.8-en-1-20200106 237
Chapter 5 | Installing and Updating Software

headers:
PRIVATE-TOKEN: "{{ access_token }}"

- name: Registry is updated


win_regmerge:
path: C:\Windows\Temp\RedHatTraining.reg

The final playbook should look like the following:

---
- name: Install Atom using Chocolatey and update the registry
hosts: all
vars:
package_name: Atom
package_url: https://chocolatey.org/api/v2/package/Atom/1.39.1
package_local_path: C:\Windows\Temp\atom.nupkg

tasks:
- name: Atom package is retrieved on managed hosts
win_uri:
url: "{{ package_url }}"
dest: "{{ package_local_path }}"
method: GET

- name: Atom is installed


win_chocolatey:
name: "{{ package_name }}"
source: "{{ package_local_path }}"
state: present

- name: Registry file is retrieved


win_uri:
url: >
https://gitlab.example.com/student/updates/raw/master/files/
RedHatTraining.reg
dest: C:\Windows\Temp\RedHatTraining.reg
validate_certs: no
force_basic_auth: yes
method: GET
headers:
PRIVATE-TOKEN: "{{ access_token }}"

- name: Registry is updated


win_regmerge:
path: C:\Windows\Temp\RedHatTraining.reg

Note
The completed file is available at solutions/review.sol in the updates folder.

3. Save your changes, and then commit the file with the Configure Atom on managed
hosts message.
Push your changes to the master branch of the updates repository.

238 DO417-RHAE2.8-en-1-20200106
Chapter 5 | Installing and Updating Software

3.1. From Visual Studio Code, save the file and stage it. Access the Source Control panel
and click + next to review.yml to stage your changes.

3.2. In the commit message field, type Configure Atom on managed hosts and click
the Commit button, or press Ctrl+Enter to commit your changes.

3.3. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to push
your local changes to the remote repository, and retrieve any new changes from the
repository.

4. Access your GitLab instance at https://gitlab.example.com, and then log in using


student and RedHat123@! as the password.
Generate a token for student that has API access. Name the token UpdatesReview.

4.1. From workstation, double-click the GitLab desktop icon. Log in to GitLab using
student as the user name and RedHat123@! as the password. Make sure that the
LDAP tab is selected.

4.2. To generate an API token, click the icon on the upper-right corner and click Settings to
access the user settings.

DO417-RHAE2.8-en-1-20200106 239
Chapter 5 | Installing and Updating Software

4.3. Click the Access Tokens entry from the side bar. Create a token according to the
following information.

• Name: UpdatesReview

• Scopes: API

Click Create personal access token to generate the token.

Do not close the page. In the next step, you will use the token.

5. From your workstation, access Ansible Tower at https://tower.example.com. Log in


using admin as the user name and RedHat123@! as the password.
Update the Run updates project job template as follows:

• Select review.yml as the playbook.

• Limit the play to win1.example.com.

• Pass the access_token as an extra variable. Give it the value of the GitLab token that
you generated during the previous step.

5.1. From workstation, double-click the Ansible Tower desktop icon. Log in to Ansible
Tower using admin as the user name and RedHat123@! as the password.

5.2. Click Templates to access Ansible Tower job templates.

240 DO417-RHAE2.8-en-1-20200106
Chapter 5 | Installing and Updating Software

Select the Run updates project to edit.

5.3. Update the job template by selecting review.yml as the Ansible Playbook. In the
LIMIT field, enter win1.example.com. Finally, in the EXTRA VARIABLES field, add
the access_token whose value is the GitLab token that you created in the previous
step.

---
access_token: "juU8gSuEHgczFy7DCNza"

5.4. Click SAVE to update the job template.

6. Run the Run updates project job template and ensure that is runs successfully.

6.1. Click LAUNCH to launch a job from the job template.

6.2. This action redirects you to the job output. Notice the output of the different tasks as
they execute. Ansible retrieves the Atom package and installs it, and then retrieves the
registry file before merging it.

DO417-RHAE2.8-en-1-20200106 241
Chapter 5 | Installing and Updating Software

7. From workstation, open your RDP client and connect to win1.example.com using
devops as the user name and RedHat123@! as the password. When prompted, accept the
insecure certificate.
Ensure that Atom is installed. You can look for the desktop icon.
Access the registry to ensure that the RedHat key is available in HKCU:\Software.

7.1. From workstation, open the remote desktop client. Select Show Options to display
extra options. Use a computer name of win1.example.com and a user name of
devops. When prompted, accept the self-signed certificate, and use RedHat123@! as
the password.

242 DO417-RHAE2.8-en-1-20200106
Chapter 5 | Installing and Updating Software

7.2. To ensure that Atom is installed, locate the desktop icon. You can also run the choco
list --local-only PowerShell command.

DO417-RHAE2.8-en-1-20200106 243
Chapter 5 | Installing and Updating Software

Note
If you did not complete the previous activities in the chapter, your output may be
different.

7.3. Click the magnifying glass icon and type Registry Editor to access the registry.
When prompted, click Yes to allow the editor to make changes.

7.4. Navigate to Computer → HKEY_CURRENT_USER → Software.


Ensure that there is a RedHat key with a Training sub-key. Click it to review its values.

This concludes the lab.

244 DO417-RHAE2.8-en-1-20200106
Chapter 5 | Installing and Updating Software

Summary
In this chapter, you learned:

• Ansible provides various modules to support software installation, including win_package,


win_chocolatey, and win_feature.

• You can run the Get-WindowsFeature PowerShell command to obtain a list of all feature
names that are available on a system.

• You can use the win_updates, win_hotfix, and win_reboot Ansible modules to update
your systems.

• You can use the win_regedit, win_reg_stat, and win_regmerge Ansible modules to
manage the Windows registry.

DO417-RHAE2.8-en-1-20200106 245
246 DO417-RHAE2.8-en-1-20200106
Chapter 6

Implementing Task Control


Goal Manage task execution using loops, conditional
tests, and handlers, and recover when tasks fail.

Objectives • Write plays efficiently using loops, and use


conditions to control when tasks run.
• Implement tasks that run only when another
task makes a change on the managed host.
• Control what happens when a task fails, recover
from task failure, and control what conditions
cause a task to report failure.

Sections • Writing Loops and Conditional Tasks (and


Guided Exercise)
• Implementing Handlers (and Guided Exercise)
• Handling Task Failure (and Guided Exercise)

Lab Implementing Task Control

DO417-RHAE2.8-en-1-20200106 247
Chapter 6 | Implementing Task Control

Writing Loops and Conditional Tasks

Objectives
After completing this section, you should be able to write plays efficiently using loops, and use
conditions to control when tasks run.

Iterating over Tasks with Loops


Repeating tasks multiple times using loops saves you time when you write multiple tasks which
perform actions that use the same module. For example, instead of writing five tasks to ensure
that five users have been created, you can write one task that iterates over a list of five users to
ensure that each has been created in turn.

Ansible supports iterating a task over a set of items using the loop keyword. You can configure
Ansible loops to repeat a task using:

• Items in a list.
• The content of each file in a list.
• A generated sequence of numbers.
• More complex structures.

This section covers simple loops that iterate over a list of items. For more advanced looping
scenarios consult the Loops — Ansible Documentation link listed in the references section.

Introducing Simple Loops


A simple loop iterates a task over a list of items. Use the loop keyword in a task, and pass the list
of items over which the task should iterate to the loop. The item loop variable holds the current
value during each iteration.

Consider the following snippet that invokes the win_chocolatey module three times to install a
set of software packages using Chocolatey:

- name: Install JRE 8


win_chocolatey:
name: jre8
state: present

- name: Install Java Runtime


win_chocolatey:
name: javaruntime-preventasktoolbar
state: present

- name: Install Dropbox


win_chocolatey:
name: dropbox
state: present

248 DO417-RHAE2.8-en-1-20200106
Chapter 6 | Implementing Task Control

You can rewrite these three tasks using a loop in a single task. The loop iterates over the three
packages:

- name: Install packages


win_chocolatey:
name: "{{ item }}"
state: present
loop:
- jre8
- javaruntime-preventasktoolbar
- dropbox

You can also define a variable for the list and pass it to the loop. In the following example, the
packages variable contains the list of packages to install:

vars:
packages:
- jre8
- javaruntime-preventasktoolbar
- dropbox
tasks:
- name: Installing Java and Dropbox
win_chocolatey:
name: "{{ item }}"
state: present
loop: "{{ packages }}"

Iterating with Hashes and Dictionaries


The items in the loop's list do not need to be simple values such as strings or integers. Each item
can be a hash or a dictionary that contains two or more keys.

In the following example, each item in the list is a dictionary, and each dictionary defines three
keys: name, description, and groups. You can retrieve each key in the current item variable by
using the item.name, item.desc, and item.grp variables, respectively.

- name: Creating local users


win_user:
name: "{{ item.name }}"
groups: "{{ item.grp }}"
description: "{{ item.desc }}"
state: present
loop:
- { name: 'itadmin', grp: 'Administrators', desc: 'New admin user' }
- { name: 'ituser1', grp: 'Users', desc: 'local user' }
- { name: 'ituser2', grp: 'Users', desc: 'local user' }

You can rewrite the dictionary using the YAML format as the following:

- name: Creating local users


win_user:
name: "{{ item.name }}"
groups: "{{ item.grp }}"

DO417-RHAE2.8-en-1-20200106 249
Chapter 6 | Implementing Task Control

description: "{{ item.desc }}"


state: present
loop:
- name: itadmin
grp: Administrators
desc: New admin user
- name: ituser1
grp: Users
desc: local user
- name: ituser2
grp: Users
desc: local user

The task ensures that the itadmin user is present with a description of New admin user and
is a member of the Administrators group. It also ensures that ituser1 and ituser2 are
present and are members of the Users group.

Iterating Using Earlier Ansible Syntax


Prior to Ansible 2.5, most playbooks used a different syntax for loops. Multiple keywords were
provided, which were prefixed with with_ followed by the name of an Ansible lookup plug-in (an
advanced feature not covered in detail in this course). Although the syntax is very common in
existing playbooks, it might be deprecated at some point in the future.

Examples of Earlier Looping Syntax

Keyword Description

with_items Behaves the same as the loop keyword for simple lists such as a list of
strings or a list of dictionaries. Unlike loops, if you use nested lists with
with_items, Ansible will flatten them into a single-level list. The item
loop variable holds the current list item used during each iteration.

with_file This keyword requires a list of files. The item loop variable holds the
content of a corresponding file from the file list during each iteration.

with_sequence Instead of requiring a list, this keyword requires parameters to generate a


list of values based on a numeric sequence. The item loop variable holds
the value of one of the items that are generated in the sequence during
each iteration.

The following example illustrates how to use the with_items keyword.

vars:
packages:
- jre8
- javaruntime-preventasktoolbar
- dropbox
tasks:
- name: Installing Java and Dropbox
win_chocolatey:
name: "{{ item }}"
state: present
with_items: "{{ packages }}"

250 DO417-RHAE2.8-en-1-20200106
Chapter 6 | Implementing Task Control

Important
Since Ansible 2.5, the recommended way to write loops is to use the loop keyword.

However, you should still understand the earlier syntax, especially with_items,
because it is widely used in existing playbooks. You are likely to encounter playbooks
and roles that continue to use with_ keywords for looping.

You can convert any task that uses the earlier syntax to use the loop keyword in conjunction with
Ansible filters. You do not need to know how to use Ansible filters to do this. For more information
on how to convert loops to the new syntax and how to loop over items that are not simple lists,
consult the Migrating from with_X to loop — Ansible Documentation page listed in the references
section.

Note
Advanced looping techniques are beyond the scope of this course. You can
implement all iteration tasks in this course with either the with_items or the loop
keyword.

Displaying Captured Output with Register Variables


and Loops
You can use the register keyword to capture the output of a task that loops. The following
example illustrates the structure of the register variable from a task that contains a loop.

---
- name: Loop register test
hosts: windows
tasks:
- name: Executing commands and registering output in the variable "output"
win_shell: "{{ item }}"
loop:
- whoami
- hostname
register: output

- name: showing the results from output variable


debug:
var: output

Saves the output of each iteration to the output variable.


Displays the content of the output variable to the output.

This is an example of output from the play:

PLAY [testing] *************************************************************

TASK [Gathering Facts] *****************************************************


ok: [winhost1]

TASK [Executing commands and registering output in the variable "output"] **

DO417-RHAE2.8-en-1-20200106 251
Chapter 6 | Implementing Task Control

changed: [winhost1] => (item=whoami)


changed: [winhost1] => (item=hostname)

TASK [showing the results from output variable] ****************************


ok: [winhost1] => {
"output": {
"changed": true,
"msg": "All items completed",
"results": [
{
"ansible_loop_var": "item",
"changed": true,
"cmd": "whoami",
"delta": "0:00:00.343753",
"end": "2019-08-16 04:48:23.980221",
"failed": false,
"item": "whoami",
"rc": 0,
"start": "2019-08-16 04:48:23.636468",
"stderr": "",
"stderr_lines": [],
"stdout": "ec2amaz-c5f1v2p\\administrator\r\n",
"stdout_lines": [
"ec2amaz-c5f1v2p\\administrator"
]
},
{
"ansible_loop_var": "item",
"changed": true,
"cmd": "hostname",
"delta": "0:00:00.328126",
"end": "2019-08-16 04:48:27.089488",
"failed": false,
"item": "hostname",
"rc": 0,
"start": "2019-08-16 04:48:26.761361",
"stderr": "",
"stderr_lines": [],
"stdout": "EC2AMAZ-C5F1V2P\r\n",
"stdout_lines": [
"EC2AMAZ-C5F1V2P"
]
}
]
}
}

PLAY RECAP ****************************************************************


winhost1 : ok=3 changed=1 unreachable=0 failed=0 skipped=0
rescued=0 ignored=0

The output variable is a dictionary of three keys, each of which has a value: changed, msg,
and results. (Ansible does not use a list here because order of those keys is unimportant.)
The results key contains the results of the task. For this loop, the result is a list of
dictionaries. Lists are enclosed in brackets '[ ]', and dictionaries are enclosed in braces '{ }'.

252 DO417-RHAE2.8-en-1-20200106
Chapter 6 | Implementing Task Control

Each list item is a dictionary of key-value pairs for each item in the loop, in order. Both list
items and key-value pairs are separated by commas.
Marks the beginning of the task metadata for the first item. The metadata consists of a set
of key-value pairs, and the item key has as its value the item from the list. The output of the
whoami and hostname commands is stored in the stdout key.
The start of task result metadata for the second item.
The closing square bracket (]) character indicates the end of the output list.

In the previous example, the results key contains a list. In the following example, the playbook is
modified such that the second task iterates over a list.

- name: Loop Register Test


hosts: winhost1
tasks:

- name: Executing commands and registering output in the variable "output"


win_shell: "{{ item }}"
loop:
- whoami
- hostname
register: output

- name: showing the results from output variable


debug:
msg: "STDOUT from previous task: {{ item.stdout }}"
loop: "{{ output.results }}"

Output from this play might appear as follows:

PLAY [testing] *************************************************************

TASK [Gathering Facts] *****************************************************


ok: [winhost1]

TASK [Executing commands and registering output in the variable "output"] **


changed: [winhost1] => (item=whoami)
changed: [winhost1] => (item=hostname)

TASK [showing the results from output variable] ****************************


ok: [winhost1] => (item=...output omitted...}) => {
"msg": "STDOUT from previous task: ec2amaz-c5f1v2p\\administrator\r\n"
}
ok: [winhost1] => (item={...output omitted...}) => {
"msg": "STDOUT from previous task: EC2AMAZ-C5F1V2P\r\n"
}

PLAY RECAP *****************************************************************


winhost1 : ok=3 changed=1 unreachable=0 failed=0
skipped=0 rescued=0 ignored=0

DO417-RHAE2.8-en-1-20200106 253
Chapter 6 | Implementing Task Control

Running Tasks Conditionally


Ansible can use conditionals to execute tasks when certain conditions are met. For example, you
can define a conditional to determine the available memory on a managed host before Ansible
installs or configures a service.

Conditionals allow you to differentiate between managed hosts and assign them functional roles
based on the conditions that they meet. Playbook variables, registered variables, and Ansible facts
or custom facts can all be tested with conditionals. You can use operators such as greater than (>)
or less than (<) to compare strings, numerical data, or Boolean values.

The following scenarios illustrate the use of conditionals in Ansible:

• Define a hard limit in a variable (for example, min_memory for the minimum amount of memory
that is required) and compare it against the available memory on a managed host.

• Capture the output of a command and evaluate it to determine whether to take further action.
For example, you can instruct Ansible to copy an index.html file only if the IIS web server is
properly installed and configured.

• Use Ansible facts to determine the managed host network configuration and decide which
template file to send.

• Compare a registered variable with a predefined variable to determine if a service changed. For
example, test the MD5 checksum of a service configuration file to see if the service changed.

Writing Conditional Tasks


Use the when statement to run a task conditionally. It takes as a value the condition to test. If the
condition that you define is met, the task runs, otherwise, Ansible skips the task.

A simple condition that you can test is whether a Boolean variable equals true or false. The
when statement in the following example causes the first task to run only if run_my_task equals
true. In the second task, the system only restarts if the win_feature.reboot_required
variable is equal to true.

- name: Simple Boolean Task Demo


hosts: winhost1
vars:
run_my_task: true
tasks:
- name: Install IIS Web-Server with sub features and management tools
win_feature:
name: Web-Server
state: present
include_sub_features: yes
include_management_tools: yes
when: run_my_task
register: feature_output

- name: Reboot if installing Web-Server feature requires it


win_reboot:
when: feature_output.reboot_required

254 DO417-RHAE2.8-en-1-20200106
Chapter 6 | Implementing Task Control

The following example is a bit more sophisticated, and tests whether the my_service variable
has a value. If it does, Ansible uses the value of my_service variable as the package to install. If
the my_service variable is not defined, Ansible skips the task.

- name: Checking if the variable is defined


hosts: winhost1
vars:
my_service: Web-Server
tasks:
- name: Install "{{ my_service }}" with sub features and management tools if
my_service is defined
win_feature:
name: "{{ my_service }}"
state: present
include_sub_features: yes
include_management_tools: yes
when: my_service is defined

Constructing Conditions with Ansible Operators


The following table describes some operations that you can use when working with conditionals:

Examples of Using Ansible Operators

Operation Example

Is equal to (with a string) ansible_facts['architecture'] == "64-bit"

Is equal to (with a numerical max_memory == 1024


value)

Is greater than ansible_facts['powershell_version'] > 2

Is less than ansible_facts['powershell_version'] < 6

Is greater than or equal to ansible_facts['processor_vcpus'] >= 2

Is less than or equal to ansible_facts['processor_vcpus'] <= 20

Is not equal to ansible_facts['memtotal_mb'] != 4000

Variable exists my_service is defined

Variable does not exist my_service is not defined

A Boolean variable on reboot_required


its own is implicitly a test
for whether it is true. The
values of 1, True, or yes
are evaluated as true. The
values of 0, False, or no
are evaluated as false.

Boolean variable is false not reboot_required

DO417-RHAE2.8-en-1-20200106 255
Chapter 6 | Implementing Task Control

Operation Example

First variable's value is ansible_facts['distribution'] in


present as a value in second supported_distros
variable's list.

The last entry in the preceding table might be confusing at first. The following example illustrates
how it works.

In the following example, the ansible_facts['distribution'] variable is a fact which


is determined during the gathering facts phase, and identifies the managed host's operating
system distribution (for Linux) or variant (for Microsoft Windows). The supported_distros
variable contains a list of operating system distributions that the playbook supports. If the value of
ansible_facts['distribution'] is in the supported_distros list, the conditional passes
and the task runs.

- name: Testing a condition


hosts: winhost1
vars:
my_service: Web-Server
supported_distros:
- "Microsoft Windows Server 2016 Datacenter"
- "Microsoft Windows Server 2016 Core"
- "Microsoft Windows Server 2012 Datacenter"
- "Microsoft Windows Server 2012 Core"
tasks:
- name: Install "{{ my_service }}" with sub features and management tools
win_feature:
name: "{{ my_service }}"
state: present
include_sub_features: yes
include_management_tools: yes
when: ansible_facts['distribution'] in supported_distros

Important
Notice the indentation of the when statement. Because the statement is not a
module variable, you must place it outside the module by indenting it at the top-
level of the task.

A task is a YAML hash or dictionary, and the when statement is simply one more
key in the task similar to the task's name and the module that it uses. A common
convention consists of placing any when keyword after the task's name and the
module and module arguments.

Testing Multiple Conditions


You can use one when statement to evaluate multiple conditions. To do so, combine conditional
statements with either the and or or operators. You can also group conditionals with parentheses
when there are more than two operators.

The following examples illustrate how to express multiple conditions.

256 DO417-RHAE2.8-en-1-20200106
Chapter 6 | Implementing Task Control

• If a conditional statement should be met when either condition is true, then you should use
the or operator. For example, the following condition is met if the machine is running either
Microsoft Windows Server 2016 Datacenter or Microsoft Windows Server 2012 Datacenter
edition.

when: ansible_facts['distribution'] == "Microsoft Windows Server 2016 Datacenter"


or ansible_facts['distribution'] == "Microsoft Windows Server 2012 Datacenter"

• With the and operator, both conditions have to be true for the entire conditional statement to
be true. For example, the following condition is met if the remote host is a Microsoft Windows
Server 2016 Datacenter host with a 64-bit architecture:

when: ansible_facts['distribution'] == "Microsoft Windows Server 2016 Datacenter"


and ansible_facts['architecture'] == "64-bit"

The when keyword also supports a list to describe a set of conditions. When you provide a list
to the keyword, Ansible combines all the conditionals using the and operator. The following
example demonstrates another way to combine multiple conditional statements using and.

when:
- ansible_facts['distribution'] == "Microsoft Windows Server 2016 Datacenter"
- ansible_facts['architecture'] == "64-bit"

This format improves readability, a key goal of well-written Ansible Playbooks.

• You can express more complex conditional statements by grouping conditions with parentheses.
This ensures that Ansible correctly interprets them.

For example, the following conditional statement is met if the machine is running either
Microsoft Windows Server 2016 Datacenter or Microsoft Windows Server 2012 Datacenter and
has a 64-bit architecture.

when: >
( ansible_facts['distribution'] == "Microsoft Windows Server 2016 Datacenter"
or
ansible_facts['distribution'] == "Microsoft Windows Server 2012 Datacenter" )
and
ansible_facts['architecture'] == "64-bit"

Combining Loops and Conditional Tasks


You can combine loops and conditionals to handle more granular deployments. In the following
example, Ansible deploys the IIS Web Server using the win_feature module if the operating
system is Microsoft Windows Server 2016 Core with a 64-bit Architecture. The task only runs if
both the conditions are true.

- name: Testing Complex condition with loop


hosts: winhost1
vars:
my_package:
- jre8
- javaruntime-preventasktoolbar

DO417-RHAE2.8-en-1-20200106 257
Chapter 6 | Implementing Task Control

- dropbox
tasks:
- name: Install packages
win_chocolatey:
name: "{{ item }}"
state: present
loop: "{{ my_package }}"
when:
- ansible_facts['distribution'] == "Microsoft Windows Server 2016 Core"
- ansible_facts['architecture'] == "64-bit"

Important
When you use the when statement in a loop, Ansible evaluates the condition for
each item in the loop.

References
Loops — Ansible Documentation
https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html

Migrating from with_X to loop — Ansible Documentation


https://docs.ansible.com/ansible/latest/user_guide/
playbooks_loops.html#migrating-from-with-x-to-loop

258 DO417-RHAE2.8-en-1-20200106
Chapter 6 | Implementing Task Control

Guided Exercise

Writing Loops and Conditional Tasks


In this exercise, you will write a playbook using tasks with loops and conditional tests.

Outcomes
You should be able to:

• Use loops to iterate over items and to reduce repetitive code.

• Use logical conditions to control when tasks should execute.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. Open the Visual Studio Code editor and clone the control repository to workstation.

1.1. Double-click the Visual Studio Code icon on the desktop.

1.2. Click View → Command Palette or type Ctrl+Shift+P to open the command
palette.
Type clone and select Git: Clone to clone a repository.

1.3. When prompted, provide a repository URL of https://gitlab.example.com/


student/control.git and choose the Documents folder as the repository
location. This clones the remote repository into the C:\Users\student\Documents
\control folder on workstation.

1.4. In the lower right corner, click Open to open the project.

2. Open the loops.yml playbook and review its contents. Notice the long list of repetitive
tasks. Each task uses the win_feature module to ensure that an IIS web server feature
is present. In the next steps you will refactor the playbook to improve readability and
maintainability.

3. Group all of the extra debugging features into a single task with a loop. Replace all of the
tasks except for the task named IIS is installed with the updated task as follows:

---
- name: IIS and debugging tools installed
hosts: win1.example.com
tasks:

DO417-RHAE2.8-en-1-20200106 259
Chapter 6 | Implementing Task Control

- name: IIS is installed


win_feature:
name: Web-Server
state: present

- name: Debug tools are installed


win_feature:
name: "{{ item }}"
state: present
loop:
- Web-Custom-Logging
- Web-Log-Libraries
- Web-Request-Monitor
- Web-Http-Tracing
- Web-Mgmt-Tools

- name: Server is rebooted


win_reboot:

Each iteration of the loop sets the value of the item variable to the next element in
the loop list.
Consolidation of the features to install into a simple list.

4. Modify the playbook to only install the extra debugging tools when there is enough space
available on the disk.

4.1. Insert a task directly before the Debug tools are installed task that gathers
facts about the disks that are present on the managed host.

- name: Disk facts are gathered


win_disk_facts:

4.2. Add the when and vars parameters to the Debug tools are installed task as
follows. Indent with six spaces to align the when and vars parameters with the loop
parameter.

when: size_remaining >= minimum_bytes


vars:
minimum_bytes: "{{ '10 GB' | human_to_bytes }}"
first_volume: "{{ ansible_facts.disks[0].partitions[0].volumes[0] }}"
size_remaining: "{{ first_volume.size_remaining }}"

Ansible evaluates the when clause on each iteration of the loop. If the
size_remaining variable is greater than or equal to the minimum_bytes
variable then Ansible invokes the win_feature module to ensure that the
feature is present.
Declare variables for the task to improve the readability of the conditional logic.
For simplicity, select the space available from the first volume of the first partition
of the first disk on our classroom managed host.

5. Verify that the final loops.yml matches the following playbook.

260 DO417-RHAE2.8-en-1-20200106
Chapter 6 | Implementing Task Control

---
- name: IIS and debugging tools installed
hosts: win1.example.com
tasks:
- name: IIS is installed
win_feature:
name: Web-Server
state: present

- name: Disk facts are gathered


win_disk_facts:

- name: Debug tools are installed


win_feature:
name: "{{ item }}"
state: present
loop:
- Web-Custom-Logging
- Web-Log-Libraries
- Web-Request-Monitor
- Web-Http-Tracing
- Web-Mgmt-Tools
when: size_remaining >= minimum_bytes
vars:
minimum_bytes: "{{ '10 GB' | human_to_bytes }}"
first_volume: "{{ ansible_facts.disks[0].partitions[0].volumes[0] }}"
size_remaining: "{{ first_volume.size_remaining }}"

- name: Server is rebooted


win_reboot:

6. Save and commit the changes to your local Git repository, then push them to the remote
repository.

6.1. Click File → Save or type Ctrl+S to save the file.

6.2. Navigate to the Source Control pane, and then click the + for the loops.yml file to
stage the changes.

6.3. Enter a brief commit message, and then press Ctrl+Enter to commit the changes.

6.4. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to
push your local changes to the remote repository, and retrieve any new changes from
the repository.

7. From workstation, access your Ansible Tower instance at http://


tower.example.com. Log in as student using RedHat123@! as the password.

8. Launch a job from the Run control project job template.

8.1. In the navigation pane, click Templates.

8.2. Click the Run control project job template to edit it

DO417-RHAE2.8-en-1-20200106 261
Chapter 6 | Implementing Task Control

8.3. Select the loops.yml playbook from the PLAYBOOK list.

8.4. Click SAVE to update the template, and then click LAUNCH to run the job.

9. Verify that the playbook completed successfully and review the log output.

9.1. After all tasks have completed, verify that the status in the DETAILS section
shows Successful. If the job was not successful, compare your playbook with the
solutions/loops.sol solution file in the control Git repository.

9.2. Review the log output and notice that the Debug tools are installed task
executes with multiple changes.

10. Connect to the win1.example.com managed host to confirm the presence of the IIS web
management tools.

10.1. Click Search Windows, and then type remote to search for and open Remote
Desktop Connection.

262 DO417-RHAE2.8-en-1-20200106
Chapter 6 | Implementing Task Control

10.2.Enter win1.example.com, devops, and RedHat123@! as the Computer, username,


and password, respectively. Note that devops is a local user, not a domain user, so do
not include the EXAMPLE domain.
Click Yes to accept the insecure certificate used in your classroom environment.

10.3.In the win1.example.com remote session, click Search Windows, and then type
IIS to search for and open Internet Information Services (IIS) Manager.

11. Run the cleanup-loops.yml playbook from the Run control project job template.

11.1. In the navigation pane, click Templates.

11.2. Click the name of the Run control project job template.

11.3. Select the cleanup-loops.yml playbook from the PLAYBOOK list.

11.4. Click SAVE to update the template, and then click LAUNCH to run the job.

This concludes the guided exercise.

DO417-RHAE2.8-en-1-20200106 263
Chapter 6 | Implementing Task Control

Implementing Handlers

Objectives
After completing this section, you should be able to implement handlers that run only when
another task makes a change on the managed host and notifies them.

Introducing Handlers
Ansible modules are designed to be idempotent. This means that you can run the playbook and its
tasks multiple times without changing any component on the managed host unless you instruct
Ansible to make a change to get the managed host to the state that you desire.

However, sometimes when a task does make a change to the system, you may need to run further
tasks. For example, if you install a new feature or package on your server or if you join a server to a
domain, you might need to restart the server so that the installation can complete or changes can
be applied successfully.

Handlers are tasks that respond to a notification that other tasks trigger. Tasks only notify their
handlers when the task changes something on a managed host. Each handler has a globally unique
name and triggers at the end of a block of tasks in a playbook. If no task notifies the handler by
name then the handler does not run. If one or more tasks notify the handler, the handler runs
exactly once after all other tasks in the play complete. Because handlers are tasks, you can use
the same modules in handlers that you would use for any other task. You typically use handlers to
restart hosts or services.

You can think of handlers as inactive tasks that trigger when they are invoked by a changed task
that has a notify statement. The following example shows how the reboot server handler
runs when Ansible installs a new package in a task.

- name: Testing Handlers


hosts: winhost1
tasks:
- name: Install Dotnet4.6.1
win_chocolatey:
name: dotnet4.6.1
state: present
notify:
- reboot server

handlers:
- name: reboot server
win_reboot:

The task that notifies the handler.


The notify statement indicates the task needs to trigger a handler.
The name of the handler to run.
The handlers keyword indicates the start of the list of handler tasks.
The name of the handler that the task invokes.
The module to use for the handler.

264 DO417-RHAE2.8-en-1-20200106
Chapter 6 | Implementing Task Control

In the previous example, the reboot server handler triggers when the win_chocolatey task
notifies Ansible that a change occurred. A task may call more than one handler in its notify
section. Ansible treats the notify statement as an array and iterates over the handler names.

The following example shows how the task invokes two handlers; the initial handler prints a
message, and the second handler restarts the server.

- name: Testing complex condition with loop


hosts: winhost1
tasks:
- name: Install Dotnet4.6.1
win_chocolatey:
name: dotnet4.6.1
state: present
notify:
- printing message
- reboot server

handlers:
- name: printing message
debug:
msg: Installation is done, rebooting the server now
- name: reboot server
win_reboot:

Describing the Features of Handlers


The following list describes some important information to know about Ansible handlers:

• Handlers always run in the order specified by the handlers section of the play. They do not
run in the order in which they are listed by notify statements in a task, or in the order in which
tasks notify them.

• In a simple play with a single section, handlers run after all other tasks in the play complete. A
handler called by a task in the tasks part of the playbook does not run until Ansible runs all
tasks. More complex plays that use pre_tasks and post_tasks sections, or roles, will trigger
handlers after each section.

• Handler names exist in a per-play namespace. If two handlers have the same name, Ansible will
only run the last one.

• Even if more than one task notifies a handler, the handler only runs once. If no task notifies it, a
handler does not run.

• If a task that includes a notify statement does not report a changed result (for example, if a
package is already installed and the task reports that no further action is required), the handler
is not notified. Ansible skips the handler unless another task notifies it. Ansible notifies handlers
only if the task reports a status of changed.

Important
Handlers are meant to perform an extra action when a task makes a change to a
managed host. You should not use them as a replacement for regular tasks.

DO417-RHAE2.8-en-1-20200106 265
Chapter 6 | Implementing Task Control

Order of Execution for Handlers


Ansible runs play sections in the following order:

1. Tasks that you define in the pre_tasks section.

2. Handlers that tasks in the pre_tasks section trigger.

3. Roles that you define in the include_role section.

4. Tasks that you define in the tasks section.

5. Handlers that tasks in the include_roles and tasks sections notify.

6. Tasks that you define in the post_tasks section.

7. Handlers that tasks in the post_tasks section trigger.

The order of these sections in a play does not modify the order of execution, as given above. For
example, if you write the tasks section before the roles section, Ansible still executes the roles
before the tasks in the tasks section. However, for readability, it is good practice to organize your
play in the following order of execution:

1. pre_tasks
2. roles
3. tasks
4. post_tasks
5. handlers

Ansible executes and flushes the handlers that the tasks notify at several points during a run:
after the pre_tasks section, after the include_roles and tasks sections, and after the
post_tasks section. This means that a handler can run more than once at different times during
the play execution if tasks notify it in multiple sections.

References
Handlers: Running Operations On Change — Ansible Documentation
https://docs.ansible.com/ansible/latest/user_guide/
playbooks_intro.html#handlers-running-operations-on-change

266 DO417-RHAE2.8-en-1-20200106
Chapter 6 | Implementing Task Control

Guided Exercise

Implementing Handlers
In this exercise, you will write a play that uses a handler to run a task if another task makes a
change to the managed host.

Outcomes
You should be able to implement tasks that run only when another task makes a change on
the managed host.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. Open the Visual Studio Code editor and clone the control repository to your
workstation.

1.1. On workstation, open the Visual Studio Code editor by double-clicking its icon on
the desktop.

1.2. Open the command palette by navigating to View → Command Palette or by typing
Ctrl+Shift+P.
Type clone and select Git: Clone to clone a repository.

1.3. When prompted, provide a repository URL of https://gitlab.example.com/


student/control.git and choose the Documents folder as the repository
location. This clones the remote repository into the C:\Users\student\Documents
\control folder on workstation.

1.4. In the lower right corner, click Open to open the project.

2. Create a playbook named handlers.yml that uses the win_updates Ansible module to
install Windows security updates on the win1.example.com server.

---
- name: System updated and restarted
hosts: win1.example.com

tasks:
- name: Security updates applied
win_updates:
category_names: SecurityUpdates
state: installed

DO417-RHAE2.8-en-1-20200106 267
Chapter 6 | Implementing Task Control

3. Below the tasks section, add a handler that uses the win_reboot module that you can
notify to reboot the server. Even though this module provides a reboot parameter, this
exercise creates a handler to manage that action, allowing you to execute the reboot when
most appropriate for your use case.

---
- name: System updated and restarted
hosts: win1.example.com

tasks:
- name: Security updates applied
win_updates:
category_names: SecurityUpdates
state: installed

handlers:
- name: Server is rebooted
win_reboot:

4. Add a notify statement to your task to invoke the handler when the task changes the
state of the target host.

---
- name: System updated and restarted
hosts: win1.example.com

tasks:
- name: Security updates applied
win_updates:
category_names: SecurityUpdates
state: installed
notify:
- Server is rebooted

handlers:
- name: Server is rebooted
win_reboot:

5. Save and commit the changes to your local Git repository, then push them to the remote
repository.

5.1. Click File → Save or type Ctrl+S to save the file.

5.2. Navigate to the Source Control pane, then click the + next to handlers.yml to
stage the changes.

5.3. Enter a brief commit message, then press Ctrl+Enter to commit the changes.

5.4. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to
push your local changes to the remote repository, and retrieve any new changes from
the repository.

268 DO417-RHAE2.8-en-1-20200106
Chapter 6 | Implementing Task Control

6. From workstation, access your Ansible Tower instance at http://


tower.example.com. Log in as student using RedHat123@! as the password.

7. In the navigation pane, click Projects. Click the synchronize button to fetch the latest
changes to the control project.

8. Launch a job from the Run control project job template.

8.1. In the navigation pane, click Templates.

8.2. Click the Run control project job template to edit it.

8.3. Select the handlers.yml playbook from the PLAYBOOK list.

8.4. Click SAVE to update the template, and then click LAUNCH to run the job.

9. Verify that the playbook completed successfully and review the log output.

9.1. After all tasks have completed, verify that the status in the DETAILS section
shows Successful. If the job was not successful, compare your playbook with the
solutions/handlers.sol solution file in the control Git repository.

9.2. Review the log output and notice that the Security updates applied task
executes, reports a status of CHANGED, and notifies the Server is rebooted
handler.

DO417-RHAE2.8-en-1-20200106 269
Chapter 6 | Implementing Task Control

10. Run the same playbook a second time. Compare the log output and notice that the
Security updates applied task executes, reports an OK status, but does not notify
the Server is rebooted handler, because it made no changes.

This concludes the guided exercise.

270 DO417-RHAE2.8-en-1-20200106
Chapter 6 | Implementing Task Control

Handling Task Failure

Objectives
After completing this section, you should be able to control what happens when a task fails,
recover from task failure, and control what conditions cause a task to report failure.

Managing Task Failures in Plays


Ansible evaluates the return code of each task to determine whether the task succeeded or failed.
Normally, when a task fails Ansible immediately aborts the rest of the play on that host, skipping all
subsequent tasks.

However, sometimes you might want to have play execution continue even if a task fails. For
example, you might expect that a particular task could fail, and you might want to recover by
running some other task conditionally. There are several Ansible features that can be used to
manage task errors.

Ignoring Task Failure


By default, if a task fails on a host, the play is aborted for that host. However, you can override this
behavior by ignoring failed tasks. You can use the ignore_errors keyword in a task to override
the default behavior.

The following example illustrates how to use ignore_errors in a task to continue playbook
execution on the host even if the task fails. For example, if notafeature is not a valid feature, the
feature installation fails, but having ignore_errors set to true instructs Ansible to continue.

- name: Install notafeature with sub features and management tools


win_feature:
name: notafeature
state: present
include_sub_features: yes
include_management_tools: yes
ignore_errors: true

Forcing Execution of Handlers after Task Failure


When a task fails and the play aborts on that host, any handlers that had been notified by earlier
tasks in the play will not run. If you set the force_handlers keyword to true on the play, then
Ansible runs the handlers that the play invokes even if the play aborted because a later task failed.

The following example illustrates how to use the force_handlers keyword in a play to force
execution of the handler even if a task fails:

- name: Testing Handlers


hosts: demo
force_handlers: true
tasks:
- name: Install Dotnet4.6.1

DO417-RHAE2.8-en-1-20200106 271
Chapter 6 | Implementing Task Control

win_chocolatey:
name: dotnet4.6.1
state: present
notify:
- reboot server

- name: Install notafeature with sub features and management tools


win_feature:
name: notafeature
state: present
include_sub_features: yes
include_management_tools: yes

handlers:
- name: reboot server
win_reboot:

Note
Remember that handlers are notified when a task reports a result of changed but
are not notified when tasks report either ok or failed.

Specifying Task Failure Conditions


You can use the failed_when keyword on a task to specify which conditions indicate that the
task has failed.

For example, you can indicate the update of a Windows Server as failed only if a
failed_update_count variable is defined and is greater than 0.

- name: Installing Windows Updates


win_updates:
category_names:
- CriticalUpdates
- SecurityUpdates
state: installed
reboot: true
reboot_timeout: 600
register: update_result
failed_when:
- update_result.failed_update_count is defined
- update_result.failed_update_count > 0

You can also use the fail module to force a task failure. You can rewrite the previously mentioned
scenario as two tasks:

- name: Installing Windows Updates


win_updates:
category_names:
- CriticalUpdates
- SecurityUpdates
state: installed
reboot: true

272 DO417-RHAE2.8-en-1-20200106
Chapter 6 | Implementing Task Control

reboot_timeout: 600
register: update_result
ignore_errors: true

- name: Reporting failure


fail:
msg: The update has failed
when:
- update_result.failed_update_count is defined
- update_result.failed_update_count > 0

The fail module allows you to provide a clear failure message for the task. This approach also
enables delayed failure, allowing you to run intermediate tasks to complete or roll back other
changes.

Handling Errors Using Ansible Blocks


In playbooks, blocks are clauses that logically group tasks; you use them to control how tasks
execute. For example, a task block can have a when keyword to apply a conditional to multiple
tasks.

The following example shows how to define a block in which the win_updates module runs.

- name: Testing Block


block:
- win_updates:
category_names:
- CriticalUpdates
- SecurityUpdates
state: installed
reboot: true
reboot_timeout: 600

You can also use blocks for handling errors through the rescue and always statements. If any
task in a block fails, Ansible executes the tasks in a rescue block to recover the execution of the
play. After the tasks in the block clause run, or the tasks in the rescue clause in case of failure,
then Ansible runs all the tasks in the always clause.

To summarize:

• block: Defines the main tasks to run.


• rescue: Defines the tasks to run if the tasks in the block clause fail.
• always: Defines the tasks that always run independently of the success or failure of tasks
defined in the block and rescue clauses.

The following example shows how to implement a block in a playbook. Even if the tasks in the
block clause fail, Ansible runs the tasks in the rescue and always clauses.

- name: Testing block, rescue and always


hosts: demo
tasks:
- name: Block, Rescue and Always
block:
# Ansible starts by running these tasks...
- name: Installing Windows Updates

DO417-RHAE2.8-en-1-20200106 273
Chapter 6 | Implementing Task Control

win_updates:
category_names:
- CriticalUpdates
- SecurityUpdates
state: installed
reboot: true
reboot_timeout: 600
register: update_result
failed_when:
- update_result.failed_update_count is defined
- update_result.failed_update_count > 0

rescue:
# ... these tasks only run if the tasks in the block fail.
- name: Showing up a failure message
debug:
msg: The Critical and Security Updates has failed.

always:
# However, these tasks always run
- name: Updating mandatory ServicePacks and FeaturePacks
win_updates:
category_names:
- ServicePacks
- FeaturePacks
state: installed
reboot: true
reboot_timeout: 600

Important
The when condition of a block clause also applies to its rescue and always
clauses if they are present.

Controlling when a Task Reports a Changed State


When a task makes a change to a managed host, it reports the changed state and notifies
handlers. When a task does not need to make a change, it reports a status of ok and does not
notify handlers.

Use the changed_when keyword to control when a task reports a changed result. The following
example shows how the win_shell is being used to run a command on servers. It would usually
always report changed when the module runs. To modify this behavior set changed_when to
false so that Ansible only reports an ok or failed status.

- name: Testing changed_when by running a command


hosts: demo
tasks:
- name: Executing a command on Windows
win_shell: hostname
changed_when: false

274 DO417-RHAE2.8-en-1-20200106
Chapter 6 | Implementing Task Control

References
Blocks — Ansible Documentation
https://docs.ansible.com/ansible/latest/user_guide/playbooks_blocks.html

Error Handling In Playbooks — Ansible Documentation


https://docs.ansible.com/ansible/latest/user_guide/playbooks_error_handling.html

DO417-RHAE2.8-en-1-20200106 275
Chapter 6 | Implementing Task Control

Guided Exercise

Handling Task Failure


In this exercise, you will explore different ways to handle task failure in an Ansible Playbook.

Outcomes
You should be able to customize how Ansible identifies and handles errors and status output.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. Open the Visual Studio Code editor and clone the control repository to workstation.

1.1. From workstation open the Visual Studio Code editor by double-clicking its icon on
the desktop.

1.2. Click View → Command Palette or type Ctrl+Shift+P to navigate to the


command palette.
Type clone and select Git: Clone to clone a repository.

1.3. Enter a repository URL of https://gitlab.example.com/student/


control.git and choose the Documents folder as the repository location. This
clones the remote repository into the C:\Users\student\Documents\control
folder.

1.4. In the lower right corner, click Open to open the project.

2. Open the file in the control repository named install-iis.yml.

3. With Ansible, you can use conditionals for tasks that verify the implementation of features
that are not yet available.
Add a task that installs a custom feature named Team-Application that your team
intends to add to the environment at a later time. Ensure that this task does not halt
playbook execution until the feature is created by adding the argument ignore_errors:
yes.

- name: Team-Application is installed


win_feature:
name: Team-Application
state: present
ignore_errors: yes

276 DO417-RHAE2.8-en-1-20200106
Chapter 6 | Implementing Task Control

4. Ansible can ensure that the content in your environment matches expected outputs and
mitigate any discrepancies. Use a registered variable to capture task output, then use it
conditionally execute foloowing tasks.

4.1. Add a task that reads the contents of the win1.example.com home page text and
stores it in the index variable.

- name: Homepage index is set


win_uri:
url: http://win1.example.com
return_content: yes
register: index

4.2. Add another line to the task that uses the conditional failed_when statement to
compare the home page output stored in the index variable with the string "Ansible
is great". This comparison will fail when the index content does match this phrase.

- name: Homepage index is set


win_uri:
url: http://win1.example.com
return_content: yes
register: index
failed_when: index.content != "Ansible is great"

4.3. The playbook should appear as follows after your edits:

---
- name: Install the IIS web service
hosts: win1.example.com

tasks:

- name: IIS service installed


win_feature:
name: Web-Server
state: present

- name: IIS service started


win_service:
name: W3Svc
state: started

- name: Website index.html created


win_copy:
content: "Hello world!"
dest: C:\Inetpub\wwwroot\index.html

- name: Team-Application is installed


win_feature:
name: Team-Application
state: present
ignore_errors: yes

- name: Homepage index is set

DO417-RHAE2.8-en-1-20200106 277
Chapter 6 | Implementing Task Control

win_uri:
url: http://win1.example.com
return_content: yes
register: index
failed_when: index.content != "Ansible is great"

5. Save and commit the changes to your local Git repository, and then push them to the
remote repository.

5.1. Click File → Save or type Ctrl+S to save the file.

5.2. Navigate to the Source Control pane, and then click the + next to the install-
iss.yml file to stage the changes.

5.3. Enter a brief commit message, and then press Ctrl+Enter to commit the changes.

5.4. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to
push your local changes to the remote repository, and retrieve any new changes from
the repository.

6. From workstation, access your Ansible Tower instance at http://


tower.example.com. Log in as student using RedHat123@! as the password.

7. Launch a job from the Run control project job template.

7.1. In the navigation pane, click Templates.

7.2. Click the name of the Run control project.

7.3. Select the install-iis.yml playbook from the PLAYBOOK list.

7.4. Click SAVE to update the template, and then click LAUNCH to run the job.

7.5. Because the error is ignored for the task Team-Application is installed, it is
reported as a failure but playbook execution continues. Because the content of the
homepage is not correctly set, the job fails on the task Homepage index is set.

278 DO417-RHAE2.8-en-1-20200106
Chapter 6 | Implementing Task Control

8. Update your playbook to fix the failure.

8.1. In Visual Studio Code, locate the existing task named Website index.html
created and update the content to have it set the home page on the
win1.example.com server to Ansible is great.

- name: Website index.html created


win_copy:
content: "Ansible is great"
dest: C:\Inetpub\wwwroot\index.html

8.2. Save, commit, and synchronize your work in Visual Studio Code. Rerun the job in
Ansible Tower. With the proper homepage content set, your playbook runs to a
successful completion.

DO417-RHAE2.8-en-1-20200106 279
Chapter 6 | Implementing Task Control

This concludes the guided exercise.

280 DO417-RHAE2.8-en-1-20200106
Chapter 6 | Implementing Task Control

Lab

Implementing Task Control


Performance Checklist
In this lab, you will write a playbook to deploy a service, and use conditional tests, handlers,
and techniques to manage task failure in your playbook.

Outcomes
You should be able to manage task flow by using conditional tests and handlers.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running and that you can access Red Hat Ansible
Tower and GitLab from the Windows workstation.

For this lab, use the Run control project job template to execute your playbook within
Ansible Tower.

Note
This activity requires win2.example.com in the Default inventory
inventory. You added the host in a previous exercise. If the host is not present,
follow the instructions in the Implementing Multiple Plays guided exercise to
create it.

1. Log in to your Red Hat Ansible Tower instance.


2. In the Inventories menu, ensure that win2.example.com is a member of the Default
inventory.
3. Launch Visual Studio Code and clone the https://gitlab.example.com/student/
control.git repository [to your Documents folder], and then open the project.
4. Create a new playbook in the control repository named review.yml.
5. Write a playbook that uses the default inventory containing both the win1.example.com
and win2.example.com machines.
6. For the win1 system, install the Web-Server feature and ensure that the web service is
running. Use a loop to add the additional Web-Security, Web-Basic-Auth, and Web-
IP-Security features to the system and update the server home page to display the host
name of the machine.
7. Write a handler named Machine is restarted that reboots the server and add it to each
of the feature installation tasks.

DO417-RHAE2.8-en-1-20200106 281
Chapter 6 | Implementing Task Control

8. Add a conditional task for the win2.example.com system to install all Windows security
updates. Notify the Machine is restarted handler.
9. Add a when statement for each task in the playbook that uses an Ansible fact to match the
host name. This addition should have the playbook perform the designated tasks only on the
target machine specified by the lab instructions.
10. In Visual Studio Code, save, commit, and synchronize your file into the control repository.
In Red Hat Ansible Tower, refresh the files for the control repository project.
Launch a job from the Run control project job template.
11. Verify that both systems are in their expected configuration.

This concludes the lab.

282 DO417-RHAE2.8-en-1-20200106
Chapter 6 | Implementing Task Control

Solution

Implementing Task Control


Performance Checklist
In this lab, you will write a playbook to deploy a service, and use conditional tests, handlers,
and techniques to manage task failure in your playbook.

Outcomes
You should be able to manage task flow by using conditional tests and handlers.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running and that you can access Red Hat Ansible
Tower and GitLab from the Windows workstation.

For this lab, use the Run control project job template to execute your playbook within
Ansible Tower.

Note
This activity requires win2.example.com in the Default inventory
inventory. You added the host in a previous exercise. If the host is not present,
follow the instructions in the Implementing Multiple Plays guided exercise to
create it.

1. Log in to your Red Hat Ansible Tower instance.

1.1. From workstation, log in to Ansible Tower at https://tower.example.com or by


double-clicking the Ansible Tower desktop icon. Authenticate with student as the
username and RedHat123@! as the password.

2. In the Inventories menu, ensure that win2.example.com is a member of the Default


inventory.

2.1. If you need to add this configuration, navigate to the Inventories page in Ansible Tower,
add the win2.example.com host, and place this host in the default inventory.

3. Launch Visual Studio Code and clone the https://gitlab.example.com/student/


control.git repository [to your Documents folder], and then open the project.

3.1. On workstation, double-click the desktop icon named Visual Studio Code.
Click View → Command Palette or type Ctrl+Shift+P to open the command
palette.

DO417-RHAE2.8-en-1-20200106 283
Chapter 6 | Implementing Task Control

Type clone and select Git: Clone to clone a repository.

3.2. Enter a repository URL of https://gitlab.example.com/student/control.git


and choose the Documents folder as the repository location. This clones the
remote repository into the C:\Users\student\Docuements\control folder on
workstation.

3.3. In the lower right corner, click Open to open the project.

4. Create a new playbook in the control repository named review.yml.

4.1. In Visual Studio Code, click the New File icon next to CONTROL and name the file
review.yml.

5. Write a playbook that uses the default inventory containing both the win1.example.com
and win2.example.com machines.
6. For the win1 system, install the Web-Server feature and ensure that the web service is
running. Use a loop to add the additional Web-Security, Web-Basic-Auth, and Web-
IP-Security features to the system and update the server home page to display the host
name of the machine.

6.1. Update the playbook to match this content:

---
- name: Control review lab
hosts: all

tasks:

- name: Web server feature is installed


win_feature:
name: Web-Server
state: present

- name: Web server is started


win_service:
name: W3Svc
state: started

- name: Website index.html created


win_copy:
content: "win1.example.com"
dest: C:\Inetpub\wwwroot\index.html

- name: Web security features are installed


win_feature:
name: "{{ item }}"
state: present
loop:
- Web-Security
- Web-Basic-Auth
- Web-IP-Security

7. Write a handler named Machine is restarted that reboots the server and add it to each
of the feature installation tasks.

284 DO417-RHAE2.8-en-1-20200106
Chapter 6 | Implementing Task Control

7.1. The playbook should now contain the following content:

---
- name: Control review lab
hosts: all

tasks:

- name: Web server feature is installed


win_feature:
name: Web-Server
state: present
notify: Machine is restarted

- name: Web server is started


win_service:
name: W3Svc
state: started

- name: Website index.html created


win_copy:
content: "win1.example.com"
dest: C:\Inetpub\wwwroot\index.html

- name: Web security features are installed


win_feature:
name: "{{ item }}"
state: present
loop:
- Web-Security
- Web-Basic-Auth
- Web-IP-Security
notify: Machine is restarted

handlers:

- name: Machine is restarted


win_reboot:

8. Add a conditional task for the win2.example.com system to install all Windows security
updates. Notify the Machine is restarted handler.

8.1. The playbook should now contain the following content:

---
- name: Control review lab
hosts: all

tasks:

- name: Web server feature is installed on win1

DO417-RHAE2.8-en-1-20200106 285
Chapter 6 | Implementing Task Control

win_feature:
name: Web-Server
state: present
notify: Machine is restarted

- name: Web server is started on win1


win_service:
name: W3Svc
state: started

- name: Website index.html created on win1


win_copy:
content: "win1.example.com"
dest: C:\Inetpub\wwwroot\index.html

- name: Web security features are installed on win1


win_feature:
name: "{{ item }}"
state: present
loop:
- Web-Security
- Web-Basic-Auth
- Web-IP-Security
notify: Machine is restarted

- name: Security updates applied on win2


win_updates:
category_names: SecurityUpdates
notify: Machine is restarted

handlers:

- name: Machine is restarted


win_reboot:

9. Add a when statement for each task in the playbook that uses an Ansible fact to match the
host name. This addition should have the playbook perform the designated tasks only on the
target machine specified by the lab instructions.

9.1. Update the playbook to match this content:

---
- name: Control review lab
hosts: all

tasks:

- name: Web server feature is installed on win1


win_feature:
name: Web-Server
state: present
notify: Machine is restarted
when: "'win1' in inventory_hostname"

286 DO417-RHAE2.8-en-1-20200106
Chapter 6 | Implementing Task Control

- name: Web server is started on win1


win_service:
name: W3Svc
state: started
when: "'win1' in inventory_hostname"

- name: Website index.html created on win1


win_copy:
content: "win1.example.com"
dest: C:\Inetpub\wwwroot\index.html
when: "'win1' in inventory_hostname"

- name: Web security features are installed on win1


win_feature:
name: "{{ item }}"
state: present
loop:
- Web-Security
- Web-Basic-Auth
- Web-IP-Security
notify: Machine is restarted
when: "'win1' in inventory_hostname"

- name: Security updates applied on win2


win_updates:
category_names: SecurityUpdates
notify: Machine is restarted
when: "'win2' in inventory_hostname"

handlers:

- name: Machine is restarted


win_reboot:

10. In Visual Studio Code, save, commit, and synchronize your file into the control repository.
In Red Hat Ansible Tower, refresh the files for the control repository project.
Launch a job from the Run control project job template.

10.1. In Visual Studio Code, save your file, add a brief commit message, and synchronize your
changes into the control repository.

10.2.In Red Hat Ansible Tower, click Get latest SCM revision on the Projects page next to
the control repository project.

10.3.Selec the Run control project job template from the Templates page to edit it.
Select review.yml from the PLAYBOOK the list, and click Launch.

11. Verify that both systems are in their expected configuration.

11.1. Inspect the job output within Ansible Tower to ensure that all tasks completed
successfully.

This concludes the lab.

DO417-RHAE2.8-en-1-20200106 287
Chapter 6 | Implementing Task Control

Summary
In this chapter, you learned:

• Loops are used to iterate over lists of values, such as a simple list of strings or a complex list of
dictionaries.

• Conditionals are used to execute tasks only when certain conditions have been met.

• Handlers are special tasks that execute at the end of a section if notified by tasks within that
section.

• Handlers are only notified when a task reports that it changed something on the managed host.

• Tasks can ignore failures, call handlers even if a task fails, mark tasks as failed even if they
succeed, or override the behavior that causes a task to be marked as changed.

• Blocks are used to group tasks as a unit and to execute other tasks depending on whether or not
all the tasks in the block succeed.

288 DO417-RHAE2.8-en-1-20200106
Chapter 7

Deploying Files to Managed


Hosts
Goal Deploy, modify, and manage files on your managed
hosts.

Objectives • Create, install, edit, and remove files on


managed hosts, and configure file permissions
and other characteristics.
• Deploy customized files to managed hosts
using Jinja2 templates.

Sections • Modifying and Transferring Files on Hosts (and


Guided Exercise)
• Templating Files with Jinja2 (and Guided
Exercise)

Lab Deploying Files to Managed Hosts

DO417-RHAE2.8-en-1-20200106 289
Chapter 7 | Deploying Files to Managed Hosts

Modifying and Transferring Files on


Hosts

Objectives
After completing this section, you should be able to create, install, edit, and remove files on
managed hosts, and configure file permissions and other characteristics.

Describing File Modules


Red Hat Ansible Engine ships with a large collection of modules (also known as the module
library) that are developed as part of the upstream Ansible project. To make it easier to organize,
document, and manage them, they are organized into groups based on function, both in the
documentation, and when installed on a system.

The Windows modules library includes modules that allow you to accomplish most tasks related to
Windows file management, such as creating, copying, editing, searching, and removing files, and
modifying ACLs and other file attributes.

The following table provides a list of the main file management modules:

Module Name Module Description

win_acl Adds or removes rights and permissions to the specified file, folder, or
registry key for a given user or group.

win_copy Copies files from local control nodes to remote managed nodes.

win_stat Returns information about files.

win_file Creates files and updates modification time stamps on existing


files. This module does not modify ownership or permissions, nor
manipulate links.

win_robocopy Synchronizes the contents of files or directories from the source to a


destination on the local Windows control nodes. This module calls the
robocopy command, which is available on modern Microsoft Windows
systems.

win_owner Sets the owner of files and directories.

win_file_version Retrieves the build versions of DLL or .EXE files.

win_find Finds files on Windows-based managed hosts based on specific


criteria.

win_tempfile Creates temporary files and directories.

win_unzip Unzips compressed files and archives on the managed hosts.

290 DO417-RHAE2.8-en-1-20200106
Chapter 7 | Deploying Files to Managed Hosts

Automation Examples with File Modules


Creating, copying, editing, searching, and removing files, and modifying ACLs on managed hosts,
are common tasks that can be simplified using modules from the Windows modules library The
following examples show how to use these modules to automate common file management tasks.

Ensuring a File or Directory Exists on Your Systems


Use the win_file module to create a file or directory on managed hosts, and to update
the modification time if the file already exists. This module does not modify ownership or file
permissions, and it does not manipulate links. Use win_acl or win_owner modules for these
tasks.

- name: Create a file or modify time stamp if already present


win_file:
path: C:\Temp\test.conf
state: touch

The following example demonstrates how to create a directory, and required parent directories, if
they do not exist.

- name: Create a folder and its parent folders


win_file:
path: C:\Temp\folder\subfolder
state: directory

Note
Use the win_tempfile module to create temporary files and directories.

If you do not specify a location for the temporary file, then the module uses the
default system temporary directory defined by the %TEMP% environment variable.

Retrieving the Status of a File on Managed Hosts


The win_stat module returns a hash/dictionary of values containing the file status data. Use this
information to examine the output data for specific attributes and values.

- name: Check the information on the file if the file exists


win_stat:
path: C:\Temp\test.conf
register: testfile

- name: Print results of win_stat


debug:
var: testfile

The following example shows the output of the win_stat module.

"testfile": {
"changed": false,
"failed": false,

DO417-RHAE2.8-en-1-20200106 291
Chapter 7 | Deploying Files to Managed Hosts

"stat": {
"attributes": "Archive",
"checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
"creationtime": 1567356109.3531778,
"exists": true,
"extension": ".conf",
"filename": "test.conf",
"hlnk_targets": [],
"isarchive": true,
"isdir": false,
"ishidden": false,
"isjunction": false,
"islnk": false,
"isreadonly": false,
"isreg": true,
"isshared": false,
"lastaccesstime": 1567356109.3531778,
"lastwritetime": 1567356195.2883112,
"nlink": 1,
"owner": "BUILTIN\\Administrators",
"path": "C:\\Temp\\test.conf",
"size": 0
}
}

The following is a more practical example set of tasks:

- name: Collect the information on C:\Temp\test.conf


win_stat:
path: C:\Temp\test.conf
register: testfile

- name: Print C:\Temp\test.conf checksum


debug:
msg: The checksum of test.conf is {{ testfile['stat']['checksum'] }}

Modifying File Attributes


Use the win_owner module to change the ownership of a file or directory, and the win_acl
module to manage file permissions.

The following task demonstrates changing the ownership of the C:\Temp\folder directory. If
you want to change the owner of all the files and directories in the C:\Temp\folder directory,
then use the recurse: true option, which is set to false by default.

- name: Change the ownership of the directory


win_owner:
path: C:\Temp\folder
user: SYSTEM
recurse: false

To modify the ACL of a file, use the win_acl module.

292 DO417-RHAE2.8-en-1-20200106
Chapter 7 | Deploying Files to Managed Hosts

- name: Prevent user Robin from having any access to a directory


win_acl:
path: C:\Confidential
user: Robin
rights: Read,Write,Modify,FullControl,Delete
type: deny
state: present

Note
For more information about Windows file system permissions, visit the
FileSystemRights Enum page accessible at https://msdn.microsoft.com/en-
us/library/system.security.accesscontrol.filesystemrights.aspx

Copying Files on Managed Hosts


In the following example, the win_copy module copies a file located on the Ansible control node
(for example, the Ansible Tower server) to the managed hosts.

By default this module assumes that the force: yes parameter is set. This parameter forces the
module to overwrite the remote file if it exists and contains content that is different from the file
being copied. If force is set to no, then Ansible only copies the file to the managed host if it does
not already exist.

In the following example, Ansible copies the file test.conf from the files directory where the
playbook resides, to C:\Temp\test.conf on the Microsoft Windows managed hosts.

- name: Copy a single file


win_copy:
src: files/test.conf
dest: C:\Temp\test.conf

Note
If you are copying large files, consider hosting them on a web server and using the
win_get_url module, instead of the win_copy module. The win_copy module
runs over WinRM which is not a very efficient transport mechanism.

Copy Files on Managed Hosts


The win_robocopy module is a wrapper around the Robust File Copy for Windows (Robocopy)
mechanism, which is available in all modern Microsoft Windows operating environments. Use this
module to copy files from one directory on the remote machine to another.

- name: Synchronize the contents of one directory with another


win_robocopy:
src: C:\Temp
dest: D:\New
recurse: yes

DO417-RHAE2.8-en-1-20200106 293
Chapter 7 | Deploying Files to Managed Hosts

Retrieving Build Version Files


The following example demonstrates using the win_file_version module to collect the build
version of DLLs and .exe files.

- name: Checking the version of cmd.exe


win_file_version:
path: C:\Windows\System32\cmd.exe
register: version

- debug:
msg: '{{ version }}'

Finding files on Windows Managed Hosts


Use the win_find module to search for files based on specific criteria. You can use several
criteria to find a file.

The following example uses the win_find module to search for all files with names matching
a specific pattern. This specific pattern instructs Ansible to locate all log files, and command or
execution output. All files must be one gigabyte or more in size, and hidden files are included.

- name: Search for a file


win_find:
paths: C:\Temp
hidden: yes
recurse: yes
patterns: [ '*.log', '*.out' ]
size: 1g

Unzipping Files
Use the win_zip module to unzip compressed files and archives. This module natively supports
.zip files. If the PowerShell Community Extensions (PSCX) module is installed, then
the win_zip module supports all files that 7zip supports. Additionally, installation of the PSCX
module is required in order to use the recurse option.

The following example uses the win_psmodule to install the PSCX module:

- name: Install PSCX module


win_psmodule:
name: pscx
state: present

The next example invokes the win_unzip module to recursively unzip compressed files and
delete the ZIP archive when complete:

- name: Unzip gz log files


win_unzip:
src: C:\Logs\logs.gz
dest: C:\Logs\extraced\applicationlogs
delete_archive: true
recurse: true

294 DO417-RHAE2.8-en-1-20200106
Chapter 7 | Deploying Files to Managed Hosts

Editing Files on Managed Hosts


To ensure a specific line of text is present in an existing file, use the win_lineinfile module:

- name: Modifying a line in the service file


win_lineinfile:
path: C:\Temp\service
regexp: '^# port for rdp'
insertbefore: '^www.*8080/tcp'
line: '# line modified by ansible'

Creating shortcuts on Windows Managed Hosts


Use the win_shortcut module to create shortcuts on your systems, as shown in the following
example:

- name: Create an application shortcut on the desktop


win_shortcut:
src: '%ProgramFiles(x86)%\Google\Chrome\Application\chrome.exe'
dest: '%UserProfile%\Desktop\Ansible Tower.lnk'
args: --new-window http://tower.example.com/
directory: '%ProgramFiles(x86)%\Google\Chrome\Application'
icon: '%ProgramFiles(x86)%\Google\Chrome\Application\chrome.exe,0'

Indicates the icon to use. The file name is followed by a comma and the number in the library
file (.dll), or use 0 for an image file.

References
Windows modules — Ansible Documentation
https://docs.ansible.com/ansible/latest/modules/list_of_windows_modules.html

robocopy — Windows Commands


https://docs.microsoft.com/en-us/windows-server/administration/windows-
commands/robocopy

Pscx — PowerShell Gallery


https://www.powershellgallery.com/packages/Pscx/3.3.2

DO417-RHAE2.8-en-1-20200106 295
Chapter 7 | Deploying Files to Managed Hosts

Guided Exercise

Modifying and Transferring Files on


Hosts
In this exercise, you will write plays that get information about files, create, copy, modify, and
delete them, and set ownership and file permissions on them.

Outcomes
You should be able to:

• Create directories on managed hosts.

• Copy a zip file to a managed host and unzip it.

• Copy files from one directory to another on a managed host.

• Create a shortcut.

• Modify file ownership and permissions.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Red Hat
Ansible Tower and GitLab from the Windows workstation.

1. Open the Visual Studio Code editor and clone the managing-files repository to your
workstation.

1.1. From workstation, open the Visual Studio Code editor from the icon on the desktop.
Alternatively, click Search Windows, search for code, and then open Visual Studio
Code.

1.2. To open the command palette, navigate to View → Command Palette or press
Ctrl+Shift+P.
Type clone, and then select Git: Clone to clone a repository.

1.3. When prompted, provide the repository URL, https://gitlab.example.com/


student/managing-files.git, and then select the Documents folder in the
home directory of the training user as the repository location. This clones the
remote repository into the managing-files folder on the workstation instance.

1.4. When prompted to open the project, click Open.

2. Open the unzip.yml playbook, and then add tasks to deploy the contents of a zip file to
the win1 managed host.

296 DO417-RHAE2.8-en-1-20200106
Chapter 7 | Deploying Files to Managed Hosts

2.1. Add a new Temp directory created task that uses the win_file module to
ensure that the C:\Temp\DO417\payload directory exists. Ansible will create the
directory if it does not exist.

- name: Temp directory created


win_file:
path: C:\Temp\DO417\payload
state: directory

2.2. Add a second task that transfers the files/example.zip file from the clone of the
managing-files Git repository on Red Hat Ansible Tower, to the C:\Temp\DO417
directory on the managed host.

- name: Zip archive is copied


win_copy:
src: files/example.zip
dest: C:\Temp\DO417\example.zip

2.3. Add a final Zip archive is unzipped task to unzip the example.zip archive into
the C:\Temp\DO417\payload directory.

- name: Zip archive is unzipped


win_unzip:
src: C:\Temp\DO417\example.zip
dest: C:\Temp\DO417\payload
delete_archive: yes

2.4. Review the YAML file and verify that your playbook matches the tasks below.

---
- name: Example archive deployed and permissions set
hosts: win1.example.com
tasks:
- name: Temp directory created
win_file:
path: C:\Temp\DO417\payload
state: directory

- name: Zip archive is copied


win_copy:
src: files/example.zip
dest: C:\Temp\DO417\example.zip

- name: Zip archive is unzipped


win_unzip:
src: C:\Temp\DO417\example.zip
dest: C:\Temp\DO417\payload
delete_archive: yes

3. Save and commit the changes to your local Git repository, and then push them to the
remote repository.

DO417-RHAE2.8-en-1-20200106 297
Chapter 7 | Deploying Files to Managed Hosts

3.1. To save the file, navigate to File → Save or press Ctrl+S.

3.2. Navigate to the Source Control pane and stage the changes.

3.3. Enter a brief commit message, and then press Ctrl+Enter to commit the changes.

3.4. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to
push your local changes to the remote repository, and retrieve any new changes from
the repository.

4. From workstation, access your Red Hat Ansible Tower instance at http://
tower.example.com. Connect as the student user with RedHat123@! as the password.

5. Run your playbook using the Run managing-files project job template.

5.1. In the navigation pane, click Templates.

5.2. Click the Run managing-files project job template.

5.3. Select the unzip.yml playbook from the PLAYBOOK list.

5.4. Click SAVE to update the template, and then click LAUNCH to run the job.

5.5. After all tasks have completed, verify that the status in the DETAILS pane displays
Successful.

6. Connect to the win1.example.com managed host to inspect the unarchived files.

6.1. Click Search Windows, search for remote, and then open Remote Desktop
Connection.

6.2. Enter win1.example.com as the computer, devops as the user name, and
RedHat123@! as the password. Note that the devops user is a local user, not a
domain user, so do not include the EXAMPLE domain.

6.3. When prompted, click Yes to accept the insecure certificate used in your classroom
environment.

6.4. Open File Explorer and navigate to the C:\Temp\DO417\payload directory.


Examine the the text document and two PowerShell scripts that Ansible unzipped.

298 DO417-RHAE2.8-en-1-20200106
Chapter 7 | Deploying Files to Managed Hosts

6.5. Right-click on the example.txt file, select Properties, and then click on Security.

6.6. Review the file permissions for the various users and groups. Notice that the SYSTEM
and Administrators groups have Full control permissions.

DO417-RHAE2.8-en-1-20200106 299
Chapter 7 | Deploying Files to Managed Hosts

Click Cancel to close the example Properties dialog box.

6.7. Close the win1.example.com remote desktop connection.

7. Edit the unzip.yml playbook to copy the files to the desktop, create a shortcut for the
text file, and modify permissions and ownership.

7.1. Return to Visual Studio Code and open the unzip.yml playbook.

7.2. Add a new task, Payload is copied to the Desktop, to copy files in the C:
\Temp\DO417\payload directory to the C:\Users\devops\Desktop\example
directory using RoboCopy.

- name: Payload is copied to the Desktop


win_robocopy:
src: C:\Temp\DO417\payload
dest: C:\Users\devops\Desktop\example

7.3. Add a Shortcut created task to create a shortcut on the desktop that links to the
text file in the example directory.

- name: Shortcut created


win_shortcut:
src: '%UserProfile%\Desktop\example\example.txt'
dest: '%UserProfile%\Desktop\example-txt.lnk'

7.4. Add a task that invokes the win_acl module to deny write permission to the
example.txt text file.

300 DO417-RHAE2.8-en-1-20200106
Chapter 7 | Deploying Files to Managed Hosts

- name: Example.txt write permissions are denied


win_acl:
path: C:\Users\devops\Desktop\example\example.txt
user: devops
rights: Write
type: deny
state: present

7.5. Use the win_acl module to add a ReadAndExecute deny rule, denying permission to
open and execute the not-runnable.ps1 PowerShell script.

- name: Not-runnable.ps1 execution is denied


win_acl:
path: C:\Users\devops\Desktop\example\not-runnable.ps1
user: devops
rights: ReadAndExecute
type: deny
state: present

7.6. Finally, add a task that invokes the win_owner module to change the owner of the
runnable.ps1 PowerShell script.

- name: Runnable.ps1 is owned by SYSTEM


win_owner:
path: C:\Users\devops\Desktop\example\runnable.ps1
user: SYSTEM

7.7. Review the completed YAML file and verify that your playbook matches the tasks
below.

---
- name: Example archive deployed and permissions set
hosts: win1.example.com
tasks:
- name: Temp directory created
win_file:
path: C:\Temp\DO417\payload
state: directory

- name: Zip archive is copied


win_copy:
src: files/example.zip
dest: C:\Temp\DO417\example.zip

- name: Zip archive is unzipped


win_unzip:
src: C:\Temp\DO417\example.zip
dest: C:\Temp\DO417\payload

DO417-RHAE2.8-en-1-20200106 301
Chapter 7 | Deploying Files to Managed Hosts

delete_archive: yes

- name: Payload is copied to the Desktop


win_robocopy:
src: C:\Temp\DO417\payload
dest: C:\Users\devops\Desktop\example

- name: Shortcut created


win_shortcut:
src: '%UserProfile%\Desktop\example\example.txt'
dest: '%UserProfile%\Desktop\example-txt.lnk'

- name: Example.txt write permissions are denied


win_acl:
path: C:\Users\devops\Desktop\example\example.txt
user: devops
rights: Write
type: deny
state: present

- name: Not-runnable.ps1 execution is denied


win_acl:
path: C:\Users\devops\Desktop\example\not-runnable.ps1
user: devops
rights: ReadAndExecute
type: deny
state: present

- name: Runnable.ps1 is owned by SYSTEM


win_owner:
path: C:\Users\devops\Desktop\example\runnable.ps1
user: SYSTEM

8. Save and commit the changes to your local Git repository, and then push them to the
remote repository.

8.1. Save the file.

8.2. Navigate to the Source Control pane, and then stage the changes.

8.3. Enter a brief commit message, and then commit the changes.

8.4. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to
push your local changes to the remote repository, and retrieve any new changes from
the repository.

9. Return to Red Hat Ansible Tower and execute your playbook again.

9.1. In the Ansible Tower navigation pane, click Templates.

9.2. Click the rocket icon in the Run managing-files project job template row to re-
execute the job with the updated playbook.

302 DO417-RHAE2.8-en-1-20200106
Chapter 7 | Deploying Files to Managed Hosts

9.3. After all tasks are complete, verify that the status in the DETAILS pane displays
Successful. If the job was not successful, compare your work with the solutions/
unzip.sol solution file in the managing-files Git repository.

10. Reconnect to the win1.example.com managed host to review the file modifications.

10.1. Click Search Windows, search for remote, and then open Remote Desktop
Connection.

10.2.Enter win1.example.com for the computer, devops as the user name, and
RedHat123@! as the password. Note that the devops user is a local user, not a
domain user, so do not include the EXAMPLE domain.

10.3.When prompted, click Yes to accept the insecure certificate used in your classroom
environment.

10.4.Double-click on the example-txt shortcut on the Desktop to open the text file
located in the example folder. Close the Notepad application after confirming that the
file opens correctly.

DO417-RHAE2.8-en-1-20200106 303
Chapter 7 | Deploying Files to Managed Hosts

10.5.Open the example folder on the Desktop and observe that the files from our
example.zip archive are all present.

10.6.Right-click on the example.txt document, select Properties, and then click on


Security to inspect the file permissions.

304 DO417-RHAE2.8-en-1-20200106
Chapter 7 | Deploying Files to Managed Hosts

Select the devops user and notice that the Write permission is denied.

Click Cancel to close the example Properties dialog box.

10.7. Double-click the example.txt file to open it in Notepad. Validate that the file is not
writable by attempting to save the file. In Notepad, select File → Save and then click
Save to save the file.

DO417-RHAE2.8-en-1-20200106 305
Chapter 7 | Deploying Files to Managed Hosts

Click Yes to confirm your intention to replace the example.txt file. When prompted,
click Yes.

A window displays a message that you do not have permission to write to the file, which
is the expected behavior.

306 DO417-RHAE2.8-en-1-20200106
Chapter 7 | Deploying Files to Managed Hosts

Important
Ansible directed the managed host to deny write permissions to the example.txt
file. The error indicates that Windows blocked the write action and that the Ansible
task was successful.

10.8.Inspect the file permissions for the not-runnable.ps1 PowerShell script. Right-click
on the file, select Properties, and then click Security.

Notice the informational warning that displays: "You must have Read permissions to
view the properties of this object." This warning is expected, because Ansible denied
the devops user permission to ReadAndExecute the file.

DO417-RHAE2.8-en-1-20200106 307
Chapter 7 | Deploying Files to Managed Hosts

Click Advanced, and then click Continue to view a list of the applied permissions.

Notice that the permission entry for the devops user displays a deny rule for Read &
execute access.

308 DO417-RHAE2.8-en-1-20200106
Chapter 7 | Deploying Files to Managed Hosts

Click Cancel twice to close the properties dialog box.

10.9.Attempt to run the not-runnable.ps1 PowerShell script to verify that Windows


denies requests to execute this script. Right-click on the not-runnable.ps1 script,
and then select Run with PowerShell from the menu.

PowerShell starts and then closes with no action. This is expected successful behavior.

Important
Ansible directed the managed host to deny the devops user permission to open and
execute the not-runnable.ps1 PowerShell script. No action is expected.

10.10.Validate the file ownership of the runnable.ps1 PowerShell script. Right-click on the
file, select Properties, and then click on Security.

DO417-RHAE2.8-en-1-20200106 309
Chapter 7 | Deploying Files to Managed Hosts

Click the Advanced button to view more detailed security information.

Notice that the owner is the SYSTEM user group.

310 DO417-RHAE2.8-en-1-20200106
Chapter 7 | Deploying Files to Managed Hosts

10.11.Verify that Windows executes the runnable.ps1 PowerShell script. Right-click on the
runnable.ps1, and then select Run with PowerShell from the menu.

A new window announces that the example script ran successfully.

10.12.Close the win1.example.com remote desktop connection.

11. Clean up your work by running the cleanup-unzip.yml playbook from the Run
managing-files project job template.

11.1. In the navigation pane, click Templates.

11.2. Click the Run managing-files project job template to open it.

11.3. Select the cleanup-unzip.yml playbook from the PLAYBOOK list.

11.4. Click SAVE to update the template, and then click LAUNCH to run the job.

DO417-RHAE2.8-en-1-20200106 311
Chapter 7 | Deploying Files to Managed Hosts

This concludes the guided exercise.

312 DO417-RHAE2.8-en-1-20200106
Chapter 7 | Deploying Files to Managed Hosts

Templating Files with Jinja2

Objectives
After completing this section, you should be able to use Jinja2 templates to deploy customized
files to managed hosts.

Templating Files
Ansible has a number of modules that can be used to modify existing files. These include
win_lineinfile and assemble, among others. However, they are not always easy to use
effectively and correctly.

A much more powerful way to manage files is to template them. With this method, you write a
template configuration file that is automatically customized for the managed host when the file
is deployed, using Ansible variables and facts. This approach is easier to manage and less error-
prone than manually authoring each file.

Introducing Jinja2
Ansible uses the Jinja2 templating system for template files. Ansible also uses Jinja2 syntax to
reference variables in playbooks, so you already have some familiarity with it.

Using Delimiters
Variables and logic expressions are placed between tags, or delimiters. For example, Jinja2
templates use {% EXPR %} for expressions or logic (for example, loops), and use {{ EXPR }}
for outputting the results of an expression or a variable to the end user. The latter tag, when
rendered, is replaced with a value or values and is seen by the end user. Use {# COMMENT #}
syntax to enclose comments that should not appear in the final file.

In the following example, the first line includes a comment that is excluded in the final file. The
values of referenced system facts replace the variable references in the second line.

{# Generate a %SystemRoot%\System32\drivers\etc\hosts line #}


{{ ansible_facts['default_ipv4']['address'] }} {{ ansible_facts['hostname'] }}

Building a Jinja2 template


A Jinja2 template is composed of multiple elements: data, variables, and expressions. Values
replace those variables and expressions when the Jinja2 template is rendered. The variables used
in the template are specified in the vars section of the playbook. Facts from managed hosts can
also be used as variables on a template.

Note
Remember that output from the setup module facilitates reviewing the facts
associated with managed hosts, because this module runs and gathers facts by
default. For more information review Managing Facts.

DO417-RHAE2.8-en-1-20200106 313
Chapter 7 | Deploying Files to Managed Hosts

The following example shows how to create a template for an HTML file with variables and facts
retrieved by Ansible from managed hosts. When the associated playbook is executed, any facts are
replaced by their values in the managed host being configured.

Note
A file containing a Jinja2 template does not require any specific file extension
(for example, .j2). However, providing such a file extension can make it easier to
recognize the template file.

<!doctype html>
<!-- {{ ansible_managed }} -->

<html lang="en">
<head>
<meta charset="utf-8">
<title>Info</title>
</head>
<body>
<h1>{{ ansible_facts['hostname'] }}</h1>

<ul>
<li>IP: {{ ansible_facts['ip_addresses'][0] }}</li>
<li>OS: {{ ansible_facts['os_name'] }}</li>
<li>Data Center: {{ data_center }}</li>
</ul>

</body>
</html>

Deploying Jinja2 Templates


Jinja2 templates are a powerful tool for customizing configuration files for deployment to
managed hosts. After creating the Jinja2 template for a configuration file, deploy it to the
managed hosts using win_template module, which supports the transfer of a local file from the
control node to the managed hosts.

Use the following syntax when working with the win_template module. The value associated
with the src key specifies the source Jinja2 template; in this example, the source is the
templates directory relative to the playbook. The value associated with the dest key specifies
the file to create on the destination hosts.

tasks:
- name: template render
win_template:
src: templates/info.j2
dest: C:\Inetpub\wwwroot\info.html

314 DO417-RHAE2.8-en-1-20200106
Chapter 7 | Deploying Files to Managed Hosts

Note
By default, the win_template module automatically ensures that the processed
template output follows the Windows standard carriage return line feed newline
sequence. Ansible converts Linux or MacOS template files with \n newline
sequences to \r\n Windows line endings.

To preserve Linux newlines, set the newline_sequence win_template


parameter to \n.

Managing Templated Files


To prevent system administrators from modifying files deployed by Ansible, it is a good practice
to include a comment at the top of the template indicating that the file should not be manually
edited.

One way to do this is to use the “Ansible managed” string set in the ansible_managed directive.
This is not a normal variable, but can be used as one in a template. Set the ansible_managed
directive in the ansible.cfg file:

ansible_managed = Ansible managed

To include the ansible_managed string inside a Jinja2 template, use the following syntax:

{{ ansible_managed }}

Describing Control Structures


Use Jinja2 control structures in template files to reduce repetitive typing, to dynamically create
entries for each host in a play, or to conditionally insert text into a file.

Providing Conditional Control


Jinja2 uses the if statement to provide conditional control. This allows you to put a line in a
deployed file, but only when certain conditions are met.

In the following example, the value of the result variable is placed in the deployed file only if the
value of the finished variable is True.

{% if finished %}
{{ result }}
{% endif %}

Iterating over Lists with Loops


Jinja2 uses the for statement to provide looping functionality. In the following example, the user
variable is replaced with all the values included in the users variable, one value per line.

{% for user in users %}


{{ user }}
{% endfor %}

DO417-RHAE2.8-en-1-20200106 315
Chapter 7 | Deploying Files to Managed Hosts

The following example template uses a for statement to run through all the values in the users
variable, replacing myuser with each value, except when the value is Administrator.

{# for statement #}
{% for myuser in users if not myuser == "Administrator" %}
User number {{ loop.index }} - {{ myuser }}
{% endfor %}

The loop.index variable expands to the index number on which the loop is currently running. It
has a value of 1 the first time the loop executes, and it increments by 1 through each iteration.

As another example, this template also uses a for statement, and assumes a myhosts variable is
defined in the current inventory file. This variable contains a list of hosts to be managed. With the
following for statement, all hosts in the myhosts group from the inventory are listed in the file.

{% for myhost in groups['myhosts'] %}


{{ myhost }}
{% endfor %}

For a more practical example, you can use this approach to dynamically generate a C:\Windows
\System32\drivers\etc\hosts file from host facts. Assume that you have the following
playbook:

- name: hosts file is up to date


hosts: all
gather_facts: yes
tasks:
- name: Hosts file is updated
win_template:
src: templates/hosts.j2
dest: C:\Windows\System32\drivers\etc\hosts

The following three line templates/hosts.j2 template constructs the file from all hosts in the
group all. In this example, the middle line in the template is extremely long, due to the length
of the variable names. Ansible iterates over each host in the group to get three facts for the C:
\Windows\System32\drivers\etc\hosts file.

{% for host in groups['all'] %}


{{ hostvars['host']['ansible_facts']['ip_addresses'][0] }} {{ hostvars['host']
['ansible_facts']['fqdn'] }} {{ hostvars['host']['ansible_facts']['hostname'] }}
{% endfor %}

Important
You can use Jinja2 loops and conditionals in Ansible templates, but not in Ansible
Playbooks.

Transforming Formats with Filters


Jinja2 provides filters that change the output format for template expressions. Filters are available
for languages such as YAML and JSON. The to_json filter formats the expression output using
JSON. The to_yaml filter formats the expression output using YAML.

316 DO417-RHAE2.8-en-1-20200106
Chapter 7 | Deploying Files to Managed Hosts

{{ output | to_json }}
{{ output | to_yaml }}

Additional filters are available, such as the to_nice_json and to_nice_yaml filters, which
format a human readable output in either JSON or YAML format.

{{ output | to_nice_json }}
{{ output | to_nice_yaml }}

Both the from_json and from_yaml filters expect strings in either JSON or YAML format,
respectively, to parse them.

{{ output | from_json }}
{{ output | from_yaml }}

References
win_template - Templates a file out to a remote server — Ansible
Documentation
https://docs.ansible.com/ansible/latest/modules/win_template_module.html

Variables — Ansible Documentation


https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html

Filters — Ansible Documentation


https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html

DO417-RHAE2.8-en-1-20200106 317
Chapter 7 | Deploying Files to Managed Hosts

Guided Exercise

Templating Files with Jinja2


In this exercise, you will create a simple template file to deploy to each of your managed
hosts, and populate with content customized for each host.

Outcomes
You should be able to use Jinja2 templates to deploy dynamic content to managed hosts.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Red Hat
Ansible Tower and GitLab from the Windows workstation.

Ensure that the win2.example.com host is listed in Default inventory.

1. Open the Visual Studio Code editor and clone the managing-files repository to your
workstation.

1.1. From workstation, double-click the Visual Studio Code editor desktop icon.
Alternatively, click Search Windows, search for code, and then open Visual Studio
Code.

1.2. To open the command palette, navigate to View → Command Palette or press
Ctrl+Shift+P.
Type clone and select Git: Clone to clone a repository.

1.3. When prompted, provide the repository URL, https://gitlab.example.com/


student/managing-files.git, and then select the Documents folder in the
home/student directory as the repository location. This clones the remote repository
into the managing-files folder on the workstation instance.

1.4. When prompted to open the project, click Open.

2. Open the hosts.j2 Jinja2 template file in the templates folder.


Windows uses the hosts file to map host names to IP addresses. The hosts.j2 template
file instructs Windows to resolve www1.example.com and www2.example.com to the
localhost IP address 127.0.0.1.
Additionally, notice the Hosts and Update At comments at the top of the file. Hosts file
comments are prefixed with a # symbol.

3. Replace the CHANGE_ME text on the first line with a template expression that evaluates to
the host name of the managed host.

318 DO417-RHAE2.8-en-1-20200106
Chapter 7 | Deploying Files to Managed Hosts

# Host: {{ ansible_facts['hostname'] }}

4. Replace the CHANGE_ME text on the second line with a template expression that evaluates
to the current date and time.

# Updated At: {{ now() }}

5. Update the hosts.j2 template to resolve the custom host names to the IPs of the win1
and win2 managed hosts. Replace 127.0.0.1 on each line with a template expression
wrapped in double curly braces, as follows:

{{ hostvars['win1.example.com'].ansible_facts.ip_addresses[0] }} www1.example.com
{{ hostvars['win2.example.com'].ansible_facts.ip_addresses[0] }} www2.example.com

Ansible stores gathered facts for each managed host in the


hostvars['host'].ansible_facts dictionary.

Note
The name of this dictionary can also use square bracket notation throughout, for
example:

hostvars['host']['ansible_facts']

However, to avoid line wraps in the example text, this syntax is not used in this
exercise.

6. Verify that the final hosts.j2 file matches the following Jinja2 template, and then select
File → Save or press Ctrl+S to save the file.

# Host: {{ ansible_facts['hostname'] }}
# Updated At: {{ now() }}

{{ hostvars['win1.example.com'].ansible_facts.ip_addresses[0] }} www1.example.com
{{ hostvars['win2.example.com'].ansible_facts.ip_addresses[0] }} www2.example.com

7. Open the hosts.yml playbook. Add tasks to update the IIS Web Server content, and then
deploy the templates/hosts.j2 template to the Windows managed host.

---
- name: Web server with custom hosts file deployed
hosts: all
tasks:
- name: IIS Web Server started
win_feature:

DO417-RHAE2.8-en-1-20200106 319
Chapter 7 | Deploying Files to Managed Hosts

name: Web-Server
state: present

- name: Index file is created


win_copy:
content: "Hello from {{ ansible_hostname }}!"
dest: C:\Inetpub\wwwroot\index.html

- name: Hosts file template deployed


win_template:
src: templates/hosts.j2
dest: C:\Windows\System32\drivers\etc\hosts
backup: yes

Task invoking the win_copy module to create an index.html file and write a host-
specific message.
Task invoking the win_template module to process the Jinja2 template and write
the output to a file.
Declares the template location using the src parameter.
Adds a dest parameter to specify a destination on the managed Windows hosts.
Because the destination is a Windows managed host, use a path with the appropriate
backslashes and any required escape characters.
Add the backup parameter to save a time-stamped backup of the file.

8. Save and commit the changes to your local Git repository, and then push them to the
remote repository.

8.1. To save the file, click File → Save or press Ctrl+S.

8.2. Navigate to the Source Control pane, and then click + to stage the changes to both
hosts.yml and hosts.j2.

8.3. Enter a brief commit message, and then press Ctrl+Enter to commit the changes.

8.4. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to
push your local changes to the remote repository, and retrieve any new changes from
the repository.

9. From workstation, access your Red Hat Ansible Tower instance at http://
tower.example.com. Login as the student user with the RedHat123@! password.

10. Use the Run managing-files project job template to run your playbook.

10.1. In the navigation pane, click Templates.

10.2.Click the Run managing-files project job template.

10.3.Select the hosts.yml playbook from the PLAYBOOK list.

320 DO417-RHAE2.8-en-1-20200106
Chapter 7 | Deploying Files to Managed Hosts

10.4.Click SAVE to update the template, and then click LAUNCH to run the job.

11. After all tasks have completed, verify that the status in the DETAILS pane displays
Successful. If the job was not successful, compare your work with the solutions/
hosts.sol and solutions/templates/hosts.j2.sol solution files in the
managing-files Git repository.

12. Connect to the win1.example.com managed host to verify the deployment of the hosts
file.

12.1. Click Search Windows, search for remote, and then open Remote Desktop
Connection.

12.2. Enter win1.example.com for the computer, devops as the user name, and
RedHat123@! as the password. Note that devops is a local user, not a domain user, so
do not include the EXAMPLE domain.

12.3. When prompted, click Yes to accept the insecure certificate used in your classroom
environment.

12.4. Open File Explorer, and navigate to the C:\Windows\System32\drivers\etc


\hosts text document. Right-click on the file to open it, and then select Notepad
when prompted with a list of applications.

DO417-RHAE2.8-en-1-20200106 321
Chapter 7 | Deploying Files to Managed Hosts

12.5. Open Internet Explorer and navigate to www1.example.com.

12.6. Navigate to www2.example.com and confirm that the domain resolves correctly to
the WIN2 host.

322 DO417-RHAE2.8-en-1-20200106
Chapter 7 | Deploying Files to Managed Hosts

12.7. Close the win1.example.com remote desktop connection.

13. Connect to the win2.example.com managed host, and then verify deployment of the
hosts file on the win2 managed host.

13.1. Click Search Windows, search for remote, and then open Remote Desktop
Connection.

13.2. Enter win2.example.com for the computer, devops as the user name, and
RedHat123@! as the password. Note that devops is a local user, not a domain user, so
do not include the EXAMPLE domain.

13.3. When prompted, click Yes to accept the insecure certificate used in your classroom
environment.

13.4. Open File Explorer, and then navigate to the C:\Windows\System32\drivers


\etc\hosts text document. Right-click on the file to open it, and then select
Notepad when prompted with a list of applications.

13.5. Open Internet Explorer and navigate to www1.example.com.

DO417-RHAE2.8-en-1-20200106 323
Chapter 7 | Deploying Files to Managed Hosts

13.6. Navigate to www2.example.com and confirm that the domain resolves correctly to
the WIN2 host.

13.7. Close the win2.example.com remote desktop connection.

14. Run the cleanup-hosts.yml playbook from the Run managing-files project job
template to clean up your work.

14.1. In the navigation pane, click Templates.

14.2.Click the Run managing-files project job template.

14.3.Select the cleanup-hosts.yml playbook from the PLAYBOOK list.

324 DO417-RHAE2.8-en-1-20200106
Chapter 7 | Deploying Files to Managed Hosts

14.4.Click SAVE to update the template, and then click LAUNCH to run the job.

This concludes the guided exercise.

DO417-RHAE2.8-en-1-20200106 325
Chapter 7 | Deploying Files to Managed Hosts

Lab

Deploying Files to Managed Hosts


Performance Checklist
In this lab, you will write a playbook that creates a file on your managed hosts, which is
customized using a Jinja2 template, and configured with appropriate file permissions.

Outcomes
You should be able to:

• Use Jinja2 templates to deploy dynamic content to managed hosts.

• Modify file permissions for a specified user or group.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. From the Windows workstation, open the Visual Studio Code editor and clone the
managing-files repository, https://gitlab.example.com/student/managing-
files.git, to C:\Users\student\Documents\managing-files, if the folder is not
already present.
2. Update the templates/index.html.j2 Jinja2 template to display information about the
managed host as follows:

• The HTML comment at the top of the file inserts the ansible_managed variable.

• The h1 element displays the host name.

• The OS definition tag displays the os_name fact.

• The Memory definition tag displays the memtotal_mb fact.

• The Processor vCPUs definition tag displays the processor_vcpus fact.

• The Processor Cores definition tag displays the processor_cores fact.


3. Define tasks in the review.yml playbook file to:

• Ensure the presence of the IIS Web Server feature.

• Deploy the templates/index.html.j2 Jinja2 template to C:\Inetpub\wwwroot


\index.html on the managed host.

• Deny Users on the managed hosts Write access to the index.html file.

326 DO417-RHAE2.8-en-1-20200106
Chapter 7 | Deploying Files to Managed Hosts

Save the review.yml playbook.


4. Commit and push your changes to the remote managing-files repository.
5. From workstation, access your Red Hat Ansible Tower instance at http://
tower.example.com. Log in as the student user the RedHat123@! password.
Add the win2.example.com host to the Default inventory inventory in Ansible Tower
if not added in a previous exercise.
6. Launch your review.yml playbook using the Run managing-files project job
template.
7. Verify that the Run managing-files project job executes successfully. Navigate to
http://win1.example.com and http://win2.example.com to confirm that the web
page is correctly rendered and served.
8. Connect to the win1.example.com managed host to verify that permission to write to C:
\Inetpub\wwwroot\index.html is denied.
9. Launch the cleanup-review.yml playbook from the Run managing-files project
job template.

This concludes the lab.

DO417-RHAE2.8-en-1-20200106 327
Chapter 7 | Deploying Files to Managed Hosts

Solution

Deploying Files to Managed Hosts


Performance Checklist
In this lab, you will write a playbook that creates a file on your managed hosts, which is
customized using a Jinja2 template, and configured with appropriate file permissions.

Outcomes
You should be able to:

• Use Jinja2 templates to deploy dynamic content to managed hosts.

• Modify file permissions for a specified user or group.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. From the Windows workstation, open the Visual Studio Code editor and clone the
managing-files repository, https://gitlab.example.com/student/managing-
files.git, to C:\Users\student\Documents\managing-files, if the folder is not
already present.

Note
The following instructions describe how to clone the managing-files repository.
If you cloned the repository in a previous exercise, then you can skip this step.

1.1. From the Windows workstation, double-click the desktop icon to open Visual Studio
Code.

1.2. To clone the updates repository, navigate to View → Command Palette or press
Ctrl+Shift+P to open the command palette.
Type clone, and then select Git: Clone to clone a repository.
When prompted, provide a repository URL of https://gitlab.example.com/
student/managing-files.git and select the Documents folder in the home
directory of the training user as the repository location. This clones the remote
repository into the managing-files folder on the workstation instance.
Click Open from the window that displays after cloning.

2. Update the templates/index.html.j2 Jinja2 template to display information about the


managed host as follows:

328 DO417-RHAE2.8-en-1-20200106
Chapter 7 | Deploying Files to Managed Hosts

• The HTML comment at the top of the file inserts the ansible_managed variable.

• The h1 element displays the host name.

• The OS definition tag displays the os_name fact.

• The Memory definition tag displays the memtotal_mb fact.

• The Processor vCPUs definition tag displays the processor_vcpus fact.

• The Processor Cores definition tag displays the processor_cores fact.

Open the index.html.j2 Jinja2 template file in the templates folder, and then modify it
to insert variables and facts as follows:

<!doctype html>
<!-- {{ ansible_managed }} -->
<html lang="en">
<head>
<meta charset="utf-8">
<title>Info</title>
<style type="text/css">
dt { font-weight: bold; }
</style>
</head>
<body>
<h1>{{ ansible_facts['hostname'] }}</h1>

<dl>
<dt>OS</dt>
<dd>{{ ansible_facts['os_name'] }}</dd>

<dt>Memory</dt>
<dd>{{ ansible_facts['memtotal_mb'] }}</dd>

<dt>Processor vCPUs</dt>
<dd>{{ ansible_facts['processor_vcpus'] }}</dd>

<dt>Processor Cores</dt>
<dd>{{ ansible_facts['processor_cores'] }}</dd>
</dl>
</body>
</html>

Click File → Save or press Ctrl+S to save the file.


3. Define tasks in the review.yml playbook file to:

• Ensure the presence of the IIS Web Server feature.

• Deploy the templates/index.html.j2 Jinja2 template to C:\Inetpub\wwwroot


\index.html on the managed host.

• Deny Users on the managed hosts Write access to the index.html file.

Save the review.yml playbook.

DO417-RHAE2.8-en-1-20200106 329
Chapter 7 | Deploying Files to Managed Hosts

3.1. Open the review.yml playbook file and modify it to insert content as follows.

---
- name: Deploying Files to Managed Hosts Lab
hosts: all
tasks:
- name: IIS Web Server started
win_feature:
name: Web-Server
state: present

- name: Hosts file template deployed


win_template:
src: templates/index.html.j2
dest: C:\Inetpub\wwwroot\index.html
backup: yes

- name: User write permission is denied


win_acl:
path: C:\Inetpub\wwwroot\index.html
user: Users
rights: Write
type: deny
state: present

Enable the IIS Web Server feature, which will serve the index.html web page.
Invoke the win_template module to deploy the index.html.js template to the
managed host. Use the backup: yes argument to create a time stamped backup.
Add a permission rule that denies the Users group write access to the
index.html file.

3.2. Click File → Save or press Ctrl+S to save the file.


4. Commit and push your changes to the remote managing-files repository.

4.1. From Visual Studio Code, save and stage the files. Navigate to the Source Control
panel, and then click + to stage all changes.

4.2. Type Deploys web page from template as the commit message, and then click
Commit or press Ctrl+Enter to commit your changes.

4.3. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to push
your local changes to the remote repository, and retrieve any new changes from the
repository.

5. From workstation, access your Red Hat Ansible Tower instance at http://
tower.example.com. Log in as the student user the RedHat123@! password.
Add the win2.example.com host to the Default inventory inventory in Ansible Tower
if not added in a previous exercise.

5.1. From workstation, double-click the Ansible Tower desktop icon. Log in to Ansible
Tower using student as the user name and RedHat123@! as the password.

5.2. Click Inventories in the navigation pane.

330 DO417-RHAE2.8-en-1-20200106
Chapter 7 | Deploying Files to Managed Hosts

5.3. Click Default inventory on the INVENTORIES page.

5.4. Click HOSTS.

5.5. If win2.example.com is not already listed in the hosts table, click + to add a new host
to the group. Select New Host from the list.

5.6. On the next screen, complete the details as follows:

Field Value

HOST NAME win2.example.com

5.7. Click SAVE to add the new host.

6. Launch your review.yml playbook using the Run managing-files project job
template.

6.1. In the navigation pane, click Templates.

6.2. Click the Run managing-files project job template.

6.3. Select the review.yml playbook from the PLAYBOOK list.

6.4. Click SAVE to update the template, and then click LAUNCH to run the job.

7. Verify that the Run managing-files project job executes successfully. Navigate to
http://win1.example.com and http://win2.example.com to confirm that the web
page is correctly rendered and served.

7.1. Verify that the status in the DETAILS pane displays Successful. Observe the tasks in
the log that indicate changes have occurred on the managed hosts.

DO417-RHAE2.8-en-1-20200106 331
Chapter 7 | Deploying Files to Managed Hosts

7.2. In Chrome, open a new tab and navigate to http://win1.example.com/. The web
server on the win1 managed host returns the generated index.html web page.

7.3. In Chrome, open a new tab and navigate to http://win2.example.com/. The web
server on the win2 managed host returns the generated index.html web page.

332 DO417-RHAE2.8-en-1-20200106
Chapter 7 | Deploying Files to Managed Hosts

8. Connect to the win1.example.com managed host to verify that permission to write to C:


\Inetpub\wwwroot\index.html is denied.

8.1. Click Search Windows, search for remote, and then open Remote Desktop
Connection.

8.2. Enter win1.example.com for the computer, devops as the user name, and
RedHat123@! as the password. Note that devops is a local user, not a domain user, so
do not include the EXAMPLE domain.

8.3. When prompted, click Yes to accept the insecure certificate used in your classroom
environment.

8.4. In the remote win1.example.com session, click Search Windows and then type C:
\Inetpub\wwwroot to search for the web server root directory. Click the file folder to
open it.

DO417-RHAE2.8-en-1-20200106 333
Chapter 7 | Deploying Files to Managed Hosts

8.5. Right-click on the index.html file, select Properties, and then click on the Security
tab.

8.6. Select Users (WIN1\Users) in the Group or user names panel, and verify that the
Deny is selected for Write permissions.

8.7. Close the win1.example.com remote desktop connection.

9. Launch the cleanup-review.yml playbook from the Run managing-files project


job template.

9.1. In the navigation pane, click Templates.

9.2. Click the Run managing-files project job template.

9.3. Select the cleanup-review.yml playbook from the PLAYBOOK list.

334 DO417-RHAE2.8-en-1-20200106
Chapter 7 | Deploying Files to Managed Hosts

9.4. Click SAVE to update the template, and then click LAUNCH to run the job.

This concludes the lab.

DO417-RHAE2.8-en-1-20200106 335
Chapter 7 | Deploying Files to Managed Hosts

Summary
In this chapter, you learned:

• Ansible includes a number of modules for Microsoft Windows file management, such as creating,
copying, and editing files, as well as management of ACLs and file ownership.

• You can use Jinja2 templates to dynamically construct files for deployment.

• A Jinja2 template is usually composed of two elements: variables and expressions. Those
variables and expressions are replaced with values when the Jinja2 template is rendered.

• Jinja2 filters transform template expressions from one kind or format of data to another.

336 DO417-RHAE2.8-en-1-20200106
Chapter 8

Interacting with Users and


Domains
Goal Manage local and domain users, manage Active
Directory domains, and generate a list of managed
hosts based on domain membership for a Red Hat
Ansible Tower dynamic inventory.

Objectives • Automate creation and management of local


user and group accounts.
• Create an Active Directory domain if it does not
exist, and configure host membership, users,
and groups in that domain.
• Generate an Ansible inventory dynamically
in Red Hat Ansible Tower based on Active
Directory domain membership.

Sections • Managing Local User Accounts (and Guided


Exercise)
• Managing Active Directory Domains (and
Guided Exercise)
• Generating Dynamic Inventories from Active
Directory (and Guided Exercise)

Lab Lab: Interacting with Users and Domains

DO417-RHAE2.8-en-1-20200106 337
Chapter 8 | Interacting with Users and Domains

Managing Local User Accounts

Objectives
After completing this section, you should be able to automate the creation and management of
local user and group accounts.

Managing User Accounts on Windows Systems


The Ansible win_user module allows you manage local user accounts on a remote Windows host.
You can manage several parameters, including removing the user, managing the user's password,
and managing the user's group memberships.

Creating a New Windows Local User Account


The following example illustrates how to add a new local user, and how to associate that user with
the proper local groups.

- name: Add new user to the development machine and assign the appropriate groups.
win_user:
name: devops_user
password: plain_text_password
state: present
groups:
- Users
- Developers
groups_action: replace

The name parameter is the only requirement for the module.


The password parameter optionally sets the user's password. The password value is written
in plain text.
The state parameter set to present instructs Ansible to create or update the user account.
The groups parameter specifies a list of groups (Users and Developers) that, by default,
the user should belong to.
The groups_action parameter controls how the list of groups is interpreted. If not listed,
the default action is replace which means the user will be a member of exactly the groups
listed if the user already exists and is a member of some groups. In the example this is
specified explicitly (a good practice which ensures what will happen is clear).

Removing a Windows Local User Account


The following example illustrates how to remove a local user from a remote system.

- name: Remove a local account


win_user:
name: devops_user
state: absent

The name parameter is the only requirement in the user module.

338 DO417-RHAE2.8-en-1-20200106
Chapter 8 | Interacting with Users and Domains

The state parameter instructs the machine to remove the user account if it exists on the
system.

Commonly Used Parameters of the win_user Module


The win_user module also returns values. Ansible modules can take return values and save them
into a variable. Use this module to query user account details without making any changes to the
system.

The following table describes some commonly used parameters.

Commonly used parameters

Parameter Comments

description Optionally sets the description of a user account.

groups Adds or removes the user from a defined list of groups.

groups_action Controls how the groups parameter is interpreted. If set


to add, the user is added to those groups, but if the user
already exists and is a member of other groups, the user
stays in those groups as well. If set to replace, the user will
be made a member of exactly those groups and removed
from all other groups. If set to remove, the user will be
removed from the listed groups.

account_locked Takes a Boolean value of yes or no. When set to no, unlocks
a user account if locked.

fullname Full name of the user.

password_never_expires Takes a Boolean value of Yes or No. If set to yes, Ansible


sets the password to never expire or if set to no, allows the
password to expire.

update_password always updates the password if it differs. on-create sets


the password for newly created users.

user_cannot_change_password Takes a Boolean value of Yes or No. Prevents the user from
changing their password if the value is set to yes.

state Takes one of three different values. When set to absent, it


removes a user account if it exists. When set to present,
it creates or updates the user account. When set to query,
it retrieves the user account details without making any
changes.

Managing Local User Profiles


Windows requires a user profile for each user account on a computer. Normally, the local user
profile is created for each user when the they log on to the computer for the first time. Using
the Ansible win_user_profile module lets you create or remove the local user profiles on a
Windows host. You can create or remove a profile for a local or a domain account, create a profile
before a user logs on, or delete a profile when a user account does not exist.

DO417-RHAE2.8-en-1-20200106 339
Chapter 8 | Interacting with Users and Domains

Creating a New Local User Profile


The following example illustrates using the win_user_profile module to create a new local
profile for an existing local user.

- name: Create a local profile for an account.


win_user_profile:
username: devops_user
state: present

when the state is set to present, set the username parameter to a valid account name.
When the state parameter set to present, the machine creates or updates the user
account.

Removing a Local User Profile


Remove a profile for an existing account, a deleted account, a deleted account based on the SID,
or multiple profiles that share the same basename path using the win_user_profile module.
The following example illustrates how to remove an existing local user profile for an existing
account.

- name: Remove a local profile for a still valid account.


win_user_profile:
username: devops_user
state: absent

When the state is set to present, the username parameter must be set to a valid account
name.
When the state parameter set to absent, the machine removes the user profile.

The following example illustrates removing an existing local user profile for a deleted account.

- name: Remove a local profile for a deleted account.


win_user_profile:
name: devops_user
state: absent

The name parameter must be set to a valid profile name. Be aware that when the state is set
to absent, and the username is not set, the module removes any profiles contained in the
profile path for the name value.
The state parameter set to absent instructs the machine to remove the user profile.

Important
Remember the important distinction between the win_user_profile module
name and username parameters. The name parameter is the base name for the
profile path. The username parameter is the account name of the security identifier
(SID) for the profile.

Local Groups
The win_group module lets you manage local groups on a Windows host. You can create or
remove a local group with this module.

340 DO417-RHAE2.8-en-1-20200106
Chapter 8 | Interacting with Users and Domains

Creating a New Local Group


The following example illustrates how to use the module to create a new local group.

- name: Create a new local group.


win_group:
name: developers
description: Developers Group
state: present

The name parameter defines the name of the group.


The description parameter describes the purpose of the group.
The state parameter set to present instructs the machine to create the local group.

Removing a Local Group


The following example illustrates how to remove an existing local group.

- name: Remove a local group.


win_group:
name: developers
state: absent

The name parameter defines the name of the group.


The state parameter set to absent instructs the machine to remove the local group.

Managing Windows Local Group Membership


Use the win_group_membership module to add and remove local users, service and domain
users, and domain groups from a local group.

Adding Members to a Local Group


The following example illustrates using the win_group_membership module to add both local
users and domain users to an existing local group.

- name: Adding a local and domain user to a local group.


win_group_membership:
name: developers
members:
- devops
- DOMAIN_NAME\DemoUser
state: present

The name parameter defines the name of the local group.


The members parameter contains a list of possible local users, domain users, or domain
groups that should be added or removed from the local group.
The state parameter sets the desired state of the members in the local group. When set
to pure, only the specified members exist, and all other existing members not specified are
removed.

The members parameter can accept the following items:

• Local users as .\username or SERVERNAME\username.

DO417-RHAE2.8-en-1-20200106 341
Chapter 8 | Interacting with Users and Domains

• Domain users and groups as DOMAIN\username and username@DOMAIN.

• Service users as NT AUTHORITY\username.

• All local, domain, and service user types as username, favoring domain lookups if the host is in a
domain.

Removing Members from a Local Group


The following example illustrates how to use the module to remove a domain group from a local
group.

- name: Remove a domain group from a local group.


win_group_membership:
name: developers
members: DOMAINNAME\DemoGroup
state: absent

The name parameter defines the name of the local group to modify.
The members parameter contains a list of possible local users, domain users or domain
groups that should be removed from the local group.
The state parameter set to absent tells the machine to remove the specified members
from the local group.

References
Windows modules — Ansible Documentation
https://docs.ansible.com/ansible/latest/modules/list_of_windows_modules.html

342 DO417-RHAE2.8-en-1-20200106
Chapter 8 | Interacting with Users and Domains

Guided Exercise

Managing Local User Accounts


In this exercise, you will manage local user accounts on your managed hosts.

Outcomes
You should be able to create a new local user, as well as modify the group membership of an
existing local user.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. Launch the Visual Studio Code editor and clone the ad repository to your workstation
instance.

1.1. Click Search Windows, search for code, and then open Visual Studio Code.

1.2. Click View → Command Palette or press Ctrl+Shift+P to open the command
palette.
Type clone, and then select Git: Clone to clone a repository.
Use a repository URL of https://gitlab.example.com/student/ad.git. When
prompted, select the Documents folder in the home directory of the training user
as the repository location, and then click Select Repository Location. This clones
the remote repository in to the ad folder.
Optionally, select Open from the window that displays after cloning to view the files,
and then skip the next step.

2. Click File → Open Folder, and then open the c:\Users\student\Documents\ad


folder.

3. Edit the localuser.yml file, and then commit your changes. Modify this file so that it
targets all hosts, and uses the win_user module to create a local user John Snow with
RedHat123@! as the password.

3.1. Select the localuser.yml file, and then change the task name and the details for
the new local user that you want to create.

...output omitted...
hosts: all

tasks:

DO417-RHAE2.8-en-1-20200106 343
Chapter 8 | Interacting with Users and Domains

- name: John Snow user is created


win_user:
name: John Snow
password: RedHat123@!
state: present
groups:
- Users

4. Edit the localuser.yml file, and then commit your changes. Add a new task to the
playbook that adds the new local user to the Print operators group. For this task use
the win_group_membership module.

4.1. Select the localuser.yml file, and then change the name of the second task and
the details for the new group to which you want to add the user.

...output omitted...
- name: John Snow added to the Print operators group
win_group_membership:
name: Print operators
members:
- John Snow
state: present

4.2. Click Save. Note the status icons in the lower left. There is an asterisk next to Master
indicating that changes were made.

4.3. Change to the Source Control view, and then click + for localuser.yml to stage
the changes.

4.4. Enter a commit message, and then press Ctrl+Enter to commit the changes.

4.5. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to
push your local changes to the remote repository, and retrieve any new changes from
the repository.
Click Yes or Ask Me Later when prompted.

5. Access the Ansible Tower web console. Use the Run ad project job template to test
your modified Ansible Playbook.

5.1. Double-click the desktop shortcut labeled Ansible Tower and authenticate with the
user admin and RedHat123@! as the password.

5.2. In the navigation pane, click Templates.

5.3. From the list of templates, select the Run ad project template.

5.4. Select the localuser.yml playbook from the PLAYBOOK list.

5.5. Select the PROMPT ON LAUNCH check box near the LIMIT option.

5.6. Click SAVE to update the job template.


Select LAUNCH to begin execution.

5.7. In the RUN AD PROJECT window, type in the win1.example.com host name. Click
NEXT, and then click LAUNCH.

344 DO417-RHAE2.8-en-1-20200106
Chapter 8 | Interacting with Users and Domains

5.8. Observe the live output of the running job.

5.9. Verify that the status of the job in the DETAILS pane displays Successful.

5.10. Click Log Out to exit the Ansible Tower web interface.

This concludes the guided exercise.

DO417-RHAE2.8-en-1-20200106 345
Chapter 8 | Interacting with Users and Domains

Managing Active Directory Domains

Objectives
After completing this section, you should be able to create an Active Directory domain if it does
not exist, and configure host membership, users, and groups in that domain.

Creating Active Directory Domains


You can use Ansible to create and manage Active Directory domains. Using the Ansible
win_domain module, you can create a new domain and a new forest. When you create a new
domain and a new forest, you can specify the domain and the forest functional level. However, the
domain functional level cannot be lower than the forest functional level. After this module makes
changes to your system, you must reboot; use a handler that invokes the win_reboot module to
reboot a Windows machine, and waits for it to go down and then come back up again.

Creating a New Active Directory Domain


The following example illustrates how to create a new domain, including a new forest and the DNS
configuration.

- name: Creates a new Windows domain in a new forest with specific parameters
win_domain:
create_dns_delegation: yes
database_path: C:\Windows\NTDS
dns_domain_name: EXAMPLE.COM
domain_mode: Win2012R2
domain_netbios_name: EXAMPLE
forest_mode: Win2012R2
safe_mode_password: plain_text_password
sysvol_path: C:\Windows\SYSVOL
register: domain_install

- name: Rebooting the server


win_reboot:
msg: "Rebooting..."
when: domain_install.reboot_required

The create_dns_delegation parameter controls the creation of a DNS delegation that


references the new DNS server you install, along with the domain controller. This is only valid
for Active Directory-integrated DNS.
The database_path parameter sets the path to the directory location where the domain
database is created.
The dns_domain_name parameter sets the DNS name of the domain.
The domain_mode parameter sets the domain functional level (available choices are:
Win2003, Win2008, Win2008R2, Win2012, Win2012R2, and WinThreshold).
The domain_netbios_name parameter sets the NetBIOS name for the root domain in the
new forest.
The forest_mode parameter sets the forest functional level for the new forest (available
choices are: Win2003, Win2008, Win2008R2, Win2012, Win2012R2, WinThreshold).

346 DO417-RHAE2.8-en-1-20200106
Chapter 8 | Interacting with Users and Domains

The safe_mode_password parameter sets the safe mode password. This parameter is
required. The password value is written in plain text.
The sysvol_path parameter sets the path to the directory where the Sysvol file is
created.
The register parameter registers the state of the outcome; depending on the state, a
handler might be triggered. In this example, when the state changes, the handler triggers a
reboot.

Creating Additional Active Directory Controllers


You can use Ansible to create and manage Active Directory controllers. Using the Ansible
win_domain_controller module, you can configure a host as a domain controller, or demote it
to a member server. When this module makes changes to your system, a reboot is required; use a
handler that invokes the win_reboot module to reboot a Windows machine, and waits for it to go
down and then come back up again.

Creating a New Active Directory Controller


The following example illustrates how to promote a server to a second domain controller.

- name: Promoting the server to a domain controller.


win_domain_controller:
dns_domain_name: example.com
domain_admin_user: demo_user@example.com
domain_admin_password: plain_text_password
safe_mode_password: plain_text_password
state: domain_controller
register: domain_state

- name: Rebooting the server


win_reboot:
msg: "Rebooting..."
when: domain_state.reboot_required

The dns_domain_name parameter specifies the DNS name of the domain for which the host
is promoted as a domain controller.
The domain_admin_user parameter is required. The parameter specifies the name of the
domain administrative user.
The domain_admin_password parameter is required, and specifies the password for the
user in the domain_admin_user parameter. The password value is written in plain text.
The safe_mode_password parameter is required when promoting a server to a domain
controller. This parameter sets the safe mode password for the controller. The password value
is written in plain text.
The state parameter set to domain_controller instructs Ansible to promote the server
to a domain controller.
The register parameter is used to register the state of the outcome; depending on the
state, a handler might be triggered. In this example, when the state changes, the handler
triggers a reboot.

Depending on your local environment configuration, this Ansible module configures the server as
a read-write domain controller in the existing domain, or it can promote the server as an additional
read-only replica of the existing domain. In order to create a read-only domain controller, you must
add the read_only parameter to the playbook, and set it to yes.

DO417-RHAE2.8-en-1-20200106 347
Chapter 8 | Interacting with Users and Domains

Installing Active Directory Windows Features


The following example illustrates how install Windows Features needed to create and manage
Active Directory services.

- name: Installing AD features.


win_feature:
name: AD-Domain-Services
include_sub_features: yes
include_management_tools: yes
state: present

The name parameter is the only requirement for the module. This parameter specifies which
of the available Windows roles or features to install.
When set to yes, this option adds all the available sub-features of the specified feature.
When set to yes, this option adds all management tools of the corresponding specified
feature.

Demoting a Domain Controller to a Domain Member


You can also use the win_domain_controller module to demote a server from a domain
controller to a domain member. The following example illustrates how to use the module to
demote an existing domain controller to a domain member.

- name: Demoting a domain controller


win_domain_controller:
dns_domain_name: example.com
domain_admin_user: demo_user@example.com
domain_admin_password: plain_text_password
local_admin_password: plain_text_password
state: member_server

The dns_domain_name parameter specifies the domain from which the server will be
demoted.
The domain_admin_user parameter is required. The parameter specifies the name of the
domain administrative user.
The domain_admin_password parameter is required. This parameter specifies the
password for the user in the domain_admin_user parameter. The password value is written
in plain text.
The local_admin_password parameter is required when demoting a server to a domain
member. This parameter sets the local administrator password for the server. The password
value is written in plain text.
The state parameter set to member instructs Ansible to demote the server from a domain
controller to a domain member.

Joining and Removing a Server from an


Active Directory Domain
You can use Ansible to join new hosts to an existing Active Directory domain. Using the Ansible
win_domain_membership module, you can join a host to a domain. When this module makes
changes to your system, you must reboot; use a handler that invokes the win_reboot module,
and waits for it to go down and come back up again.

348 DO417-RHAE2.8-en-1-20200106
Chapter 8 | Interacting with Users and Domains

Joining an Active Directory Domain


The following example illustrates how to join a server to a domain.

- name: Joining a domain


win_domain_membership:
dns_domain_name: EXAMPLE.COM
domain_admin_user: demo_admin@example.com
domain_admin_password: plain_text_password
state: domain
register: domain_state

- name: Rebooting the server


win_reboot:
msg: "Rebooting..."
when: domain_state.reboot_required

The dns_domain_name parameter sets the DNS name of the domain.


The domain_admin_user parameter is required. The parameter specifies the name of the
domain administrative user.
The domain_admin_password parameter is required. This parameter specifies the
password for the user in the domain_admin_user parameter. The password value is written
in plain text.
The state parameter set to domain instructs Ansible to join the server to a domain.
The register parameter is used to register the state of the outcome; depending on the
state, a handler might be triggered. In this example, when the state changes, the handler
triggers a reboot.

Removing a Server from an Active Directory Domain


You can use the same Ansible module to remove a server from a domain. The following example
illustrates how to remove a server from a domain.

- name: Removing the server from the domain


win_domain_membership:
workgroup_name: demo_workgroup
domain_admin_user: demo_admin@example.com
domain_admin_password: plain_text_password
state: workgroup

The workgroup_name parameter sets the name for the workgroup of which the server will
be a part.
The domain_admin_user parameter is required. The parameter specifies the name of the
domain administrative user.
The domain_admin_password parameter is required. This parameter specifies the
password for the user in the domain_admin_user parameter. The password value is written
in plain text.
The state parameter set to workgroup instructs Ansible to remove the server from a
domain.

DO417-RHAE2.8-en-1-20200106 349
Chapter 8 | Interacting with Users and Domains

Creating, Modifying or Removing Objects in an


Active Directory Domain
You can use Ansible to manipulate objects in your Active Directory domain. For example, you can
create, modify, or remove domain users, groups, and computer accounts from your domain.

Managing Active Directory User Accounts


You can use the win_domain_user module to manage domain user accounts. The following
example illustrates how to create or remove a domain user account.

- name: Creating a new domain user account with details


win_domain_user:
name: robert
firstname: Robert
surname: Johnson
company: Demo Inc.
password: plain_text_password
state: present
groups:
- Domain Users
street: 123 14th St.
city: Demotown
state_province: IN
postal_code: 12345
country: US
attributes:
telephoneNumber: 111-123456

The name parameter is required. The parameter sets the name of the user to create, remove
or modify.
The firstname parameter sets the user's first name.
The lastname parameter sets the user's last name.
The company parameter set the user's company name.
The password parameter specifies the password for the user. The password value is written
in plain text.
The state parameter defines what type of action that Ansible should perform. When set
to present, Ansible creates or updates the user if the account exists. When set to absent,
Ansible deletes the user account from the domain. When set to query Ansible retrieves the
user account details without making any changes.
The groups parameter adds or removes the user from a list of groups.
Additional details about the user can be specified and stored in your domain.

To remove a user account from the domain, the module requires only two parameters. These
parameters are the proper name of the account to delete, and the state parameter set to
absent.

Creating a New Domain Group


Use the win_domain_group module to manage the domain groups. The following example
illustrates how to create or make sure a domain group exists.

350 DO417-RHAE2.8-en-1-20200106
Chapter 8 | Interacting with Users and Domains

- name: Create a new domain group


win_domain_group:
name: developers
description: Developers Group
state: present

The name parameter defines the name of the group.


The description parameter describes the purpose of the group.
The state parameter set to present instructs Ansible to create the domain group.

Removing a Domain Group


The following example illustrates how to remove an existing domain group or make sure it does not
exist.

- name: Remove a domain group


win_domain_group:
name: developers
state: absent

The name parameter defines the name of the group.


The state parameter set to absent instructs Ansible to remove the domain group.

Adding Domain Users to a Domain Group


Using the win_domain_group_membership module, you can add and remove domain users, or
domain groups, from a domain group.

The following example illustrates how to use the win_domain_group_membership module to


add domain users to an existing domain group.

- name: Adding domain users to a domain group


win_domain_group_membership:
name: developers
members:
- DomainUser
- DomainUser2
state: present

The name parameter defines the name of the domain group.


The members parameter contains a list of possible domain users or domain groups to add or
remove from the domain group.
The state parameter sets the desired state of the members in the domain group. When set
to pure, only the specified members exist, and Ansible removes all other existing members
that are not specified.

Creating a New Computer Account


You can use Ansible to add new computer accounts to your existing Active Directory domain.
The following example illustrates how to use the win_domain_computer module to add a new
computer account to your domain.

DO417-RHAE2.8-en-1-20200106 351
Chapter 8 | Interacting with Users and Domains

- name: Creating a new computer account in the domain


win_domain_computer:
name: WINDOWS1
sam_acount_name: windows1$
dns_hostname: windows1.example.com
ou: "CN=Computers,DC=example,DC=com"
state: present

The name parameter defines the name of the LDAP object.


The sam_account_name parameter specifies the Security Account Manager (SAM) account
name of the computer. All the SAM account names must end with a $ sign.
The dns_hostname parameter sets the desired DNS fully qualified domain name (FQDN) of
the computer.
The ou parameter specifies the Organizational Unit in which to create the new computer
object.
The state parameter sets the desired state of the computer in the domain. When set to
present, the computer object is created. When set to absent, the object is removed.

References
Ansible Documentation — Windows Modules
https://docs.ansible.com/ansible/latest/modules/list_of_windows_modules.html

352 DO417-RHAE2.8-en-1-20200106
Chapter 8 | Interacting with Users and Domains

Guided Exercise

Managing Active Directory Domains


In this exercise, you will add a new Active Directory domain controller to your existing
domain, and add hosts, users, and groups to that domain.

Outcomes
You should be able to:

• Join a new server to a domain.

• Add a second domain controller to your existing domain.

• Add users and groups to a domain.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. Launch the Visual Studio Code editor. If you have not previously cloned the ad repository,
then clone it to your workstation instance.

1.1. Click Search Windows, search for code, and then open Visual Studio Code.

1.2. Navigate to View → Command Palette or press Ctrl+Shift+P to open the


command palette.
Type clone, and then select Git: Clone to clone a repository.
Use a repository URL of https://gitlab.example.com/student/ad.git. When
prompted, select the Documents folder in the home directory of the training user
as the repository location, and then click Select Repository Location. This clones
the remote repository into the ad folder.
Optionally, select Open from the window that displays after cloning to view the files.

2. Navigate to File → Open Folder, and then select the c:\Users\student\Documents


\ad folder to open the c:\Users\student\Documents\ad directory.

3. Edit the join-ad.yml file, and then commit and push your changes. Modify the file
so that it targets all hosts, and uses the win_domain_membership module to join the
win2.example.com server to the existing example.com AD domain.

3.1. Select the join-ad.yml file, and then change the task name and the details that are
needed for a server to join the example.com domain.

DO417-RHAE2.8-en-1-20200106 353
Chapter 8 | Interacting with Users and Domains

...output omitted...
hosts: all
vars:
domainname: EXAMPLE.COM
dnsname: example.com
domain_admin: Administrator@example.com

tasks:
- name: Joining the "{{ domainname }}" domain
win_domain_membership:
dns_domain_name: "{{ dnsname }}"
domain_admin_user: "{{ domain_admin }}"
domain_admin_password: "{{ password }}"
state: domain
register: domain_state

...output omitted...

Note
Note that the domain_admin_password uses a variable that is not set in the
playbook. For security reasons, the password is not stored in the playbook itself.
Instead, you will create a survey in Ansible Tower to set the value for that variable in
a later step.

3.2. Click Save. Note the status icons in the lower left. There is an asterisk next to Master,
indicating that changes were made.

3.3. Change to the Source Control view, and then click + for join-ad.yml to stage the
changes.

3.4. Enter a commit message, and then press Ctrl+Enter to commit the changes.

3.5. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to
push your local changes to the remote repository, and retrieve any new changes from
the repository.
Click Yes or Ask Me Later when prompted.

4. Add a survey to the Run ad project job template.

Note
More details about Ansible Tower Surveys are discussed in a later chapter. Surveys
prompt users with customized questions. This method supports prompts for
user input of extra variable values that are more user-friendly than those in the
PROMPT ON LAUNCH method.

4.1. Log in to the Ansible Tower interface. Click Templates in the navigation pane.

4.2. In the list of available templates, click Run ad project to edit the job template.

4.3. Click ADD SURVEY to add a survey.

354 DO417-RHAE2.8-en-1-20200106
Chapter 8 | Interacting with Users and Domains

4.4. On the next screen, supply the following information in the EXTRA VARIABLES text
field at the bottom of the window:

Field Value

PROMPT Active Directory Administrator Password

DESCRIPTION This is the AD Admin password.

ANSWER VARIABLE NAME password

ANSWER TYPE Text

MINIMUM LENGTH 1

MAXIMUM LENGTH 40

REQUIRED Selected

4.5. Click +ADD to add this Survey Prompt to the survey. A preview of your survey displays.

Important
Before saving, make sure that the ON/OFF switch in the Survey editor window is
set to ON.

4.6. Click SAVE to add the survey to the job template.

4.7. Click SAVE to update the job template.

5. Add the win2.example.com server to the Default inventory inventory in Ansible


Tower.

5.1. Click Inventories in the navigation pane.

5.2. Click Default inventory from the INVENTORIES page.

5.3. Click the GROUPS tab then select the Windows group.

5.4. Click the HOSTS tab to access the list of hosts in the group.

5.5. Click + and select New host to add a new host to the group.

5.6. On the next screen, fill in the details as follows:

Field Value

HOST NAME win2.example.com

5.7. Click SAVE to add the new host.

6. Use the Run ad project job template to test your modified Ansible Playbook.

6.1. Click Templates in the navigation pane.

6.2. From the list of templates, select the Run ad project template.

DO417-RHAE2.8-en-1-20200106 355
Chapter 8 | Interacting with Users and Domains

Note
To select a project for editing, click its name.

6.3. Select the join-ad.yml playbook from the PLAYBOOK list.

6.4. Make sure that the PROMPT ON LAUNCH check field for the LIMIT option is
selected.

6.5. Click SAVE to update the job template, then click LAUNCH to begin execution.

6.6. In the RUN AD PROJECT window, enter win2.example.com as the host name. Click
NEXT.

6.7. In the ACTIVE DIRECTORY ADMINISTRATOR PASSWORD field, enter


RedHat123@!, which is the password of the Active Directory administrator user. This
password is the same as the administrator account of windc. Click NEXT to review the
survey values and then click LAUNCH.

6.8. Observe the live output of the running job. Joining the domain requires a reboot of the
win2.example.com server. The playbook contains a handler that is triggered when
the host domain settings are changed, causing Ansible to reboot the server. The status
of the job changes after the server successfully restarts.

6.9. Verify that the status of the job in the DETAILS pane displays Successful.

7. Edit the second-ad-server.yml file, and then commit and push your changes. Modify
this file so that it targets all hosts, and uses the win_domain_controller module to
promote the win2.example.com server to a domain controller. You can use this same
module to create a completely new Active Directory domain.

7.1. Select the second-ad-server.yml file, and then change the task name and the
details that are needed for promoting the win2.example.com server to a domain
controller.

...output omitted...
hosts: all
vars:
domainname: EXAMPLE.COM
dnsname: example.com
domain_admin: Administrator@example.com
safe_password: RedHat123@!

tasks:
- name: Promoting the server to an AD controller
win_domain_controller:
dns_domain_name: "{{ dnsname }}"
domain_admin_user: "{{ domain_admin }}"
domain_admin_password: "{{ password }}"
safe_mode_password: "{{ safe_password }}"
state: domain_controller
register: domain_state
...output omitted...

356 DO417-RHAE2.8-en-1-20200106
Chapter 8 | Interacting with Users and Domains

Note
Note that the domain_admin_password uses a variable that is not set in the
playbook. For security reasons, the password is not stored in the playbook itself.
Instead, survey in Ansible Tower is used to set the value for that variable.

7.2. Click Save. Note the status icons in the lower left. There is an asterisk next to Master
indicating that changes were made.

7.3. Change to the Source Control view, and then select + for second-ad-server.yml
to stage the changes.

7.4. Enter a commit message, and then press Ctrl+Enter to commit the changes.

7.5. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to
push your local changes to the remote repository, and retrieve any new changes from
the repository.
Click Yes or Ask Me Later when prompted.

8. Use the Run ad project job template to test your modified Ansible Playbook.

8.1. In the navigation pane, click Templates.

8.2. From the list of templates, select the Run ad project template.

Note
To select a project for editing, click its name.

8.3. Select the second-ad-server.yml playbook from the PLAYBOOK list.

8.4. Make sure that the PROMPT ON LAUNCH check box for the LIMIT option is
selected.

8.5. Click SAVE to update the job template.


Click LAUNCH to begin execution.

8.6. In the RUN AD PROJECT window, use win2.example.com as the host name. Click
NEXT.

8.7. In the ACTIVE DIRECTORY ADMINISTRATOR PASSWORD field, enter


RedHat123@!, which is the password of the Active Directory administrator user. This
password is the same as the administrator account of windc.
Click NEXT, and then click LAUNCH.

8.8. Observe the live output of the running job. Joining the domain requires a reboot of the
win2.example.com server. The playbook contains a handler that is triggered when
the host domain settings are changed, causing Ansible to reboot the server. The status
of the job changes after the server successfully restarts.

8.9. Verify that the status of the job in the DETAILS pane displays Successful. It takes
some time for the Active Directory Domain Services to complete the status update.

DO417-RHAE2.8-en-1-20200106 357
Chapter 8 | Interacting with Users and Domains

9. Edit the domain-mod.yml file, and then commit and push your changes. Use this file to
create a new domain group, and a domain user who is a member of that new group.

9.1. Select the domain-mod.yml file, and then change the task name and the details that
are needed for creating the new group and the new user.

...output omitted...
hosts: all
...output omitted...
user_password: RedHat123@!

tasks:
- name: Creating a new group in the {{ domainname }} domain
win_domain_group:
name: Test Group
scope: domainlocal
category: security
attributes:
mail: helpdesk@example.com
wWWHomePage: www.example.com
ignore_protection: yes

- name: Creating a new user


win_domain_user:
name: daniel
firstname: Daniel
surname: George
password: "{{ user_password }}"
state: present
groups:
- Domain Users
- Test Group
street: 125 42nd St.
city: Sometown
state_province: CA
postal_code: 1234
country: US
attributes:
telephoneNumber: 543-123456

9.2. Click Save. Note the status icons in the lower left. There is an asterisk next to Master
indicating that changes were made.

9.3. Change to the Source Control view, and then select + for domain-mod.yml to stage
the changes.

9.4. Enter a commit message, and then press Ctrl+Enter to commit the changes.

9.5. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to
push your local changes to the remote repository, and retrieve any new changes from
the repository.
Click Yes or Ask Me Later when prompted.

358 DO417-RHAE2.8-en-1-20200106
Chapter 8 | Interacting with Users and Domains

10. Add the windc.example.com server to the Default inventory inventory in Ansible
Tower.

10.1. Click Inventories in the navigation pane.

10.2.Click Default inventory on the INVENTORIES page.


Click GROUPS to access the inventory groups and select the Windows group.

10.3.Click HOSTS to add an host to that group.

10.4.Click + to add a new host to the group. Select New Host from the list that displays.

10.5.Change the authentication method that Ansible uses for the windc.example.com
server to Kerberos to configure centralized authentication. On the next screen, fill in
the details as follows:

Field Value

HOST NAME windc.example.com

VARIABLES ansible_winrm_transport: kerberos

10.6.Click SAVE.

11. Create a new credential called AD Administrator.

11.1. Click Credentials in the navigation pane.

11.2. Click + to add a new credential.

11.3. On the next screen, fill in the details as follows:

Field Value

NAME AD Administrator

DESCRIPTION AD Administrator Credential

ORGANIZATION Default

CREDENTIAL TYPE Machine

USERNAME Administrator

PASSWORD RedHat123@!

11.4. Leave the other fields untouched, and click SAVE to create the new credential.

12. Use the Run ad project job template to test your modified Ansible Playbook.

12.1. In the navigation pane, click Templates.

12.2. From the list of templates, select the Run ad project template.

12.3. Select the domain-mod.yml playbook from the PLAYBOOK list.

DO417-RHAE2.8-en-1-20200106 359
Chapter 8 | Interacting with Users and Domains

12.4. Make sure that the PROMPT ON LAUNCH check box for the LIMIT option is
selected.

12.5. Select the PROMPT ON LAUNCH option of the CREDENTIAL field.

12.6. Click SAVE to update the job template.


Click LAUNCH to begin execution.

12.7. In the RUN AD PROJECT window, choose the AD Administrator credentials and
click NEXT.

12.8. In the LIMIT text field, type the windc.example.com hostname, and then click
NEXT.

12.9. In the ACTIVE DIRECTORY ADMINISTRATOR PASSWORD field, type


RedHat123@!, which is the password of the Active Directory administrator user. Click
NEXT, and then click LAUNCH.

12.10.Observe the live output of the running job.

12.11. Verify that the status of the job in the DETAILS pane displays Successful.

13. Edit the Run ad project job template and turn off the survey.

13.1. In the navigation pane, click Templates.

13.2. From the list of templates, select Run ad project.

Note
To select a project for editing, click its name.

13.3. Click EDIT SURVEY.

13.4. At the top of the Survey editor window, toggle ON/OFF and set it to OFF.

13.5. Click SAVE to update the survey.

14. Click Log Out to exit the Ansible Tower web interface.

This concludes the guided exercise.

360 DO417-RHAE2.8-en-1-20200106
Chapter 8 | Interacting with Users and Domains

Generating Dynamic Inventories from


Active Directory

Objectives
After completing this section, you should be able generate an Ansible inventory dynamically in
Red Hat Ansible Tower, based on Active Directory domain membership.

Dynamic Inventories
When Ansible runs a playbook, it uses an inventory to determine against which hosts the plays
should run. Both Ansible and Ansible Tower make it easy to set up a static inventory of hosts that
you specify explicitly in an inventory.

However, these static lists require manual administration to keep them up to date. This can be
inconvenient or challenging, especially when an organization wants to run the playbooks against
hosts that are dynamically created in a virtualization or cloud computing environment.

In this scenario, using a dynamic inventory is preferable. Dynamic inventories are scripts that, when
run, dynamically determine which hosts and host groups should be in the inventory, based on
information from some external source. External sources can include the API for cloud providers,
Cobbler, LDAP directories, or other third-party configuration management database (CMDB)
software. Using a dynamic inventory is a recommended practice in a large and quickly changing IT
environment, where systems are frequently deployed, tested, and then removed.

By default, Ansible Tower comes with built-in dynamic inventory support for a number of external
inventory sources (or cloud inventory sources), including:

• Amazon Web Services EC2

• Google Compute Engine

• Microsoft Azure Resource Manager

• VMware vCenter

• Red Hat Satellite 6

• Red Hat CloudForms

• Red Hat Virtualization

• OpenStack

In addition, custom dynamic inventory scripts can direct Ansible Tower to access inventory
information from other sources. Ansible Tower can retrieve those scripts from a project that uses a
repository like Git as a source.

The remainder of this section examines two examples of dynamic inventory configuration in
Ansible Tower. The first example illustrates the built-in support for Microsoft Azure Resource
Manager. The second example investigates how you can use a custom dynamic inventory scripts
with Active Directory.

DO417-RHAE2.8-en-1-20200106 361
Chapter 8 | Interacting with Users and Domains

Microsoft Azure Resource Manager Dynamic


Inventories
Cloud technologies like Microsoft Azure bring many changes to the server life cycle. Hosts change
over time as external applications create and start new hosts. Maintaining an accurate static
inventory file is challenging over any period of time. Therefore, updating the inventory dynamically,
based on information provided directly from Microsoft Azure Resource Manager, is very helpful.

The basic process for configuring dynamic inventories is similar when using any of the built-in
cloud sources:

1. Create a credential to authenticate to the cloud data source you intend to use; the credential
type must match the source.

2. Create a new inventory to provide dynamic inventory information.

3. In the new inventory, create a Source with one of the built-in dynamic inventory sources
(instead of Manual). Use the new credential to authenticate to that source. You might also
want to set other options, like having it automatically update upon launch.

4. Update the source in the inventory for the first time.

This process works for Microsoft Azure based dynamic inventories. Figure 8.1 illustrates how to
create credentials for use by an Microsoft Azure Resource Manager dynamic inventory, including
the information that you must provide:

Figure 8.1: Cloud credentials creation

Some of these items will be familiar from working with other objects in Ansible Tower, including
Name, Description and Organization. The only new item is the Credential Type. You must
choose the appropriate credential type for the product that you are using. In this example, the
product is Microsoft Azure Resource Manager.

An Microsoft Azure Resource Manager Credential requires some additional information:

Username
The user who can connect to the Microsoft Azure account.

Password
The password for the user.

362 DO417-RHAE2.8-en-1-20200106
Chapter 8 | Interacting with Users and Domains

Subscripton ID (required)
Subscription UUID in an Azure construct, which is mapped to a username.

Client ID
The Azure client ID.

Client Secret
The Azure client secret.

Tenant ID
The Azure client tenant ID.

Azure Cloud Environment


The variable associated with Azure cloud environments.

The Ansible Tower synchronization mechanism uses these newly created credentials. After
creating the credentials, select Inventories in the navigation pane. As Figure 8.2 illustrates, you
must create a new Inventory:

Figure 8.2: Cloud inventory creation

Give the new inventory a unique name, and assign it to an existing organization. After saving the
new inventory configuration, click SOURCES to create a new source for the inventory. Ansible
Tower uses this source in conjunction with the existing Microsoft Azure Resource Manager scripts
and the previously created credentials. Figure 8.3 shows an example of such a source:

DO417-RHAE2.8-en-1-20200106 363
Chapter 8 | Interacting with Users and Domains

Figure 8.3: Cloud source creation

This new source uses the built-in Ansible Tower support for Microsoft Azure Resource Manager
as the SOURCE, and the new credentials for your Microsoft Azure environment as the
CREDENTIAL. There are three UPDATE OPTIONS from which to choose:

Overwrite
If this option is selected, then the inventory update process deletes all child groups and hosts
from the local inventory that not found on the external source. By default, this option is not
active, which means that all child hosts and groups not found on the external source remain
untouched.

Overwrite Variables
If this option is not selected, then Ansible Tower merges local variables with those found on
the external source. Ansible Tower removes all variables not found on the external source.

Update on Launch
If this option is activated, then each time a job runs using this inventory, Ansible Tower
refreshes this inventory from the external source before the job tasks are executed.

In the source list for the inventory, the small cloud icon to the left of the source name shows
the status of the dynamic inventory synchronization for that source. When it is disabled, no
status is available. To start the synchronization process, click the syncronize button. When the
synchronization finishes, the status of the cloud icon changes to green if the synchronization is
successful, or red if it failed.

After a successful synchronization with the external source, review the child groups and hosts
which have been created in Ansible Tower using information from the external source. The child
groups contain the hosts visible on the HOSTS lists. Click the group name to display the contents
of that group, and then review each child group including a list of the associated hosts. This
inventory is updated every time you synchronize it with the external source. You can perform the
synchronization manually, schedule it using Ansible Tower mechanisms, or set it to automatically
update each time a job runs using that inventory.

Custom Dynamic Inventory Scripts


Ansible allows you to write custom scripts to generate a dynamic inventory. Although Ansible
Tower offers built-in support for a number of dynamic inventory sources, Ansible Tower also
accepts custom dynamic inventory scripts.

364 DO417-RHAE2.8-en-1-20200106
Chapter 8 | Interacting with Users and Domains

Writing or Obtaining Custom Inventory Scripts


Ansible Tower supports custom inventory scripts written in Bash or Python. These scripts run as
the awx user and have limited access to the Ansible Tower server. The script must start with an
appropriate shebang line (for example, #!/usr/bin/python for a Python script).

Many examples of custom inventory scripts for use with various external sources have been
contributed by the community the Git repository for Ansible at https://github.com/ansible/
ansible/tree/devel/contrib/inventory/.

If you want to write your own custom inventory script, information is available at
Developing Dynamic Inventory Sources [http://docs.ansible.com/ansible/dev_guide/
developing_inventory.html] in the Ansible Developer Guide. When you invoke the dynamic
inventory script with the --list option, it must output the inventory in JSON format.

This is example output from a custom dynamic inventory script:

{
"databases" : {
"vars" : {
"example_db" : true
},
"hosts" : [
"db1.demo.example.com",
"db2.demo.example.com"
]
},
"webservers" : [
"web1.demo.example.com",
"web2.demo.example.com"
],
"boston" : {
"children" : [
"backup",
"ipa"
],
"vars" : {
"example_host" : false
},
"hosts" : [
"server1.demo.example.com",
"server2.demo.example.com",
"server3.demo.example.com"
]
},
"backup" : [
"server4.demo.example.com"
],
"ipa" : [
"server5.demo.example.com"
]
}

As demonstrated in the preceding example, each group contains a list of hosts, potential child
groups, possible group variables, or a list of hosts.

DO417-RHAE2.8-en-1-20200106 365
Chapter 8 | Interacting with Users and Domains

Note
When called with the option --host hostname, the script prints a JSON hash/
dictionary of the variables for the specified host (potentially an empty JSON hash
or dictionary if there are no variables provided).

Optionally, if the --list option returns a top-level element called _meta, all host
variables can be returned in one script call, which improves script performance. In
that case, --host calls are not made.

See the previously referenced documentation in the Developing Dynamic Inventory


Sources section of the Ansible Developer Guide for more information.

Using Custom Inventory Scripts in Ansible Tower


After creating or downloading the appropriate custom inventory script, you must import it into
Ansible Tower and configure the inventory. Figure 8.4 demonstrates how this task is accomplished:

To upload a custom inventory script into Ansible Tower, select Inventories Scripts in the
navigation pane of the Ansible Tower web interface. Click the + button to add a new custom
inventory script.

Figure 8.4: Ansible Tower Inventory Script

Define a new name for the custom inventory script in the NAME field, select an organization in the
ORGANIZATION field, and then paste the actual script into the CUSTOM SCRIPT text box. Click
the SAVE button.

After importing and defining the dynamic inventory script in Ansible Tower, configure it just like any
of the built-in dynamic inventories:

1. Create a new source in an existing inventory for the dynamic inventory. Set the SOURCE to
Custom Script, and provide the name of the custom script in the CUSTOM INVENTORY
SCRIPT field; this is the name you gave the script when importing it into Ansible Tower.

2. Synchronize the source with the inventory source, for example from your Active Directory
server.

366 DO417-RHAE2.8-en-1-20200106
Chapter 8 | Interacting with Users and Domains

Figure 8.5: Adding new custom script as a source for a dynamic inventory

References
Ansible Tower User Guide
https://docs.ansible.com/ansible-tower/latest/html/userguide/

Ansible Tower Administration Guide


https://docs.ansible.com/ansible-tower/latest/html/administration/

DO417-RHAE2.8-en-1-20200106 367
Chapter 8 | Interacting with Users and Domains

Guided Exercise

Generating Dynamic Inventories from


Active Directory
In this exercise, you will configure your Red Hat Ansible Tower system with a dynamic
inventory that is generated from membership in an Active Directory domain.

Outcomes
You should be able to add a custom inventory script and use it to populate a Dynamic
Inventory in Tower.

Before You Begin


Important
This exercise uses resources in Ansible Tower from the previous guided
exercise. Before you can start this exercise, you must complete the previous
exercise.

Open your RDP client and connect to the Windows workstation system using training
as the user name. Use the unique password that is displayed on the Online Lab tab of the
ROL interface to connect to workstation over RDP.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. From workstation, click the Ansible Tower icon on your desktop to access Ansible
Tower.
Log in to the web console using admin, and RedHat123@! as the password.

2. Add the ldap-inventory.py custom inventory script to Ansible Tower.

2.1. Click Inventory Scripts in the navigation pane.

2.2. Click + to add a new custom inventory script.

2.3. On the next screen, fill in the details as follows:

Field Value

NAME ldap-inventory.py

DESCRIPTION Dynamic inventory script for Active Directory

ORGANIZATION Default

368 DO417-RHAE2.8-en-1-20200106
Chapter 8 | Interacting with Users and Domains

2.4. Launch the Visual Studio Code editor, navigate to File → Open Folder, and then
select the C:\Users\student\Documents\ad folder to open the ad repository.
Copy the contents of the ldap-inventory.py script into the CUSTOM SCRIPT
field.

2.5. Click SAVE to add the custom inventory script.

3. Create the Dynamic inventory inventory.

3.1. Click Inventories in navigation pane.

3.2. Click + to add a new inventory, and then select Inventory.

3.3. On the next screen, fill in the details as follows:

Field Value

NAME Dynamic inventory

DESCRIPTION Dynamic inventory from AD server

ORGANIZATION Default

VARIABLES • ansible_port: 5986

• ansible_connection: winrm

• ansible_winrm_server_cert_validation: ignore

• ansible_winrm_transport: kerberos

3.4. Click SAVE to create the inventory.

4. Add the ldap-inventory.py script as a new source for the inventory.

4.1. Click SOURCES.

4.2. Click + to add a new source.

4.3. On the next screen, fill in the details as follows:

Field Value

NAME Custom Script

DESCRIPTION Custom script for dynamic inventory

SOURCE Custom Script

CUSTOM INVENTORY SCRIPT ldap-inventory.py

4.4. For UPDATE OPTIONS, select the OVERWRITE option. This option instructs Ansible
Tower to overwrite the hosts if they are already present in the inventory.

4.5. Click SAVE to create the source.

DO417-RHAE2.8-en-1-20200106 369
Chapter 8 | Interacting with Users and Domains

5. Update the dynamic inventory.

5.1. Scroll down and click the synchronize button for Custom Script, and then wait until
the cloud becomes green and static.

5.2. Click HOSTS to ensure that the inventory now contains four hosts, all of them
associated with a new windows group.

6. Switch back to Visual Studio Code, and then edit the add-computers.yml file. Modify
this file so that it targets all hosts, and uses the win_domain_membership module to join
the win2.example.com server to the existing example.com AD domain. When you are
finished, commit and push your changes.

6.1. Select the add-computers.yml file, and then change the task name and the details
that are needed for a server to join the example.com domain.

...output omitted...
- name: A new Linux host is added to the "{{ domainname }}"" AD domain
win_domain_computer:
name: LINUX1
dns_hostname: linux1.{{ dnsname }}
ou: "CN=Computers,DC=example,DC=com"
description: Linux server example
enabled: yes
state: present

- name: A new Windows host is added to the "{{ domainname }}" AD domain
win_domain_computer:
name: WIN_TEST
sam_account_name: win_test$
dns_hostname: win_test.{{ dnsname }}
ou: "CN=Computers,DC=example,DC=com"
description: Windows server example
state: present

Warning
Make sure that the name in the sam_account_name: option ends with a $ sign.
SAM accounts must always end with the $ sign.

6.2. Click Save. Note the status icons in the lower left. There is an asterisk next to master
indicating that changes have been made.

6.3. Change to the Source Control view, and then click + for add-computers.yml to
stage the changes.

6.4. Enter a commit message of Define configuration for joining Linux


server to the AD domain, and then press Ctrl+Enter to commit the changes.

6.5. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to
push your local changes to the remote repository, and retrieve any new changes from
the repository.
Click Yes or Ask Me Later when prompted.

370 DO417-RHAE2.8-en-1-20200106
Chapter 8 | Interacting with Users and Domains

7. Switch to the Ansible Tower web interface, and then use the Run ad project job
template to test your modified Ansible Playbook.

7.1. In the navigation pane, click Templates.

7.2. From the list of templates, select Run ad project.

Note
To select a project for editing, click its name.

7.3. Select the add-computers.yml playbook from the PLAYBOOK list.

7.4. Make sure that the PROMPT ON LAUNCH check box for the LIMIT option is
selected.

7.5. Make sure that the PROMPT ON LAUNCH check box for the CREDENTIAL option is
selected.

7.6. Select the PROMPT ON LAUNCH check box for the INVENTORY option.

7.7. Click SAVE to update the job template.


Click LAUNCH to begin execution.

7.8. In the RUN AD PROJECT window, select Dynamic inventory. Click NEXT.

7.9. From the list of available credentials, choose the AD Administrator credentials. Click
NEXT.

Note
The AD Administrator credentials were created in the previous exercise. If you do
not have these credentials, follow the instructions from the previous guided exercise
(Step 11) to create them.

DO417-RHAE2.8-en-1-20200106 371
Chapter 8 | Interacting with Users and Domains

7.10. In the LIMIT field type the windc.example.com hostname. Click NEXT then click
LAUNCH.

7.11. In the ACTIVE DIRECTORY ADMINISTRATOR PASSWORD field, type


RedHat123@!, which is the password of the Active Directory administrator user. This
password is the same as the administrator account of windc. Click NEXT, and then
click LAUNCH.

7.12. Observe the live output of the running job. The status of the job changes after the
server successfully restarts.

7.13. Verify that the status of the job in the DETAILS pane displays Successful.

8. Synchronize the host list from Active Directory using the dynamic inventory, and verify that
the two new hosts are present in the inventory.

8.1. Click Inventories in the navigation pane.

8.2. Click Dynamic inventory.

8.3. Click SOURCES.

8.4. Click the synchronize button for Custom Script, and then wait until the cloud
becomes green and static.

8.5. Click HOSTS, and then verify that the linux1.example.com and
win_test.example.com hosts added to Active Directory are now in the inventory.

This concludes the guided exercise.

372 DO417-RHAE2.8-en-1-20200106
Chapter 8 | Interacting with Users and Domains

Lab

Interacting with Users and Domains


Performance Checklist
In this lab, you will add users and groups, both local and domain-based.

Outcomes
You should be able to:

• Add two local users.

• Add a new user to an existing local group.

• Add a new domain user.

• Add a new user to a newly created domain group.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. Edit the localuser-review.yml playbook in the ad repository, and make the indicated
changes. Commit and push your changes to the Git repository, using a commit message of of
Adds users and manage group membership. Comments in the playbook indicate the
changes to make.

• Modify the playbook so that it targets all hosts.

Give the first task a name of Two local users are created.

• Rename the second task to The Review User1 user is added to the Print
Operators group.

• Update the first task with the correct Ansible module, and the module options to add two
local users.

• Update the second task with the correct Ansible module and the module options to add
the Review User1 user to the Print Operators local group.
2. Update the Run ad project job template to use the modified localuser-review.yml
Ansible Playbook. Update the template to instruct Ansible Tower to prompt you for the host
to target, and the credentials and inventory to use.
Launch a job using the template, and when prompted use win1.example.com as the target
host, DevOps as the credentials, and Default inventory as the inventory.

DO417-RHAE2.8-en-1-20200106 373
Chapter 8 | Interacting with Users and Domains

3. From workstation, edit the domain-mod-review.yml playbook in the ad project in


Visual Studio Code. Update the playbook so that Ansible creates a new domain group, and
a domain user who is a member of that new group. Make sure the playbook uses the correct
Ansible modules and module options to create the new group and the new user.
Use the first task to create a new group in the EXAMPLE.COM domain. Use the second task to
create a new user in the domain. The user should be member of the newly created group, and
of the Domain Users group.
Commit and push your changes to the remote Git repository using the commit message
Create new group in domain and user.
4. Update the Run ad project job template in Ansible Tower to use the domain-mod-
review.yml Ansible Playbook. Update the job template so that it prompts you at launch for
the credential, the inventory, and the host to target.
Launch a job using the template, and when prompted select Dynamic inventory as the
inventory, AD Administrator as the credentials, and windc.example.com as the host.

Note
You created the AD Administrator credentials in a previous exercise. If you do
not have these credentials, follow the instructions in the Managing Active Directory
Domains guided exercise to create them. The steps are also displayed in the solution
for this lab.

This concludes the lab.

374 DO417-RHAE2.8-en-1-20200106
Chapter 8 | Interacting with Users and Domains

Solution

Interacting with Users and Domains


Performance Checklist
In this lab, you will add users and groups, both local and domain-based.

Outcomes
You should be able to:

• Add two local users.

• Add a new user to an existing local group.

• Add a new domain user.

• Add a new user to a newly created domain group.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. Edit the localuser-review.yml playbook in the ad repository, and make the indicated
changes. Commit and push your changes to the Git repository, using a commit message of of
Adds users and manage group membership. Comments in the playbook indicate the
changes to make.

• Modify the playbook so that it targets all hosts.

Give the first task a name of Two local users are created.

• Rename the second task to The Review User1 user is added to the Print
Operators group.

• Update the first task with the correct Ansible module, and the module options to add two
local users.

• Update the second task with the correct Ansible module and the module options to add
the Review User1 user to the Print Operators local group.

1.1. Launch the Visual Studio Code editor. Navigate to File → Open Folder, and then
select the c:\Users\student\Documents\ad folder to open the c:\Users
\student\Documents\ad directory.

1.2. Edit the localuser-review.yml playbook, modifying it as follows:

DO417-RHAE2.8-en-1-20200106 375
Chapter 8 | Interacting with Users and Domains

• The playbook should target all hosts.

• The first task should use the win_user module to create the Review User1 and
Review User2 users.

Set RedHat123@! as the password.

• The second task should use the win_group_membersip module to add Review
User1 to the Print operators group.

The completed playbook should look like the following:

---
hosts: all

tasks:
- name: Two local users are created
win_user:
name: "{{ item }}"
password: RedHat123@!
state: present
groups:
- Users
loop:
- Review User1
- Review User2

- name: The Review User1 user is added to the Print operators group
win_group_membership:
name: Print operators
members:
- Review User1
state: present

1.3. Save your changes. Note the status icons in the lower left. There will be an asterisk next
to Master to indicate that there are new changes

1.4. Change to the Source Control view, and then click + for the localuser-review.yml
playbook to stage the changes.

1.5. Enter a commit message of Adds users and manage group membership, and
then press Ctrl+Enter to commit the changes.

1.6. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to push
your local changes to the remote repository, and retrieve any new changes from the
repository.

2. Update the Run ad project job template to use the modified localuser-review.yml
Ansible Playbook. Update the template to instruct Ansible Tower to prompt you for the host
to target, and the credentials and inventory to use.
Launch a job using the template, and when prompted use win1.example.com as the target
host, DevOps as the credentials, and Default inventory as the inventory.

2.1. Double-click the Ansible Tower desktop icon to access Ansible Tower.

376 DO417-RHAE2.8-en-1-20200106
Chapter 8 | Interacting with Users and Domains

Log in using admin with a password of RedHat123@!

2.2. In the navigation pane, click Templates.

2.3. From the list of templates, select the Run ad project template.

Note
To select a project for editing, click its name.

2.4. Select the localuser-review.yml playbook from the PLAYBOOK list.

2.5. Make sure that the PROMPT ON LAUNCH check box for the LIMIT option is selected.

2.6. Make sure that the PROMPT ON LAUNCH check box for the CREDENTIAL option is
selected.

2.7. Make sure that the PROMPT ON LAUNCH check box for the INVENTORY option is
selected.

2.8. Click SAVE to update the job template.


Click LAUNCH to begin execution.

2.9. In the RUN AD PROJECT window, choose the Default inventory and then click
NEXT.

2.10. In the RUN AD PROJECT window, choose the DevOps credentials and then click
NEXT.

2.11. In the LIMIT field, type win1.example.com as the host name, click NEXT, and then
click LAUNCH.

DO417-RHAE2.8-en-1-20200106 377
Chapter 8 | Interacting with Users and Domains

2.12. Observe the live output of the running job.

2.13. Verify that the status of the Job in the DETAILS pane displays Successful.

3. From workstation, edit the domain-mod-review.yml playbook in the ad project in


Visual Studio Code. Update the playbook so that Ansible creates a new domain group, and
a domain user who is a member of that new group. Make sure the playbook uses the correct
Ansible modules and module options to create the new group and the new user.
Use the first task to create a new group in the EXAMPLE.COM domain. Use the second task to
create a new user in the domain. The user should be member of the newly created group, and
of the Domain Users group.
Commit and push your changes to the remote Git repository using the commit message
Create new group in domain and user.

3.1. From Visual Studio Code, open the domain-mod-review.yml playbook in the ad
project and update it. Use the win_domain_group module for the first task, to create a
new group in the EXAMPLE.COM domain.

---
- name: Creating AD groups and users
hosts: all
vars:
domainname: EXAMPLE.COM
user_password: RedHat123@!

tasks:
- name: New group in the "{{ domainname }}" is created
win_domain_group:
name: Review Group
scope: global

3.2. Update the second task to use win_domain_user to create a new user in the domain.
The groups parameter allows you to manage group membership for the user.

...output omitted...
- name: New user in the "{{ domainname }}" is created
win_domain_user:
name: oliver
firstname: Oliver
lastname: Stone
password: "{{ user_password }}"
state: present
groups:
- Domain Users
- Review Group

3.3. Save your changes. Note the status icons in the lower left. There is an asterisk next to
Master, indicating that changes have been made.

3.4. Change to the Source Control view, then click + for domain-mod-review.yml to
stage the changes.

3.5. Enter a commit message of Create new group in domain and user, and then
press Ctrl+Enter to commit your changes.

378 DO417-RHAE2.8-en-1-20200106
Chapter 8 | Interacting with Users and Domains

3.6. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to push
your local changes to the remote repository, and retrieve any new changes from the
repository.

4. Update the Run ad project job template in Ansible Tower to use the domain-mod-
review.yml Ansible Playbook. Update the job template so that it prompts you at launch for
the credential, the inventory, and the host to target.
Launch a job using the template, and when prompted select Dynamic inventory as the
inventory, AD Administrator as the credentials, and windc.example.com as the host.

Note
You created the AD Administrator credentials in a previous exercise. If you do
not have these credentials, follow the instructions in the Managing Active Directory
Domains guided exercise to create them. The steps are also displayed in the solution
for this lab.

4.1. From workstation, go back to the Ansible Tower web console.

4.2. If you have not yet created the AD Administrator credentials, click Credentials in
the navigation pane.

4.3. Click the + button to add a new credential.

4.4. On the next screen, fill in the details as follows:

Field Value

NAME AD Administrator

DESCRIPTION AD Administrator Credential

ORGANIZATION Default

CREDENTIAL TYPE Machine

USERNAME Administrator

PASSWORD Type RedHat123@!, which is the password of the


Active Directory administrator user.

4.5. Leave the other fields untouched, and click SAVE to create the credential.

4.6. In the navigation pane, click Templates.

4.7. From the list of templates, select the Run ad project template.

Note
To select a project for editing, click its name.

4.8. Select the domain-mod-review.yml playbook from the PLAYBOOK list.

4.9. Make sure that the PROMPT ON LAUNCH check box for the LIMIT option is selected.

DO417-RHAE2.8-en-1-20200106 379
Chapter 8 | Interacting with Users and Domains

4.10.Make sure that the PROMPT ON LAUNCH check box for the CREDENTIAL option is
selected.

4.11. Make sure that the PROMPT ON LAUNCH check box for the INVENTORY option is
selected.

4.12. Click SAVE to update the job template.


Click LAUNCH to begin execution.

4.13. In the RUN AD PROJECT window, choose the Dynamic inventory, and then click
NEXT.

4.14.Select the AD Administrator credentials, and then click NEXT.

4.15. In the LIMIT field, type the windc.example.com hostname, and then click NEXT.

4.16.Observe the live output of the running job.

4.17. Verify that the status of the job in the DETAILS pane displays Successful.

4.18. Click Log Out to exit the Ansible Tower web interface.

This concludes the lab.

380 DO417-RHAE2.8-en-1-20200106
Chapter 8 | Interacting with Users and Domains

Summary
In this chapter, you learned:

• You can use the win_user Ansible module to manage local user accounts, including passwords
and groups.

• You can create and modify local and domain groups with the win_group and
win_domain_group modules.

• You can use the win_group_membership module to manage users from local groups.

• You can use the win_domain, win_domain_controller, and win_domain_membership


modules to create Active Directory domains and control domain membership.

• A dynamic inventory is an inventory that automatically updates its list of members and groups
from an external data source, such as a cloud service's API, a database, or another CMDB
provider.

• Red Hat Ansible Tower includes built-in support for some dynamic inventory sources, and scripts
can be imported to support others.

DO417-RHAE2.8-en-1-20200106 381
382 DO417-RHAE2.8-en-1-20200106
Chapter 9

Automating Windows
Administration Tasks
Goal Automate common Windows Server administration
tasks.

Objectives • Run arbitrary PowerShell commands, configure


PowerShell modules, and set up scheduled
tasks on managed hosts with Ansible
playbooks.
• Automate configuration of storage devices on
managed hosts.

Sections • Running Commands and Scheduling Tasks on


Hosts (and Guided Exercise)
• Configuring and Managing Storage (and
Guided Exercise)

Lab Automating Windows Administration Tasks

DO417-RHAE2.8-en-1-20200106 383
Chapter 9 | Automating Windows Administration Tasks

Running Commands and Scheduling


Tasks on Hosts

Objectives
After completing this section, you should be able to run arbitrary PowerShell commands, configure
PowerShell modules, and set up scheduled tasks on managed hosts with Ansible Playbooks.

Running Direct Commands with Modules


Ansible provides a variety of modules for interacting with Windows systems. You can use modules
designed specifically to accomplish a particular task, or you can use modules to directly run
commands on managed hosts.

For example, win_user is a module designed to perform a particular task: managing local users.
However, there are a number of modules that you can use to run commands from the command
line or through scripts. In this section, we will look at four of these modules:

• win_command runs a command, but does not use the Windows shell.

• win_shell runs a command using a Windows shell, and supports variable expansion and other
shell features.

• win_psexec runs a command using psexec.

• script transfers a script to the managed host and runs it.

Running Arbitrary Commands


Use the win_command module to run arbitrary commands on the nodes, which is the equivalent of
running a command in the command prompt.

- name: Run the WBAdmin command


win_command: wbadmin -backupTarget:C:\backup\
args:
chdir: C:\somedir\
creates: C:\backup\

The command to run. This example invokes wbadmin to create a backup of the operating
system in C:\backup.
The context for the command, such as the directory in which Ansible runs the command.
chdir instructs Ansible to run the command from the specified directory. This is the
equivalent of running cd before running the command.
creates instructs Ansible to verify if the specified resource exists before running the
command. In this example, Ansible runs the command only if C:\backup is not present on
the system.

Running Commands Through a Shell


Use the win_shell module to run commands through a shell, which defaults to PowerShell.
This module allows you to select the shell that runs the command and a context for it, such as the
directory from which the command runs.

384 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

- name: Test the availability of a server


win_shell: |
if (Test-Connection -ComputerName "server-1" -Count 2 -Quiet ) {
Write-Output "[OK]"
} else {
Write-Output "[FAIL]"
}

This demonstrates how you can pass multiple lines to the module. In this example, Ansible
uses the Test-Connection PowerShell function to send ICMP packets to the server-1
server.

Running Commands as a User with Elevated Permissions


Use the win_psexec module to run remote commands as a user with elevated permissions. The
module invokes psexec on the managed hosts, and runs the commands that you define in the
module. This module has many options, including psexec command options, the host names to
target, the command priority, and the credentials to use when running commands.

Important
The win_psexec module requires that PsExec is available on the Ansible managed
hosts on which the task runs. However, PsExec need not be present on the servers
that PsExec itself targets.

In addition, using this module with a certain set of privileges (for example, a
credential) assumes that you configured the privileges on the servers that PsExec
targets.

This is a useful module when running a set of commands on multiple hosts managed by Ansible,
when Ansible cannot access the hosts directly. For example, if the hosts are on a protected
network, they might not be directly accessible. You can configure software or update the network
configuration of your environment using this command. Use the hostnames parameter to define
the list of servers to which to connect.

- name: Restart IIS service firewall rule to the web servers


win_psexec:
command: > iisreset /noforce
hostnames:
- web-001
- web-002
- web-003
elevated: yes
username: demo
password: password
priority: realtime

This instructs Ansible to connect to each server in the list and run the command. This
example is equivalent to the following commands:

DO417-RHAE2.8-en-1-20200106 385
Chapter 9 | Automating Windows Administration Tasks

psexec \\web-001 -u demo -p D3m0$ iisreset /noforce


psexec \\web-002 -u demo -p password iisreset /noforce
psexec \\web-003 -u demo -p password iisreset /noforce

In the example, the password is set in the task, but Ansible Tower can prompt the user to
enter a value for the password variable.
Defines a list of hosts to target. Ansible connects to the managed host, then runs PsExec
against the hosts defined in the list. You can use either a DNS name, or an IP address, to
connect to the managed hosts. If you use a DNS name, the managed host must be able to
resolve the name. To run against all computers in the current domain use \\*.
When set to no, this option allows you to run the remote command as a limited user, stripping
Administrator privileges from the process or command. When set to yes, PsExec runs the
remote command as a privileged user.
Use this parameter to define a process priority level from among the following six levels:

• Realtime
• High
• Above normal
• Normal
• Below normal
• Low

Transferring and Running Scripts


Transfer a script from the control node to the managed host, and run that script, using the script
module. Ansible processes the script through the default remote shell, but you can specify the
path to another shell, such as PowerShell.

Like the other modules, you can set the context for the execution of the script, such as the
directory in which Ansible must run the script.

This module is useful if you have a script that the control node can access, but that the managed
hosts cannot. This is also useful if you have legacy scripts that cannot be converted to Ansible
modules.

Important
When using Ansible Tower, put your scripts in the repository that contains the
playbooks to run, and use a relative path to access the scripts. This allows Ansible to
access the scripts without the need to access your Ansible Tower instance and make
changes.

- name: Restart services


script: files/scripts/Windows/restart_services.cmd
args:
creates: C:\Windows\logs\restarted_services.log
executable: >
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe

Defines the local path to a script; that is, a path on the host that runs Ansible. In this example,
the local path is a Linux directory that contains Windows scripts in the repository.

386 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

Instructs Ansible to abort the execution of the script if the resource that you define in the
creates parameter exists on the remote system.
Instructs Ansible to use the shell that you define here to run the script.

Risks of Running Direct Commands


All four of these modules are convenient to use for automation, but use them with caution. These
modules are not naturally idempotent like other Ansible modules. Because these modules can
flexibly run any command, they do not have built-in code to check whether it is necessary or safe
to rerun the command.

Moreover, Ansible always returns a status of changed, even if the command does not make a
change to the system. One mitigation strategy is to use changed_when, which allows you to
implement your own logic to decide what constitutes a change. Operations that do not change
anything on your systems return a status of OK.

In short, these modules can have some unexpected and dangerous effects. Some possible
situations you might encounter these effects include:

• You attempt to delete a file that is no longer present.

• You have made changes to a file that a command references.

• A component depends on a file that is recreated every time you run a playbook, such as a TLS
certificate.

• The task restores a database each time that you run a play.

Note
Be careful when using these modules, and choose Ansible modules designed
for specific tasks whenever possible. This saves time by reducing the need for
conditionals to check the system before and after running tasks, and makes your
plays more robust.

Comparing Modules
The following table compares and contrasts the various modules.

win_command win_shell win_psexec script

Commands are run No Yes Yes Yes


through a shell

Can transfer a local script, No No No Yes


and run it remotely

Can set the context for Yes Yes Yes Yes


the command to run

Can use different shells No Yes No Yes

Can run remote No No Yes No


commands as another
user

DO417-RHAE2.8-en-1-20200106 387
Chapter 9 | Automating Windows Administration Tasks

win_command win_shell win_psexec script

Can set the stdin to a Yes Yes No No


specified value.

Can set a timeout value No No Yes No

Describing Direct Command Use Cases


The following section describes some use cases for the aforementioned modules, using return
codes and Ansible statements.

Updating DNS Servers


Use the win_shell module to change the DNS server of an interface, referenced by its index. A
handler restarts the sever after the change.

Note
The block style indicator (>) allows you to use multiline statements, which are
concatenated at execution. This is a useful syntax for passing multiple parameters to
a command.

- name: Update DNS configuration on NICs


hosts: all
vars:
net_adapter: 'Ethernet 3'

tasks:
- name: Interface index is retrieved
win_shell: >
(Get-NetIpInterface "{{ net_adapter }}" |
Select-Object -ExpandProperty InterfaceIndex -last 1 |
Out-String)
register: net_index

- name: DNS server is set


win_shell: >
Set-DnsClientServerAddress
-InterfaceIndex '"{{ net_index.stdout_lines[0] | trim }}"''
-ServerAddresses ("10.0.0.1","10.0.0.2")
notify:
- restart_server

handlers:
- name: restart_server
win_reboot:

Defines the name of the network interface to query.


Lists all adapters and filters on the index and captures the output in a variable. The last
property of the Select-Object cmdlet limits the output to one result. This prevents
duplicate output.
The DNS server is set using the interface index returned by the previous task.

388 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

The trim filter strips the output for characters, such as carriage returns.
This command notifies the restart_server handler, which instructs the server to reboot if
the command updates the network device.

Note
In this example, the trigger always runs and the server restarts every time. One
way to improve this playbook is to add an extra task that verifies whether the DNS
entries are already set. Doing so prevents the server from restarting if there is no
change to DNS entries.

Running Backups Using Robocopy


To backup a folder using Robocopy, use win_shell. Ansible instructs the systems to create
mirror copies of folders, while preserving all preexisting files and folders in the destination.

Ansible skips the backup if the log file exists, as defined by the creates variable. The
failed_when statement instructs Ansible to abort the play if Robocopy returns an exit code
other than 0.

Note
Although you can use the win_robocopy Ansible module, it does not support all
Robocopy options.

- name: Data is backed up


win_shell: >
robocopy C:\sites\ C:\Storage\Backup\sites
/MIR /XX
/log:C:\Storage\Backup\backup_result.log
args:
creates: C:\Storage\Backup\backup_result.log
register: backup_result
failed_when: backup_result.rc != 0

Optionally, you can use win_shell to send an email to administrators about the failure.

- name: Data is backed up


win_shell: >
robocopy C:\sites\ C:\Storage\Backup\sites
/MIR /XX
/log:C:\Storage\Backup\backup_result.log
args:
creates: C:\Storage\Backup\backup_result.log
register: backup_result
failed_when: backup_result.rc != 0

- name: Email is sent to backup administrators


win_shell: >
Send-MailMessage
-To backup-admins@acme.org
-from backup_server@acme.org

DO417-RHAE2.8-en-1-20200106 389
Chapter 9 | Automating Windows Administration Tasks

-Subject 'Backup did not complete'


-SmtpServer 127.0.0.1
when: backup_result.rc != 0

For more sophisticated automation, you can run the following PowerShell script when the backup
fails. The PowerShell scripts supports the usage of external SMTP servers with authentication.

# This PowerShell script


$Username = "Username";
$Password = "Password";

function Send-ToEmail([string]$email){
$message = new-object Net.Mail.MailMessage;
$message.From = "backup_server@acme.org";
$message.To.Add($email);
$message.Subject = "Backup did not complete";
$message.Body = "Backup did not complete on the backup server. Please review the
logs";

$smtp = new-object Net.Mail.SmtpClient("smtp.acme.org", "587");


$smtp.EnableSSL = $true;
$smtp.Credentials = New-Object System.Net.NetworkCredential($Username,
$Password);
$smtp.send($message);
write-host "Mail Sent";
$attachment.Dispose();
}
Send-ToEmail -email "backup-admins@acme.org";

- name: Email is sent to backup administrators


script: files/send-email.ps1
when: backup_result.rc != 0

Generating Certificates using Ansible


The following example shows an advanced usage of the win_shell module to generate a TLS
certificate for a service.

The playbook queries the certificates store and the configuration of the default IIS website, and
then runs additional verifications to determine the actions to take.

- name: Generate a self-signed certificate


hosts: web.acme.org
gather_facts: false
vars:
dns_name: 'acme.org'

tasks:
- name: Certificate is retrieved
win_shell: dir cert:\localmachine\my\
register: result_output

- name: Certificate is generated

390 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

win_shell: >
New-SelfSignedCertificate
-DnsName "{{ inventory_hostname }}"
-CertStoreLocation cert:\LocalMachine\My
-KeyExportPolicy Exportable
failed_when: cert_creation.rc != 0
when: 'dns_name not in result_output.stdout'

- name: IIS Binding is retrieved


win_shell: Get-IISSiteBinding 'Default Web Site'
changed_when: false
register: binding_result

- name: Certificate thumbprint is retrieved


win_shell: >
(Get-ChildItem -Path Cert:\LocalMachine\My |
Where-Object {$_.Subject -match "{{ dns_name }}"}).Thumbprint;
register: cert_thumbprint

- name: SSL binding is configured


win_iis_webbinding:
name: Default Web Site
protocol: https
port: 443
ip: "*"
certificate_hash: "{{ cert_thumbprint.stdout | trim }}"
state: present
when: "'443' not in binding_result.stdout"

The task checks for the presence of a certificate in the SSL store, and then saves the output
in the result_output variable.
The task generates an SSL certificate whose name matches the dns_name variable.
The task aborts the play if the command fails, that is, if the return code is other than 0.
Ansible instructs the system to create the certificate only if it is not present in the store. For
this verification, the task inspects the output of the result_output variable.
The task invokes the Get-IISSiteBinding cmdlet to verify if the default IIS site has an
SSL binding.
The task retrieves the thumbprint of the SSL certificate, and then saves the output in the
cert_thumbprint variable.
Finally, the playbook creates a binding that associates the SSL certificate to the IIS site.
Ansible passes the standard output that is in the cert_thumbprint variable to the
certificate_hash parameter.

The when statement instructs Ansible to skip the task if the binding is present.

Running Commands with PsExec


PsExec is a utility for running commands on remote hosts; it execute processes on other systems
without having to manually install the program, and is a replacement for telnet.

Important
To use this module, you must allow connections through the TCP port 45 and UDP
port 137 on the servers to which PsExec connects.

DO417-RHAE2.8-en-1-20200106 391
Chapter 9 | Automating Windows Administration Tasks

To interact with PsExec, use the win_psexec module. This module supports various options, such
as the credentials to use, whether to interact with the desktop on the remote systems, and setting
a priority for the process.

The following example shows how to configure the firewall for two web servers, and how to retrieve
a file from these servers after the command runs. The return code allows Ansible to abort the play
if the PsExec command does not succeed.

Note
The hostname parameter defines a list of hosts that PsExec connects to, and
on which commands are run. They can be different from the hosts that Ansible
manages.

- name: Configure firewall rule and retrieve CA certificate on web servers


hosts: all

tasks:
- name: Firewall rule is added
win_psexec:
command: >-
netsh advfirewall firewall
add rule name="Open Port 80" dir=in
action=allow protocol=TCP localport=80"
executable: C:\PsTools\PsExec.exe
hostnames:
- web-001
- web-002
- web-003
elevated: yes
username: Administrator
password: 'D3m0$'
priority: realtime
register: psexec_command
failed_when: psexec_command.rc != 0

- name: CAs are retrieved


win_shell: >
Invoke-WebRequest -Uri "https://{{ item }}.acme.org:80/CA.crt"
-OutFile 'C:\temp\{{ item }}.crt'
loop:
- web-001
- web-002
- web-003

- name: CAs are imported


win_shell: >
Import-Certificate -FilePath 'C:\temp\{{ item }}.crt'
-CertStoreLocation Cert:\LocalMachine\Root
loop:
- web-001
- web-002
- web-003

392 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

The >- sign instructs Ansible to remove the new line at the end of the command.
Instructs Ansible to connect to each server in the list, and run the netsh command to open
the firewall port 80. The psexec_command variable stores the result of the command.
Defines the location of the PsExec utility. This is a useful setting as PsExec can run from
anywhere.
Defines a list of hosts to target. Ansible connects to the managed host, as defined by the
hosts parameter, and then runs PsExec against the hosts that you define in the list. You can
use either a DNS name, or an IP address, to connect to the managed hosts. The managed
host must be able to either resolve or access the server.

Note
To run against all computers in the current domain use \\*.

Retrieves a file from the web servers, after PsExec configured the firewall on those servers.

The item keyword instructs Ansible to loop over the three web servers.
Adds the Certificate Authority (CA) to the certificate store of the local machine.

Managing PowerShell Modules


PowerShell modules are a set of Windows PowerShell functionalities grouped as a convenient
bundle with the .psm1 extension. A module minimally contains a PowerShell script that performs a
set of operations through PowerShell.

Use Ansible to download new modules from module galleries, such as the PowerShell Gallery,
available at https://www.powershellgallery.com/.

PowerShell repositories describe the endpoints that host these modules; after adding a repository,
use the Install-Module cmdlet to install that repository.

Ansible offers two modules for managing your PowerShell repositories and modules:

• win_psmodule

Supports installing or removing a PowerShell module from the list of configured repositories or a
custom gallery.

• win_psrepository

Supports managing your PowerShell modules repository. It takes a name and a source as
parameters to either add or remove a repository.

This is the equivalent of using the Register-PSRepository cmdlet.

The following example shows how to add a custom repository, and install a PowerShell module
from that repository, using Ansible.

- name: Install PowerShell modules


hosts: all

tasks:
- name: Repository is added
win_psrepository:
source: https://www.powershellgallery.com/api/v2/
name: PowerShell Gallery
state: present

DO417-RHAE2.8-en-1-20200106 393
Chapter 9 | Automating Windows Administration Tasks

- name: Repository is queried


win_shell: Get-PSRepository "PowerShell Gallery"
register: repository_output
failed_when: repo_status.rc != 0
changed_when: false

- name: Modules are installed


win_psmodule:
name: "{{ item }}"
state: present
loop:
- Carbon
- PowerShellGet
- xCertificate

This task creates the PowerShell Gallery repository. It then saves the output to the
ps_gallery variable. Use state: absent to remove the repository, which is what the
Unregister-PSRepository PowerShell cmdlet does.
This is the API endpoint of the repository.
This task invokes the Get-PSRepository cmdlet to ensure that the repository is present. If
not, the play fails.
This task instructs the system to install a set of modules from the repository. To remove
these modules, give the state parameter a value of absent. This is equivalent to the
Uninstall-Module PowerShell cmdlet.

Scheduling Tasks in Windows


Windows systems ship with a task scheduler that enables you to perform routine tasks on your
systems. Define a set of criteria for each task, referred to as triggers, that instructs the system to
run the task, also referred to as actions.

You can run many tasks, such as running a program, executing a PowerShell script, sending an
email, installing a service, and so on. You can create tasks for the following:

• When a system event occurs, such as the renaming of the host.

• At a specific time, such as a day in the week or in the month.

• When the system reboots.

• When a user logs in.

There are many ways to interact with the task scheduler, such as using the interface, or
programmatically via PowerShell, using C++, or C# code for your Windows applications.

A powerful way to use the task scheduler is the invocation of PowerShell as an action, which then
runs a script via the -F option. This allows you to create advanced scripts for managing your
systems, and to use the task scheduler to run them at intervals that you define.

394 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

Figure 9.1: The Windows task scheduler

Scheduling Tasks Using Ansible


Ansible ships with two modules for scheduling tasks and managing the schedules:
win_scheduled_task and win_scheduled_task_stat. Use win_scheduled_task to
manage scheduled tasks, and win_scheduled_task_stat to retrieve information about a
scheduled task, or the list of the scheduled tasks in a folder.

win_scheduled_task has many options, such as the list of actions to configure for the task (the
arguments, the working directory, and a path for the executable), whether to run the task using the
Run command or the Context menu, the schedule for the task, and the task priority.

Note
For the list of all parameters, consult win_scheduled_task — Ansible Documentation
listed in the references section.

The following example shows how to create a scheduled task that runs a PowerShell script when
the server starts, and when the user that owns the task logs on. The script iterates over a list of
servers and attempts to reach them.

- name: Create a scheduled task


hosts: all

tasks:
- name: A scheduled task is created
win_scheduled_task:
name: QueryHosts
description: >
Run a PowerShell script that uses ping to reach the servers
in the environment

DO417-RHAE2.8-en-1-20200106 395
Chapter 9 | Automating Windows Administration Tasks

author: sylvia@acme.org
enabled: true
hidden: true
actions:
- path: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
arguments: >
-ExecutionPolicy Unrestricted
-NonInteractive -File C:\Scripts\pingHosts.ps1
triggers:
- type: boot
- type: logon
priority: 1
state: present

When hidden is set to true, the task does not appear in the task manager console. By
default, hidden is set to false.
Creates a new action; in this example, that action is a task that invokes PowerShell.
The arguments parameters defines a list of optional arguments. The task scheduler passes
these arguments to the command.
Defines the list of triggers; in this example, the scheduled task runs when the system starts,
and when the owner of the task logs in.
Defines a priority for the task, which accepts a value between 0-10. See TaskSettings.Priority
property — Windows Documentation listed in the references section for a list of possible
priorities.

After executing the play, the task is visible in the task scheduler interface.

Figure 9.2: The Windows task scheduler

396 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

Use the win_scheduled_task_stat module to retrieve information about the scheduled tasks
on the system. The module returns information such as the actions, the owner of the task, or the
triggers.

The following playbook uses win_scheduled_task_stat to retrieve information about the


task created in the previous example. Using the optional path parameter allows you to retrieve
information about tasks that are stored outside the root folder.

- name: Retrieve information about task


hosts: all

tasks:
- name: Information about QueryHosts is retrieved
win_scheduled_task_stat:
name: QueryHosts

The output is a JSON dictionary that contains detailed information about the task:

The state JSON dictionary contains information about the execution of the scheduled task. You
can further parse this data to determine the success or failure of the job.

{
...output omitted...
"principal": {
"display_name": null,
"logon_type": "TASK_LOGON_INTERACTIVE_TOKEN",
"user_id": "WIN1\\devops",
"group_id": null,
"id": "Author",
"run_level": "TASK_RUNLEVEL_HIGHEST"
},
"task_exists": true,
...output omitted...
"state": {
"status": "TASK_STATE_READY",
"last_task_result": 0,
"next_run_time": "1899-12-30T00:00:00",
"last_run_time": "2019-09-25T17:08:16",
"number_of_missed_runs": 0
},
{
"hide_app_window": false,
"arguments": "-ExecutionPolicy Unrestricted -NonInteractive -File C:\
\Scripts\\pingHosts.ps1",
"path": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
"working_directory": null,
"type": "TASK_ACTION_EXEC",
"id": null
}
],
"registration_info": {
"description": "Run a PowerShell script that uses ping to reach the
servers in the environment",
"author": "sylvia@acme.org",

DO417-RHAE2.8-en-1-20200106 397
Chapter 9 | Automating Windows Administration Tasks

"documentation": null,
"uri": "\\QueryHosts",
"source": null,
"version": null,
"date": null,
"security_descriptor": null
},
"settings": {
"run_only_if_network_available": false,
"execution_time_limit": "PT72H",
"idle_settings": {
"wait_timeout": "PT1H",
"idle_duration": "PT10M",
"stop_on_idle_end": true,
"restart_on_idle": false
...output omitted...

Note
Use this module to obtain information about your scheduled task and how to further
tweak it.

References
win_scheduled_task — Ansible Documentation
https://docs.ansible.com/ansible/latest/modules/win_scheduled_task_module.html

PsExec v2.2 — Windows Documentation


https://docs.microsoft.com/en-us/sysinternals/downloads/psexec

PowerShell Gallery
https://www.powershellgallery.com/

Using the Task Scheduler — Windows Documentation


https://www.powershellgallery.com/https://docs.microsoft.com/en-us/windows/
win32/taskschd/using-the-task-scheduler

TaskSettings.Priority property — Windows Documentation


https://docs.microsoft.com/en-us/windows/win32/taskschd/tasksettings-priority

398 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

Guided Exercise

Running Commands and Scheduling


Tasks on Hosts
In this exercise, you will write playbooks that manage PowerShell modules, run arbitrary
commands idempotently, and set up a scheduled task.

Outcomes
You should be able to:

• Create Ansible Tower credentials.

• Write an Ansible Playbook to manage PowerShell repositories and modules.

• Write an Ansible Playbook to generate an SSL certificate, and configure an IIS site to use
it.

• Write an Ansible Playbook to schedule a task.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. Open Visual Studio Code, and then clone the windows repository available at https://
gitlab.example.com/student/windows.git.

1.1. Click the Visual Studio Code desktop icon to open the editor.

1.2. Navigate to View → Command Palette or press Ctrl+Shift+P to open the


command palette.
Type clone, and then select Git: Clone to clone a repository. Use a repository URL of
https://gitlab.example.com/student/windows.git.
When prompted, select the Documents folder in the home directory of the training
user, and then click Select Repository Location. This clones the remote repository
into the windows folder.
Click Open from the window that displays after cloning to add the folder to the
workspace.

2. Open the powershell-modules.yml Ansible Playbook. The following steps describe the
changes to make to the playbook in order to configure a PowerShell repository and install a
set of modules.

2.1. Open the powershell-modules.yml file at the top-level of the project.

DO417-RHAE2.8-en-1-20200106 399
Chapter 9 | Automating Windows Administration Tasks

The playbook contains placeholders that you must change. Do not update the first
task, which clears any existing repositories.

2.2. Create two variables in the vars section of the playbook as follows:

• The powershell_repo_endpoint points to a PowerShell repository API endpoint


accessible at https://www.powershellgallery.com/api/v2/.

• The powershell_modules variable is a YAML list that defines the list of


PowerShell modules to install. Define the following two modules:
• PSWindowsUpdate
• Get-PSGoodFirstIssue

The beginning of the playbook should display as follows:

- name: Install PowerShell modules


hosts: all
vars:
powershell_repo_endpoint: https://www.powershellgallery.com/api/v2/
powershell_modules:
- PSWindowsUpdate
- Get-PSGoodFirstIssue

2.3. Next, create a task that registers a new PowerShell repository. Use the
win_psrespository module to accomplish this task. The module requires a source,
a name, and a state. Use the powershell_repo_endpoint as the module source
parameter.

...output omitted...
tasks:
- name: Current repositories are unregistered
win_shell: Unregister-PSRepository "{{ item }}"
ignore_errors: true
loop:
- PowerShell Gallery
- PSGallery

- name: Repository is added


win_psrepository:
source: "{{ powershell_repo_endpoint }}"
name: "PowerShell Gallery"
state: present

2.4. Add a task to ensures that the PowerShell repository is present. The task captures the
output in the repo_status variable, and then fails if the command does not return 0.
The changed_when: false statement instructs Ansible to return a status of ok,
because the task does not make any changes to the system.

Note
Notice the indentation. Because register, failed_when, and changed_when
are not part of the module parameters, you must indent them at the same level as
the module name.

400 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

...output omitted...
- name: Repository is queried
win_shell: Get-PSRepository "PowerShell Gallery"
register: repo_status
failed_when: repo_status.rc != 0
changed_when: false

2.5. Add a task for installing the PowerShell modules listed in the powershell_modules
list. Use the win_psmodule module to accomplish this task. Because there is more
than one package, create a loop to iterate over the elements in the list.

Note
Because the variable is a list, you can pass it to the loop as is.

...output omitted...
- name: PowerShell modules are installed
win_psmodule:
name: "{{ item }}"
state: present
loop: "{{ powershell_modules }}"

After completion, the playbook should display as follows:

- name: Install PowerShell modules


hosts: all
vars:
powershell_repo_endpoint: https://www.powershellgallery.com/api/v2/
powershell_modules:
- PSWindowsUpdate
- Get-PSGoodFirstIssue

tasks:
- name: Current repositories are unregistered
win_shell: Unregister-PSRepository "{{ item }}"
ignore_errors: true
loop:
- PowerShell Gallery
- PSGallery

- name: Repository is added


win_psrepository:
source: "{{ powershell_repo_endpoint }}"
name: PowerShell Gallery
state: present

- name: Repository is queried


win_shell: Get-PSRepository "PowerShell Gallery"
register: repo_status
failed_when: repo_status.rc != 0

DO417-RHAE2.8-en-1-20200106 401
Chapter 9 | Automating Windows Administration Tasks

changed_when: false

- name: PowerShell modules are installed


win_psmodule:
name: "{{ item }}"
state: present
loop: "{{ powershell_modules }}"

Note
The completed playbook is available in the solutions directory of the project.

3. Save and commit your changes, then synchronize the repository.

3.1. Click Source Control.

3.2. Click + for the powershell-modules.yml file to stage your changes.

3.3. In the commit message field, type the commit message Register PowerShell
repository and install modules, and then click commit above the message
field, or press Ctrl+Enter.

3.4. Click Synchronize Changes in the lower left corner of the editor. This action
synchronizes your changes with GitLab.

4. Access Ansible Tower, and then update the Run windows project template. Use the
powershell-modules.yml Ansible Playbook.

4.1. From workstation, double-click Ansible Tower to access the web console.
Log in to Ansible Tower using admin as the user name and RedHat123@! as the
password.

4.2. Click Templates to access the list of templates, and then select Run windows
project to edit it.

4.3. Select powershell-modules.yml in the PLAYBOOK field. Leave the other values
as is and click SAVE.

402 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

4.4. Click LAUNCH to run a job based on the job template.

4.5. Observe the output as Ansible Tower clears any existing repositories, registers the
repository that you have defined, and installs the two PowerShell modules.

5. From workstation, open the remote desktop client to connect to win1.example.com.


Ensure that the modules are installed on the server.

5.1. Access the Remote Desktop Connection client available from the Start menu.
The client is accessible from the Windows Server applications list.
Access win1 using devops as the user name. Click Connect to initiate the
connection. Use a password of RedHat123@!, and then click OK.
When prompted, click Yes to accept the self-signed certificate.

DO417-RHAE2.8-en-1-20200106 403
Chapter 9 | Automating Windows Administration Tasks

5.2. Click Windows PowerShell from the Start menu to open a PowerShell console.

5.3. Type the following command to import the PSWindowsUpdate module:

PS C:\Users\devops> import-Module PSWindowsUpdate

5.4. Query the available options of the module.

PS C:\Users\devops> Get-Command –module PSWindowsUpdate

CommandType Name Version Source


----------- ---- ------- ------
Alias Clear-WUJob 2.1.1.2 PSWindowsUpdate
Alias Download-WindowsUpdate 2.1.1.2 PSWindowsUpdate
Alias Get-WUInstall 2.1.1.2 PSWindowsUpdate
Alias Get-WUList 2.1.1.2 PSWindowsUpdate
Alias Hide-WindowsUpdate 2.1.1.2 PSWindowsUpdate
Alias Install-WindowsUpdate 2.1.1.2 PSWindowsUpdate
Alias Show-WindowsUpdate 2.1.1.2 PSWindowsUpdate
Alias UnHide-WindowsUpdate 2.1.1.2 PSWindowsUpdate
...output omitted...

5.5. Repeat the preceding two steps to import the Get-PSGoodFirstIssue module, and
query the available options. Exit the RDP connection when finished.

404 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

PS C:\Users\devops> import-Module Get-PSGoodFirstIssue


PS C:\Users\devops> Get-Command –module Get-PSGoodFirstIssue
CommandType Name Version Source
----------- ---- ------- ------
Function Get-PSGoodFirstIssue 0.0.7 Get-PSGoodFirstIssue
Function Get-PSHacktoberFestIssue 0.0.7 Get-PSGoodFirstIssue

6. Return to Visual Studio Code and open the IIS-ssl.yml Ansible Playbook. The playbook
has initial tasks that configure the IIS site.
The following steps describe the list of changes to make to the playbook in order to
configure an IIS website on win1.example.com with a self-generated SSL certificate.

6.1. Append a task that verifies whether the IIS site has an SSL binding on port 8888. In a
later step, you configure that port to serve the website over TLS.
The task uses the Get-IISSiteBinding cmdlet to retrieve the SSL binding of the
DO417-windows IIS site, and then saves the output to the iis_ssl_stat variable.
Because the task does not make any changes to the system, add the changed_when:
false statement.

...output omitted...
## DO NOT EDIT ABOVE THIS LINE ##

- name: IIS binding is retrieved


win_shell: Get-IISSiteBinding "DO417-windows"
changed_when: false
register: iis_ssl_stat

6.2. Add a task that checks the presence of an SSL certificate for win1.example.com.
Save the result in a variable and use the ignore_errors: true statement to ensure
that the play runs even if the certificate does not exist.
Because the command does not make any change to the system, add
changed_when: False.

...output omitted...
- name: SSL is queried
win_shell: dir cert:\localmachine\my\
ignore_errors: True
changed_when: False
register: ssl_status

6.3. If the preceding task does not return any matching value for a certificate, then add a
task that generates the SSL certificate.
The task invokes the New-SelfSignedCertificate cmdlet to generate a self-
signed certificate with a host name of win1.example.com; Ansible substitutes
inventory_hostname with the server host name.

DO417-RHAE2.8-en-1-20200106 405
Chapter 9 | Automating Windows Administration Tasks

...output omitted...
- name: SSL certificate is generated
win_shell: >
New-SelfSignedCertificate
-DnsName "{{ inventory_hostname }}"
-CertStoreLocation cert:\LocalMachine\My
-KeyExportPolicy Exportable
when: "'win1' not in ssl_status.stdout"

6.4. Add a block clause that instructs Ansible to configure IIS with an SSL certificate if the
SSL binding is absent. It performs the following tasks:

• Retrieves the certificate thumbprint and stores it in a variable.


• Creates a new SSL binding for the DO417-windows IIs site.
• Restarts the IIS site.

Add a when statement to instruct Ansible to run the block if the SSL binding is not
present.

...output omitted...
- name: IIS site is configured
block

when: "'8888' not in iis_ssl_stat.stdout"

6.5. In the block statement, create a task named Certificate thumbprint is


retrieved. The task retrieves the SSL certificate thumbprint and stores it in
cert_thumbprint.

...output omitted...
- name: IIS site is configured
block:
- name: Certificate thumbprint is retrieved
win_shell: >
(Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object
{$_.Subject -match "{{ inventory_hostname }}"}).Thumbprint;
register: cert_thumbprint

6.6. Add a second task in the block that configures the SSL binding of the DO417-
windows IIS site. Name the task SSL binding is added. This task reuses the
cert_thumbprint variable in the certificate_hash parameter. The trim filter
removes any line continuation.

...output omitted...
- name: SSL binding is added
win_iis_webbinding:
name: DO417-windows
protocol: https
port: 8888
ip: "*"
certificate_hash: "{{ cert_thumbprint.stdout | trim }}"
state: present

406 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

6.7. Finally, add a task named IIS site is restarted to restart the IIS site. It uses the
win_iis_website module to restart the site, and then defines a new entry for IIS.

...output omitted...
- name: IIS site is restarted
win_iis_website:
name: DO417-windows
state: started

The updated playbook displays as follows: Tasks that are already included in the playbook
are omitted from the output.

- name: IIS site with SSL certificate is Installed and Configured


hosts: win1.example.com

tasks:
...output omitted...
- name: IIS binding is retrieved
win_shell: Get-IISSiteBinding "DO417-windows"
changed_when: false
register: iis_ssl_stat

- name: SSL is queried


win_shell: dir cert:\localmachine\my\
ignore_errors: True
changed_when: False
register: ssl_status

- name: SSL certificate is generated


win_shell: >
New-SelfSignedCertificate
-DnsName "{{ inventory_hostname }}"
-CertStoreLocation cert:\LocalMachine\My
-KeyExportPolicy Exportable
when: "'win1' not in ssl_status.stdout"

- name: IIS site is configured


block:
- name: Certificate thumbprint is retrieved
win_shell: >
(Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object
{$_.Subject -match "{{ inventory_hostname }}"}).Thumbprint;
register: cert_thumbprint

- name: SSL binding is added


win_iis_webbinding:
name: DO417-windows
protocol: https
port: 8888
ip: "*"
certificate_hash: "{{ cert_thumbprint.stdout | trim }}"
state: present

DO417-RHAE2.8-en-1-20200106 407
Chapter 9 | Automating Windows Administration Tasks

- name: IIS site is restarted


win_iis_website:
name: DO417-windows
state: started

when: "'8888' not in iis_ssl_stat.stdout"

Note
The completed playbook is available in the solutions directory of the project.

7. Save the playbook and stage it. Click Source Control.


Click + for the IIS-ssl.yml file to stage your changes.

8. In the commit message field, type a commit message of Configure an SSL


certificate for IIS and click the commit button above the message field or type
Ctrl+Enter.

9. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to push
your local changes to the remote repository, and retrieve any new changes from the
repository.

10. Access Ansible Tower and update the Run windows project template. Select IIS-
ssl.yml as the Ansible Playbook for the job template.

10.1. From workstation, access Ansible Tower. Navigate to Templates from the side
menu to access the templates.
Click Run windows project to edit the job template.

10.2.Select IIS-ssl.yml in the PLAYBOOK field and click SAVE.

408 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

10.3.Click LAUNCH to run the job. Ansible redirects you to the job output. The output
indicates that Ansible configures the IIS site, generates the SSL certificate, and
updates the IIS site.

11. From workstation, open a new Google Chrome tab and access https://
win1.example.com:8888. Click the Not secure button at the top to review the
certificate information This confirms that the site is properly running with a self-signed
security certificate.

12. Return to Visual Studio Code and open the scheduled-tasks.yml Ansible Playbook.
This playbook creates a scheduled task that runs a PowerShell script. The script iterates
over a list of two servers and attempts to reach them.
The following steps describe the list of changes to make to the playbook in order to
schedule a task in the Windows scheduler.

DO417-RHAE2.8-en-1-20200106 409
Chapter 9 | Automating Windows Administration Tasks

12.1. Define a ps_script variable in the vars section of the playbook. Give it a value of
pingHosts.ps1

- name: Create a scheduled task


hosts: win1.example.com
vars:
ps_script: 'pingHosts.ps1'

12.2. Define the first task that uses the win_file module. The task creates the scripts
directory on the managed host.

- name: Create a scheduled task


hosts: win1.example.com
vars:
ps_script: 'pingHosts.ps1'

tasks:
- name: Script directory is created
win_file:
path: C:\Scripts\
state: directory

12.3. Create a task that uses the win_copy module to transfer the PowerShell script to the
managed host in C:\Scripts. Reuse the ps_script variable for the src parameter.

Note
Make sure to use slashes and not backslashes Because the file is located on the
Ansible Tower host.

...output omitted...
- name: PowerShell script is transferred
win_copy:
src: "files/{{ ps_script }}"
dest: C:\Scripts\

12.4. Create a task that uses the win_scheduled_task module to create the scheduled
task. Use the following information:

• Give the task a name of QueryHosts.

• Give the task a description of Run a PowerShell script that uses ping
to reach servers in the environment.

• Invoke PowerShell in non-interactive mode, and use the -File option to pass the
pingHosts.ps1 PowerShell script as the argument.

• Define two triggers for the task: one that instructs the scheduled task to run when
the system starts, and one that instructs the task to run when the user logs in.

• Define a priority of 1.

410 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

Note
Some values are already pre-filled to help with the completion of the task.

...output omitted...
- name: A scheduled task is created
win_scheduled_task:
name: QueryHosts
description: >
Run a PowerShell script that uses ping to reach a servers
in the environment
author: student@example.com
enabled: true
actions:
- path: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
arguments: >
-ExecutionPolicy Unrestricted
'-NonInteractive -File C:\Scripts\{{ ps_script }}'
triggers:
- type: boot
- type: logon
priority: 1
state: present

12.5. Add a final task that uses the win_scheduled_task_stat module to retrieve some
information about that the scheduled task. The module dumps a JSON dictionary that
is accessible from the Ansible Tower job output. Give the name of the scheduled task
to the name parameter.
Use a changed_when: False statement Because the task does not make any
change to the system.

...output omitted...
- name: Status of the task is retrieved
win_scheduled_task_stat:
name: QueryHosts
changed_when: False

The completed playbook should display as follows:

- name: Create a scheduled task


hosts: win1.example.com
vars:
ps_script: 'pingHosts.ps1'

tasks:
- name: Script directory is created
win_file:
path: C:\Scripts\
state: directory

DO417-RHAE2.8-en-1-20200106 411
Chapter 9 | Automating Windows Administration Tasks

- name: PowerShell script is transferred


win_copy:
src: "files/{{ ps_script }}"
dest: C:\Scripts\

- name: A scheduled task is created


win_scheduled_task:
name: QueryHosts
description: >
Run a PowerShell script that uses ping to reach a servers
in the environment
author: student@example.com
enabled: true
actions:
- path: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
arguments: >
-ExecutionPolicy Unrestricted
'-NonInteractive -File C:\Scripts\{{ ps_script }}'
triggers:
- type: boot
- type: logon
priority: 1
state: present

- name: Status of the task is retrieved


win_scheduled_task_stat:
name: QueryHosts
changed_when: False

Note
The completed playbook is available in the solutions folder of the project.

13. Save and commit your changes, then synchronize the repository.

13.1. Click the Source Control icon from the sidebar.

13.2. Click the + symbol for the scheduled-tasks.yml file to stage your changes.

13.3. In the commit message field, type a commit message of Configure a scheduled
task, and then click commit or press Ctrl+Enter.

13.4. Click Synchronize Changes in the lower left corner of the editor. This action
synchronizes your changes with GitLab.

14. Access Ansible Tower and update the Run windows project template. Use the
scheduled-tasks.yml Ansible Playbook.

14.1. From workstation, access Ansible Tower. Navigate to Templates to access the
templates.
Click Run windows project to edit the job template.

14.2.Select scheduled-tasks.yml in the PLAYBOOK field and click SAVE.

412 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

14.3.Click LAUNCH to run the job. Ansible redirects you to the job output. The output
indicates that Ansible installs the PowerShell script to the scripts directory and
creates a new scheduled task.

14.4.From the job output, click the ok: [win1.example.com] entry for the Status of
the task is retrieved task to read the information about the scheduled task.
Review the JSON dictionary that contains information about the scheduled task run
level, task arguments, and other information about the task.

DO417-RHAE2.8-en-1-20200106 413
Chapter 9 | Automating Windows Administration Tasks

15. From workstation, open the remote desktop client to connect to win1.example.com.
Launch the task scheduler to confirm the present of the scheduled task.

15.1. Access the Remote Desktop Connection client, available from the Start menu.
The client is accessible from the Windows Server applications list.
Access win1 using devops as the user name. Click Connect to initiate the
connection. Use a password of RedHat123@!, and then click OK.
When prompted, click Yes to accept the self-signed certificate.

15.2. Click the magnifying glass icon and type Task Scheduler to access the task
scheduler.

15.3. From the Active Tasks panel, double-click the QueryHosts entry.

Note
If you do not see the task, navigate to Action → Refresh to update the list of
scheduled tasks.

15.4. Click through the tabs to review the various options that the task uses. Exit the RDP
connection when finished.

414 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

This concludes the guided exercise.

DO417-RHAE2.8-en-1-20200106 415
Chapter 9 | Automating Windows Administration Tasks

Configuring and Managing Storage

Objectives
After completing this section, you should be able to automate configuration of storage devices on
managed hosts.

Managing Storage on Windows


Ansible includes modules for managing partitions and file systems on block based storage devices,
and for managing network storage, such as shares and mapped drives. Operations, such as
obtaining storage information from a managed host, or defragmenting an existing volume, are also
supported. The following list provides detail on some of the capabilities provided.

Windows Storage Modules

win_defrag
When a volume has a lot of activity, the files can become fragmented, meaning that they are
spread over different areas of the file system. Fragmented files can have slower read/write
speeds due to the increase in the number of seeks required. A seek is when the drive moves
the head to the start of the data to be read. When a file is fragmented, the drive must seek
each chunk before reading or writing.

After a file system has been defragmented, all the chunks of each file are contiguous, meaning
that they are next to each other on the disk; this results in fewer seeks. File systems on solid
state drives do not require defragmenting, as there are no physical heads to move.

Figure 9.13: File system fragmentation

Using the win_defrag module, administrators can decide exactly when defragmentation
should occur, as disk performance will be impacted during the operation. The module
has several useful parameters, such as parallel, which enables all drives to be
defragmented at the same time; exclude_volumes is used to exclude a drive from the
defragmentation operation. You can also specify priority to reduce the performance hit,
and freespace_consolidation, which may be useful when a drive needs to be reduced.

win_disk_facts
Before enacting changes to disk partitions and file systems, you must ensure that the storage
configuration on the managed host is suitable. This module retrieves the storage system
information from the managed host as facts, which are then included in the ansible_facts
variable under the disks array.

416 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

The output includes a wide variety of information, including bus type, manufacturer, whether
the partition is MBR or GPT style, as well as physical and virtual disk attributes. Testing fields
in the ansible_facts['disks'] array enables running tasks conditionally.

win_disk_image
Provides the ability to mount a disk image, which can also be classified as a storage task.
Images in ISO, VHD, or VHDX format are supported, allowing operations such as software
installation from an ISO image, or manipulation of virtual machine disks.

win_format
Formats a new or existing Windows volume, with a choice of FAT, FAT32, EXFAT, NTFS, or
ReFS file systems. Specify only one of the drive_letter, path, or label parameters when
using this module. Other available parameters include compress to enable compression, and
full to perform a full format.

win_mapped_drive
Supports mapping Windows shares to drive letters.

Note
The username and password parameters of this module are only useful for testing
a mapped drive connection; you must use the win_credential module to store
credentials persistently.

win_partition
Defines MBR style partitions of type FAT12, FAT16, extended, huge, IFS, or FAT32. GPT style
partitions can be any of the following: system_partition, microsoft_reserved, basic_data,
or microsoft_recovery types. Other parameters include active to make an MBR partition
bootable, and hidden to prevent the OS from seeing the partition.

win_share
Defines shared folders and the access permitted; this module is a partner to
win_mapped_drive, Parameters for access control include change, deny, full, list, and
read.

The following example shows the win_defrag module in use. The system drive is excluded, and
all other drives are defragmented in parallel, but with a low priority.

- name: Data drives defragmented


win_defrag:
parallel: yes
exclude_volumes: C
priority: low

This example demonstrates using the win_disk_facts module to extract information for a
specific disk.

---
- name: System disk firmware versions are printed
hosts: demo.example.com

tasks:
- name: Populate disk facts
win_disk_facts:

DO417-RHAE2.8-en-1-20200106 417
Chapter 9 | Automating Windows Administration Tasks

- name: Show firmware version for drive C


debug:
var: ansible_facts['disks'][0]['firmware_version']

The following example demonstrates the win_disk_image module mounting an ISO. The debug
module is used to display the drive letter on which the ISO is mounted.

- name: MyApp ISO is mounted


win_disk_image:
image_path: C:\myapp_installer.iso
state: present
register: myapp_iso

- name: MyApp ISO drive letter is shown


debug:
msg: "MyApp ISO mounted at: {{ myapp_iso['mount_paths'][0] }}"

The following example uses the win_format module to perform a full format of drive E:.

- name: Log volume (E:) is formatted as NTFS


win_format:
drive_letter: E
file_system: NTFS
new_label: Logs
full: true

The following example demonstrates using the win_mapped_drive module to map a drive with
credentials persistently.

- name: Data drive for SQL Server is mapped


block:
- name: Service account credentials are saved
win_credential:
name: '*.example.com'
type: domain_password
username: "{{ sql_svc_acct_name }}@EXAMPLE"
secret: "{{ sql_svc_acct_pass }}"
state: present

- name: Data drive is mapped


win_mapped_drive:
letter: S
path: \\NAS01\DB_DATA$
state: present
vars:
ansible_become: yes
ansible_become_method: runas
ansible_become_user: '{{ ansible_user }}'
ansible_become_pass: '{{ ansible_password }}'

418 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

Note
Note the use of win_credential to persistently store the service account
credentials. Also, notice the use of *_become variables that enable access to the
user's credential store.

Here the win_partition module creates a 50 GiB partition.

- name: Scratch disk is created


win_partition:
drive_letter: F
partition_size: 50 GiB
disk_number: 1

The following example uses the win_share module to share a company forms folder.

- name: Forms share is added


win_share:
name: Forms
description: Company forms
path: D:\shares\Forms
list: yes
full: Domain Admins,HR
read: Domain Users

Common use cases will likely require several of these modules working together. For
example, using win_disk_facts to determine the exact storage configuration, followed by
win_partition and win_format to create a formatted drive. Another example is using
win_share to create a shared folder, followed by win_credential and win_mapped_drive to
persistently map a drive letter to the share on client machines.

References
Windows modules — Ansible documentation
https://docs.ansible.com/ansible/latest/modules/list_of_windows_modules.html

JSON Query Filter — Ansible documentation


https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#json-
query-filter

DO417-RHAE2.8-en-1-20200106 419
Chapter 9 | Automating Windows Administration Tasks

Guided Exercise

Configuring and Managing Storage


In this exercise, you will write a playbook that ensures a specific storage device is configured
and formatted, and that a Windows share is created on the new volume.

Outcomes
You should be able to create and format new partitions, and create Windows shares.

Before You Begin


Confirm that the workstation and all infrastructure machines are running, and that you
can access Ansible Tower and GitLab in a browser.

Open your RDP client and connect to workstation using example.com as the domain,
student as the user name and RedHat123@! as the password.

You can find the connection information to your systems in the email that you received.

1. Launch the Visual Studio Code editor. If you have not previously cloned the windows
repository, clone it to your workstation instance.

1.1. Click Search Windows, search for code, and then open Visual Studio Code.

1.2. Navigate to View → Command Palette or press Ctrl+Shift+P to view the


command palette.
Type clone, and then select Git: Clone to clone a repository.
Use a repository URL of https://gitlab.example.com/student/
windows.git. When prompted, select the Documents folder in the home directory
of the training user, and then click Select Repository Location. This clones the
remote repository in to the windows folder.
To view the files, select Open from the window that displays after cloning, and then
skip the next step.

2. To navigate to the C:\Users\student\Documents\windows directory, click File →


Open Folder, and then select the C:\Users\student\Documents\windows folder.

3. Open the storage.yml playbook, and then complete the tasks.

Note
The Second disk extracted as standalone fact task uses an advanced
filter method to obtain the facts for the second disk. This method will not be
discussed in this course, but is required for this exercise. For further information,
please see the References section in the Configuring and Managing Storage section.

3.1. Complete the Second disk size printed task to display the value of the
second_disk[0]['size'] variable.

420 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

- name: Second disk size printed


debug:
var: second_disk[0]['size']

3.2. Modify the Partition is created on second disk task to set the following
values:

• Disk number 1
• Drive F
• Sized at 1 GiB

- name: Partition is created on second disk


win_partition:
disk_number: 1
drive_letter: F
partition_size: 1 GiB
register: partition_task

3.3. Complete the New partition is formatted task to create an NTFS volume
named data on drive F:. The task will run conditionally, depending on whether the
previous task resulted in changed resolving to true.

- name: New partition is formatted


win_format:
drive_letter: F
file_system: NTFS
new_label: data
full: true
when: partition_task['changed']

3.4. Complete the Share folder is created task to create the F:\shares\forms
folder.

- name: Share folder is created


win_file:
path: F:\shares\forms
state: directory

3.5. Complete the Content added to forms folder task to create the F:\shares
\forms\leave_requests.txt file. This task uses the win_copy module.

- name: Content added to forms folder


win_copy:
content: 'All leave requests are now handled by our Intranet site:
https://intranet.example.com/forms'
dest: F:\shares\forms\leave_requests.txt

3.6. Complete the task named Forms folder is shared to share the F:\shares
\forms folder. Administrators require full access, Domain Users require read access,
and listing must be enabled. This task uses the win_copy module.

DO417-RHAE2.8-en-1-20200106 421
Chapter 9 | Automating Windows Administration Tasks

- name: Forms folder is shared


win_share:
name: forms
description: Company forms share
path: F:\shares\forms
list: yes
full: Administrators
read: Domain Users

3.7. The completed playbook should display as follows.

---
- name: Configure local storage
hosts: win1.example.com

tasks:
- name: Disk facts are populated
win_disk_facts:

- name: Second disk extracted as standalone fact


set_fact:
second_disk: "{{ ansible_facts['disks'] | json_query('[?number==`1`]') }}"

- name: Second disk size printed


debug:
var: second_disk[0]['size']

- name: Initialize second disk if required


win_shell: "Initialize-Disk -Number 1"
when: second_disk[0]['guid'] is none

- name: Partition is created on second disk


win_partition:
disk_number: 1
drive_letter: F
partition_size: 1 GiB
register: partition_task

- name: New partition is formatted


win_format:
drive_letter: F
file_system: NTFS
new_label: data
full: true
when: partition_task['changed']

- name: Share folder is created


win_file:
path: F:\shares\forms
state: directory

- name: Content added to forms folder


win_copy:

422 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

content: 'All leave requests are now handled by our Intranet site:
https://intranet.example.com/forms'
dest: F:\shares\forms\leave_requests.txt

- name: Forms folder is shared


win_share:
name: forms
description: Company forms share
path: F:\shares\forms
list: yes
full: Administrators
read: Domain Users

4. Save and commit the changes to your local Git repository, and then push them to the
remote repository.

4.1. To save the file, click File → Save or press Ctrl+S.

4.2. Navigate to the Source Control pane, and then click + for the storage.yml file to
stage the changes.

4.3. Enter a brief commit message, and then press Ctrl+Enter to commit the changes.

4.4. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to
push your local changes to the remote repository, and retrieve any new changes from
the repository.

5. From workstation, access your Ansible Tower instance available at http://


tower.example.com. Connect as the student user with the RedHat123@! password.

6. Test your playbook using the Run windows project job template.

6.1. In the navigation pane, click Templates.

6.2. Click the Run windows project job template.

6.3. Select the storage.yml playbook from the PLAYBOOK list.

6.4. Click SAVE to update the template, and then click LAUNCH to run the job.

7. After all tasks complete, verify that the status in the DETAILS pane shows Successful.
If the job is not successful, compare your playbook with the solutions/storage.sol
solution file in the windows Git repository.

8. Browse to the new share to verify that the playbook was successful.

8.1. Click Search Windows, search for run, and then open the Run window.

8.2. Type \\win1, and then press Enter.

8.3. The forms share is displayed. Open the share, and then open the
leave_requests.txt file to verify that the content matches the playbook.

8.4. Close the leave_requests.txt file and the forms share.

DO417-RHAE2.8-en-1-20200106 423
Chapter 9 | Automating Windows Administration Tasks

9. Switch back to the Ansible Tower web UI. Edit the Run windows project template to
revert your changes and use the revert_storage.yml playbook, and then launch a job.

9.1. In the navigation pane, click Templates.

9.2. Click the Run windows project job template.

9.3. Select the revert_storage.yml playbook from the PLAYBOOK list.

9.4. Click SAVE to update the template, and then click LAUNCH to run the job.

This concludes the guided exercise.

424 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

Lab

Automating Windows Administration


Tasks
In this exercise, you will create and format a partition, create a scheduled task, and install a
PowerShell module.

Outcomes
You should be able to create and format a disk partition and map it to a drive letter, schedule
a task to defragment the file system on that device, add a PowerShell Gallery repository, and
install a PowerShell module on managed hosts using Ansible.

Before You Begin


Confirm that the workstation and all infrastructure machines are running, and that you
can access Ansible Tower and GitLab in a browser.

Open your RDP client and connect to workstation using example.com as the domain,
student as the user name and RedHat123@! as the password.

Find the connection information to your systems in the email that you received.

1. Launch the Visual Studio Code editor. If you did not previously clone the windows repository,
clone it to your workstation instance.
2. Select File → Open Folder, and then select the C:\Users\student\Documents
\windows folder to display the contents.
3. Open the review.yml playbook, and then complete the tasks so that they result in the
following outcomes.

• Create and format a 2 GiB NTFS partition on the second disk as the S: drive.
• Schedule a task named DefragDBDrive to defragment the new drive every Sunday.
• Add the PowerShell Gallery repository.
• Install the SqlServer PowerShell module.
4. Save and commit the changes to your local Git repository, and then push them to the remote
repository.
5. From workstation, access your Ansible Tower instance available at http://
tower.example.com. Connect as the student user and RedHat123@! as the password.
6. To test your playbook, modify the Run windows project job template to use the
review.yml playbook, and then launch a job.
7. After all tasks complete, verify that the status in the DETAILS pane shows Successful. If
the job is not successful, compare your playbook with the solutions/review.sol solution
file in the windows Git repository.

DO417-RHAE2.8-en-1-20200106 425
Chapter 9 | Automating Windows Administration Tasks

8. Inspect win1 to verify the success of the playbook.

• Verify that the S: drive exists.


• Verify the DefragDBDrive task is scheduled.
• Verify that the SqlServer module can be imported.
9. Switch back to the Ansible Tower web UI. To revert your changes, edit the Run windows
project template to use the revert_review.yml playbook, and then launch a job.

Note
If you did not exit the PowerShell console in the previous step then running this
playbook will fail.

This concludes the lab.

426 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

Solution

Automating Windows Administration


Tasks
In this exercise, you will create and format a partition, create a scheduled task, and install a
PowerShell module.

Outcomes
You should be able to create and format a disk partition and map it to a drive letter, schedule
a task to defragment the file system on that device, add a PowerShell Gallery repository, and
install a PowerShell module on managed hosts using Ansible.

Before You Begin


Confirm that the workstation and all infrastructure machines are running, and that you
can access Ansible Tower and GitLab in a browser.

Open your RDP client and connect to workstation using example.com as the domain,
student as the user name and RedHat123@! as the password.

Find the connection information to your systems in the email that you received.

1. Launch the Visual Studio Code editor. If you did not previously clone the windows repository,
clone it to your workstation instance.

1.1. Click Search Windows, search for code, and then open Visual Studio Code.

1.2. Navigate to View → Command Palette or press Ctrl+Shift+P to open the


command palette.
Type clone, and then select Git: Clone to clone a repository.
Use a repository URL of https://gitlab.example.com/student/windows.git.
When prompted, select the Documents folder in the home directory of the training
user, and then click Select Repository Location. This clones the remote repository in
to the windows folder.
To view the files, select Open from the window that displays after cloning, and then skip
the next step.

2. Select File → Open Folder, and then select the C:\Users\student\Documents


\windows folder to display the contents.
3. Open the review.yml playbook, and then complete the tasks so that they result in the
following outcomes.

• Create and format a 2 GiB NTFS partition on the second disk as the S: drive.
• Schedule a task named DefragDBDrive to defragment the new drive every Sunday.
• Add the PowerShell Gallery repository.
• Install the SqlServer PowerShell module.

3.1. Modify the task named Partition is created on second disk to set the
following values.

DO417-RHAE2.8-en-1-20200106 427
Chapter 9 | Automating Windows Administration Tasks

• Disk number 1
• Drive letter S
• Sized at 2 GiB

- name: Partition is created on second disk


win_partition:
disk_number: 1
drive_letter: "{{ db_drive_letter }}"
partition_size: 2 GiB
register: partition_task

3.2. Complete the New partition is formatted task to create an NTFS volume named
db on the S: drive. This task will run conditionally depending on whether the previous
task resulted in changed resolving to true.

- name: New partition is formatted


win_format:
drive_letter: "{{ db_drive_letter }}"
file_system: NTFS
new_label: db
full: true
when: partition_task['changed']

3.3. Complete the task that creates the scheduled defragmentation task.

- name: Defrag scheduled task is created


win_scheduled_task:
name: DefragDBDrive
description: Degfragment the database drive
actions:
- path: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
arguments: >
-ExecutionPolicy Unrestricted
-NonInteractive
-Command {Optimize-Volume -DriveLetter {{ db_drive_letter }} -Defrag -
Verbose}
triggers:
- type: weekly
days_of_week: sunday
start_boundary: '2019-09-29T03:05:00'
username: SYSTEM
run_level: highest
state: present

3.4. Complete the task that registers a new PowerShell repository. Use the
powershell_gallery_endpoint variable as the module source parameter.

...output omitted...
- name: Current repositories are unregistered
win_shell: Unregister-PSRepository "{{ item }}"
ignore_errors: true
loop:

428 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

- PowerShell Gallery
- PSGallery

- name: PowerShell Gallery repository is added


win_psrepository:
source: "{{ powershell_gallery_endpoint }}"
name: "PowerShell Gallery"
state: present

3.5. Complete the task that queries the PowerShell Gallery repository. This task captures the
output in the repo_status variable, and then fails if the command does not return 0.
The changed_when: false statement indicates to Ansible to return a status of ok,
because the task does not make any changes to the system.

- name: PowerShell Gallery repository is queried


win_shell: Get-PSRepository "PowerShell Gallery"
register: repo_status
failed_when: repo_status.rc != 0
changed_when: false

3.6. Complete the task to install the PowerShell modules listed in the
powershell_modules list. To complete this task, use the win_psmodule module.

- name: PowerShell modules are installed


win_psmodule:
name: "{{ item }}"
state: present
loop: "{{ powershell_modules }}"

3.7. The completed playbook should display as follows:

---
- name: Configure database host
hosts: win1.example.com
vars:
db_drive_letter: S
powershell_gallery_endpoint: https://www.powershellgallery.com/api/v2/
powershell_modules:
- SqlServer

tasks:
- name: Disk facts are populated
win_disk_facts:

- name: Second disk extracted as standalone fact


set_fact:
second_disk: "{{ ansible_facts['disks'] | json_query('[?number==`1`]') }}"

- name: Initialize second disk if required


win_shell: "Initialize-Disk -Number 1"
when: second_disk[0]['guid'] is none

- name: Partition is created on second disk

DO417-RHAE2.8-en-1-20200106 429
Chapter 9 | Automating Windows Administration Tasks

win_partition:
disk_number: 1
drive_letter: "{{ db_drive_letter }}"
partition_size: 2 GiB
register: partition_task

- name: New partition is formatted


win_format:
drive_letter: "{{ db_drive_letter }}"
file_system: NTFS
new_label: db
full: true
when: partition_task['changed']

- name: Defrag scheduled task is created


win_scheduled_task:
name: DefragDBDrive
description: Degfragment the database drive
actions:
- path: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
arguments: >
-ExecutionPolicy Unrestricted
-NonInteractive
-Command {Optimize-Volume -DriveLetter {{ db_drive_letter }} -Defrag -
Verbose}
triggers:
- type: weekly
days_of_week: sunday
start_boundary: '2019-09-29T03:05:00'
username: SYSTEM
run_level: highest
state: present

- name: Current PowerShell repositories are unregistered


win_shell: Unregister-PSRepository "{{ item }}"
ignore_errors: true
loop:
- PowerShell Gallery
- PSGallery

- name: PowerShell Gallery repository is added


win_psrepository:
source: "{{ powershell_gallery_endpoint }}"
name: PowerShell Gallery
state: present

- name: PowerShell Gallery repository is queried


win_shell: Get-PSRepository "PowerShell Gallery"
register: repo_status
failed_when: repo_status.rc != 0
changed_when: false

- name: PowerShell modules for database support are installed

430 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

win_psmodule:
name: "{{ item }}"
state: present
loop: "{{ powershell_modules }}"

4. Save and commit the changes to your local Git repository, and then push them to the remote
repository.

4.1. Click File → Save or press Ctrl+S.

4.2. Navigate to the Source Control pane, and then click + to stage the changes to the
time.yml file.

4.3. Enter a brief commit message, and then press Ctrl+Enter to commit the changes.

4.4. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to push
your local changes to the remote repository, and retrieve any new changes from the
repository.

5. From workstation, access your Ansible Tower instance available at http://


tower.example.com. Connect as the student user and RedHat123@! as the password.
6. To test your playbook, modify the Run windows project job template to use the
review.yml playbook, and then launch a job.

6.1. In the navigation pane, click Templates.

6.2. Click the Run windows project job template.

6.3. Select the review.yml playbook from the PLAYBOOK list.

6.4. Click SAVE to update the template, and then click LAUNCH to run the job.

7. After all tasks complete, verify that the status in the DETAILS pane shows Successful. If
the job is not successful, compare your playbook with the solutions/review.sol solution
file in the windows Git repository.
8. Inspect win1 to verify the success of the playbook.

• Verify that the S: drive exists.


• Verify the DefragDBDrive task is scheduled.
• Verify that the SqlServer module can be imported.

8.1. Log on to win1 using Remote Desktop Connection.

8.2. Launch Explorer, and then verify that the S: drive exists.

8.3. Open the Task Scheduler, click Task Scheduler Library, and then verify that the
DefragDBDrive task is listed with the correct settings.

DO417-RHAE2.8-en-1-20200106 431
Chapter 9 | Automating Windows Administration Tasks

Figure Error.1: Task Scheduler task list

8.4. Launch a PowerShell console, import the SqlServer module, and then display its
commands. Exit the PowerShell console when finished.

PS C:\Users\devops> Import-Module -Name SqlServer


PS C:\Users\devops> Get-Command -Module SqlServer
...output omitted...
Cmdlet Set-SqlSmartAdmin 21.1.18179 SqlServer
Cmdlet Start-SqlInstance 21.1.18179 SqlServer
Cmdlet Stop-SqlInstance 21.1.18179 SqlServer
Cmdlet Suspend-SqlAvailabilityDatabase 21.1.18179 SqlServer
Cmdlet Switch-SqlAvailabilityGroup 21.1.18179 SqlServer
Cmdlet Test-SqlAvailabilityGroup 21.1.18179 SqlServer
Cmdlet Test-SqlAvailabilityReplica 21.1.18179 SqlServer
Cmdlet Test-SqlDatabaseReplicaState 21.1.18179 SqlServer
Cmdlet Test-SqlSmartAdmin 21.1.18179 SqlServer
Cmdlet Write-SqlTableData 21.1.18179 SqlServer

PS C:\Users\devops>

9. Switch back to the Ansible Tower web UI. To revert your changes, edit the Run windows
project template to use the revert_review.yml playbook, and then launch a job.

Note
If you did not exit the PowerShell console in the previous step then running this
playbook will fail.

9.1. In the navigation pane, click Templates.

9.2. Click the Run windows project job template.

9.3. Select the revert_review.yml playbook from the PLAYBOOK list.

9.4. Click SAVE to update the template, and then click LAUNCH to run the job.

This concludes the lab.

432 DO417-RHAE2.8-en-1-20200106
Chapter 9 | Automating Windows Administration Tasks

Summary
In this chapter, you learned:

• There are several modules for running commands on Windows, such as the win_command,
win_shell, and win_psexec modules.

• The win_psexec module is useful when Ansible does not have direct access to the target
hosts. To manage hosts on an isolated network, use the win_psexec module on a jump host.

• For more complex commands, the script module allows you to transfer and execute a script.

• Ansible provides the win_scheduled_task module to create and manage scheduled tasks on
managed nodes.

• A wide variety of Ansible modules are available that can be used to get information about
storage devices, to partition, format, and defragment disks, and to map devices to drive letters.

DO417-RHAE2.8-en-1-20200106 433
434 DO417-RHAE2.8-en-1-20200106
Chapter 10

Managing Large Projects


Goal Write playbooks that are optimized for larger and
more complex projects and that reuse existing
automation code.

Objectives • Manage large playbooks by importing or


including other playbooks or tasks from files,
unconditionally or based on a conditional test.
• Create a role to allow code reuse by different
Ansible projects, and run it as part of a play in a
playbook.
• Select and retrieve roles from Ansible Galaxy or
other sources such as a Git repository, and use
them in playbooks.
• Automate tasks by configuring and running
PowerShell Desired State Configuration (DSC)
resources from your Ansible Playbook.

Sections • Including and Importing Files (and Guided


Exercise)
• Creating Roles (and Guided Exercise)
• Deploying Roles with Ansible Galaxy (and
Guided Exercise)
• Integrating Ansible with Desired State
Configuration Resources (and Guided Exercise)

Lab Managing Large Projects

DO417-RHAE2.8-en-1-20200106 435
Chapter 10 | Managing Large Projects

Including and Importing Files

Objectives
After completing this section you should be able to manage large playbooks by importing or
including other playbooks or tasks from external files, either unconditionally or based on a
conditional test.

Managing Large Projects


When a playbook is long or complex, you can divide it up into smaller files to make it easier to
manage. You can combine multiple playbooks into the main playbook modularly, or insert lists of
tasks from a file into a play. This can make it easier to reuse plays or sequences of tasks in different
projects.

Including Or Importing Files


There are two operations that Ansible can use to bring content into a playbook. You can include
content, or you can import content.

When you include content, it is a dynamic operation. Ansible processes included content during the
run of the playbook.

When you import content, it is a static operation. Ansible preprocesses imported content when the
playbook is initially parsed before the run starts.

Importing Playbooks
The import_playbook directive allows you to import external files containing lists of plays into
a playbook. In other words, you can have a master playbook that imports one or more additional
playbooks.

Because the content being imported is a complete playbook, you can only use the
import_playbook feature at the top-level of a playbook, but not inside a play. If you import
multiple playbooks, then they are imported and run in order.

The following example shows shows how a master playbook imports two additional playbooks:

- name: Create users in windows server


import_playbook: win-create-users.yml

- name: Install msi packages


import_playbook: install-msi-packages.yml

You can also interleave plays in your master playbook with imported playbooks. In the following
example, the Play to install IIS Web Server play runs first, followed by the plays of the
imported deploy-site.yml Ansible Playbook.

436 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

- name: Play to install IIS Web Server


hosts: winhost1
tasks:
- name: Ensure IIS is installed
win_feature:
name: "Web-Server"
state: present
restart: yes
include_sub_features: yes
include_management_tools: yes

- name: Import playbook plays to deploy website


import_playbook: deploy-site.yml

Importing and Including Tasks


You can import or include tasks from a task file into a play. A task file is a file that contains a flat list
of tasks.

The following excerpt shows the content of a windows_tasks.yml task file:

- name: Add User


win_user:
name: Demo
password: "S3cr3tP@ssw0rd"
state: present

- name: Run PowerShell script


script: files/helloworld.ps1

Importing Task Files


You can statically import a task file into a play inside a playbook by using the import_tasks
feature. The location of import_tasks in the playbook controls where the tasks are inserted and
the order in which multiple imports are run.

The following is an example of importing tasks from the windows_tasks.yml task file into a play:

- name: Running tasks from imported files


hosts: winhost1

tasks:
- name: Importing external task file
import_tasks: windows_tasks.yml

When you import a task file, the tasks in that file are directly inserted when the playbook is parsed.
Because import_tasks statically imports the tasks when the playbook is parsed, there are some
constraints:

• When using the import_tasks feature, conditional statements set on the import, such as
when, are applied to each of the tasks that are imported.

• You cannot use loops with the import_tasks feature.

DO417-RHAE2.8-en-1-20200106 437
Chapter 10 | Managing Large Projects

• If you use a variable to specify the name of the file to import, then you cannot use a host or
group inventory variable.

Including Task Files


You can also dynamically include a task file into a play inside a playbook by using the
include_tasks feature.

The following is an example of including tasks from the windows_tasks.yml task file into a play:

- name: Running tasks from included files


hosts: winhost1
tasks:
- name: Importing external task file
include_tasks: windows_tasks.yml

The include_tasks feature does not process content in the playbook until the play is running
and that part of the play is reached. The order in which playbook content is processed impacts how
the include tasks feature works:

• You can use loops with the include_tasks statement. The included tasks or role are executed
once for each item in the loop.

• When using the include_tasks feature, conditional statements set on the include, such as
when, determine whether the tasks are included in the play.

• You cannot use a notify statement to trigger a handler name that is in an included task file.
You can trigger a handler in the main playbook that includes an entire task file, in which case all
tasks in the included file run.

Note
You can find a more detailed discussion of the differences in behavior between
import_tasks and include_tasks when conditionals are used in the
Conditionals chapter in the Ansible User Guide at https://docs.ansible.com/ansible/
latest/user_guide/playbooks_conditionals.html#applying-when-to-roles-imports-
and-includes.

Use Cases for Task Files


Consider the following examples where it might be useful to manage sets of tasks as external files
separate from the playbook:

• If new servers require complete configuration, then administrators could create various sets
of tasks for creating users, installing features, configuring services, configuring privileges,
setting up access to a shared file system, hardening the servers, installing security updates, and
installing a monitoring agent. Each of these sets of tasks could be managed through a separate,
self-contained task file.

• If developers collectively manage servers, the system administrators, and the database
administrators, then every organization can write their own task file, which can then be reviewed
and integrated by the system manager.

• If a server requires a particular configuration, then it can be integrated as a set of tasks that
execute based on a conditional. In other words, tasks are included and executed only if specific
criteria are met.

438 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

• If a group of servers must run a particular task or set of tasks, then the tasks might only run on a
server if it is part of a specific host group.

Managing Task Files


You can create a dedicated directory for task files, and save all task files in that directory. Then,
your playbook can simply include or import task files from that directory. This allows construction
of a complex playbook, while making it easy to manage its structure and components.

Defining Variables for External Plays and Tasks


Incorporating plays or tasks from external files into playbooks, using Ansible import and include
features, greatly enhances the reuse of tasks and playbooks across an Ansible environment. To
maximize the possibility of reuse, these tasks and play files should be as generic as possible.
Variables can be used to parameterize play and task elements to expand the application of tasks
and plays.

For example, the following task installs the feature needed for a web service, and then starts the
necessary service.

- name: IIS service installed


win_feature:
name: Web-Server
state: present

- name: IIS service started


win_service:
name: W3Svc
state: started

If you parameterize the feature and service elements as shown in the following example, then you
can also use the task file for the installation and administration of other features and their services,
rather than exclusively for a web service.

- name: "{{ package }}" service installed


win_feature:
name: "{{ package }}"
state: present

- name: "{{ svc }}" service started


win_service:
name: "{{ svc }}"
state: started

Subsequently, when incorporating the task file into a playbook, define the variables to use for the
task execution as follows:

DO417-RHAE2.8-en-1-20200106 439
Chapter 10 | Managing Large Projects

...output omitted...
tasks:
- name: Import task file and set variables
import_tasks: task.yml
vars:
package: Web-Server
svc: W3Svc

Ansible makes the passed variables available to the tasks imported from the external file.

You can use the same technique to make play files more reusable. When incorporating a play file
into a playbook, pass the variables to use for the play execution as follows:

...output omitted...
- name: Import play file and set the variable
import_playbook: play.yml
vars:
package: Web-Server

Important
Earlier versions of Ansible used an include feature to include both playbooks
and task files, depending on the context. This functionality is still available, but
considered deprecated for a number of reasons.

Prior to Ansible 2.0, include operated like a static import. In Ansible 2.0 it was
changed to operate dynamically, but this created some limitations. In Ansible 2.1 it
became possible for include to be dynamic or static depending on task settings,
which was confusing and error-prone. There were also issues with ensuring that
include worked correctly in all contexts.

Thus, include was replaced in Ansible 2.4 with new directives such as
include_tasks, import_tasks, and import_playbook. You might find
examples of include in older playbooks, but you should avoid using it in new ones.

References
— Ansible Documentation
https://docs.ansible.com/ansible/latest/user_guide/index.html

440 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

Guided Exercise

Including and Importing Files


In this exercise, you will include and import playbooks and tasks in a top-level Ansible
Playbook.

Outcomes
You should be able to include and import playbooks and tasks.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

Important
This exercise uses resources created in the Interacting with Users and
Domains chapter. You must complete the exercises in this chapter before
starting this exercise.

1. Launch the Visual Studio Code editor, and then clone the projects repository to your
workstation instance.

1.1. Click Search Windows, search for code, and then open Visual Studio Code.

1.2. Navigate to View → Command Palette or press Ctrl+Shift+P to open the


command palette.
Type clone, and then select Git: Clone to clone a repository.
Use a repository URL of https://gitlab.example.com/student/
projects.git. When prompted, select the Documents folder in the home directory
of the training user, and then click Select Repository Location. This clones the
remote repository in to the tower folder.
Click Open from the window that displays after cloning to view the files.

2. Review and fix the the contents of the three files in the tasks subdirectory. After making
the changes, commit and push the changes to the master branch.

2.1. Go to the tasks directory, located at the top-level. Select the environment.yml
file, this file contains a task for package installation. Change the file as follows:

DO417-RHAE2.8-en-1-20200106 441
Chapter 10 | Managing Large Projects

---
- name: IIS and .Net 4.5 are installed
win_feature:
name: "{{ iis_package_names }}"
include_management_tools: True
state: present

2.2. Click Save. Note the status icons in the lower left corner of the editor. There is now an
asterisk next to Master, indicating that changes have been made.

2.3. In the same subdirectory, select the firewall.yml file, which contains a task for
adding a new rule to the firewall. Change the content of the file as follows:

---
- name: Firewall rule is enabled
win_firewall_rule:
name: HTTP
localport: "{{ iis_site_port }}"
action: allow
direction: in
protocol: tcp
state: present
enabled: yes

2.4. In the same subdirectory, select the site.yml file. This file contains tasks for creating
the IIS site and directories, and to copy the index.html file into the proper directory.
Review the contents of the file:

---
- name: Logs directory is created
win_file:
path: C:\sites\logs
state: directory

- name: Site directory is created


win_file:
path: "{{ iis_site_path }}"
state: directory

- name: Index page for site is installed


win_copy:
src: files/index.html
dest: '{{ iis_site_path }}\index.html'

- name: IIS site is created


win_iis_website:
name: "{{ iis_site_name }}"
state: started
port: "{{ iis_site_port }}"
ip: "*"
hostname: "{{ inventory_hostname }}"

442 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

application_pool: DefaultAppPool
physical_path: "{{ iis_site_path }}"
parameters: logfile.directory:C:\sites\logs

2.5. Change to the Source Control view, and then click + next to all the files that you have
modified to stage the changes.

2.6. Enter a commit message, and then press Ctrl+Enter to commit the changes.

2.7. The status icon in the lower left corner of the window indicates that there are changes
to push to the remote repository. Click Synchronize Changes to send your changes to
the remote repository, and to receive any new changes from the remote repository.

3. Review and fix the the content of the test.yml file in the plays subdirectory. After
making the changes, commit and push the changes to the master branch.

3.1. Go to the plays directory, located at the top-level. Select the test.yml file, which
contains a play that tests connections to a web service. Change the file as follows:

---
- name: Test web service
hosts: win1.example.com
gather_facts: false

tasks:

- name: Connect to internet web server


win_uri:
url: "{{ url }}"
status_code: 200

3.2. Click Save. Note the status icons in the lower left corner. There is an asterisk next to
Master to indicate that changes were made.

3.3. Switch to the Source Control view, and then click + for the test.yml file to stage
the changes.

3.4. Enter a commit message, and then press Ctrl+Enter to commit the changes.

3.5. The status icon in the lower left indicates that there is a change to the remote
repository. Click Synchronize Changes to send the change to the remote repository,
and to receive any new changes from the remote repository.

4. Review and fix the the content of the deploy.yml file in the top-level directory. After
making the changes, commit and push the changes to the master branch.

4.1. Navigate to the top-level directory. Select the deploy.yml file, which contains a
set of tasks that include and import tasks and plays from different files located in this
project directory. Change the file as follows:

---
- name: Configure web server
hosts: all
gather_facts: false

DO417-RHAE2.8-en-1-20200106 443
Chapter 10 | Managing Large Projects

tasks:
- name: Include the environment task file and set the variables
include_tasks: tasks/environment.yml
vars:
iis_package_names:
- Web-Server
- NET-Framework-Core
- Web-Asp-Net45

- name: Import the site task file and set the variables
import_tasks: tasks/site.yml
vars:
iis_site_path: C:\sites\projects
iis_site_name: "DO417-projects"
iis_site_port: 8080

- name: Import the firewall task file and set the variable
import_tasks: tasks/firewall.yml
vars:
iis_site_port: 8080

- name: Import test play file and set the variable


import_playbook: plays/test.yml
vars:
url: 'http://win1.example.com:8080'

4.2. Click Save. Note the status icons in the lower left. There is an asterisk next to Master,
which indicates that changes have been made.

4.3. Change to the Source Control view, and then click + for the deploy.yml file to
stage the changes.

4.4. Enter a commit message, and then press Ctrl+Enter to commit the changes.

4.5. The status icon in the lower left corner indicates that there is a change to push to
the remote repository. Click Synchronize Changes to send the change to the remote
repository, and to receive any new changes from the remote repository.

5. In previous activities, you created IIS websites and HTTP firewall rules. Run the Run
projects project job remove-iis.yml playbook to remove the websites and firewall
rules.

5.1. In the navigation pane, click Templates.

5.2. From the list of templates, select the Run projects project template.

5.3. Select the remove-iis.yml playbook from the PLAYBOOK list.

5.4. If cleared, select the PROMPT ON LAUNCH check box for the LIMIT option.

5.5. If selected, clear the PROMPT ON LAUNCH check box for the CREDENTIAL and
INVENTORY options.

5.6. In the INVENTORY option choose Dynamic inventory.

5.7. In the CREDENTIAL option, choose AD Administrator.

444 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

5.8. Click SAVE to update the template, and then click LAUNCH to run the job.

5.9. In the RUN PROJECTS PROJECT window, type in the


win1.example.com,win2.example.com hostname. Click NEXT, and then click
LAUNCH.

5.10. Observe the live output of the running job.

5.11. Verify that the status of the job in the DETAILS pane displays Successful.

6. Run the Run projects project job to test your playbook with the import and include
tasks.

6.1. In the navigation pane, click Templates.

6.2. From the list of templates, select the Run projects project template.

6.3. Select the deploy.yml playbook from the PLAYBOOK list.

6.4. Click SAVE to update the template, and then click LAUNCH to run the job.

6.5. In the RUN PROJECTS PROJECT window, type in the win1.example.com


hostname. Click NEXT, and then click LAUNCH.

6.6. Observe the live output of the running job.

6.7. Verify that the status of the job in the DETAILS pane displays Successful.

7. The last play executes a test using the managed host. If the job status is successful, then
the web page is accessible. Optionally, you can open Chrome from workstation and
access http://win1.example.com:8080. The new web page will be available.

8. Click Log Out to log out of Ansible Tower

This concludes the guided exercise.

DO417-RHAE2.8-en-1-20200106 445
Chapter 10 | Managing Large Projects

Creating Roles

Objectives
After completing this section, you should be able to create a role to allow code reuse by different
Ansible projects, and run it as part of a play in a playbook.

Structuring Ansible Playbooks with Roles


As you develop more playbooks, you will discover that you have many opportunities to reuse code
from playbooks that you have already written. For example, a play to configure a Microsoft SQL
database for one application could be repurposed, with different host names, passwords, and
users, to configure a Microsoft SQL database for another application.

However, that play might be long and complex, with many included or imported files, and with
tasks and handlers to manage various situations. Copying all that code into another playbook
might not be trivial work.

Ansible roles make it easier to reuse Ansible code generically. You can package, in a standardized
directory structure, all the tasks, variables, files, templates, and other resources needed to
provision infrastructure or deploy applications. Copy that role from project to project by copying
the directory. Then, call that role from a play to execute it.

A well-written role allows you to pass variables to the role from the playbook that adjust its
behavior, setting all the site-specific hostnames, IP addresses, user names, secrets, and other
specific details. For example, a role to deploy a database server might support variables that
set the host name, database admin user and password, and other parameters that require
customization for your installation. The author of the role can also ensure that reasonable default
values are set for those variables if you choose not to set them in the play.

Ansible roles have the following benefits:

• Roles group content, allowing easy sharing of code with others.

• You can write roles in a way that they define the essential elements of a system type: web server,
database server, Git repository, and more.

• Roles make larger projects more manageable.

• Different administrators and develop roles in parallel.

In addition to writing, using, reusing, and sharing your own roles, you can get numerous community
supported roles from the Ansible Galaxy website. Later in this chapter, you will learn more about
these roles.

Discussing the Role Creation Process


Creating roles in Ansible requires no special development tools. Creating and using a role is a three
step process:

1. Create the role directory structure.

2. Define the role content.

446 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

3. Use the role in a playbook.

Creating the Role Directory Structure


By default, Ansible looks for roles in the directory containing your Ansible Playbooks, in the
subdirectory roles. This allows you to store roles with the playbook and other supporting files.

Each role has its own directory with a standardized directory structure. The top-level directory
defines the name of the role itself. Files are organized into subdirectories that are named
according to the purpose of each file in the role, such as tasks and handlers. The files and
templates subdirectories contain files referenced by tasks in other YAML files.

Creating a Role Skeleton


You must create all the subdirectories and files manually. However, if you are not using a particular
subdirectory in your role, you do not need to create it.

Figure 10.1: Role Directory Structure

Examining the Role Directory Structure


As noted previously, an Ansible role is defined by a standardized structure of subdirectories and
files. The following displays a role's typical directory structure:

The following displays the typical directory structure of a role:

win_package.example
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml

DO417-RHAE2.8-en-1-20200106 447
Chapter 10 | Managing Large Projects

├── README.md
├── tasks
│ └── main.yml
├── templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml

The following table explains the Ansible role subdirectories:

Directory Function

defaults The main.yml file in this directory contains the default values of
role variables that can be overwritten when the role is used. These
variables have low precedence and are intended to be changed and
customized in plays.

files This directory contains static files that are referenced by role tasks.

handlers The main.yml file in this directory contains the handler definitions for
the role.

meta The main.yml file in this directory contains information about


the role, including author, license, platforms, and optional role
dependencies.

tasks The main.yml file in this directory contains task definitions for the
role.

templates This directory contains Jinja2 templates that are referenced by role
tasks.

tests This directory can contain an inventory and test.yml playbook that
can be used to test the role.

vars The main.yml file in this directory defines the variable values for the
role. Often these variables are used for internal purposes within the
role. These variables have high precedence, and are not intended to be
changed when used in a playbook.

Not every role will have all of these directories. If a subdirectory exists but is empty, it is ignored. If
a role does not use a feature, the subdirectory can be omitted altogether.

Typically, a README.md file in the root of the role directory provides a basic human-readable
description of the role, documentation, and examples of how to use it, and any non-Ansible
requirements that must be met.

Defining the Role Content


Once you have created the directory structure, you must write the content of the role. A good
place to start is the role-name\tasks\main.yml task file, which is the main list of tasks run by
the role.

448 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

For example, if you are converting a play into a role, copy all of the tasks from the play into the
tasks\main.yml file.

The following tasks\main.yml file makes sure the Web-Server feature is installed, that
the W3Svc service is running, and that the index.html file is templated into place using the
win_template module.

Because the win_template module is called by a task in a role, the index.j2 template is
retrieved from the templates subdirectory:

---
# tasks file for win_package.example role

- name: IIS service installed


win_feature:
name: Web-Server
state: present

- name: IIS service started


win_service:
name: W3Svc
state: started

- name: Website index.html created


win_template:
src: index.j2
dest: C:\Inetpub\wwwroot\index.html

The following displays the contents of the index.j2 template of the role, located in the
templates directory. It references Ansible facts and a system_owner variable.

Hello World!
Welcome to {{ ansible_facts['hostname'] }}.

You can contact {{ system_owner }} for more details.

The role defines a default value for the system_owner variable. Set this value in the defaults
\main.yml file in the directory structure for the role. The following defaults\main.yml file
sets the system_owner variable to user@host.example.com . This is the email address that is
written in the index.html file of managed hosts to which this role is applied.

---
system_owner: user@host.example.com

Recommended Practices for Role Content Development


Roles allow playbooks to be written modularly. To maximize the effectiveness of newly developed
roles, consider implementing the following recommended practices:

• Maintain each role in its own version control repository. Ansible works well with Git-based
repositories.

• Do not store in the role repository sensitive information, such as passwords or SSH keys.
Parameterize sensitive values as variables with default values that are not sensitive. Playbooks

DO417-RHAE2.8-en-1-20200106 449
Chapter 10 | Managing Large Projects

that use the role are responsible for defining sensitive variables through Ansible Vault variable
files, Ansible Tower surveys, the "prompt on launch" feature when started with an Ansible Tower
job template, or other appropriate means.

• Create only the directories and files that you need.

• Create and maintain README.md and meta\main.yml files to document what your role is for,
who wrote it, and how to use it.

• Keep your role focused on a specific purpose or function. Instead of making one role do many
things, write more than one role.

• Reuse and refactor roles often. Resist creating new roles for edge configurations. If an existing
role accomplishes a majority of the required configuration, refactor the existing role to integrate
the new configuration scenario. Use integration and regression testing techniques to ensure that
the role provides the required new functionality, and also does not cause problems for existing
playbooks.

Defining Role Variables and Defaults


To define role variables, create a vars\main.yml file with key: value pairs in the role directory
hierarchy. These value pairs are referenced in the role YAML file, just like any other variable:
{{ VAR_NAME }}. These variables have high precedence and can not be overridden by inventory
variables. The intent of these variables is supporting the internal functioning of the role.

Default variables allow setting default values for variables that can be used in a play to configure
the role or customize its behavior. To define these variables, create a defaults\main.yml file
with key: value pairs in the role directory hierarchy. Default variables have the lowest precedence
of any variables available. They can be easily overridden by any other variable, including inventory
variables. These variables provide the person writing a play that uses the role with a way to
customize or control exactly how that role will function. They also provide information to the role
that it needs to configure or deploy something properly.

Define a specific variable in either vars\main.yml or defaults\main.yml, but not in both


places. Default variables should be used when it is expected that the values will be overridden.

Important
Roles should not have site-specific data in them. They should never contain any
secrets, like passwords or private keys.

Roles are supposed to be generic, reusable, and freely shareable. Site-specific


details should not be hard coded into them.

Secrets should be provided to the role through other means. This is one reason you
might want to set role variables when calling a role. Role variables set in the play
could provide the secret, or point to an Ansible Vault-encrypted file containing the
secret.

Using a Role in a Playbook


To call a role in a play, reference it in the roles: section. The following playbook refers to the
win_package.example role. Because no variables are specified, the role is applied with its
default variable values.

450 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

---
- name: use win_package.example role in play
hosts: winhost1
roles:
- win_package.example

When the playbook runs, you can identify the tasks resulting from a role by the role name
preceding the task name.

For example, the output of the play above might look like this:

PLAY [use win_package.example role in play] ************************************

TASK [setup] *******************************************************************


ok: [winhost1]

TASK [win_package.example: IIS service installed] ******************************


changed: [winhost1]

TASK [win_package.example: IIS service started] ********************************


changed: [winhost1]

TASK [win_package.example: Website index.html created] *************************


changed: [winhost1]

PLAY RECAP *********************************************************************


winhost1 : ok=4 changed=3 unreachable=0 failed=0

Changing Role Behavior with Variables


A well-written role uses default variables to alter the behavior of a role to match a related
configuration scenario. This helps make the role more generic and reusable in a variety of contexts.

The value of any variable defined in the defaults directory for a role will be overwritten if that same
variable is defined:

• In an inventory file, either as a host variable or a group variable.

• In a YAML file, under the group_vars or host_vars directories of a playbook project.

• As a variable, nested in the vars keyword of a play.

• As a variable, when including the role in roles keyword of a play.

The following example demonstrates using the win_package.example role with a different
value for the system_owner role variable. The value specified, someone@host.example.com,
replaces the variable reference when the role is applied to a managed host.

DO417-RHAE2.8-en-1-20200106 451
Chapter 10 | Managing Large Projects

---
- name: use win_package.example role in play with a variable setting
hosts: winhost1
vars:
system_owner: someone@host.example.com
roles:
- win_package.example

When defined in this way, the value of system_owner declared in vars overrides the value
of the variable of the same name defined in the defaults directory. However, the value of
system_owner does not override any declaration in the vars directory.

The following example shows how to use the win_package.example role with a different value
for the system_owner role variable. The value specified, someone@host.example.com,
replaces the variable reference even though it is defined in the vars or defaults directory for
the role.

---
- name: use windows role in playbook
hosts: winhost1
roles:
- win_package.example
system_owner: someone@host.example.com

Important
Variable precedence can be confusing when working with role variables in a play.

• Almost any other variable will override default variables for a role, including
inventory variables, play vars, inline role parameters, and more.

• Fewer variables can override role variables defined in a the vars directory. Facts,
variables loaded with include_vars, registered variables, and role parameters
are some variables that can take precedence. Inventory variables and play vars
cannot. This is important because it helps keep your play from accidentally
changing the internal functioning of the role.

• However, variables declared inline as role parameters, like the last of the
preceding examples, have very high precedence. They can override role variables
defined in the vars directory. If a role parameter has the same name as a variable
set in vars for a play, in vars for a role, or in an inventory or playbook variable,
the role parameter overrides the other variables.

Calling Multiple Roles


Using multiple roles in a play is straightforward:

---
- hosts: remote.example.com
roles:
- role1
- role2

452 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

The following example sets values for two role variables of role2, var1, and var2. Any
defaults and vars variables are overridden when role2 is used.

---
- hosts: remote.example.com
roles:
- role1
- role: role2
vars:
var1: val1
var2: val2

Equivalent YAML syntax that you might see used follows:

---
- hosts: remote.example.com
roles:
- role1
- { role: role2, vars: { var1: val1, var2: val2 } }

There are situations where this can be harder to read, even though it is more compact.

Important
Role variables set inline (role parameters), as in the preceding examples, have very
high precedence. They override most other variables.

Be very careful not to reuse the names of any role variables that you set inline
anywhere else in your play, since the values of the role variables override inventory
variables and any play vars.

Controlling Order of Task Execution


For each play in a playbook, tasks execute as ordered in the tasks list. After all tasks execute, any
notified handlers are executed.

But, when a role is added to a play using the roles directive, the tasks from that role are added to
the beginning of the tasks list. If a second role is included in a play, the tasks list is added after the
tasks list from the first role. The order of the tasks and roles directives do not matter. However,
for clarity it helps if you put the roles section first in the play.

---
- hosts: remote.example.com
roles:
- role: role1
- role: role2
tasks:
- task1

Role handlers are added to plays in the same manner that role tasks are added to plays. Each play
defines a handlers list. Role handlers are added to the handlers list first, followed by any handlers
defined in the handlers section of the play.

DO417-RHAE2.8-en-1-20200106 453
Chapter 10 | Managing Large Projects

In certain scenarios, it may be necessary to execute some play tasks before the roles. To support
such scenarios, plays can be configured with a pre_tasks section. Any task listed in this section
executes before any roles are executed. If any of these tasks notify a handler, then those handler
tasks execute before the roles or normal tasks.

Plays also support a post_tasks keyword. These tasks execute after the normal tasks in the play,
and any handlers they notify run.

The following play demonstrates pre_tasks, roles, tasks, post_tasks and handlers. In a
production scenario, it is unusual for a play to contain all of these sections. Although most tasks in
this example are unnamed to save space, omitting task names is not recommended when working
outside of this test environment.

- name: Play to illustrate order of execution


hosts: remote.example.com
pre_tasks:
- debug:
msg: 'pre-task'
notify: my handler
roles:
- role1
tasks:
- debug:
msg: 'first task'
notify: my handler
post_tasks:
- debug:
msg: 'post-task'
notify: my handler
handlers:
- name: my handler
debug:
msg: Running my handler

In the above example, a debug task executes in each section to notify the my handler handler.
The my handler task is executed three times:

• After all the pre_tasks tasks execute.

• After all role tasks and tasks from the tasks section execute.

• After all the post_tasks execute.

Including and Importing Roles


In addition to including roles in a play using the roles section, roles can be added to a play using
an ordinary task. Use the include_role module to dynamically include a role, and use the
import_role module to statically import a role.

The following playbook demonstrates how a role can be included using a task with the
include_role module.

454 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

- name: Execute a role as a task


hosts: remote.example.com
tasks:
- name: A normal task
debug:
msg: 'first task'
- name: A task to include role2 here
include_role: role2

Note
The include_role module was added in Ansible 2.3, and the import_role
module in Ansible 2.4.

References
Ansible User Guide — Ansible Documentation
https://docs.ansible.com/ansible/latest/user_guide/index.html

DO417-RHAE2.8-en-1-20200106 455
Chapter 10 | Managing Large Projects

Guided Exercise

Creating Roles
In this exercise, you will create an Ansible role, add it to a playbook, and run the playbook to
test the new role.

Outcomes
You should be able to:

• Create an Ansible role.

• Use the role in a playbook.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

All Chapter 8, Interacting with Users and Domains guided exercises must be completed prior
to starting this exercise, due to changes in inventory and authentication.

1. Open the Visual Studio Code editor and clone the projects repository to your
workstation.

1.1. From workstation, double-click the desktop icon to open the Visual Studio Code
editor. Alternatively, click Search Windows, search for code, and then open Visual
Studio Code.

1.2. Navigate to View → Command Palette or press Ctrl+Shift+P to open the


command palette.
Type clone, and then select Git: Clone to clone a repository.

1.3. When prompted, provide a repository URL of https://gitlab.example.com/


student/projects.git, and select the Documents folder in the home directory of
the training user as the repository location. This clones the remote repository into
the projects folder on the workstation instance.

1.4. When a prompt to open the project displays in the lower right corner of the editor, click
Open.

2. Open the roles-example.yml playbook file and review its contents. The playbook
declares a few variables to insert strings into a template and a Boolean debug_tools:
True declaration. The tasks ensure that the IIS web server is started, and then deploy static
files and a Jinja2 template. The debug_tools variable is used as a condition for installing
the HTTP Tracing IIS feature.

456 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

3. Move all but the first and last tasks in the roles-example.yml file to the roles\web
\tasks\main.yml web role playbook file.

3.1. In the roles-example.yml file, select the four tasks starting with the task named
IIS Web Server started.

3.2. Select Edit → Cut or press Ctrl+X to paste the text into the empty roles\web
\tasks\main.yml playbook.

3.3. Navigate to Edit → Paste or press Ctrl+V to paste the text into the empty roles
\web\tasks\main.yml playbook.

3.4. Select all of the text and press Shift+Tab twice to remove the task indentation.

3.5. Because roles follow a predetermined directory structure, Ansible finds templates
and files in their respective directories. Remove the templates/ and files/
subdirectories from the win_template and win_copy src parameters.

3.6. Verify that your roles\web\tasks\main.yml matches the following:

---
- name: IIS Web Server started
win_feature:
name: Web-Server
state: present

- name: HTTP Tracing is installed


win_feature:
name: Web-Http-Tracing
state: present
when: debug_tools

- name: Index page is deployed


win_template:
src: index.html.j2
dest: C:\Inetpub\wwwroot\index.html

- name: Info page is deployed


win_copy:
src: info.html
dest: C:\Inetpub\wwwroot\info.html

3.7. Save the changes in both the roles\web\tasks\main.yml and roles-


example.yml files.

4. Move the deployed_by: Ansible variable from the roles-example.yml playbook to


roles\web\vars\main.yml. Ansible role vars are used for variables that are internal to
the role.

4.1. Remove the deployed_by: Ansible line from the roles-example.yml playbook.

4.2. Add the variable declaration to the roles\web\vars\main.yml file, so that it


matches the following:

DO417-RHAE2.8-en-1-20200106 457
Chapter 10 | Managing Large Projects

---
deployed_by: Ansible

4.3. Save both the updated roles\web\vars\main.yml and roles-example.yml


files.

5. Use Ansible role defaults to override variables in the invoking playbook.

5.1. Remove the site_title: Default Site and site_subtitle: Example Web
Site lines from the roles-example.yml playbook.

5.2. Add the variable declaration to the roles\web\defaults\main.yml file, so that it


displays as follows:

---
site_title: Default Site
site_subtitle: Welcome!
debug_tools: False

Notice the specification of a default subtitle of Welcome!, and the disabling of


debug_tools.

5.3. Save both the roles\web\defaults\main.yml and roles-example.yml files.

6. Click the templates\index.html.j2 file in the PROJECTS pane, and then drag it into
the roles\web\templates directory.

7. Click the files\info.html file in the PROJECTS pane, and then drag it into the roles
\web\files directory.

8. Update roles-example.yml to use roles, pre_tasks, and post_tasks as follows:

---
- name: Deploy website
hosts: all
vars:
debug_tools: True

pre_tasks:
- debug:
msg: Installing with debug tools enabled.
when: debug_tools

roles:
- role: web
site_title: Example Web Site

post_tasks:
- name: Custom page is added
win_copy:
content: "Hello!"
dest: C:\Inetpub\wwwroot\example.html

458 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

Move the debug message task to a pre_task, so that it will run before the role tasks.
Add a list of roles with a single item role: web invoking the web role.
Override the default site_title to insert a custom heading on the web site.
Move the final Custom page is added task to a post_task that Ansible invokes
after the role tasks have completed.

9. Commit the changes to your local Git repository, and then push them to the remote
repository.

9.1. Navigate to the Source Control pane, and then stage the changes.

9.2. Enter a brief commit message, and then press Ctrl+Enter to commit the changes.

9.3. Locate the status icons in the lower left corner of the editor, and notice that there is a
change to be pushed to the remote Git repository. Click the Synchronize Changes to
push your changes.

10. From workstation, access your Red Hat Ansible Tower instance available at http://
tower.example.com. Connect as the student user with the RedHat123@! password.

11. Run your playbook using the Run projects project job template.

11.1. In the navigation pane, click Templates.

11.2. Click the Run projects project job template.

11.3. Click the magnifying glass icon in the INVENTORY input field. Click Dynamic
inventory, and then click SELECT.

11.4. Click the magnifying glass icon in the CREDENTIAL input field. Click AD
Administrator, and then click SELECT.

11.5. Select the PROMPT ON LAUNCH option of the LIMIT feature.

11.6. Select the roles-example.yml playbook from the PLAYBOOK list.

11.7. Click SAVE to update the template, and then click LAUNCH to run the job.

DO417-RHAE2.8-en-1-20200106 459
Chapter 10 | Managing Large Projects

11.8. Type win1.example.com,win2.example.com in the LIMIT field. Click NEXT, and


then click LAUNCH.

11.9. After all tasks have completed, verify that the status in the DETAILS pane displays
Successful.

12. In Chrome, open a new tab and navigate to http://win1.example.com/. Click the "info
page" link to verify the deployment of the static info.html.

460 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

13. In Chrome, navigate to http://win2.example.com/ to verify that Ansible deployed the


web site to both win1 and win2 managed hosts.

14. Run the cleanup-roles.yml playbook from the Run projects project job template
to clean up your work.

14.1. In the navigation pane, click Templates.

14.2.Click the Run projects project job template.

14.3.Make sure that the INVENTORY field is set to Dynamic inventory.

14.4.Make sure that the CREDENTIAL field is set to AD Administrator.

14.5. Make sure that the PROMPT ON LAUNCH check box for the LIMIT option is
selected.

14.6.Select the cleanup-roles.yml playbook from the PLAYBOOK list.

14.7. Click SAVE to update the template, and then click LAUNCH to run the job.

This concludes the guided exercise.

DO417-RHAE2.8-en-1-20200106 461
Chapter 10 | Managing Large Projects

Deploying Roles with Ansible Galaxy

Objectives
After completing this section, you should be able to select and retrieve roles from Ansible Galaxy
or other sources, such as a Git repository, and use them in playbooks.

Introducing Ansible Galaxy


Ansible Galaxy [https://galaxy.ansible.com] is a public library of Ansible content written by a
variety of Ansible administrators and users. It contains thousands of Ansible roles, and it has a
searchable database that helps Ansible users identify roles that might help them accomplish an
administrative task. Ansible Galaxy includes links to documentation and videos for new Ansible
users and role developers.

Figure 10.6: Ansible Galaxy

Getting Help with Ansible Galaxy


The Documentation tab on the Ansible Galaxy website home page describes how to use Ansible
Galaxy. This page provides information about downloading and using roles from Ansible Galaxy.
Instructions on how to develop roles, and upload them to Ansible Galaxy, are also included.

Browsing Ansible Galaxy for Roles


The Search tab on the Ansible Galaxy website home page gives users access to information about
the roles published on Ansible Galaxy. You can search for an Ansible role by its name, using tags, or
by other role attributes.

462 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

Many of the roles on Ansible Galaxy are designed for other operating systems or network devices.
Use the Search tab to find Microsoft Windows-compatible roles. For example, searching for the
keyword or tag "windows" returns a large number of results.

Results are presented in descending order, based on the Best Match score, which is a computed
score derived from role quality, role popularity, and searches criteria.

Note
Consult the Content Scoring [https://galaxy.ansible.com/docs/contributing/
content_scoring.html] section of the Ansible Galaxy documentation for more
information on how Ansible Galaxy scores roles.

Figure 10.7 demonstrates how to use the search feature to browse roles. The Filters menu allows
you to perform searches by keywords, author IDs, platform, and tags. Possible platform values
include Windows for Microsoft Windows, among others.

Tags are arbitrary, single-word strings set by the role author that describe and categorize the role.
Users can use tags to find relevant roles. Possible tag values include system, development, web,
monitoring, and others. A role can have up to 20 tags in Ansible Galaxy.

Figure 10.7: Searching roles in Ansible Galaxy

Ansible Galaxy reports the number of times each role has been downloaded from Ansible Galaxy.
Ansible Galaxy also reports the number of watchers, forks, and stars for each GitHub repository
that stores a role. Use this information to determine how active development is for a particular
role, and how popular that role is in the community.

Figure 10.8 demonstrates a role page, which contains information such as tags, the Ansible version
the role requires, or the production readiness of the role.

DO417-RHAE2.8-en-1-20200106 463
Chapter 10 | Managing Large Projects

Figure 10.8: Reviewing roles in Ansible Galaxy

Important
In the Ansible Galaxy search interface, keyword searches match words or phrases in
the README file, content name, or content description. Tag searches, by contrast,
specifically match tag values set for the role by the author.

Installing Roles Using a Requirements File


Ansible Tower can install a list of roles based on definitions in a text file. For example, if you have a
playbook that requires installing specific roles, then you can create a roles/requirements.yml
file in the project directory that specifies the needed roles.

Use the name keyword to override the local name of the role. Use the version keyword to specify
the version of the role. You can use the version keyword with any value that corresponds to a
branch, tag, or commit hash in the software repository for the role. The src attribute specifies the
source of the role, for example, the arillso.chocolatey role from Ansible Galaxy.

The following excerpt shows an example of a roles/requirements.yml file that installs a


specific role from Ansible Galaxy:

- src: arillso.chocolatey
name: test.chocolatey
version: 1.3.2

Important
Specify the version of the role in your requirements.yml file, especially for
playbooks in production. If you do not specify a version, then the most recent
version of the role is used. If the upstream author makes changes to the role that
are incompatible with your playbook, then it may cause automation failure or other
problems.

464 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

Specify roles that are not in Ansible Galaxy in your roles/requirements.yml file, and
Ansible Tower can automatically retrieve them. You can host your proprietary or internal roles
in a private Git repository, or on a web server. The following example shows how to configure a
requirements file using a variety of remote sources.

# from Ansible Galaxy, using the latest version


- src: geerlingguy.redis

# from Ansible Galaxy, overriding the name and using a specific version
- src: geerlingguy.redis
version: "1.5.0"
name: redis_prod

# from any Git-based repository, using HTTPS and a specific commit hash
- src: https://gitlab.com/guardianproject-ops/ansible-nginx-acme.git
scm: git
version: 56e00a54
name: nginx-acme

# from any Git-based repository, using SSH and a specific Git branch
- src: git@gitlab.com:guardianproject-ops/ansible-nginx-acme.git
scm: git
version: master
name: nginx-acme-ssh

The src keyword specifies the Ansible Galaxy role name. If the role is not hosted on Ansible
Galaxy, the src keyword indicates the URL for the role.

If the role is hosted in a source control repository, the scm attribute is required. Ansible Tower is
capable of downloading and installing roles from either Git-based or mercurial-based software
repositories. A Git-based repository requires an scm value of git, whereas a role hosted on a
mercurial repository requires a value of hg. If the role is hosted on Ansible Galaxy or as a tar
archive on a web server, then the scm keyword is omitted.

References
Galaxy Documentation — Ansible Documentation
https://galaxy.ansible.com/docs/

DO417-RHAE2.8-en-1-20200106 465
Chapter 10 | Managing Large Projects

Guided Exercise

Deploying Roles with Ansible Galaxy


In this exercise, you will use Ansible Galaxy to download and install a role from your Git
server.

Outcomes
You should be able to use Ansible Tower to download a role from Ansible Galaxy and use it in
your environment.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

Important
This exercise uses resources created in Chapter 8, Interacting with Users and
Domains. You must complete the exercises for that chapter before attempting
the following activity.

1. Launch the Visual Studio Code editor, and then clone the projects repository to your
workstation instance.

1.1. Click Search Windows, search for code, and then open Visual Studio Code.

1.2. Navigate to View → Command Palette or press Ctrl+Shift+P to open the


command palette.
Type clone, and then select Git: Clone to clone a repository.
Use a repository URL of https://gitlab.example.com/student/
projects.git. When prompted, select the Documents folder of the /home/
student directory, and then click Select Repository Location. This clones the
remote repository to the projects folder.
In the window that displays after cloning the files, click Open.

2. Review and fix the content of the requirements.yml file in the roles subdirectory. After
making the changes, commit and push the changes to the master branch.

2.1. Go to the roles directory, located at the top-level. Select the _requirements.yml
file, and then press F2 to rename the file to requirements.yml. The underscore
prevented Ansible from attempting to parse the incomplete file when syncing the
project.

466 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

2.2. Open the requirements.yml file. This file contains everything needed for Ansible
Tower to download the proper role. Change the file as follows:

- src: https://github.com/arillso/ansible.chocolatey.git
version: 1.3.2
name: ansible-chocolatey-role

2.3. Click Save. Note the status icons in the lower left corner. The asterisk on Master
indicates that changes were made.

3. Review and fix the the content of the install_chocolatey.yml file in the top-level
directory. After making the changes, commit and push the changes to the master branch.

3.1. Navigate to the top-level directory. Select the install_chocolatey.yml file; this
playbook uses the role from the requirements.yml file to install Chocolatey with
custom options. You can find this particular role at https://galaxy.ansible.com/
arillso/chocolatey . Change the file as follows:

---
- name: Installing chocolatey using a role
hosts: all
tasks:
- name: Install chocolatey
vars:
chocolatey_config:
- commandExecutionTimeoutSeconds: 2300
chocolatey_feature:
- virusCheck: true
- usePackageRepositoryOptimizations: true
import_role:
name: ansible-chocolatey-role

Important
Usually, a role has a lot of variables that are set to some default values. Use the
Galaxy interface to access the README.md file, which describes the usage of the
role, including the variables that customize the behavior of the role.

3.2. Click Save.

3.3. Change to the Source Control view, and then click + to stage the changes.

3.4. Enter a commit message, and then press Ctrl+Enter to commit the changes.

3.5. The status icon in the lower left indicates that there is a change to push to the remote
repository. Click Synchronize Changes to send the change to the remote repository,
and to receive any new changes from the remote repository.

4. Start an update of the projects repository project to synchronize the changes that
you made, and to automatically download the role defined in the requirements.yml file
from Ansible Galaxy.

4.1. In the navigation pane, click Projects.

DO417-RHAE2.8-en-1-20200106 467
Chapter 10 | Managing Large Projects

4.2. In the list of projects, click the synchronize changes icon for the projects
repository project to start the synchronization process.

4.3. Click the status icon and observe the automatic SCM update of the projects
repository project.

Note
Notice the fetch galaxy roles from requirements.yml task. This task
is automatically triggered at the end of the project synchronization when Ansible
Tower finds the roles/requirements.yml file.

5. Run the Run projects project job to test your playbook and the new role.

5.1. In the navigation pane, click Templates.

5.2. From the list of templates, select the Run projects project template.

Note
To select a project for editing, click its name.

5.3. Select the install_chocolatey.yml playbook from the PLAYBOOK list.

5.4. If cleared, select the PROMPT ON LAUNCH check box for the LIMIT option.

5.5. If selected, clear the PROMPT ON LAUNCH check box of the CREDENTIAL and
INVENTORY options.

5.6. In the INVENTORY option, choose Dynamic inventory.

5.7. In the CREDENTIAL option, choose AD Administrator.

5.8. Click SAVE to update the job template.


Click LAUNCH to begin execution.

5.9. In the RUN PROJECTS PROJECT window, type in the win1.example.com


hostname. Click NEXT, and then click LAUNCH.

5.10. Observe the live output of the running job.

5.11. Verify that the status of the job in the DETAILS pane displays Successful.
Installation of Chocolatey with custom options, using a role from Ansible Galaxy, is
complete.

6. Add a role stored in your local git repository to the requirements.yml file.

6.1. Edit the content of the requirements.yml file in the roles subdirectory. After
making the changes, commit and push the changes to the master branch.

6.2. Go to the roles directory, located at the top-level. Select the requirements.yml
file, which contains everything needed for Ansible Tower to download the proper
role. Add a role to the file; the role was downloaded from Ansible Galaxy and
stored in your local git repository. You can find this particular role at https://

468 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

galaxy.ansible.com/meyerf99/7zip . Add the following role at the end of the


file:

...output omitted...
- name: Ansible 7-zip Galaxy role
src: https://gitlab.example.com/student/ansible-7zip.git
scm: git
name: ansible-7zip

6.3. Click Save. Note the status icons in the lower left corner. There is an asterisk for
Master that indicates changes were made.

6.4. Change to the Source Control view, and then click + for requirements.yml to
stage the changes.

6.5. Enter a commit message, and then press Ctrl+Enter to commit the changes.

6.6. The status icon in the lower left indicates that there are changes to push to the remote
repository. Click Synchronize Changes to send your changes to the remote repository,
and retreive any new changes from the remote repository.

7. Review the content of the install_7zip.yml file in the top-level directory.

7.1. Navigate to the top-level directory. Select the install_7zip.yml file; this playbook
uses the role from the requirements.yml file to install 7zip. It displays as follows:

---
- name: Installing 7zip using a local role
hosts: all
tasks:
- name: Install 7zip
import_role:
name: ansible-7zip

8. Start an update of the projects repository project to synchronize the changes that
you made, and to automatically download the role defined in the requirements.yml file
from Ansible Galaxy.

8.1. In the navigation pane, click Projects.

8.2. In the list of projects, click the synchronize changes icon for the projects
repository project to start the synchronization process.

8.3. Click the status icon and observe the automatic SCM update of the project projects
repository.

Note
Notice the fetch galaxy roles from requirements.yml task. This task
is automatically triggered at the end of the project synchronization, when Ansible
Tower finds the roles/requirements.yml file.

9. The 7zip role that you synchronized uses the deprecated win_msi module, and an earlier
version of 7zip. In the following steps, you modify the role to replace the deprecated
module, and changethe version of 7zip to a later one.

DO417-RHAE2.8-en-1-20200106 469
Chapter 10 | Managing Large Projects

9.1. Launch the Visual Studio Code editor and clone the ansible-7zip repository to your
workstation instance.

9.2. Click Search Windows, search for code, and then open Visual Studio Code.

9.3. Navigate to View → Command Palette or press Ctrl+Shift+P to open the


command palette.
Type clone, and then select Git: Clone to clone a repository.
Use a repository URL of https://gitlab.example.com/student/
ansible-7zip.git. When prompted, select the Documents folder of the /home/
student directory, and then click Select Repository Location. This clones the
remote repository to the ansible-7zip folder.
In the window that displays after cloning, click Open to view the files.

9.4. Review and fix the content of the main.yml file in the tasks directory. After making
the changes, commit and push the changes to the master branch.

9.5. Go to the tasks directory. Select the main.yml file; this file contains a set of tasks
required to download and install 7zip. Change all occurrences of win_msi module to
win_package module. Change the 7zip version from 1604 to 1900 . The main.yml
file with all the changes displays as follows:

---
# tasks file for 7zip
- name: create directory on localhost
file:
path: /tmp/ansible
state: directory
delegate_to: localhost

- name: download 7zip from URL


get_url:
url: http://7-zip.org/a/7z1900-x64.msi
dest: /tmp/ansible
delegate_to: localhost

- name: create directory


win_file:
path: C:\ansible
state: directory

- name: copy 7zip from localhost to windows server


win_copy:
src: /tmp/ansible/7z1900-x64.msi
dest: C:\ansible\7z1900-x64.msi

- name: install 7 zip


win_package:
path: 'C:\ansible\7z1900-x64.msi'
state: present
when: not sevenzip_uninstall

- name: uninstall 7 zip


win_package:

470 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

path: 'C:\ansible\7z1900-x64.msi'
state: absent
when: sevenzip_uninstall

- name: remove 7zip install folder


win_file:
path: C:\ansible
state: absent

- name: remove 7zip temp destination


file:
path: /tmp/ansible
state: absent
delegate_to: localhost

9.6. Click Save. Note the status icons in the lower left. There is an asterisk next to Master,
indicating that changes were made.

9.7. Switch to the Source Control view, and then click + for the main.yml file to stage
the changes.

9.8. Enter a commit message, and then press Ctrl+Enter to commit the changes.

9.9. The status icons in the lower left indicates that there is a change to push to the remote
repository. Click Synchronize Changes to send the change to the remote repository,
and to receive any new changes from the remote repository.

10. Because you changed the role, Ansible Tower must download the correct version
of the role from the repository. The following steps demonstrate ho to change the
requirements.yml file, so that Ansible Tower uses the correct version of the role.

10.1. The commit number is now the role version number. To find out the proper commit
number in Visual Studio Code editor, click master on the status bar.

10.2.In the newly opened window take note of the number next to master. This is the
number of the last commit with your change. For example, the number might be
b967f3e4.

10.3.Change the working directory in Visual Studio Code. Click File, click Open Folder, and
select the projects directory.

10.4.Edit the content of the requirements.yml file in the roles subdirectory. After
making the changes, commit and push the changes to the master branch.

10.5.Go to the roles directory, located at the top-level. Select the requirements.yml
file. Add the commit version number as a parameter for the role version. Modify the file
as follows:

...output omitted...
- name: Ansible 7-zip Galaxy role
src: https://gitlab.example.com/student/ansible-7zip.git
scm: git
version: b967f3e4 <--INSERT THE COMMIT VERSION NUMBER HERE
name: ansible-7zip

DO417-RHAE2.8-en-1-20200106 471
Chapter 10 | Managing Large Projects

10.6.Click Save. Note the status icons in the lower left corner. There is an asterisk next to
Master, which indicates that changes were made.

10.7. Change to the Source Control view, and then click + next to requirements.yml to
stage the changes.

10.8.Enter a commit message, and then press Ctrl+Enter to commit the changes.

10.9.The status icon at the lower left corner indicates that there are changes to push to the
remote repository. Click Synchronize Changes to send your changes to the remote
repository, and to receive any new changes from the remote repository.

11. Start an update of the projects repository project, to synchronize the changes that
you made, and to automatically download the role defined in the requirements.yml file
from Ansible Galaxy.

11.1. In the navigation pane, click Projects.

11.2. In the list of projects, click the synchronize changes icon for the projects
repository project to start the synchronization process.

11.3. Click the status icon and observe the automatic SCM update of the projects
repository project.

Note
Notice the fetch galaxy roles from requirements.yml task. This task
is automatically triggered at the end of the project synchronization, when Ansible
Tower finds the roles/requirements.yml file.

12. Run the Run projects project job to test your updated role.

12.1. In the navigation pane, click Templates.

12.2. From the list of templates, select the Run projects project template.

Note
To select a project for editing, click its name.

12.3. Select the install_7zip.yml playbook from the PLAYBOOK list.

12.4. If cleared, select the PROMPT ON LAUNCH check box for the LIMIT option.

12.5. If selected, clear the PROMPT ON LAUNCH check box of the CREDENTIAL and
INVENTORY options.

12.6. In the INVENTORY option, choose Dynamic inventory.

12.7. In the CREDENTIAL option, choose AD Administrator.

12.8. Click SAVE to update the job template.


Click LAUNCH to begin execution.

12.9. In the RUN PROJECTS PROJECT window, type in the win1.example.com


hostname. Click NEXT, and then click LAUNCH.

472 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

12.10.Observe the live output of the running job.

12.11. Verify that the status of the job in the DETAILS pane displays Successful.

13. You modified a role, and used that role to install 7zip on one of the managed hosts.
Click the Log Out icon to log out of Ansible Tower

This concludes the guided exercise.

DO417-RHAE2.8-en-1-20200106 473
Chapter 10 | Managing Large Projects

Integrating Ansible with Desired State


Configuration Resources

Objectives
After completing this section, you should be able to configure and run PowerShell Desired State
Configuration (DSC) resources from your Ansible Playbook to automate tasks.

Introducing Desired State Configuration


Desired State Configuration (DSC) is a system configuration management platform built into
PowerShell that uses a declarative model. It uses a push-mode execution to send configurations
to the target hosts through code. This configuration management platform is executed differently
than Ansible, and is specific to the Windows platform. DSC uses a Local Configuration Manager
that runs on all the remote nodes as the DSC execution engine.

Microsoft fosters a community effort to build and maintain DSC resources for many technologies.
These resources are published each month to the PowerShell Gallery as the DSC Resource Kit,
and are available from the GitHub site: https://github.com/PowerShell/DscResources.

The win_dsc Ansible module was introduced in Ansible 2.4, and allows Ansible to use existing
DSC resources for Windows hosts. The minimum requirement to run this module on hosts is
Powershell v5.0 or later.

Choosing Ansible Modules or DSC Resources


Both DSC resources and Ansible modules have a common goal: to define and ensure the correct
state of a system resource. As such, they can be complementary technologies. Because Ansible
can run DSC resources from a playbook, you can use the cross-platform Ansible tool to manage
automation in a centralized, standardized way, and still take advantage of the Windows-specific
DSC resources in the PowerShell Gallery for Windows automation.

DSC resources support code reuse, similar to Ansible roles, but provide a larger library of existing,
community-supported automation code than using only Ansible modules.

In many cases, you might have a choice between an Ansible module or a DSC resource to
automate a particular task. The following lists discuss some criteria that you might use when
deciding which approach to use:

Reasons to use Ansible modules

• The host does not support PowerShell v5.0, or you cannot easily upgrade it.

• The Ansible module you are using has a feature that the DSC resource does not.

• The Ansible module checks for idempotency are better suited for your needs than the limited
DSC check mode support.

• The Ansible module in question supports diff mode, and DSC resources do not.

• There are bugs in a DSC resource, but the Ansible module works.

474 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

Reasons to use DSC resources through Ansible

• You are familiar with the DSC resource, and more comfortable with how it functions.

• You want to use DSC resources and Ansible modules in the same automation runs, or in cross-
platform automation operations.

• The Ansible module does not support a feature present in a DSC resource.

• There is no Ansible module available.

• There are bugs in an existing Ansible module but the DSC resource works.

Listing DSC Resources


The following are examples of the built-in DSC resources available for managing Windows:

• Archive

• File

• Group

• Package

• WindowsFeature

You can find the list of all the DSC Resources at https://docs.microsoft.com/en-us/powershell/
scripting/dsc/resources/resources?view=powershell-6#built-in-resources.

Microsoft, and the community through the DSC Resource Kit, provide many additional custom
DSC resources, including:

• Domain Controller

• IIS Web Site

• SQL Server Cluster

• Failover Cluster

• DNS

Additional custom resources can be found at https://www.powershellgallery.com.

Running DSC Resources in an Ansible Playbook


It is easy to use the win_dsc module to drive a single DSC resource provider, like an Ansible
module.

In the first example, this excerpt from the tasks section of a play uses Ansible modules to install
Internet Information Services (IIS), and create a web page:

- name: Install IIS Web-Server


win_feature:
name: Web-Server
state: present
restart: True
include_sub_features: True
include_management_tools: True

DO417-RHAE2.8-en-1-20200106 475
Chapter 10 | Managing Large Projects

- name: Create IIS site


win_iis_website:
name: Ansible
state: started
physical_path: C:\website\DO417

- name: Add HTTP webbinding to IIS


win_iis_webbinding:
name: Ansible
protocol: http
port: 8080
ip: '*'
state: present

Use the win_dsc module to accomplish the same tasks using DSC resources:

- name: Install required DSC module:


win_psmodule:
name: xWebAdministration
state: present

- name: Install IIS Web-Server


win_dsc:
resource_name: windowsfeature
name: Web-Server

- name: Create IIS site and add HTTP webbinding


win_dsc:
resource_name: xWebsite
Ensure: Present
Name: Ansible
State: Started
PhysicalPath: C:\website\DO417
BindinInfo:
- Protocol: http
Port: 8080
IPAddress: '*'

In the preceding code, Ansible installs the xWebAdministration DSC Resource Module using
the win_psmodule module. With the right DSC Resources now present, windowsfeature
resource is invoked to install the Web-Server feature. xWebsite resource is invoked in the last
task to create the IIS Website, and to add an HTTP binding to IIS Web Server.

Ansible's win_psmodule module installs the xWebAdministration DSC resource module.


The windowsfeature resource is called to install the Web-Server feature.
The xWebsite resource is called in the last task, to create the IIS Website and add an HTTP
binding to IIS.

Running DSC from Ansible as a Non-SYSTEM User


By default, DSC runs each resource using the SYSTEM account, and not the account that Ansible
uses to run the module. This means that dynamically loaded resources that are based on a user
profile, like the HKEY_CURRENT_USER registry hive, are loaded under the SYSTEM profile.

476 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

The parameter PsDscRunAsCredential, can be set for every DSC resource, forcing the DSC
engine to run under a different account. PsDscRunAsCredential has a type of PSCredential
that you configure with the username and password suffix.

Using the Registry resource type as an example, the following example demonstrates defining a
task to access the HKEY_CURRENT_USER hive of the Ansible user:

- name: use win_dsc with PsDscRunAsCredential to run as a different user


win_dsc:
resource_name: Registry
Ensure: Present
Key: HKEY_CURRENT_USER\ExampleKey
ValueName: TestValue
ValueData: TestData
PsDscRunAsCredential_username: '{{ansible_user}}'
PsDscRunAsCredential_password: '{{ansible_password}}'
no_log: true

References
Ansible Documentation — Desired State Configuration
https://docs.ansible.com/ansible/latest/user_guide/windows_dsc.html

DO417-RHAE2.8-en-1-20200106 477
Chapter 10 | Managing Large Projects

Guided Exercise

Integrating Ansible with Desired State


Configuration Resources
In this exercise, you will configure and use a DSC resource from an Ansible Playbook.

Outcomes
You should be able to use the win_dsc module to create files and directories.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

Important
This exercise uses resources created in Chapter 8, Interacting with Users and
Domains. You must complete the exercises for that chapter before attempting
the following activity.

1. Launch the Visual Studio Code editor and then clone the projects repository to your
workstation instance.

1.1. Click Search Windows, search for code, and then open Visual Studio Code.

1.2. Navigate to View → Command Palette or press Ctrl+Shift+P to open the


command palette.
Type clone, and then select Git: Clone to clone a repository.
Use a repository URL of https://gitlab.example.com/student/
projects.git. When prompted, select the Documents folder of the /home/
student directory, and then click Select Repository Location. This clones the
remote repository in to the projects folder.
In the window that displays after cloning, click Open to view the files.

2. Review and fix the the content of the dsc_usage.yml file. After making the changes,
commit and push the changes to the master branch.

2.1. Select the dsc_usage.yml file; this file contains tasks for creating a directory,
creating a file, and extracting a zip archive. Change the file as follows:

478 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

...output omitted...
- name: Create a new directory
win_dsc:
resource_name: File
DestinationPath: C:\DO417\dsc-usage-example
Ensure: Present
Type: Directory

- name: Create a new file with text


win_dsc:
resource_name: File
DestinationPath: C:\DO417\dsc-usage-example\new-file.txt
Contents: |
Hello
This is the DO417 course.
Ensure: Present
Type: File

- name: Copy a zip file to the managed host


win_copy:
src: do417-example.zip
dest: C:\DO417\dsc-usage-example\do417-example.zip

- name: Extract a zip file in the new directory


win_dsc:
resource_name: Archive
Destination: C:\DO417\dsc-usage-example\extracted-zip
Path: C:\DO417\dsc-usage-example\do417-example.zip
Ensure: Present

2.2. Click Save. Note the status icons in the lower left. There is an asterisk next to Master
indicating that changes were made.

2.3. Change to the Source Control view, and then click + for the modified file to stage the
changes.

2.4. Enter a commit message, and then press Ctrl+Enter to commit the changes.

2.5. The status icon in the lower left corner indicates that there are changes to push to the
remote repository. Click Synchronize Changes to send your changes to the remote
repository, and to receive any new changes from the remote repository.

3. Run the Run projects project job to test your playbook with the win_dsc modules.

3.1. In the navigation pane, click Templates.

3.2. From the list of templates, select the Run projects project template.

Note
To select a project for editing, and then click its name.

3.3. Select the dsc_usage.yml playbook from the PLAYBOOK list.

DO417-RHAE2.8-en-1-20200106 479
Chapter 10 | Managing Large Projects

3.4. If cleared, select the PROMPT ON LAUNCH check box for the LIMIT option.

3.5. If selected, clear the PROMPT ON LAUNCH check box for the CREDENTIAL and
INVENTORY options.

3.6. In the INVENTORY option, choose Dynamic inventory.

3.7. In the CREDENTIAL option, choose AD Administrator.

3.8. Click SAVE to update the job template.


Click LAUNCH to begin execution.

3.9. In the RUN PROJECTS PROJECT window, type in the win1.example.com


hostname. Click NEXT, and then click LAUNCH.

3.10.Observe the live output of the running job.

3.11. Verify that the status of the job in the DETAILS pane displays Successful.

4. Click the Log Out icon to log out of Ansible Tower.

5. Log in to win1.example.com host as the devops user with the RedHat123@! password.
Verify that you have a C:\DO417\dsc-usage-example directory with a new-file.txt
file in it, and an extracted-zip subdirectory containing the unzipped Example-of-a-
extracted-file.txt file.

This concludes the guided exercise.

480 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

Lab

Managing Large Projects


Performance Checklist
In this lab, you will create Ansible roles and playbooks that use Ansible roles and DSC
resources to automate repeatable tasks.

Outcomes
You should be able to:

• Modify a playbook to use DSC resources.

• Convert the playbook to a role.

• Create a playbook that uses the role to create new directories and install a Windows
feature.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

All Chapter 8, Interacting with Users and Domains guided exercises must be completed prior
to starting this exercise, due to changes in inventory and authentication.

1. Edit the projects-review.yml playbook in the projects repository, and make the
changes indicated. Commit and push your changes to the Git repository. Comments in the
playbook indicate the changes to make.

• Use DSC to create the proper directory structure, and to unzip the provided archive.

Use DSC to install the telnet-client Windows Feature.

• Update the first task with the correct Ansible module, and the module options needed to
create the defined directory.

• Update the third task with the correct Ansible module, and the module options to install
the telnet-client Windows Feature.
2. Convert the projects-review.yml playbook that you modified to a role named
projects-review. The necessary directories and files inside the roles\projects-
review role directory are already populated. Copy and paste the code from the original
playbook into the proper main.yml files in the new role structure. When you copy the code
to the proper locations, make sure the indentation is correct.
Comments in each of the main.yml files help you identify which part of the original
playbook should be pasted into which directory or file in the new role structure.

DO417-RHAE2.8-en-1-20200106 481
Chapter 10 | Managing Large Projects

Commit and push your changes to the Git repository.

• Put the first variable from the playbook in the roles\projects-review\defaults


\main.yml file.

• Put all the other variables from the playbook in the roles\projects-review\vars
\main.yml file.

• Put all the tasks from the playbook in the roles\projects-review\tasks\main.yml


file.

• Copy the do417-example.zip file from the projects\files directory to the roles
\projects-review\files directory.
3. Create a new projects_review_role.yml playbook that uses your new role to create the
directory structure and installs the Windows feature. Override the default variable of this role
by pointing it to the C:\DO417\projects-review-role\ directory.
Commit the changes to your local Git repository, and then push them to the remote
repository.
4. Start an update of the projects repository project to synchronize your
changes. Update the Run projects project job template to use your new
projects-review role. Update the template to instruct Ansible Tower to use the
projects_review_role.yml playbook to prompt you for the host to target, and to set
the proper credentials and inventory to use.
Launch a job using the template, and when prompted use win2.example.com as the target
host, AD Administrator as the credentials, and Dynamic inventory as the inventory.
5. You modified a playbook and converted it to a role. You used that role to install a Windows
feature, and to create directories and files on one of the managed hosts. If necessary, you
can log in to win2.example.com to verify that the new C:\DO417\projects-review-
role\ directory has been created, along with all the subdirectories and files defined in the
role. Use the EXAMPLE\Administrator username and AD Administrator password to
access win2.example.com.
6. Click Log Out to exit the Ansible Tower web interface.

This concludes the lab.

482 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

Solution

Managing Large Projects


Performance Checklist
In this lab, you will create Ansible roles and playbooks that use Ansible roles and DSC
resources to automate repeatable tasks.

Outcomes
You should be able to:

• Modify a playbook to use DSC resources.

• Convert the playbook to a role.

• Create a playbook that uses the role to create new directories and install a Windows
feature.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

All Chapter 8, Interacting with Users and Domains guided exercises must be completed prior
to starting this exercise, due to changes in inventory and authentication.

1. Edit the projects-review.yml playbook in the projects repository, and make the
changes indicated. Commit and push your changes to the Git repository. Comments in the
playbook indicate the changes to make.

• Use DSC to create the proper directory structure, and to unzip the provided archive.

Use DSC to install the telnet-client Windows Feature.

• Update the first task with the correct Ansible module, and the module options needed to
create the defined directory.

• Update the third task with the correct Ansible module, and the module options to install
the telnet-client Windows Feature.

1.1. Launch the Visual Studio Code editor. Navigate to File → Open Folder, and then
select the c:\Users\student\Documents\projects folder to open the c:\Users
\student\Documents\projects directory.

1.2. Edit the projects-review.yml playbook, modifying it as follows:

• Use DSC to create the proper directory structure, and to unzip the provided archive.

DO417-RHAE2.8-en-1-20200106 483
Chapter 10 | Managing Large Projects

Use DSC to install the telnet-client Windows Feature.

• Update the first task with the correct Ansible module, and the module options to
create the defined directory.

• Update the third task with the correct Ansible module and the module options to
install the telnet-client Windows Feature.

The completed playbook should display as follows:

---
- name: Configure a host using DSC
hosts: all
vars:
directory_location: C:\DO417\projects-review\
file_name: "{{ directory_location }}new-file.txt"
windows_resource: WindowsFeature
feature_name: telnet-client
zip_file_location: files/do417-example.zip
zip_remote_location: "{{ directory_location }}do417-example.zip"
zip_extracted_location: "{{ directory_location }}extracted-zip"

tasks:

- name: Create a new directory


win_dsc:
resource_name: File
DestinationPath: "{{ directory_location }}"
Ensure: Present
Type: Directory

- name: Create a new file with text


win_dsc:
resource_name: File
DestinationPath: "{{ file_name }}"
Contents: |
Hello
This is the DO417 course.
Ensure: Present
Type: File

- name: Install a Windows feature


win_dsc:
resource_name: "{{ windows_resource }}"
Name: "{{ feature_name }}"

- name: Copy a zip file to the managed host


win_copy:
src: "{{ zip_file_location }}"
dest: "{{ zip_remote_location }}"

- name: Extract a zip file in the new directory


win_dsc:

484 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

resource_name: Archive
Destination: "{{ zip_extracted_location }}"
Path: "{{ zip_remote_location }}"
Ensure: Present

1.3. Save your changes. Note the status icons in the lower left corner. The asterisk next to
Master indicates that there are new changes

1.4. Switch to the Source Control view, and then click + for the projects-review.yml
playbook to stage the changes.

1.5. Enter a commit message and then press Ctrl+Enter to commit the changes.

1.6. The status icon in the lower left corner indicates that there are changes to push to the
remote repository. Click Synchronize Changes to send your changes to the remote
repository, and to receive any new changes from the remote repository.

2. Convert the projects-review.yml playbook that you modified to a role named


projects-review. The necessary directories and files inside the roles\projects-
review role directory are already populated. Copy and paste the code from the original
playbook into the proper main.yml files in the new role structure. When you copy the code
to the proper locations, make sure the indentation is correct.
Comments in each of the main.yml files help you identify which part of the original
playbook should be pasted into which directory or file in the new role structure.
Commit and push your changes to the Git repository.

• Put the first variable from the playbook in the roles\projects-review\defaults


\main.yml file.

• Put all the other variables from the playbook in the roles\projects-review\vars
\main.yml file.

• Put all the tasks from the playbook in the roles\projects-review\tasks\main.yml


file.

• Copy the do417-example.zip file from the projects\files directory to the roles
\projects-review\files directory.

2.1. Open the projects-review.yml playbook file.

2.2. Copy all tasks in the projects-review.yml file to the roles\projects-review


\tasks\main.yml role playbook file.
In the projects-review.yml file, select the tasks beginning with the task named
Create a new directory.

2.3. Select Edit → Copy or press Ctrl+C to cut the tasks from the file.

2.4. Navigate to Edit → Paste or press Ctrl+V to paste the text into the empty roles
\projects-review\tasks\main.yml playbook.

2.5. Select all of the text and press Shift+Tab twice to remove the task indentation.

2.6. Verify that your roles\projects-review\tasks\main.yml file displays as follows:

DO417-RHAE2.8-en-1-20200106 485
Chapter 10 | Managing Large Projects

---
- name: Create a new directory
win_dsc:
resource_name: File
DestinationPath: "{{ directory_location }}"
Ensure: Present
Type: Directory

- name: Create a new file with text


win_dsc:
resource_name: File
DestinationPath: "{{ file_name }}"
Contents: |
Hello
This is the DO417 course.
Ensure: Present
Type: File

- name: Install a Windows feature


win_dsc:
resource_name: "{{ windows_resource }}"
Name: "{{ feature_name }}"

- name: Copy a zip file to the managed host


win_copy:
src: "{{ zip_file_location }}"
dest: "{{ zip_remote_location }}"

- name: Extract a zip file in the new directory


win_dsc:
resource_name: Archive
Destination: "{{ zip_extracted_location }}"
Path: "{{ zip_remote_location }}"
Ensure: Present

2.7. Save the changes in the roles\projects-review\tasks\main.yml file.

2.8. Copy all the variables, except the directory_location: variable, from the
projects-review.yml playbook to the roles\projects-review\vars
\main.yml file.

2.9. Add the variable declaration to the roles\projects-review\vars\main.yml file


so that it displays as follows:

---
file_name: "{{ directory_location }}new-file.txt"
windows_resource: WindowsFeature
feature_name: telnet-client
zip_file_location: files/do417-example.zip
zip_remote_location: "{{ directory_location }}do417-example.zip"
zip_extracted_location: "{{ directory_location }}extracted-zip"

2.10. Save the updated roles\projects-review\vars\main.yml file.

486 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

2.11. Copy the directory_location: C:\DO417\projects-review\ line from


the projects-review.yml playbook. Add the variable declaration to the roles
\projects-review\defaults\main.yml file, so that it displays as follows:

---
directory_location: C:\DO417\projects-review\

2.12. Save the roles\projects-review\defaults\main.yml file.

2.13. Copy the files\do417-example.zip file to the roles\projects-review\files


directory.

2.14. Commit the changes to your local Git repository, and then push them to the remote
repository.

2.15. Navigate to the Source Control pane, and then stage the changes.

2.16. Enter a brief commit message, and then press Ctrl+Enter to commit the changes.

2.17. Locate the status icons in the lower left corner, and notice that they indicate a change to
push to the remote Git repository. Click the Synchronize Changes to push your changes.

3. Create a new projects_review_role.yml playbook that uses your new role to create the
directory structure and installs the Windows feature. Override the default variable of this role
by pointing it to the C:\DO417\projects-review-role\ directory.
Commit the changes to your local Git repository, and then push them to the remote
repository.

3.1. Create the projects\projects_review_role.yml file and use the new role as
follows:

---
- name: Configure a host using a role
hosts: all
roles:
- role: projects-review
directory_location: C:\DO417\projects-review-role\

3.2. Commit the changes to your local Git repository, and then push them to the remote
repository.
Navigate to the Source Control pane, and then stage the changes.

3.3. Enter a brief commit message, and then press Ctrl+Enter to commit the changes.

3.4. Locate the status icons in the lower left corner and notice that they indicate a change to
push to the remote Git repository. Click the Synchronize Changes to push your changes.

4. Start an update of the projects repository project to synchronize your


changes. Update the Run projects project job template to use your new
projects-review role. Update the template to instruct Ansible Tower to use the
projects_review_role.yml playbook to prompt you for the host to target, and to set
the proper credentials and inventory to use.
Launch a job using the template, and when prompted use win2.example.com as the target
host, AD Administrator as the credentials, and Dynamic inventory as the inventory.

DO417-RHAE2.8-en-1-20200106 487
Chapter 10 | Managing Large Projects

4.1. Double-click the Ansible Tower desktop icon to access Ansible Tower.
Log in using admin as the user name and RedHat123@! as the password.

4.2. In the navigation pane, click Projects.

4.3. In the list of projects, click the synchronization icon for the projects repository
project to start the synchronization process.

4.4. Click the status icon and observe the automatic SCM update of the project projects
repository.

4.5. When the project has synchronized successfully, click Templates.

4.6. Click the Run projects project job template to edit it.

4.7. Click the magnifying glass icon in the INVENTORY field. Click Dynamic inventory,
and then click SELECT.

4.8. Click the magnifying glass icon in the CREDENTIAL field. Click the AD
Administrator button, and then click SELECT.

4.9. Select the PROMPT ON LAUNCH check box for the LIMIT option.

4.10.Select the projects_review_role.yml playbook from the PLAYBOOK list.

4.11. Click SAVE to update the template, and then click LAUNCH to run the job.

4.12. Type win2.example.com in the LIMIT field. Click NEXT, and then click LAUNCH.

4.13. After all tasks have completed, verify that the status in the DETAILS pane displays
Successful.

5. You modified a playbook and converted it to a role. You used that role to install a Windows
feature, and to create directories and files on one of the managed hosts. If necessary, you
can log in to win2.example.com to verify that the new C:\DO417\projects-review-
role\ directory has been created, along with all the subdirectories and files defined in the
role. Use the EXAMPLE\Administrator username and AD Administrator password to
access win2.example.com.
6. Click Log Out to exit the Ansible Tower web interface.

This concludes the lab.

488 DO417-RHAE2.8-en-1-20200106
Chapter 10 | Managing Large Projects

Summary
In this chapter, you learned:

• You can import playbooks into higher level playbooks to manage large projects with many plays
in a modular way.

• You can dynamically include or statically import tasks into plays in a playbook.

• Ansible roles make it easier for you to share and reuse Ansible code.

• Ansible Galaxy is a public library of Ansible content written and maintained by a variety of
Ansible administrators and users.

• You can use PowerShell DSC resources as tasks in your Ansible plays to run tasks, using existing
automation in the PowerShell Gallery maintained by Microsoft and the community.

DO417-RHAE2.8-en-1-20200106 489
490 DO417-RHAE2.8-en-1-20200106
Chapter 11

Constructing Ansible Tower


Workflows
Goal Simplify management of jobs and launch complex
jobs using Red Hat Ansible Tower.

Objectives • Describe users and teams in Red Hat Ansible


Tower, the roles to which they may be assigned,
and how to create and manage them.
• Create a survey to make it simple for users to
launch jobs with Red Hat Ansible Tower.
• Schedule automatic execution of a job
template in Red Hat Ansible Tower.
• Create a sequence of job templates to execute
using workflows and workflow job templates in
Red Hat Ansible Tower.

Sections • Managing Users and Teams (and Guided


Exercise)
• Creating and Using Surveys (and Guided
Exercise)
• Scheduling Job Launches (and Guided
Exercise)
• Running Complex Workflows (and Guided
Exercise)

Lab Constructing Ansible Tower Workflows

DO417-RHAE2.8-en-1-20200106 491
Chapter 11 | Constructing Ansible Tower Workflows

Creating and Managing Ansible Tower


Users

Objectives
After completing this section, you should be able to describe users and teams in Red Hat Ansible
Tower, the roles to which they can be assigned, and how to create and manage them.

Role-Based Access Controls


In Ansible Tower, users, organizations, resources, such as projects, inventories, or job templates,
are all handled as objects at a Tower-wide level. Users are assigned roles that control permissions,
defining who can view, change, or delete an object in Ansible Tower. Roles are applied not only to
individual users, but also to organizations and teams, as a means of controlling access to resources.

Different people using an Ansible Tower installation require different levels of access. Some users
must have access to run existing job templates against a preconfigured inventory of machines.
Others must modify particular inventories, job templates, and playbooks. Still, others must have
access to change anything in the Ansible Tower installation.

Setting up user accounts for each person makes it easier to manage individual access to
inventories, credentials, projects, and job templates.

Users are assigned roles that control permissions, defining who can view, change, or delete an
object in Ansible Tower. Roles are managed with Role-Based Access Controls (RBAC). You can
manage roles collectively by granting them to a team, which is a collection of users. All users in
a team inherit the team's roles. Roles can also be granted to an organization, which is a logical
grouping of teams and resources. Each user must be assigned to an organization, and users inherit
roles from the organization, based on their user type.

Note
Roles determine whether users and teams can see, use, change, or delete objects
such as inventories and projects.

Managing User Accounts


By default, the Ansible Tower installer creates an admin user account, with full control of the
Ansible Tower installation. With that special admin account, an Ansible Tower administrator can
log in to the web interface and create additional users.

The three user types in Ansible Tower are:

System Administrator
The System Administrator user type (also known as Superuser) provides unrestricted
access to perform any action within the entire Ansible Tower environment. System
Administrator is a special singleton role, which has read-write permission on all objects in
all organizations on the Ansible Tower.

The admin user created by the installer has the system administrator singleton role. therefore,
an Ansible Tower administrator should connect to Ansible Tower as this admin user.

492 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

System Auditor
The System Auditor user type also has a special singleton role, which has read-only access
to the entire Ansible Tower environment.

Normal User
Normal User is the standard user type. Initially, this user type has no special roles assigned
and starts with minimal access. A Normal User has no singleton roles, and is only assigned
roles associated with the organization of which the user is a member.

Creating Users
The following steps demonstrates how a user, that is logged in to Ansible Tower as the admin user,
can create additional user accounts.

• Click Users in the navigation pane.

• Click + to create a new user.

• Enter the first name, last name, and email address for the new user into the FIRST NAME,
LAST NAME, and EMAIL fields, respectively.

• In the USERNAME field, specify a unique username for the new user.

• Click the magnifying glass icon for the ORGANIZATION field to display a list of organizations
within Ansible Tower. Select an organization from the list, and then click SAVE.

• Enter the desired password for the new user in the PASSWORD and CONFIRM PASSWORD
fields.

• Select a user type.

• Click SAVE to finish.

Figure 11.1: Fill in information for the new user

DO417-RHAE2.8-en-1-20200106 493
Chapter 11 | Constructing Ansible Tower Workflows

Editing Users
Use the Edit User window to edit the properties of the newly created user, as described in the
following steps:

• Click Users in the navigation pane.

• Click the user to edit.

• Make changes to the desired fields.

• Click SAVE to finish.

Managing Ansible Tower with Organizations


An Ansible Tower organization is a logical collection of teams, projects, and inventories. All Ansible
Tower users must belong to at least one organization.

One benefit of using Ansible Tower is the ability to share Ansible roles and playbooks across
departmental or functional boundaries within an enterprise. For example, the operations group in
an organization might already have Ansible roles for provisioning production, web, database, and
application servers. Developers can use these same roles to provision servers when preparing their
development environment. Ansible Tower makes it easier for different users and groups to use
existing roles and playbooks.

For very large deployments, it can be useful to categorize large numbers of users, teams, projects,
and inventories under one umbrella organization. Certain departments may not deploy to
certain inventories of hosts, or run certain playbooks. By using organizations, you can configure a
collection of users and teams to work with only those Ansible Tower resources that they expect to
use.

Creating Additional Organizations


As part of the Ansible Tower installation, a default organization is created. The following steps
describe creating additional organizations using the Ansible Tower web interface.

• Log in to the Ansible Tower web interface as the admin user.

• Click Organizations in the navigation pane.

• Click + to create a new organization.

• In the fields, enter a name for the new organization, and an optional description if desired.

494 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

Figure 11.2: Complete information about the new Organization

• Click SAVE to finish.

Organization Roles
Newly created users inherit specific roles from the organization, based on the user type. You can
assign additional roles to a user after creation to grant permissions to view, use, or change other
Ansible Tower objects. An organization is itself one of these objects. There are four roles that users
can be assigned to in an organization:

Organizational Admin
A user with the organizational Admin role can manage all aspects of that organization,
including reading and changing the organization, and adding or removing users and teams.

DO417-RHAE2.8-en-1-20200106 495
Chapter 11 | Constructing Ansible Tower Workflows

Note
A number of related administrative roles grant more limited access than Admin:

Project Admin
A user with this role can create, read, update, and delete any project in the
organization. In conjunction with the Inventory Admin role, this allows users
to create job templates.

Inventory Admin
A user with this role can create, read, update, and delete any inventory in the
organization. In conjunction with the Job Template Admin and Project
Admin roles, this allows the user full control over job templates within the
organization.

Credential Admin
A user with this role can create, read, update, and delete shared credentials.

Notification Admin
A user with this role can be assigned notifications.

Workflow Admin
A user with this role can create workflows within the organization.

Job Template Admin


A user with this role can make changes to nonsensitive fields on job templates.
To make changes to fields that impact job runs, the user must also have the
Admin role on the Job Template, the Use role on the related project, and the
Use role on the related inventory.

Auditor
A user with this role has read-only access to the organization.

Member
A user with this role has read-only access to the organization. The organization Member role
only provides a user the ability to view the list of users who are members of the organization,
and their assigned organization roles.

Unlike the organization Admin and Auditor roles, the Member role does not give users
permissions to any of the resources in the organization, such as teams, credentials, projects,
inventories, job templates, work templates, or notifications.

Read
A user with this role has read-only access to the organization object only. The Read role
allows a user to view the list of users who are members of the organization, and their assigned
organization roles.

However, unlike the organization Admin and Auditor roles, the Read role does not inherit
roles on any of the resources the organization contains, such as teams, credentials, projects,
inventories, job templates, work templates, and notifications.

You cannot assign roles to the organization object on Ansible Tower resources. Therefore,
a user that has the Member role or Read role on an organization only has access to the
organization object, and inherits no other permissions as a result of these roles.

Execute
A user with this role can execute job templates and workflow job templates in the organization.

496 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

Important
Users with the System Administrator singleton role inherit the Admin role on
every organization within Ansible Tower.

Users with the System Auditor singleton role inherit the Auditor role on every
organization within Ansible Tower.

A user created with the Normal User user type is assigned a Member role on
the organization to which they were assigned at the time of the user's creation in
Ansible Tower. You can add other roles later, including additional Member roles on
other organizations.

Managing Organization Roles for Users


The Edit User screen only allows changes to user type, and the organization to which a user
belongs. Because user types determine a user's inherited organization roles, modifying a user's
organization and user type can impact their organization role.

Full administration of a user's role in an organization requires admin access. The following steps
provide an overview of administering user roles in Ansible Tower.

• Log in to the Ansible Tower web interface as admin, or any user with the Admin role on the
organization being modified.

• Click Organizations on the navigation pane.

• Click Permissions for the organization being managed. A list of users who have been granted
roles to the organization displays.

• In the ADD USERS/TEAMS pane, select the check box for the desired user.

• Click SELECT ROLES, and then select the desired organization role for the user. This step can
be repeated multiple times to add multiple roles for a user.

Note
For a list of role definitions, click the KEY button.

DO417-RHAE2.8-en-1-20200106 497
Chapter 11 | Constructing Ansible Tower Workflows

Figure 11.3: Set the roles to assign on Organization

• Click SAVE to assign roles to the user for the organization.

• Click the X symbol preceding to the role to remove existing roles from a user.

Managing Groups of Users with Teams


Teams are groups of users that make managing roles on Ansible tower objects, such as inventories,
projects, and job templates, more efficient than managing them for each user separately. Rather
than assigning the same roles to multiple users, you can assign roles to the team representing a
group of users. Users who are members of a team will inherit the roles assigned to that team.

In Ansible Tower, users exist as objects at a Tower-wide level. A user can have roles in multiple
organizations. A team belongs to only one organization, but an Ansible Tower System
Administrator can assign the team roles on resources that belong to other organizations.

Important
Although a team belongs to a particular organization, you cannot assign
organizational roles to a team, as you can individual users. To manage the
organization object, you must directly assign roles to specific users.

However, you can assign roles to teams that give access to resources that belong to
a particular organization, such as projects, inventories, or job templates.

Creating Teams
The following steps describe how to create teams in an organization.

• Log in to the Ansible Tower web interface as the admin user, or as a user assigned the admin
role for the organization to which the new team will belong.

• Click Teams in the left navigation pane.

• Click +.

• in the New Team pane, enter a name for the new team in the NAME field.

498 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

• Enter a description in the DESCRIPTION field if desired.

• To complete the ORGANIZATION field, click the magnifying glass icon to get a list. In the
SELECT ORGANIZATION pane, select the organization to which the team belongs.

• Click SAVE to create the new team.

Adding Users to a Team


After a team is created, you can add users to the new team. The following steps summarize how to
add users, assigned the Member role, to a team in an organization:

• Log in to the Ansible Tower web interface as the admin user, or a user assigned the admin role
for the organization to which the team belongs.

• Click Organizations on the left navigation pane.

• Click TEAMS under the organization to which the team belongs.

• In the Teams pane, click the name of the team to which to add the user.

• In the team details pane, click USERS.

• Click +.

Figure 11.4: Add a user to a team with the Member role

• In the ADD USERS pane, select one or more users to add to the team. Then, click SAVE to add
the selected users to the team.

Integrating Ansible Tower with Active Directory


You can integrate Ansible Tower with your local Active Directory server. Ansible Tower uses the
LDAP server to authenticate users. Ansible Tower automatically creates an account for each user
that logs in with an LDAP user name and password. Users created in this way cannot change their
username, first name, last name, or set a local password for themselves.

The following steps describe how to integrate Ansible Tower with Active Directory:

• In Active Directory, create a user with read permissions to the entire LDAP structure.

• Log in to the Ansible Tower web interface as the admin user, or as a user assigned the admin
role.

DO417-RHAE2.8-en-1-20200106 499
Chapter 11 | Constructing Ansible Tower Workflows

• Click Settings in the left navigation pane.

• Click Authentication on the SETTINGS page.

• Click LDAP.

• In the LDAP SERVER URI field, enter the LDAP server address to which Ansible Tower will
connect. For example, ldap://demo.example.com:389.

• In the LDAP BIND DN field, enter the Bind DN for the user that you
want Ansible Tower to use to connect to the LDAP server. For example,
CN=demo_user,CN=Users,DC=example,DC=com.

• In the LDAP BIND PASSWORD field, enter the binding user's password.

• From the LDAP GROUP TYPE list, choose the ActiveDirectoryGroupType type.

• In the LDAP USER SEARCH field, enter the pattern for the LDAP user search query. For
Active Directory, use the sAMAccountName=%(user)s) template. For example:

[
"CN=Users,DC=example,DC=com",
"SCOPE_SUBTREE",
"(sAMAccountName=%(user)s)"
]

• In the LDAP GROUP SEARCH field, enter the pattern for the LDAP search query to find
groups. For example:

[
"dc=example,dc=com",
"SCOPE_SUBTREE",
"(objectClass=group)"
]

• In the LDAP USER ATTRIBUTE MAP field, enter the pattern for mapping the LDAP users to
Ansible Tower API user attributes. For example:

{
"first_name": "givenName",
"last_name": "sn",
"email": "mail"
}

• This step is optional, but depending on your environment configuration, you might find it useful.
With this setting, you can map users to Ansible Tower organizations, relative to their LDAP group
membership. In the LDAP ORGANIZATION MAP field, enter the pattern for mapping the
LDAP groups to Ansible Tower organizations. In the below example members of the Domain
Admins group map to the Demo Organization with the admin role, whereas members of the
Users group map to the organization with the Member role:

500 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

{
"Demo Organization": {
"admins": "CN=Domain Admins,CN=Users,DC=example,DC=com",
"users": [
"CN=Users,DC=example,DC=com"
],
"remove_users": true,
"remove_admins": true
}
}

• This step is optional, but depending on your environment configuration, you might find it useful.
With this setting, you can map all Active Directory users as members of a particular team. In the
LDAP TEAM MAP field, enter the pattern for mapping the LDAP users to Ansible Tower teams.
In the below example, all members of the Active Directory that successfully log into Ansible
Ansible Tower are automatically added to the My Demo Team team with a Member role:

{
"My Demo Team": {
"organization": "Demo Organization",
"users": true
}
}

• Click SAVE to save the new settings.

You should now be able to log in to Ansible Tower using a user and password stored in
Active Directory.

References
Ansible Tower User Guide
https://docs.ansible.com/ansible-tower/latest/html/userguide

DO417-RHAE2.8-en-1-20200106 501
Chapter 11 | Constructing Ansible Tower Workflows

Guided Exercise

Managing Users and Teams


In this exercise, you will create and manage users and teams in Red Hat Ansible Tower.

Outcomes
You should be able to create user accounts and teams, and describe the access provided by
different account types.

Before You Begin


Open your RDP client and connect to the Windows workstation system using
example.com as the domain, and student as the user name. Your unique password is
displayed on the Online Lab tab of the ROL interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running and that you can access Ansible Tower
and GitLab from the Windows workstation.

Important
This exercise uses resources created in Chapter 8: Interacting with Users and
Domains; you must complete those exercises before starting this exercise.

1. Access Ansible Tower by double-clicking the Ansible Tower shortcut on your desktop, or
by navigating to https://tower.example.com. Log in using the admin account and
RedHat123@! as the password.

2. Modify the Run tower project job template to run a new job that uses the domain-
users.yml playbook. The playbook populates Active Directory with additional user
accounts. You will use some of these accounts to create users in Ansible Tower.

2.1. In the left navigation pane, click Templates.

2.2. From the list of templates, select the Run tower project template.

2.3. Select the domain-users.yml playbook from the PLAYBOOK list.

2.4. Select the PROMPT ON LAUNCH check box for the LIMIT option.

2.5. Select the PROMPT ON LAUNCH check box for the INVENTORY option.

2.6. Select the PROMPT ON LAUNCH check box for the CREDENTIAL option.

2.7. Click SAVE to update the job template.


Click LAUNCH to begin execution.

2.8. From the RUN TOWER PROJECT window, select Dynamic Inventory, and then
click NEXT.

502 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

2.9. Select the AD Administrator credentials, and then click NEXT.

2.10. In the LIMIT field, type in the windc.example.com hostname. Click NEXT, and then
click LAUNCH.

2.11. Observe the live output of the running job.

2.12. Verify that the status of the job in the DETAILS pane displays Successful.

3. Create a user sam with the Normal User privilege.

3.1. Click Users in the navigation pane.

3.2. Click + to add a new user.

3.3. On the next window, fill in the details as follows:

Field Value

FIRST NAME Sam

LAST NAME Simons

ORGANIZATION Default

EMAIL sam@example.com

USERNAME sam

PASSWORD RedHat123@!

CONFIRM PASSWORD RedHat123@!

USER TYPE Normal User

3.4. Click SAVE to create the user.

4. Verify the permissions for the newly created sam user.

4.1. Click PERMISSIONS to access the user’s permissions.

4.2. As shown, sam is member of the Default organization.

4.3. Click Log Out in the upper right corner to log out, and then log back in as the user sam
and RedHat123@! as the password.

4.4. In the navigation pane, you can see that the user's access is limited because some
options are unavailable.

4.5. Click Users in the navigation pane to manage user permission. The user sam should
not be able to create new users.

4.6. Click the Log Out icon in the upper right corner to log out.

5. Create the user sylvia, as a System Auditor.

5.1. Log back in as the admin user the RedHat123@! password.

5.2. Click Users in the navigation pane to manage users.

DO417-RHAE2.8-en-1-20200106 503
Chapter 11 | Constructing Ansible Tower Workflows

5.3. Click the + button to add a new user.

5.4. On the next window, fill in the details as follows:

Field Value

FIRST NAME Sylvia

LAST NAME Simons

ORGANIZATION Default

EMAIL sylvia@example.com

USERNAME sylvia

PASSWORD RedHat123@!

CONFIRM PASSWORD RedHat123@!

USER TYPE System Auditor

5.5. Click SAVE to create the new user.

6. Verify the permissions for sylvia.

6.1. Click the PERMISSIONS tab to see the user’s permissions.

6.2. As you can see, sylvia has the role of a System Auditor.

6.3. Log out, and then log back in as the user sylvia and RedHat123@! as the password.

6.4. Because sylvia is a system auditor, she has access to all the elements in the Ansible
Tower interface.

6.5. Click Users in the navigation pane to manage users. The user sylvia should not be
able to add new users.

6.6. Click the Log Out icon to log out of the Ansible Tower web interface.

7. Create the user simon with the System Administrator privilege.

7.1. Log in to the Ansible Tower web interface as the admin user with RedHat123@! as the
password.

7.2. Click Users in the navigation pane to manage users.

7.3. Click + to add a new user.

7.4. On the next window, fill in the details as follows:

Field Value

FIRST NAME Simon

LAST NAME Stephens

ORGANIZATION Default

504 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

Field Value

EMAIL simon@example.com

USERNAME simon

PASSWORD RedHat123@!

CONFIRM PASSWORD RedHat123@!

USER TYPE System Administrator

7.5. Click SAVE to create the new user.

8. Verify the permissions for the user simon.

8.1. Click PERMISSIONS to see the user’s permissions. This time, the permissions
frame explicitly reads "SYSTEM ADMINISTRATORS HAVE ACCESS TO ALL
PERMISSIONS".

8.2. Log out, and then log back in as simon with RedHat123@! as the password.

8.3. You can see, the user has access to all the elements in the navigation pane.

8.4. Click Users in the navigation pane to manage users. As you can see, simon has the
rights to create new users.

8.5. Click the Log Out icon to log out of the Ansible Tower web interface.

9. In the following steps, you integrate Ansible Tower with Active Directory.

Important
In your classroom environment, some of the options are already pre-populated.
Normally, all the fields are empty and you will have to populate them with the proper
settings according to your environment configuration.

Log in to the Ansible Tower web interface as the admin user or as a user assigned the
admin role.

9.1. Click Settings in the navigation pane.

9.2. Click Authentication on the SETTINGS page.

9.3. Click LDAP.

9.4. In the LDAP SERVER URI field, enter ldap://windc.example.com:389.

9.5. In the LDAP BIND DN field, enter CN=admin,CN=Users,DC=example,DC=com.

9.6. In the LDAP BIND PASSWORD field, enter the binding user's password of
RedHat123@!.

9.7. From the LDAP GROUP TYPE list, select the ActiveDirectoryGroupType type.

9.8. In the LDAP USER SEARCH field, enter the pattern for the LDAP user search query.

DO417-RHAE2.8-en-1-20200106 505
Chapter 11 | Constructing Ansible Tower Workflows

[
"CN=Users,DC=example,DC=com",
"SCOPE_SUBTREE",
"(sAMAccountName=%(user)s)"
]

9.9. In the LDAP GROUP SEARCH field, enter the pattern for the LDAP search query to
find groups.

[
"CN=Builtin,dc=example,dc=com",
"SCOPE_SUBTREE",
"(objectClass=group)"
]

9.10.In the LDAP USER ATTRIBUTE MAP field, enter the pattern for mapping the LDAP
users to Ansible Tower API user attributes.

{
"first_name": "givenName",
"last_name": "sn",
"email": "mail"
}

9.11. Clear the LDAP GROUP TYPE PARAMETERS field, so that it contains only {}.

{}

9.12. In the LDAP ORGANIZATION MAP field, enter the pattern for mapping the LDAP
groups to Ansible Tower organizations.

{
"Default": {
"admins": "CN=Administrators,CN=Builtin,DC=example,DC=com",
"users": false,
"remove_admins": true
}
}

9.13. In the LDAP TEAM MAP field, enter the pattern for mapping the LDAP users to
Ansible Tower teams.

{
"Developers": {
"organization": "Default",
"users": true
}
}

9.14.Click SAVE to save the new settings.

506 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

You can now log in to Ansible Tower using a user and password stored in
Active Directory.

9.15. Click the Log Out icon to log out of the Ansible Tower web interface.

10. Log in to Ansible Tower as the Active Directory user robert and RedHat123@! as the
password. With the LDAP integration that you have configured, Ansible Tower automatically
assigns this user the admin role, based on his Active Directory group membership.

10.1. Log in to the Ansible Tower web interface as the robert user and RedHat123@! as
the password.
You can see, the user has access to all the elements in the navigation pane.

10.2.Click the user robert to access the account details for this user.
Notice that Ansible automatically creates the user when first logged in, based on the
Active Directory integration and the proper LDAP group membership mapping.

10.3.Click PERMISSIONS to see the user’s permissions.

Notice that the user has the admin role for the Default organization, becuase
this user is member of the Administrators group in Active Directory. When the
user robert logged in for the first time, Ansible Tower created a new team called
Developers. This user was added to the team and assigned the role of Member. The
team creation and user assignment are based on the user's membership in the Domain
Users Active Directory group, whose members are mapped automatically as members
of the Developers team.

10.4.Click Users in the navigation pane to manage users. As you can see, robert has the
rights to create new users.

11. Create a new Devops team.

11.1. Click Teams in the navigation pane to manage teams.

DO417-RHAE2.8-en-1-20200106 507
Chapter 11 | Constructing Ansible Tower Workflows

11.2. Click + to add a new team.

11.3. On the next window, complete the details as follows:

Field Value

NAME Devops

DESCRIPTION Devops Team

ORGANIZATION Default

11.4. Click SAVE to create the new team.

12. Add an existing user as a member to the Devops team.

12.1. On the Devops team details page, click USERS.

12.2. Click + to add a new users to the team.

12.3. Select sylvia

12.4. Click SAVE.


Notice that sylvia has a new Member role. This means that she is now a System
Auditor, and is also a member of the Devops team.

12.5. Click the Log Out icon to log out.

13. Log in to Ansible Tower as the Active Directory user david and RedHat123@! as the
password. Ansible Tower automatically assigns this user the normal user role, based on
his Active Directory group membership.

13.1. Log in to the Ansible Tower web interface as the david user with RedHat123@! as the
password.
As you can see, this user has limited access to Ansible Tower elements in the navigation
pane.

13.2. Click david to access the user account details.


Notice that Ansible Tower automatically creates the user upon first login, based on the
Active Directory integration and the proper LDAP group membership mapping.

13.3. Click PERMISSIONS to review the user’s permissions.


Notice that the user has only the Member role in the Developers team, based on
membership in the Domain Users Active Directory group.

13.4. Click Users in the navigation pane to manage users. The user david should not be
able to create new users.

14. Click the Log Out icon in the top right corner to log out.

This concludes the guided exercise.

508 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

Creating and Using Surveys

Objectives
After completing this section, you should be able to create a survey to make it simple for users to
launch jobs with Red Hat Ansible Tower.

Managing Variables
Writing playbooks that you can reuse in different situations, or for different systems, is
recommended. These systems might require slightly different behaviors, configurations, or work
in different environments. One easy way to deal with this variation is to use variables that you can
override when you run your plays.

You can set values for variables in several ways in Ansible, and you can override values if they are
properly set up. For example, a role provides a default value for a variable that can be overridden
by values set for that variable in an inventory or by a playbook. In general, it is best to set a value
for a variable in exactly one place to avoid issues with variable precedence.

In Ansible Tower, job templates can set extra variables and prompt users for a value when
launching a Job Template, or they may be set automatically by rerunning a job that was launched
with extra variables. Ansible Tower does not support playbooks with vars_prompt questions; the
closest replacement is surveys, which are discussed further in this section.

Important
Ansible Tower does not support playbooks that use vars_prompt to interactively
set variables.

Defining Extra Variables


In Ansible Tower, you can use job templates to set extra variables in one of two ways:

• Set extra variables by entering them in YAML or JSON format in the EXTRA VARIABLES field
of the Job Template.

• Select the PROMPT ON LAUNCH option on the EXTRA VARIABLES field; Ansible Tower
prompts users to interactively modify the list of extra variables to use before running a job.

The following example demonstrates setting extra variables in the job template:

DO417-RHAE2.8-en-1-20200106 509
Chapter 11 | Constructing Ansible Tower Workflows

Figure 11.7: Adding extra variables to a job template

If you select the PROMPT ON LAUNCH option on the EXTRA VARIABLES field, then a window
displays to edit the variables when you launch a job from a job template.

Figure 11.8: Adjusting extra variables on job launch

510 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

If you relaunch the resulting job, the job reuses the same extra variables. You cannot modify the
extra variables of a job when it is rerun. To modify the extra variables, launch the job from the
original job templates and use different values for the variables.

Setting Extra Variables with Surveys


It can be difficult to use extra variables because the user launching the job must understand
the available variables, and how playbooks associated with the job template use them. Surveys
configure the job template to display a short form before running, which prompts you for
information that sets the value for the extra variables.

Prompting for user input offers several advantages over other ways to set extra variables. No
detailed knowledge about how extra variables work, or the names of the extra variables that
playbooks use, is necessary. The user might not even know that extra variables are used in the job
template.

Because prompts can contain arbitrary text, they can be phrased in user-friendly language that is
easily understood, even if users lack detailed knowledge about Ansible.

Important
Surveys set extra variables. The values set for variables using a survey override the
values set on variables of the same name in any other way. This includes the EXTRA
VARIABLES field and PROMPT ON LAUNCH option set on the job template.

Some of the things that you can configure in a survey include:

User-friendly Questions
Surveys can prompt users for input using customized questions. This allows for more user-
friendly prompts for user input of extra variable values than the PROMPT ON LAUNCH
method.

Answer Type
Aside from offering a user-friendly prompt, surveys can also define rules for, and perform
validation of, user inputs. User responses to survey questions can be limited to one of the
following seven answer types:

Type Description

Text Single-line text

Textarea Multiline text

Password Data is treated as sensitive information.

Multiple Choice (single select) A list of options from which users can only
choose one option as a response.

Multiple Choice (multiple select) A list of options from which users can
choose one or more options as a response.

Integer Integer number

Float Floating-point decimal number

DO417-RHAE2.8-en-1-20200106 511
Chapter 11 | Constructing Ansible Tower Workflows

Answer Length
You can also define rules for the size of user responses to survey questions. For the following
answer types, a survey can define the minimum and maximum allowable character length for
user responses: Text, Textarea, Password, Integer, and Float.

Default Answer
You can provide a default answer for a question. The question can also be marked as
REQUIRED, which indicates that the users must provide an answer to the question.

Creating a Survey
You cannot add a survey when creating a job template. Add a survey to a job template after
creating the job template.

Figure 11.9 illustrates how to add a survey to an existing job template.

1. Click Templates in navigation pane to see a list of existing job templates.

2. Click the desired job template to edit it.

3. Click ADD SURVEY to enter the survey creation interface.

4. Add a question to the survey.

1. In the PROMPT field, enter the question to to display to the user.

2. In the ANSWER VARIABLE NAME field, enter the name of the extra variable to
which the user's response is assigned.

3. From the ANSWER TYPE list, select the desired answer type for the user's response.

4. If using a multiple choice answer type, then define the list by entering one list item per
line in the MULTIPLE CHOICE OPTIONS field.

5. If using any answer type other than multiple choice, optionally specify the minimum
and maximum character length for the user's response in the MINIMUM LENGTH
and MAXIMUM LENGTH fields, respectively.

6. If desired, optionally define a default value for the extra variable being surveyed in the
DEFAULT ANSWER field. Ansible Tower uses this value if the user does not provide a
response.

7. Select REQUIRED to specify that a response is mandatory. Clear this field if a


response is optional.

8. Click +ADD to add the question to the Survey. A preview of the new question appears
in the PREVIEW panel.

5. Repeat the preceding steps to add additional questions to the survey. After you have added
all if your questions, scroll to the top of the window. A switch in the upper-left, next to
SURVEY, determines whether the survey is enabled or disabled. By default, surveys are
enabled upon creation, so the switch is in the ON position. To disable the survey, toggle the
switch to the OFF position.

6. Click SAVE to save the survey.

512 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

Figure 11.9: Adding Surveys to a job template

After adding a survey to a job template, users are prompted for answers to the survey questions
when they launch jobs with that job template. If the job template has extra variables, or is
configured to prompt the user to set extra variables, then these values are set before the survey
is displayed to the user. Answers to the survey questions override any extra variables that were
already set.

Figure 11.10: Survey Prompt

References
Ansible Tower User Guide
https://docs.ansible.com/ansible-tower/latest/html/userguide

DO417-RHAE2.8-en-1-20200106 513
Chapter 11 | Constructing Ansible Tower Workflows

Guided Exercise

Creating and Using Surveys


In this exercise, you will create a new survey for a job template in Red Hat Ansible Tower, and
then use it to launch jobs.

Outcomes
You will be able to add a survey to an existing job template and launch a job using a survey
from the Ansible Tower web UI.

Before You Begin


Open your RDP client and connect to the Windows workstation system using
example.com as the domain, and student as the user name. Your unique password is
displayed on the Online Lab tab of the ROL interface.

Important
This exercise uses resources created in Chapter 8: Interacting with Users and
Domains; you must complete those exercises before starting this exercise.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. Launch the Visual Studio Code editor, and then clone the tower repository to your
workstation instance.

1.1. Click Search Windows, search for code, and then open Visual Studio Code.

1.2. Navigate to View → Command Palette or press Ctrl+Shift+P to open the


command palette.
Type clone and select Git: Clone to clone a repository.
Use a repository URL of https://gitlab.example.com/student/tower.git.
When prompted, select the Documents folder in the home directory of the training
user as the repository location. This clones the remote repository in to the tower
folder.
To view the files, click Open in the dialog that displays after cloning.

2. Edit the index.html.j2 file in the templates folder; modify this file so that it uses
variables to generate the index.html file. After making the changes, commit and push
the changes to the master branch.

2.1. Go to the templates directory, located at the top-level. Select the index.html.j2
file, then change the file as follows:

514 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

...output omitted...
<h2 style="color: #2e6c80;">This page has been provisioned by {{ student_name }}
using Ansible on the {{ ansible_facts['hostname'] }} host>/h2>
<h2 style="color: #2e6c80;">This page version is {{ version }}>/h2>

2.2. Click Save. Note the status icons in the lower left corner. There is an asterisk next to
Master that indicates that changes have been made.

2.3. Change to the Source Control view, and then click + for index.html.j2 to stage
the changes.

2.4. Enter a commit message, and then press Ctrl+Enter to commit the changes.

2.5. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to
push your local changes to the remote repository, and retrieve any new changes from
the repository.

3. Add a survey to the Run tower project job template. This survey will collect values for
the variables needed to generate the index.html file.

3.1. Log in to Ansible Tower. Click Templates on the navigation pane.

3.2. In the list of available templates, click Run tower project to edit the job template.

3.3. Click ADD SURVEY to add a survey.

3.4. On the next window, fill in the details as follows:

Field Value

PROMPT What version are you deploying?

DESCRIPTION This is the page version

ANSWER VARIABLE NAME version

ANSWER TYPE Text

MINIMUM LENGTH 1

MAXIMUM LENGTH 40

REQUIRED Checked

3.5. Click +ADD to add this prompt to the survey, and then display a preview of the survey.

3.6. Add another question to the survey, filling in the details as follows:

Field Value

PROMPT What is your name?

DESCRIPTION This is the page owner

DO417-RHAE2.8-en-1-20200106 515
Chapter 11 | Constructing Ansible Tower Workflows

Field Value

ANSWER VARIABLE NAME student_name

ANSWER TYPE Text

MINIMUM LENGTH 1

MAXIMUM LENGTH 40

REQUIRED Checked

3.7. Click +ADD to add this prompt to the survey, and then display a preview of the survey.

Important
Before saving, make sure that the Survey toggle switch is set to ON at the top of the
Survey editor window.

3.8. Click SAVE to add the Survey to the job template.

3.9. Click SAVE to update the job template.

4. Run the Run tower project job to test your Jinja template and the survey.

4.1. In the navigation pane, click Templates.

4.2. From the list of templates, select the Run tower project template.

Note
To select a project for editing, click its name.

4.3. Select the manage.yml playbook from the PLAYBOOK list.

4.4. Select the PROMPT ON LAUNCH check box for the LIMIT option if not already
selected.

4.5. If selected, clear the PROMPT ON LAUNCH check box for both the CREDENTIAL
and the INVENTORY options.

4.6. In the INVENTORY option, choose Dynamic inventory.

4.7. In the CREDENTIAL option, choose AD Administrator.

4.8. Click SAVE to update the job template.


Click LAUNCH to begin execution.

4.9. In the RUN TOWER PROJECT window, type in the win2.example.com hostname.
Click NEXT.

4.10.In the WHAT VERSION ARE YOU DEPLOYING? field, type 1.0 as the value. In the
WHAT IS YOUR NAME? field, type in your name. Click NEXT, followed by LAUNCH.

4.11. Observe the live output of the running job. The status of the job changes after the
server successfully restarts.

516 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

4.12. Verify that the job status in the DETAILS pane displays Successful.

5. From workstation, open Chrome and access http://win2.example.com:8080.


Ensure that the home page matches the following:

Notice the page version number and your name as the page creator.

6. Rerun the Run tower project job, this time with different version number value.

6.1. In Ansible Tower, click Templates from the navigation pane.

6.2. From the list of templates, select the rocket icon of the Run tower project
template.

6.3. In the RUN TOWER PROJECT window, type in the win2.example.com hostname.
Click NEXT.

6.4. In the WHAT VERSION ARE YOU DEPLOYING? field, type 1.5 as the value. In the
WHAT IS YOUR NAME? field, type in your name. Click NEXT followed by LAUNCH.

6.5. Observe the live output of the running job. The status of the job changes after the
server successfully restarts.

6.6. Verify that the job status in the DETAILS pane displays Successful.

7. Open Chrome and access http://win2.example.com:8080. Ensure that the home


page matches the following:

DO417-RHAE2.8-en-1-20200106 517
Chapter 11 | Constructing Ansible Tower Workflows

Notice the new page version value.

8. Edit the Run tower project job template to turn off the survey.

8.1. In Ansible Tower, access the job templates from the navigation pane.

8.2. From the list of templates, select Run tower project.

8.3. Click EDIT SURVEY.

8.4. At the top of the survey editor window, toggle the Survey switch and set it to the OFF
position.

8.5. Click SAVE to update the survey.

9. Click Log Out to log out of Ansible Tower

This concludes the guided exercise.

518 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

Scheduling Job Launches

Objectives
After completing this section, you should be able to schedule automatic execution of a job
template in Red Hat Ansible Tower.

Scheduling Job Execution


Sometimes you might want to launch a job template automatically at a particular time, or on a
particular schedule. Red Hat Ansible Tower lets you configure scheduled jobs, which launch job
templates on a customizable schedule.

If you have the Execute role on a job template, then you can launch jobs from that template using
a schedule. To configure scheduled jobs, first select Templates from the navigation pane. Click
the job template that you want to schedule, and then click SCHEDULES. Click + to create a new
schedule for that job template.

Figure 11.13: Scheduling Job execution

Enter the required details:

• NAME: The name of the schedule.

• START DATE: The date the job schedule should start.

• START TIME: The time the associated job will be launched.

• LOCAL TIME ZONE: Run the Get-TimeZone PowerShell command to determine your local
time zone.

• REPEAT FREQUENCY: How often to repeat the job that the schedule manages. You can
choose None (run once), Minute, Hour, Day, Week, Month, or Year.

DO417-RHAE2.8-en-1-20200106 519
Chapter 11 | Constructing Ansible Tower Workflows

Depending on the chosen frequency, you might need to provide additional information, such as
launching a job every two days, or on the first Sunday of every month.

When finished, click SAVE to save the schedule. You can deactivate or activate a schedule using
the Survey ON/OFF toggle switch next to the schedule name.

Temporarily Disabling a Schedule


Click Schedules in the navigation pane to display the Scheduled Jobs pane. This pane lists all
the defined schedules. To the left of each schedule name is an ON/OFF toggle switch. Toggle the
switch ON or OFF to activate or deactivate the schedule, respectively.

You can also edit or delete any schedule from this pane, assuming you have sufficient privileges to
do so..

Scheduled Management Jobs


Red Hat Ansible Tower includes two special scheduled jobs by default. These two schedules are for
built-in Management Jobs that perform periodic maintenance on the Ansible Tower server; these
jobs clean up old log information for the activity stream, and historic job execution.

Cleanup Job Schedule deletes the details of historic jobs to save space. This job runs once
a week on Sundays to remove information about jobs more than 120 days old by default. You
can change edit the schedule to adjust the day or frequency of the job, and the data it keeps or
removes.

Cleanup Activity Schedule runs once a week on Tuesdays to remove information from the
activity stream that is more than 355 days old. Again, you can edit the schedule to change when
the job runs, and how much data it keeps.

References
Ansible Tower User Guide
https://docs.ansible.com/ansible-tower/latest/html/userguide

520 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

Guided Exercise

Scheduling Job Launches


In this exercise, you will schedule a job template to launch automatically on a recurring
schedule.

Outcomes
You should be able to schedule a job template to launch automatically.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

Important
This exercise uses resources created in Chapter 8: Interacting with Users and
Domains; you must complete those exercises before starting this exercise.

1. Add a schedule to the Run tower project job template that configures it to run at three
minutes from the current time. Use the win1.example.com host.
Access Ansible Tower using the Ansible Tower shortcut on your desktop, or navigate to
https://tower.example.com. Log in using the admin account and RedHat123@! as
the password.

2. In the navigation pane, click Templates.

3. From the list of templates, select Run tower project.

4. Select the facts.yml playbook from the PLAYBOOK list.

5. Ensure that the PROMPT ON LAUNCH option is cleared for the LIMIT, INVENTORY,
and CREDENTIAL fields.
Select the Default inventory from the INVENTORY field. In the LIMIT field, enter
the win1.example.com as the host name. Ensure that the DevOps credential is set in the
CREDENTIAL field.

6. Click SAVE to update the job template.

7. Click SCHEDULES to manage automatic execution of a job based on this job template.

DO417-RHAE2.8-en-1-20200106 521
Chapter 11 | Constructing Ansible Tower Workflows

8. Click + to add a new schedule.

9. On the next screen, complete the details as follows:

Field Value

NAME Automatic job run

START DATE Look at the current date on workstation, and set the
execution of the job to today's date.

START TIME Look at the current time on workstation, and set the
execution of the job to +3 minutes from the current time.

REPEAT FREQUENCY Choose Hour

FREQUENCY DETAILS • Every hour

• End after five occurrences

Note
The start time uses a 24-hour clock notation, for example, enter 18:00 to indicate 6
p.m.

10. Click SAVE to create the new schedule.

Note
To save the schedule, you must turn off the survey. If you did not disable the survey
in the preceding exercise, go back and follow the steps to turn the survey off.

522 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

11. Click Jobs in the navigation bar and wait for the scheduled jobs to run.

This concludes the guided exercise.

DO417-RHAE2.8-en-1-20200106 523
Chapter 11 | Constructing Ansible Tower Workflows

Running Complex Workflows

Objectives
After completing this section, you will be able to create a sequence of job templates to execute
using workflows and workflow job templates in Red Hat Ansible Tower.

Workflow Job Templates


In a previous section, you learned how to use job templates to run a single Ansible Playbook as
a job. As Ansible usage in an organization grows, the number of Ansible Playbooks it has also
grows. To manage complexity as the number of users and playbooks increases, playbooks typically
perform a set of tasks associated with a particular function. Instead of writing one large playbook
to automate a complex operation, consider running several playbooks in sequence.

Instead of writing one large playbook to automate a complex operation, consider running several
playbooks in sequence. For example, to provision a server you might want to use a playbook from
the Networking team to allocate an IP address to the server and set up a DNS record, and then
use a separate playbook from the Operations team to install and configure the server operating
system. Finally, you could use a playbook from the Development team to deploy an application. In
other words, there is a particular workflow that you must follow for the process to succeed.

To manage this workflow in Ansible Tower, users can manually launch multiple jobs in sequence.
However, the jobs must execute in the correct order for everything to work correctly, as defined by
your workflow:

1. Networking jobs must be executed first.

2. Operations jobs follow, but only if the networking jobs successfully complete.

3. Likewise, application development jobs follow operations jobs only if the networking and
operations jobs successfully complete.

Finally, if one of these playbooks fails, users might need to run other playbooks to recover.

To make this workflow easier to manage, Red Hat Ansible Tower supports Workflow Job Templates.
A workflow job template connects multiple job templates in a workflow. When launched, the
workflow job template starts a job using the first job template; whether the job succeeds or fails
determines which job template to launch next. This allows a sequence of jobs to run, and for
recovery steps to automatically run if a job fails.

You can start workflow job templates in several ways: manually, from the Ansible Tower web UI; as a
scheduled job; or using the Ansible Tower API with an external program.

Workflow job templates do not just serially run job templates. Using the graphical workflow editor,
workflow job templates chain together multiple job templates and run different job templates
depending on whether the preceding job succeeds or fails.

Creating Workflow Job Templates


You must create a workflow job template before you can define a workflow or associate it to the
workflow job template. Workflow job templates can be created with or without an organization.

524 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

Creating a workflow job template within the context of an organization requires the admin role for
the organization. Creating a workflow job template that is not part of an organization requires a
user with the singleton System Administrator user type.

Figure 11.15: Creating a workflow job template in Ansible Tower

Creating workflow job templates is similar to creating job templates.

1. Click Templates in the navigation pane to access the template management interface.

2. Click +, and then select Workflow Template.

3. Enter a unique name for the workflow job template in the NAME field. Optionally, enter any
desired key-value pairs in the EXTRA VARIABLES field.

4. Click SAVE to create the workflow job template. After the workflow job template is created,
use the workflow visualizer to define and associate a workflow.

Using the Workflow Visualizer


After creating a workflow job template, the WORKFLOW VISUALIZER becomes active in the
workflow job template editing screen. The workflow editor opens in a new window. The workflow
visualizer is a graphical interface for defining the job templates to incorporate in a workflow, as well
as the decision tree structure, which is used to chain job templates together.

Figure 11.16: Starting a workflow in the workflow visualizer

DO417-RHAE2.8-en-1-20200106 525
Chapter 11 | Constructing Ansible Tower Workflows

When you launch the workflow visualizer, it contains a single START node representing the starting
point for the execution of the workflow. Click START to initiate the workflow editing process; the
workflow visualizer displays a list of Ansible Tower resources that you can add as the first step of
the workflow. Select the desired resource type, the specific resource, and then click SELECT to
add the selected Ansible Tower resource as the first node.

In addition to job templates, you can also incorporate jobs that synchronize projects or inventories
into your workflow. This is useful to ensure that Ansible Tower updates projects and inventory
resources before starting the job templates that depend on them . To make these jobs easier to
identify in the workflow, project synchronization and inventory synchronization nodes are indicated
by a P or an I symbol respectively, which is displayed in the lower left corner of the node. This
notation is explained by the key at the top of the workflow editor screen. Job template nodes are
not marked with any special notation because they are the main node type in a workflow.

Figure 11.17: Adding an 'On Success' node to the workflow

After adding a resource as the first workflow node, hovering over it causes two buttons to appear.
The red - button deletes the node, and the green + button adds a subsequent node. When adding
subsequent nodes, the RUN prompt appears in the resource selection panel, prompting for
additional input when you select a resource. The following three choices are offered by this prompt
to designate the relationship between the new node and the preceding node.

RUN Node Relationship

On Success Ansible Tower executes this node resource upon successful completion
of the actions associated with the previous node.

On Failure Ansible Tower executes this node resource upon failure of the actions
associated with the previous node.

Always Ansible Tower executes this node resource regardless of the outcome
of the actions associated with the previous node.

A node can have more than one child node. You can add a child node with a parent node
association type of On Success, and then add another child node with an association type of On
Failure. This creates a branch in the workflow structure, such that one course of action is taken
upon the success of an action, and a different course is taken upon failure.

526 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

Figure 11.18: Adding multiple child nodes to the workflow

As you add nodes to a workflow, differently colored lines connecting the nodes in the Workflow
Editor indicate the relationships between parent and child nodes. A green line indicates an On
Success type relationship between a parent and child node, and a red line indicates an On Failure
type relationship. A blue line indicates an Always type relationship.

Figure 11.19: Workflow node relationships

After creating the entire decision tree structure of the workflow in the Workflow Editor, click SAVE
to save the workflow.

Surveys
Workflow job templates have access to many of the features that were discussed in previous
chapters for job templates. Like job templates, you can add surveys to workflow job templates to
allow users to interactively set extra variables.

DO417-RHAE2.8-en-1-20200106 527
Chapter 11 | Constructing Ansible Tower Workflows

Note
When a survey is added to a workflow job template, every job executed by the
workflow can access the resulting extra variables.

Launching Workflow Jobs


Like job templates, users need the execute role on the workflow job template to execute it. When
assigned the execute role, a user can launch a job through a workflow job template, even if they
do not have permissions to independently launch the job templates it uses.

Launching a workflow job template is similar to launching a job template, as illustrated in the
following:

1. Click Templates in the navigation pane to access the template management interface.

2. Click the rocket icon for the workflow job template to launch the job.

Evaluating Workflow Job Execution


After launching a workflow job, Ansible Tower displays the job details page for the executing job.
This page has two panes: the DETAILS pane displays details of the workflow job execution, and
the workflow progress pane displays the progress of the job through the steps in the workflow.

As each step is completed, its node is outlined in either green or red, indicating the success or
failure of the actions associated with that step in the workflow. Progressions from one step to
another are represented by colored lines that indicate the decision responsible for the progression.
Green indicates an On Success progression, and red indicates an On Failure progression. Blue
indicates an Always progression.

Figure 11.20: Workflow job progress

Details of the workflow job run can be displayed either during or after execution. Click the
DETAILS link for each node in the workflow diagram, to display details about a currently running
job or a completed job. Click this link to display the results and standard output for the job run.

528 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

References
Ansible Tower User Guide
https://docs.ansible.com/ansible-tower/latest/html/userguide/

DO417-RHAE2.8-en-1-20200106 529
Chapter 11 | Constructing Ansible Tower Workflows

Guided Exercise

Running Complex Workflows


In this exercise, you will create a workflow job template that will run various playbooks,
depending on whether the preceding playbooks successfully completed or reported failures.

Outcomes
You should be able to create a workflow job template and launch a workflow from the Ansible
Tower web UI.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

Important
This exercise uses resources created in Chapter 8: Interacting with Users and
Domains; you must complete those exercises before starting this exercise.

1. Access Ansible Tower using the Ansible Tower shortcut on your desktop, or navigate to
https://tower.example.com. Log in using the admin account and RedHat123@! as
the password.

2. Run the prepare.yml playbook from the Run tower project job template.

2.1. In the navigation pane, click Templates.

2.2. Click the Run tower project job template to open it.

2.3. Select the prepare.yml playbook from the PLAYBOOK list.

2.4. Make sure that the PROMPT ON LAUNCH check box for the LIMIT option is cleared
and the text field is blank.

2.5. Make sure that the PROMPT ON LAUNCH check box for the CREDENTIAL option is
cleared. From the list of available credentials choose AD Administrator .

2.6. Make sure that the PROMPT ON LAUNCH check box of the INVENTORY option is
cleared. From the list of available inventories, choose Dynamic Inventory.

2.7. Click SAVE to update the template, and then click LAUNCH to run the job.

530 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

3. Modify the existing Run tower project job template. Limit the job template to only
run on win2.example.com, using the AD Administrator credentials, the Dynamic
inventory, and the manage.yml playbook.

3.1. In the navigation pane, click Templates.

3.2. From the list of templates, select Run tower project.

3.3. Select the manage.yml playbook from the PLAYBOOK list.

3.4. In the LIMIT field, enter the win2.example.com host name.

3.5. Click SAVE to update the job template.

4. Create a new Deploy the web page workflow job template.

4.1. Click Templates in the navigation pane.

4.2. Click + to add a new workflow job template.

4.3. Select Workflow Template from the list.

4.4. On the next window, complete the details as follows:

Field Value

NAME Deploy the web page

DESCRIPTION Deploy the web page workflow

ORGANIZATION Default

4.5. Click SAVE to create the new workflow job template.

5. Configure the workflow of the Deploy the web page workflow job template.

5.1. The WORKFLOW VISUALIZER window opens automatically.

5.2. Click START to add the first action. This displays a list of available actions in the ADD
A NODE panel.

5.3. Click PROJECT SYNC to display the list of projects available.

5.4. Select tower repository and click SELECT. This links the START node with a blue
line (always perform) to the node project node, tower repository, in the Workflow
Visualizer window.

5.5. Move your mouse over the new node and click + to add an action following the project
synchronization of the tower repository. This displays a list of available actions in
the ADD A NODE panel.

5.6. Click PROJECT SYNC to display the list of projects available.

5.7. Select broken repository, and then click SELECT. This links the node for the
tower repository project to a new node for the broken repository project
synchronization in the Workflow Visualizer window. The green link indicates that the
progression only takes place upon success of the preceding node.

DO417-RHAE2.8-en-1-20200106 531
Chapter 11 | Constructing Ansible Tower Workflows

5.8. Move your mouse over the new node and click + to add an action after the project
synchronization of broken repository. This displays a list of actions to be
performed.

5.9. Click JOBS if not already there, and then select the Run tower project job
template.

5.10. Select On Success from the RUN list, and then click SELECT. This links the node
for the broken repository project to a new node for the Run tower project
job template in the workflow visualizer window. The green link indicates that the
progression only takes place upon success of the preceding node.

5.11. Move your mouse over the broken repository node and click + to add an action
after the project synchronization of broken repository. This displays a list of
actions to be performed. This time, you will add a node to execute if the broken
repository project synchronization node fails.

5.12. Click JOBS if not already there, and then select the Clean win2 job template.

5.13. Select On Failure from the RUN list, and then click SELECT. This links the node for
the broken repository project to a new node for the Clean win2 job template in
the workflow visualizer window. The red link indicates that the progression only takes
place upon failure of the preceding node.

5.14. Click SAVE to save the workflow.


After the editor closes, click SAVE one more time to save the job template.

6. Launch a job using the Deploy the web page workflow job template.

6.1. Click Templates in the navigation pane.

6.2. Click the rocket icon for the Deploy the web page workflow job template, to launch
the workflow. This redirects you to a detailed status page for the running workflow.

6.3. Observe the running jobs in the workflow. Click DETAILS for each running job to see
more detailed output.

6.4. Notice that the broken repository node is marked red, and the Clean win2 node
runs. The red border around the broken repository node indicates that the job
associated with that node failed; based on the workflow logic the Clean win2 node
executes and successfully finishes.

6.5. Verify that the status of the workflow in the DETAILS pane displays Successful.

7. Fix the issue in the broken repository project, and then execute the workflow again.
Observe how the workflow logic executes a different selection of nodes based on the
successful execution of each node in the workflow.

7.1. Click Projects in the navigation pane.

7.2. Click the broken repository project.

7.3. In the SCM URL field, enter the url for synchronizing the repository, https://
gitlab.example.com/student/windows.git.

7.4. Click SAVE to save the changes.

532 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

8. Workflows can use surveys to assign values to existing variables. Add a survey to the
Deploy the web page workflow.

8.1. Add a survey to the Deploy the web pag workflow. This survey will collect values
for the variables needed to generate the index.html file.

8.2. Click Templates in the navigation pane.

8.3. In the list of available templates, click Deploy the web page to edit the workflow
template.

8.4. Click ADD SURVEY to add a survey.

8.5. On the next window, complete the details as follows:

Field Value

PROMPT What version are you deploying?

DESCRIPTION This is the page version

ANSWER VARIABLE NAME version

ANSWER TYPE Text

MINIMUM LENGTH 1

MAXIMUM LENGTH 40

REQUIRED Selected

8.6. Click +ADD to add this survey prompt to the survey. This displays a preview of the
survey.

8.7. Add another question to the survey, completing the details as follows:

Field Value

PROMPT What is your name?

DESCRIPTION This is the page owner

ANSWER VARIABLE NAME student_name

ANSWER TYPE Text

MINIMUM LENGTH 1

MAXIMUM LENGTH 40

REQUIRED Selected

8.8. Click +ADD to add this prompt to the Survey. This displays a preview of the Survey.

Important
Before saving, make sure that the ON/OFF toggle switch is set to ON.

DO417-RHAE2.8-en-1-20200106 533
Chapter 11 | Constructing Ansible Tower Workflows

8.9. Click SAVE to add the survey to the job template.

8.10.Click SAVE to update the job template.

9. Launch the modified workflow with the survey, and verify the successful execution of each
of the nodes. Click Templates in the navigation pane.

9.1. Click the rocket icon for the Deploy the web page workflow template to launch the
workflow.

9.2. A DEPLOY THE WEB PAGE window displays. In the WHAT VERSION ARE YOU
DEPLOYING? field, type 3.0. In the WHAT IS YOUR NAME? field, type in your
name. Click NEXT, and then click LAUNCH.

9.3. Observe the running jobs of the workflow. Click DETAILS for each running job to see a
more detailed output. All the workflow nodes should complete their jobs successfully.

9.4. Verify that the workflow status displayed in the DETAILS pane is Successful.

10. Open Chrome, and then access http://win2.example.com:8080 . The new webpage
is deployed using your workflow, including all the data provided by the survey.

11. Click the Log Out icon to log out of Ansible Tower

This concludes the guided exercise.

534 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

Lab

Constructing Ansible Tower Workflows


Performance Checklist
In this lab, you will add users and teams, and create and use surveys associated with a new
workflow.

Outcomes
You should be able to:

• Add two new users.

• Create a new team.

• Create a new workflow.

• Add a survey to the workflow, and execute the workflow.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. Add two users as Normal Users to the Default organization with the following information:

User 1 User 2

FIRST NAME Adam Ophelia

LAST NAME Brilliant Dunham

ORGANIZATION Default Default

EMAIL adam@example.com ophelia@example.com

USERNAME adam ophelia

PASSWORD RedHat123@! RedHat123@!

CONFIRM PASSWORD RedHat123@! RedHat123@!

2. Create an Operations team in the Default organization.


3. Add adam and ophelia to the Operations team.

DO417-RHAE2.8-en-1-20200106 535
Chapter 11 | Constructing Ansible Tower Workflows

4. Copy the existing Run tower project job template and name it TEST webservers
setup.
Use the following details to modify the new job template:

Field Value

NAME TEST webservers setup

INVENTORY Dynamic inventory

CREDENTIAL AD Administrator

PROJECT tower repository

PLAYBOOK manage.yml

LIMIT win2.example.com

5. Copy the existing Run tower project job template and give it the name PROD
webservers setup.
Use the following details to modify the copied job template:

Field Value

NAME PROD webservers setup

INVENTORY Dynamic inventory

CREDENTIAL AD Administrator

PROJECT tower repository

PLAYBOOK manage.yml

LIMIT windc.example.com

6. Create a new From Test to Prod workflow job template using the following details:

Field Value

NAME From Test to Prod

DESCRIPTION Deploy to Test and on success deploy to Prod

ORGANIZATION Default

7. Configure the From Test to Prod workflow job template so that it contains the following
steps:

• Synchronize the tower repository project.

• Upon success of the previous step, launch the TEST webservers setup job template.

• Upon success of the previous step, launch the PROD webservers setup job template.

536 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

8. Add a Survey containing the following information to the From Test to Prod workflow job
template. Make sure this is a required survey.

Field Value

PROMPT What version are you deploying?

DESCRIPTION This version number will be displayed at the


bottom of the index page.

ANSWER VARIABLE NAME version

ANSWER TYPE Text

MINIMUM LENGTH 1

MAXIMUM LENGTH 40

Add a second question to the survey with the following details:

Field Value

PROMPT What is your name?

DESCRIPTION This is the page owner

ANSWER VARIABLE NAME student_name

ANSWER TYPE Text

MINIMUM LENGTH 1

MAXIMUM LENGTH 40

9. Launch a workflow using the From Test to Prod workflow job template. When prompted
by the survey, enter v1.3 for the page version and your name.
10. Verify that the web servers have been updated: win2.example.com,
windc.example.com. Open Chrome and access http://win2.example.com:8080 and
http://windc.example.com:8080 .

This concludes the lab.

DO417-RHAE2.8-en-1-20200106 537
Chapter 11 | Constructing Ansible Tower Workflows

Solution

Constructing Ansible Tower Workflows


Performance Checklist
In this lab, you will add users and teams, and create and use surveys associated with a new
workflow.

Outcomes
You should be able to:

• Add two new users.

• Create a new team.

• Create a new workflow.

• Add a survey to the workflow, and execute the workflow.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

1. Add two users as Normal Users to the Default organization with the following information:

User 1 User 2

FIRST NAME Adam Ophelia

LAST NAME Brilliant Dunham

ORGANIZATION Default Default

EMAIL adam@example.com ophelia@example.com

USERNAME adam ophelia

PASSWORD RedHat123@! RedHat123@!

CONFIRM PASSWORD RedHat123@! RedHat123@!

1.1. Log in to the Ansible Tower web interface as the admin user with RedHat123@! as the
password.

1.2. Click Users in the navigation pane to manage users.

538 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

1.3. Click + to add a new user.

1.4. In the next window, complete the details as follows:

Field Value

FIRST NAME Adam

LAST NAME Brilliant

ORGANIZATION Default

EMAIL adam@example.com

USERNAME adam

PASSWORD RedHat123@!

CONFIRM PASSWORD RedHat123@!

USER TYPE Normal User

1.5. Click SAVE to create the new user.

1.6. Scroll down the next pane, and then click + to add another user.

1.7. In the next window, complete the details as follows:

Field Value

FIRST NAME Ophelia

LAST NAME Dunham

ORGANIZATION Default

EMAIL ophelia@example.com

USERNAME ophelia

PASSWORD RedHat123@!

CONFIRM PASSWORD RedHat123@!

USER TYPE Normal User

1.8. Click SAVE to create the new user.

2. Create an Operations team in the Default organization.

2.1. Click Teams in the navigation window to manage Teams.

2.2. Click + to add a new team.

2.3. In the next window, complete the details as follows:

DO417-RHAE2.8-en-1-20200106 539
Chapter 11 | Constructing Ansible Tower Workflows

Field Value

NAME Operations

DESCRIPTION Ops Team

ORGANIZATION Default

2.4. Click SAVE to create the Operations team.

3. Add adam and ophelia to the Operations team.

3.1. In the Operations team editor window, click USERS to manage team users.

3.2. Click + to add a new user to the team.

3.3. Check the box next to adam to select that user.

3.4. Repeat the same step for ophelia

3.5. Click SAVE.

3.6. In the next window, verify that adam and ophelia have the Member role in the
Operations team.

4. Copy the existing Run tower project job template and name it TEST webservers
setup.
Use the following details to modify the new job template:

Field Value

NAME TEST webservers setup

INVENTORY Dynamic inventory

CREDENTIAL AD Administrator

PROJECT tower repository

PLAYBOOK manage.yml

LIMIT win2.example.com

4.1. Click Templates in the navigation pane.

4.2. Click the copy icon for the Run tower project job template.

4.3. Click the new Run tower project@DATE template.

4.4. Use the following details to modify the new job template:

Field Value

NAME TEST webservers setup

540 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

Field Value

INVENTORY Dynamic inventory

CREDENTIAL AD Administrator

PROJECT tower repository

PLAYBOOK manage.yml

LIMIT win2.example.com

4.5. Click SAVE.

5. Copy the existing Run tower project job template and give it the name PROD
webservers setup.
Use the following details to modify the copied job template:

Field Value

NAME PROD webservers setup

INVENTORY Dynamic inventory

CREDENTIAL AD Administrator

PROJECT tower repository

PLAYBOOK manage.yml

LIMIT windc.example.com

5.1. Click Templates in the navigation pane.

5.2. Click the copy icon for the Run tower project job template.

5.3. Click the new Run tower project@DATE template.

5.4. In the next window, complete the details as follows:

Field Value

NAME PROD webservers setup

INVENTORY Dynamic inventory

CREDENTIAL AD Administrator

PROJECT tower repository

PLAYBOOK manage.yml

LIMIT windc.example.com

5.5. Click SAVE .

DO417-RHAE2.8-en-1-20200106 541
Chapter 11 | Constructing Ansible Tower Workflows

6. Create a new From Test to Prod workflow job template using the following details:

Field Value

NAME From Test to Prod

DESCRIPTION Deploy to Test and on success deploy to Prod

ORGANIZATION Default

6.1. Click Templates in the navigation pane.

6.2. Click + to add a new workflow job template.

6.3. Select Workflow Template from the list.

6.4. In the next window, complete the details as follows:

Field Value

NAME From Test to Prod

DESCRIPTION Deploy to Test and on success deploy to


Prod

ORGANIZATION Default

6.5. Click SAVE to create the new workflow job template.

7. Configure the From Test to Prod workflow job template so that it contains the following
steps:

• Synchronize the tower repository project.

• Upon success of the previous step, launch the TEST webservers setup job template.

• Upon success of the previous step, launch the PROD webservers setup job template.

7.1. Click WORKFLOW VISUALIZER to open the Workflow Visualizer.

7.2. Click START to add the first action in the workflow. A list of actions to perform displays
in the ADD A NODE pane.

7.3. Click PROJECT SYNC to display the list of available projects. Select tower repository,
and then click SELECT. In the Workflow Visualizer window, this connects the START
node to the node for the tower repository project with a blue line, indicating that
this step will always be performed.

7.4. Move your mouse over the new node, and then click + to add an action after the project
synchronization of tower repository. A list of actions to perform displays.

7.5. In the ADD A NODE pane, click JOBS if not already selected. Select the TEST
webservers setup job template. Depending on the size of your web browser window,
you may need to look at the next page to find the job template. Select On Success from
the RUN list, and then click SELECT.
The workflow visualizer window shows the node for the tower repository project
linked by a green line to the TEST webservers setup job template. This indicates

542 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

that if the project synchronization for tower repository is successful, then the TEST
webservers setup job template will be launched.

7.6. Move your mouse over the new node and click + to add an action after the TEST
webservers setup job template.

7.7. Click JOBS if not there already, and then select the PROD webservers setup job
template. Select On Success from the RUN list, and then click SELECT.

7.8. Click SAVE to save the workflow job template.

8. Add a Survey containing the following information to the From Test to Prod workflow job
template. Make sure this is a required survey.

Field Value

PROMPT What version are you deploying?

DESCRIPTION This version number will be displayed at the


bottom of the index page.

ANSWER VARIABLE NAME version

ANSWER TYPE Text

MINIMUM LENGTH 1

MAXIMUM LENGTH 40

Add a second question to the survey with the following details:

Field Value

PROMPT What is your name?

DESCRIPTION This is the page owner

ANSWER VARIABLE NAME student_name

ANSWER TYPE Text

MINIMUM LENGTH 1

MAXIMUM LENGTH 40

8.1. Click ADD SURVEY to add a Survey.

8.2. In the next window, complete the details as follows:

Field Value

PROMPT What version are you deploying?

DESCRIPTION This version number will be displayed at


the bottom of the index page.
DO417-RHAE2.8-en-1-20200106 543
Chapter 11 | Constructing Ansible Tower Workflows

Field Value

ANSWER VARIABLE NAME deployment_version

ANSWER TYPE Text

MINIMUM LENGTH 1

MAXIMUM LENGTH 40

REQUIRED Selected

8.3. Click ADD to add the survey prompt to the survey. This displays a preview of the survey.

8.4. Add another question to the survey, completing the details as follows:

Field Value

PROMPT What is your name?

DESCRIPTION This is the page owner

ANSWER VARIABLE NAME student_name

ANSWER TYPE Text

MINIMUM LENGTH 1

MAXIMUM LENGTH 40

REQUIRED Checked

8.5. Click +ADD to add the survey prompt to the survey. This displays a preview of the
survey.

Important
Before saving, make sure that the ON/OFF toggle switch is set to ON in the Survey
editor window.

8.6. Click SAVE to add the Survey to the job template.

8.7. Click SAVE to update the job template.

9. Launch a workflow using the From Test to Prod workflow job template. When prompted
by the survey, enter v1.3 for the page version and your name.

9.1. Scroll down to the TEMPLATES section.

9.2. Click the rocket icon for the From Test to Prod workflow job template to launch the
workflow. This opens the survey that you just created, and prompts for input.

9.3. In the WHAT VERSION ARE YOU DEPLOYING? field, type 1.3. In the WHAT IS
YOUR NAME? field, type in your name. Click NEXT, and then click LAUNCH. This
redirects you to a detailed status page for the running workflow.

544 DO417-RHAE2.8-en-1-20200106
Chapter 11 | Constructing Ansible Tower Workflows

9.4. Observe the running jobs of the workflow. Click DETAILS for a running or completed job
to see a more detailed output from the job.

10. Verify that the web servers have been updated: win2.example.com,
windc.example.com. Open Chrome and access http://win2.example.com:8080 and
http://windc.example.com:8080 .

10.1. Open a web browser and navigate to http://win2.example.com:8080 and


http://windc.example.com:8080 in separate tabs. You should see the new page
with the correct name and version.

10.2.When ready, log out from the Ansible Tower web UI.

This concludes the lab.

DO417-RHAE2.8-en-1-20200106 545
Chapter 11 | Constructing Ansible Tower Workflows

Summary
In this chapter, you learned:

• Organizations are logical collections of users, teams, projects, and inventories.

• There are three user types: System Administrator, System Auditor, and Normal User.

• System Administrator and System Auditor are singleton roles that grant read-write and
read-only access to all Ansible Tower resources, respectively.

• A team is a group of users, and you can use a team to make it easier to assign particular roles on
Ansible Tower resources to a set of users.

• Use surveys to enable single-step automation. You can prompt users for the values of extra
variables that playbooks use.

• A workflow job template allows you to launch a job that runs several playbooks in sequence.

546 DO417-RHAE2.8-en-1-20200106
Chapter 12

Comprehensive Review
Goal Review tasks from Microsoft Windows Automation
with Red Hat Ansible

Objectives • Review tasks from Microsoft Windows


Automation with Red Hat Ansible

Sections • Comprehensive Review

Lab • Lab: Comprehensive Review Lab 1


• Lab: Comprehensive Review Lab 2
• Lab: Comprehensive Review Lab 3
• Lab: Comprehensive Review Lab 4

DO417-RHAE2.8-en-1-20200106 547
Chapter 12 | Comprehensive Review

Comprehensive Review

Objectives
After completing this section, you should have reviewed and refreshed the knowledge and skills
learned in Microsoft Windows Automation with Red Hat Ansible.

Reviewing Microsoft Windows Automation with Red


Hat Ansible
Before beginning the comprehensive review for this course, you should be comfortable with the
topics covered in each chapter.

You can refer to earlier sections in the textbook for extra study.

Chapter 1, Introducing Red Hat Ansible Automation


Describe the purpose and benefits of automating Windows server administration tasks, and the
basic architecture of a solution based on Red Hat Ansible Automation.

• Describe fundamental concepts of automation with Red Hat Ansible Automation, its basic
design, and common use cases.

• Describe the architecture of a Windows automation implementation using Red Hat Ansible
Tower and a Git repository as a central point of control.

• Retrieve, manage, edit, and store files in a remote Git version control system, such as GitHub or
GitLab, using Visual Studio Code.

Chapter 2, Running Simple Automation Commands


Prepare Microsoft Windows hosts for automation and Red Hat Ansible Tower as a central
automation control system, and run one-off automation tasks on those hosts from Ansible Tower.

• Configure Microsoft Windows systems to provide the prerequisites and access needed for
management by Red Hat Ansible Automation.

• Configure Red Hat Ansible Tower with an inventory of Windows hosts to manage, and
credentials needed to authenticate and connect to those hosts.

• Describe what an Ansible module is, and run a single operation on managed hosts as an ad hoc
command using Red Hat Ansible Tower.

Chapter 3, Implementing Ansible Playbooks


Write a simple playbook to automate tasks on multiple Microsoft Windows-based hosts, and then
use Red Hat Ansible Tower to run it.

• Write a basic playbook and store it in a Git repository.

• Configure a job template for a playbook in Red Hat Ansible Tower, and then use it to run the
playbook on managed hosts.

548 DO417-RHAE2.8-en-1-20200106
Chapter 12 | Comprehensive Review

• Write a playbook that includes multiple plays, and then use per-play privilege escalation to
perform tasks as particular users.

Chapter 4, Managing Variables and Facts


Write playbooks that use variables to simplify management of the playbook and facts to reference
information about managed hosts.

• Create and reference variables that affect specific hosts or host groups, the play, or the global
environment, and describe how variable precedence works.

• Encrypt sensitive variables using Ansible Vault, and run playbooks that reference Vault-
encrypted variables.

• Reference data specific to particular managed hosts using Ansible facts.

Chapter 5, Installing and Updating Software


Install, manage, and ensure software is up to date using Ansible Playbooks.

• Ensure software is installed and up to date on Microsoft Windows systems.

• Inspect the Windows Registry and ensure that registry keys are correctly configured.

Chapter 6, Implementing Task Control


Manage task execution using loops, conditional tests, and handlers, and recover when tasks fail.

• Write plays efficiently using loops, and use conditions to control when tasks run.

• Implement tasks that run only when another task makes a change on the managed host.

• Control what happens when a task fails, recover from task failure, and control what conditions
cause a task to report failure.

Chapter 7, Deploying Files to Managed Hosts


Deploy, modify, and manage files on your managed hosts.

• Create, install, edit, and remove files on managed hosts, and configure file permissions and other
characteristics.

• Deploy customized files to managed hosts using Jinja2 templates.

Chapter 8, Interacting with Users and Domains


Manage local and domain users, manage Active Directory domains, and generate a list of managed
hosts based on domain membership for a Red Hat Ansible Tower dynamic inventory.

• Automate creation and management of local user and group accounts.

• Create an Active Directory domain if it does not exist, and configure host membership, users,
and groups in that domain.

• Generate an Ansible inventory dynamically in Red Hat Ansible Tower based on Active Directory
domain membership.

Chapter 9, Automating Windows Administration Tasks


Automate common Windows Server administration tasks.

DO417-RHAE2.8-en-1-20200106 549
Chapter 12 | Comprehensive Review

• Run arbitrary PowerShell commands, configure PowerShell modules, and set up scheduled tasks
on managed hosts with Ansible playbooks.

• Automate configuration of storage devices on managed hosts.

Chapter 10, Managing Large Projects


Write playbooks that are optimized for larger and more complex projects and that reuse existing
automation code.

• Manage large playbooks by importing or including other playbooks or tasks from files,
unconditionally or based on a conditional test.

• Create a role to allow code reuse by different Ansible projects, and run it as part of a play in a
playbook.

• Select and retrieve roles from Ansible Galaxy or other sources such as a Git repository, and use
them in playbooks.

• Automate tasks by configuring and running PowerShell Desired State Configuration (DSC)
resources from your Ansible Playbook.

Chapter 11, Constructing Ansible Tower Workflows


Simplify management of jobs and launch complex jobs using Red Hat Ansible Tower.

• Describe users and teams in Red Hat Ansible Tower, the roles to which they may be assigned,
and how to create and manage them.

• Create a survey to make it simple for users to launch jobs with Red Hat Ansible Tower.

• Schedule automatic execution of a job template in Red Hat Ansible Tower.

• Create a sequence of job templates to execute using workflows and workflow job templates in
Red Hat Ansible Tower.

550 DO417-RHAE2.8-en-1-20200106
Chapter 12 | Comprehensive Review

Lab

Comprehensive Review Lab 1


In this exercise, you will examine system facts, and ensure that some specific registry keys are
set correctly.

Outcomes
You should be able to run ad hoc commands and configure Windows Registry keys.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

Instructions
In this exercise, you will configure a login message populated with some system facts.

• From Ansible Tower, use the Run Commands feature to run the setup module against
win1.example.com. Note the facts that are available.

• From workstation, open Visual Studio Code and clone the compreview repository
if you have not cloned it previously. The repository is accessible at https://
gitlab.example.com/student/compreview.git.

• Open the lab1.yml playbook, and then complete the tasks so that the following items
are included. After updating the Ansible Playbook, the message should display, in order,
the name of the system, its IP address, the operating system version, the CPU count, and
the total memory.
• legalnoticecaption defines the login message caption.
• legalnoticetext defines the login message text.
• ansible_facts["fqdn"]
• ansible_facts["ip_addresses"][0]
• ansible_facts["distribution"]
• ansible_facts["processor_count"]
• ansible_facts["memtotal_mb"]

• Save, commit, and push your changes to GitLab.

• In the Ansible Tower web UI, edit the Run compreview project to use the lab1.yml
playbook, and then launch a job.

• Log on to win1 as student to verify that the login message displays.

DO417-RHAE2.8-en-1-20200106 551
Chapter 12 | Comprehensive Review

Note
If you have logged in to win1 previously, and then logged out, use the Sign
out option before reconnecting. Disconnecting leaves the user session
logged in, so that the login message is not displayed until you log out and
then log in again.

This concludes the comprehensive review.

552 DO417-RHAE2.8-en-1-20200106
Chapter 12 | Comprehensive Review

Solution

Comprehensive Review Lab 1


In this exercise, you will examine system facts, and ensure that some specific registry keys are
set correctly.

Outcomes
You should be able to run ad hoc commands and configure Windows Registry keys.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

Instructions
In this exercise, you will configure a login message populated with some system facts.

• From Ansible Tower, use the Run Commands feature to run the setup module against
win1.example.com. Note the facts that are available.

• From workstation, open Visual Studio Code and clone the compreview repository
if you have not cloned it previously. The repository is accessible at https://
gitlab.example.com/student/compreview.git.

• Open the lab1.yml playbook, and then complete the tasks so that the following items
are included. After updating the Ansible Playbook, the message should display, in order,
the name of the system, its IP address, the operating system version, the CPU count, and
the total memory.
• legalnoticecaption defines the login message caption.
• legalnoticetext defines the login message text.
• ansible_facts["fqdn"]
• ansible_facts["ip_addresses"][0]
• ansible_facts["distribution"]
• ansible_facts["processor_count"]
• ansible_facts["memtotal_mb"]

• Save, commit, and push your changes to GitLab.

• In the Ansible Tower web UI, edit the Run compreview project to use the lab1.yml
playbook, and then launch a job.

• Log on to win1 as student to verify that the login message displays.

DO417-RHAE2.8-en-1-20200106 553
Chapter 12 | Comprehensive Review

Note
If you have logged in to win1 previously, and then logged out, use the Sign
out option before reconnecting. Disconnecting leaves the user session
logged in, so that the login message is not displayed until you log out and
then log in again.

1. From workstation, access the Ansible Tower instance available at http://


tower.example.com. Connect as the student user, with RedHat123@! as the password.
Click Inventories on the Ansible Tower navigation pane, browse to the Default
inventory page, and then open the ad hoc command execution pane for the
win1.example.com host.

1.1. From workstation, double-click the Ansible Tower shortcut icon on your Desktop
to access your Ansible Tower instance located at http://tower.example.com.

1.2. Log in to Ansible Tower using student as the user name and RedHat123@! as the
password.

1.3. From the main dashboard page, select Inventories from the navigation pane, and then
select Default inventory from the inventories listed.

1.4. From the Default inventory page, click HOSTS, and then select the check box next to
the win1.example.com host entry.

1.5. After selecting win1.example.com, click RUN COMMANDS to enter the ad hoc
command execution pane.

1.6. On the RUN COMMAND page, select setup from the MODULE list. Select the
DevOps machine credential, and then click LAUNCH to run the module.

1.7. Review the output to verify that the module ran successfully, and make a note of the
various facts available.

2. Launch the Visual Studio Code editor. If you have not previously cloned the compreview
repository, clone it to your workstation instance.

2.1. Click Search Windows, search for code, and then open Visual Studio Code.

2.2. Navigate to View → Command Palette or press Ctrl+Shift+P.


Type clone, and then select Git: Clone to clone a repository.
Use a repository URL of https://gitlab.example.com/student/
compreview.git. When prompted, select the Documents folder in the home directory
of the training user as the repository location, and then click Select Repository
Location. This clones the remote repository into the compreview folder.
Click Open from the window that displays after cloning to view the files, and then skip
the next step.

3. Navigate to File → Open Folder, and then select the C:\Users\student\Documents


\compreview folder to open this directory.
4. Open the lab1.yml playbook, and then complete the following tasks.

554 DO417-RHAE2.8-en-1-20200106
Chapter 12 | Comprehensive Review

4.1. Modify the Configure login message caption task to configure the caption for
the login message. This modifies the legalnoticecaption value.

- name: Configure login message caption


win_regedit:
path: '{{ message_key }}'
name: legalnoticecaption
data: 'Hello!'
type: string

4.2. Modify the Configure login message text task. This modifies the
legalnoticetext value.

- name: Configure login message text


win_regedit:
path: '{{ message_key }}'
name: legalnoticetext
data: >
'Welcome to the {{ ansible_facts['fqdn'] }}
({{ ansible_facts['ip_addresses'][0] }}) system.
This system is running {{ ansible_facts['distribution'] }},
and has {{ ansible_facts['processor_count'] }} cpu/s
and {{ ansible_facts['memtotal_mb'] }} MiB of RAM.'
type: string

5. Save and commit the changes to your local Git repository, and then push them to the remote
repository.

5.1. Click File → Save or press Ctrl+S to save the file.


5.2. Navigate to the Source Control pane, and then click + for the lab1.yml file to stage
the changes.

5.3. Enter a brief commit message, and then press Ctrl+Enter to commit the changes.

5.4. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to push
your local changes to the remote repository, and to retrieve any new changes from the
repository.

6. From workstation, access your Ansible Tower instance available at http://


tower.example.com. Connect as the student user with RedHat123@! as the password.
7. Test your playbook by using the Run compreview project job template.

7.1. In the navigation pane, click Templates.

7.2. Click the Run compreview project job template to select it.

7.3. Select the lab1.yml playbook from the PLAYBOOK list.

7.4. Click SAVE to update the template, and then click LAUNCH to run the job.

8. After all tasks have completed, verify that the status in the DETAILS section shows
Successful. If the job is not successful, compare your playbook with the solutions/
lab1.sol solution file of the compreview project.

DO417-RHAE2.8-en-1-20200106 555
Chapter 12 | Comprehensive Review

9. From workstation, open the RDP client and connect to win1.example.com as the
devops user, with RedHat123@! as the password. Accept the insecure certificate, and then
verify that the login message displays.

Click OK to continue.
Disconnect from win1.example.com.

This concludes the lab.

556 DO417-RHAE2.8-en-1-20200106
Chapter 12 | Comprehensive Review

Lab

Comprehensive Review Lab 2


In this exercise, you will manage services and file content using a template.

Outcomes
You should be able to work with Microsoft Windows services, and use a template to generate
a file on a managed host.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

Instructions
In this exercise you will disable unnecessary services to reduce the attack surface of the
system, and populate the hosts file with the names and IP addresses for all hosts in the
Windows group.

Note
Note that the playbook contains two plays. The first play gathers facts for
all hosts in the Windows group, so that the template in the second play can
access host variables (hostvars) for all members of the group.

• From workstation, launch the Visual Studio Code editor, and then clone the
compreview repository if you have not cloned it previously. The repository is available at
https://gitlab.example.com/student/compreview.git.

• Open the lab2.yml playbook, and then complete the tasks. The following list describes
the services to disable.
• Application Host Helper Service (AppHostSvc)
• Geolocation Service (lfsvc)
• Print Spooler (Spooler)
• SSDP Discovery (SSDPSVC)

• In the playbook, use the correct module to send to the managed host the hosts.j2
template file. Reuse the variable that points to the directory that contains the hosts file.

• Update the second task to use the module for managing services. Disable and stop the
services listed in the disabled_services loop.

• Edit the templates/hosts.j2 template file.

DO417-RHAE2.8-en-1-20200106 557
Chapter 12 | Comprehensive Review

Add the following host variables (hostvars) entries to the for loop at the bottom of the
file. The format should be a space-separated list containing the IP address, the FQDN, and
the host name in that order.
• {{ hostvars[host]['ansible_ip_addresses'][0] }}
• {{ hostvars[host]['ansible_fqdn'] }}
• {{ hostvars[host]['inventory_hostname_short'] }}

• Save, commit, and push your changes to GitLab.

• In the Ansible Tower web UI, edit the Run compreview project template to use the
lab2.yml playbook, and then launch a job.

• Log on to win2 as EXAMPLE\Administrator with the AD Administrator password


to verify that the C:\Windows\System32\drivers\etc\hosts file contains an entry
for each host in the Windows group, and that the appropriate services are disabled.

• In the Ansible Tower web UI, edit the Run compreview project template to use the
revert_lab2.yml playbook, and then launch a job.

This concludes the comprehensive review.

558 DO417-RHAE2.8-en-1-20200106
Chapter 12 | Comprehensive Review

Solution

Comprehensive Review Lab 2


In this exercise, you will manage services and file content using a template.

Outcomes
You should be able to work with Microsoft Windows services, and use a template to generate
a file on a managed host.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

Instructions
In this exercise you will disable unnecessary services to reduce the attack surface of the
system, and populate the hosts file with the names and IP addresses for all hosts in the
Windows group.

Note
Note that the playbook contains two plays. The first play gathers facts for
all hosts in the Windows group, so that the template in the second play can
access host variables (hostvars) for all members of the group.

• From workstation, launch the Visual Studio Code editor, and then clone the
compreview repository if you have not cloned it previously. The repository is available at
https://gitlab.example.com/student/compreview.git.

• Open the lab2.yml playbook, and then complete the tasks. The following list describes
the services to disable.
• Application Host Helper Service (AppHostSvc)
• Geolocation Service (lfsvc)
• Print Spooler (Spooler)
• SSDP Discovery (SSDPSVC)

• In the playbook, use the correct module to send to the managed host the hosts.j2
template file. Reuse the variable that points to the directory that contains the hosts file.

• Update the second task to use the module for managing services. Disable and stop the
services listed in the disabled_services loop.

• Edit the templates/hosts.j2 template file.

DO417-RHAE2.8-en-1-20200106 559
Chapter 12 | Comprehensive Review

Add the following host variables (hostvars) entries to the for loop at the bottom of the
file. The format should be a space-separated list containing the IP address, the FQDN, and
the host name in that order.
• {{ hostvars[host]['ansible_ip_addresses'][0] }}
• {{ hostvars[host]['ansible_fqdn'] }}
• {{ hostvars[host]['inventory_hostname_short'] }}

• Save, commit, and push your changes to GitLab.

• In the Ansible Tower web UI, edit the Run compreview project template to use the
lab2.yml playbook, and then launch a job.

• Log on to win2 as EXAMPLE\Administrator with the AD Administrator password


to verify that the C:\Windows\System32\drivers\etc\hosts file contains an entry
for each host in the Windows group, and that the appropriate services are disabled.

• In the Ansible Tower web UI, edit the Run compreview project template to use the
revert_lab2.yml playbook, and then launch a job.

1. From workstation, open Visual Studio Code. If you have not previously cloned the
compreview repository, clone it to your workstation instance.

1.1. Click Search Windows, search for code, and then open Visual Studio Code.

1.2. Navigate to View → Command Palette or press Ctrl+Shift+P to open the


command palette.
Type clone, and then select Git: Clone to clone a repository.
Use a repository URL of https://gitlab.example.com/student/
compreview.git. When prompted, select the Documents folder in the home directory
of the training user, and then click Select Repository Location. This clones the
remote repository into the compreview folder.
Click Open from the window that displays after cloning to view the files.

2.
Note
Run this step only if you have already cloned the compreview repository.

Navigate to File → Open Folder, and then select the C:\Users\student\Documents


\compreview folder to open the directory.
3. Open the lab2.yml playbook, and then complete the following tasks.

3.1. Complete the list of services for the disabled_services variable.

disabled_services:
- AppHostSvc
- lfsvc
- Spooler
- SSDPSRV

3.2. Complete the Configure hosts file from template task. This populates the C:
\Windows\System32\drivers\etc\hosts file.

560 DO417-RHAE2.8-en-1-20200106
Chapter 12 | Comprehensive Review

- name: Configure hosts file from template


win_template:
src: templates/hosts.j2
dest: '{{ etc_dir }}\hosts'

3.3. Modify the Reduce server footprint task. The ignore_errors parameter is
used so that absent services do not cause the whole task to fail.

- name: Reduce server footprint


win_service:
name: "{{ item }}"
start_mode: disabled
state: stopped
loop: "{{ disabled_services }}"
ignore_errors: yes

4. Complete the templates/hosts.j2 file.


Add the appropriate hostvars entries to the loop body. Format the hosts entry as
'IP_ADDRESS FQDN HOSTNAME'.

{% for host in groups['Windows'] %}


{{ hostvars[host]['ansible_ip_addresses'][0] }} {{ hostvars[host]
['ansible_fqdn'] }} {{ hostvars[host].inventory_hostname_short }}
{% endfor %}

5. Save and commit the changes to your local Git repository, and then push them to the remote
repository.

5.1. Click File → Save or press Ctrl+S to save the file.

5.2. Navigate to the Source Control pane, and then click + for the lab2.yml file to stage
this file.

5.3. Enter a brief commit message, and then press Ctrl+Enter to commit the changes.

5.4. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to push
your local changes to the remote repository, and to retrieve any new changes from the
repository.

6. From workstation, access your Ansible Tower instance available at http://


tower.example.com. Connect as the student user with RedHat123@! as the password.
7. Use the Run compreview project job template to test your playbook.

7.1. In the navigation pane, click Templates.

7.2. Click the Run compreview project job template to navigate to it.

7.3. Select the lab2.yml playbook from the PLAYBOOK list.

7.4. Select Default inventory from the INVENTORY list.

DO417-RHAE2.8-en-1-20200106 561
Chapter 12 | Comprehensive Review

7.5. If you completed Chapter 8: Interacting with Users and Domains, select the AD
Administrator credential from the CREDENTIAL list and update the EXTRA
VARIABLES text field to match the following:

---
ansible_winrm_transport: kerberos

7.6. Click SAVE to update the template, and then click LAUNCH to run the job.

8. After all tasks have completed, verify that the status in the DETAILS pane shows
Successful. If the job is not successful, compare your playbook with the solutions/
lab2.sol and solutions/hosts.sol solution files in the compreview Git repository.
9. Verify all changes have been executed.

9.1. From workstation, connect to win2.example.com with the remote desktop client.
Use EXAMPLE\Administrator as the user name and the AD Administrator
password.

9.2. Use a text editor to verify that the C:\Windows\System32\drivers\etc\hosts file


contains an entry for each host in the Windows group.

# localhost name resolution is handled within DNS itself.


# 127.0.0.1 localhost
# ::1 localhost

172.25.250.224 win2.example.com win2


172.25.250.70 win1.example.com win1

9.3. Open the Services control panel applet, and verify that the appropriate services are
disabled.

9.4. Disconnect from win2.example.com when testing is complete.

10. In the Ansible Tower web UI, edit the Run compreview project template to use the
revert_lab2.yml playbook, and then launch a job.

This concludes the lab.

562 DO417-RHAE2.8-en-1-20200106
Chapter 12 | Comprehensive Review

Lab

Comprehensive Review Lab 3


In this exercise you will copy files and install software.

Outcomes
You should be able to work with installation packages, and use blocks in playbooks to control
sets of tasks.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

Instructions
In this exercise you will install the 7zip package.

• From workstation, launch Visual Studio Code, and then clone the compreview
repository if you have not cloned it previously.

• Open the lab3.yml playbook and complete the following tasks:

• Add an initial clause for handling failures in the playbook.

• Use the Ansible module to transfer the 7z.exe file.

• Replace the two placeholders for the win_package module with the two parameters
that provide the product ID and the installation arguments to pass.

• Add a second clause in the playbook to instruct Ansible to display the debug message,
and attempt the removal of 7-Zip.

• Add a final clause in the playbook to instruct Ansible to always run the tasks.

• Use the correct Ansible module, with a parameter, to instruct the deletion of the
installation package.

• Save, commit, and push your changes to GitLab.

• In the Ansible Tower web UI, edit the Run compreview project template to use the
lab3.yml playbook, and then launch a job.

• Log on to win1 as student to verify that 7zip is installed.

This concludes the comprehensive review.

DO417-RHAE2.8-en-1-20200106 563
Chapter 12 | Comprehensive Review

Solution

Comprehensive Review Lab 3


In this exercise you will copy files and install software.

Outcomes
You should be able to work with installation packages, and use blocks in playbooks to control
sets of tasks.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

Instructions
In this exercise you will install the 7zip package.

• From workstation, launch Visual Studio Code, and then clone the compreview
repository if you have not cloned it previously.

• Open the lab3.yml playbook and complete the following tasks:

• Add an initial clause for handling failures in the playbook.

• Use the Ansible module to transfer the 7z.exe file.

• Replace the two placeholders for the win_package module with the two parameters
that provide the product ID and the installation arguments to pass.

• Add a second clause in the playbook to instruct Ansible to display the debug message,
and attempt the removal of 7-Zip.

• Add a final clause in the playbook to instruct Ansible to always run the tasks.

• Use the correct Ansible module, with a parameter, to instruct the deletion of the
installation package.

• Save, commit, and push your changes to GitLab.

• In the Ansible Tower web UI, edit the Run compreview project template to use the
lab3.yml playbook, and then launch a job.

• Log on to win1 as student to verify that 7zip is installed.

1. From workstation, launch Visual Studio Code. If you have not previously cloned the
compreview repository, clone it to your workstation instance.

564 DO417-RHAE2.8-en-1-20200106
Chapter 12 | Comprehensive Review

1.1. Click Search Windows, search for code, and then open Visual Studio Code.

1.2. Navigate to View → Command Palette or press Ctrl+Shift+P to open the


command palette.
Type clone, and then select Git: Clone to clone a repository.
Use a repository URL of https://gitlab.example.com/student/
compreview.git. When prompted, select the Documents folder in the home directory
of the training user, and then click Select Repository Location. This clones the
remote repository into the compreview folder.
Click Open from the window that displays after cloning to view the files.

2.
Note
Skip this step if you previously cloned the repository.

Navigate to the c:\Users\student\Documents\compreview directory, select File →


Open Folder, and then select the C:\Users\student\Documents\compreview folder.
3. Open the lab3.yml playbook, and then complete the following tasks:

3.1. Correct the block structure so that the uninstall is performed in the rescue section, and
the installation package is always cleaned up.

- name: Handle package installation


block:
- name: Copy package to target host
...output omitted...

rescue:
- debug:
msg: "Sorry, it didn't work out :("
...output omitted...

always:
- name: Clean up installation package

3.2. Ensure that the Copy package to target host task is using the correct module.

- name: Copy package to target host


win_copy:
src: files/7z.exe
dest: C:\Users\student\Downloads\

3.3. Complete the Install package task.

- name: Install package


win_package:
path: C:\Users\student\Downloads\7z.exe
product_id: 7-Zip
arguments: /S
state: present
ignore_errors: true

DO417-RHAE2.8-en-1-20200106 565
Chapter 12 | Comprehensive Review

3.4. Complete the Clean up installation package task.

- name: Clean up installation package


win_file:
path: C:\Users\student\Downloads\7z.exe
state: absent

4. Save and commit the changes to your local Git repository, and then push them to the remote
repository.

4.1. Click File → Save or press Ctrl+S to save the file.

4.2. Navigate to the Source Control pane, and then click the + next to lab3.yml to stage
the changes.

4.3. Enter a brief commit message, and then press Ctrl+Enter to commit the changes.

4.4. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to push
your local changes to the remote repository, and retrieve any new changes from the
repository.

5. From workstation, access your Ansible Tower instance available at http://


tower.example.com. Connect as the student user with RedHat123@! as the password.
6. Use the Run compreview project job template to test your playbook.

6.1. In the navigation pane, click Templates.

6.2. Click the Run compreview project job template to navigate to it.

6.3. Select the lab3.yml playbook from the PLAYBOOK list.

6.4. Click SAVE to update the template, and then click LAUNCH to run the job.

7. After all tasks have completed, verify that the status in the DETAILS pane shows
Successful. If the job is not successful, compare your playbook with the solutions/
lab3.sol file in the compreview Git repository.
8. Verify all changes are complete.

8.1. Connect to win1.example.com using the remote desktop client. Use devops as the
user name and RedHat123@! as the password.

8.2. Click Search Windows, search for 7-zip, and then note that 7-Zip File Manager
appears in the search results.

8.3. Disconnect from win1.example.com when testing is complete.

This concludes the lab.

566 DO417-RHAE2.8-en-1-20200106
Chapter 12 | Comprehensive Review

Lab

Comprehensive Review Lab 4


In this exercise, you will use a role to configure a service, and install a package from the
Chocolatey repository.

Outcomes
You should be able to import roles to manage features, and install software using the
win_chocolatey module.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

Instructions
In this exercise you will configure the SNMP service on win2, and install an SNMP client on
win1. Then, use the SNMP client on win1 to walk the MIB tree on win2.

• Launch the Visual Studio Code editor, and then clone the compreview repository if you
have not cloned it previously.

• Open the lab4.yml playbook, and then populate the variables and complete the tasks in
the SNMP configured on server play.

The variables require the following values:

Variables and values for the ansible.snmp role

snmp_access_address
{{ hostvars['win1.example.com']['ansible_ip_addresses'][0] }}

snmp_community
public

snmp_contact
Adam Admin

snmp_location
Arizona

snmp_monitoring_server
{{ hostvars['win1.example.com']['ansible_ip_addresses'][0] }}

snmp_password
Password1!

DO417-RHAE2.8-en-1-20200106 567
Chapter 12 | Comprehensive Review

snmp_user
admin

Variable and value for the SNMP client configuration play

package
snmpb

• In the SNMP configured on server play, use the Ansible import statement to import
the ansible.snmp role.

• In the SNMP configured on client play, use the correct Ansible module to install the
chocolatey package.

• In the last task of the SNMP configured on client play, use the correct Ansible
module to install the package defined by the package variable.

• Save, commit, and push your changes to GitLab.

• In the Ansible Tower web UI, edit Run compreview project to use the lab4.yml
playbook, and then launch a job.

• From workstation, use the RDP client to log in to win1 as student, and then use the
snmpb tool to walk the MIB of win2.

This concludes the comprehensive review.

568 DO417-RHAE2.8-en-1-20200106
Chapter 12 | Comprehensive Review

Solution

Comprehensive Review Lab 4


In this exercise, you will use a role to configure a service, and install a package from the
Chocolatey repository.

Outcomes
You should be able to import roles to manage features, and install software using the
win_chocolatey module.

Before You Begin


Open your RDP client and connect to the Windows workstation system using training
as the user name. Your unique password is displayed on the Online Lab tab of the ROL
interface.

This tab also displays information for connecting to all of your systems.

Confirm that all infrastructure machines are running, and that you can access Ansible Tower
and GitLab from the Windows workstation.

Instructions
In this exercise you will configure the SNMP service on win2, and install an SNMP client on
win1. Then, use the SNMP client on win1 to walk the MIB tree on win2.

• Launch the Visual Studio Code editor, and then clone the compreview repository if you
have not cloned it previously.

• Open the lab4.yml playbook, and then populate the variables and complete the tasks in
the SNMP configured on server play.

The variables require the following values:

Variables and values for the ansible.snmp role

snmp_access_address
{{ hostvars['win1.example.com']['ansible_ip_addresses'][0] }}

snmp_community
public

snmp_contact
Adam Admin

snmp_location
Arizona

snmp_monitoring_server
{{ hostvars['win1.example.com']['ansible_ip_addresses'][0] }}

snmp_password
Password1!

DO417-RHAE2.8-en-1-20200106 569
Chapter 12 | Comprehensive Review

snmp_user
admin

Variable and value for the SNMP client configuration play

package
snmpb

• In the SNMP configured on server play, use the Ansible import statement to import
the ansible.snmp role.

• In the SNMP configured on client play, use the correct Ansible module to install the
chocolatey package.

• In the last task of the SNMP configured on client play, use the correct Ansible
module to install the package defined by the package variable.

• Save, commit, and push your changes to GitLab.

• In the Ansible Tower web UI, edit Run compreview project to use the lab4.yml
playbook, and then launch a job.

• From workstation, use the RDP client to log in to win1 as student, and then use the
snmpb tool to walk the MIB of win2.

1. From workstation, launch Visual Studio Code. If you have not previously cloned the
compreview repository, clone it to your workstation system..

1.1. Click Search Windows, search for code, and then open Visual Studio Code.

1.2. Navigate to View → Command Palette or press Ctrl+Shift+P to open the


command palette.
Type clone, and then select Git: Clone to clone a repository.
Use a repository URL of https://gitlab.example.com/student/
compreview.git. When prompted, select the Documents folder in the home directory
of the training user as the repository location, and then click Select Repository
Location. This clones the remote repository into the compreview folder.
Click Open from the window that displays after cloning to view the files, then skip the
next step.

2. Navigate to the c:\Users\student\Documents\compreview directory and click File →


Open Folder, to open the C:\Users\student\Documents\compreview folder.
3. Open the lab4.yml playbook, and then complete the following tasks:

3.1. Populate the variables for the ansible.snmp role, as provided earlier in this lab.

vars:
snmp_access_address: >-
{{ hostvars['win1.example.com']['ansible_ip_addresses'][0] }}
snmp_community: public
snmp_contact: Adam Admin

570 DO417-RHAE2.8-en-1-20200106
Chapter 12 | Comprehensive Review

snmp_location: Arizona
snmp_monitoring_server: >-
{{ hostvars['win1.example.com']['ansible_ip_addresses'][0] }}
snmp_password: Password1!
snmp_user: admin

Note
The >- sign instructs Ansible to remove the new line at the end of the string.

3.2. Import the ansible.snmp role.

...output omitted...
snmp_user: admin

import_role:
name: ansible.snmp

3.3. Add the package variable for the second play, as listed in the table. Give it a value of
snmpb.

vars:
package: snmpb

3.4. Complete the Chocolatey is installed task. This task uses the win_chocolatey
module to install the chocolatey package.

- name: Chocolatey is installed


win_chocolatey:
name: chocolatey
state: present

3.5. Complete the Packages are installed task, using the variable configured earlier.

- name: Packages are installed


win_chocolatey:
name: "{{ package }}"
state: present
pinned: true

4. Save and commit the changes to your local Git repository, and then push them to the remote
repository.

4.1. Click File → Save or press Ctrl+S to save the file.

4.2. Navigate to the Source Control pane, and then click the + next to lab4.yml to stage
the changes.

4.3. Enter a brief commit message, and then press Ctrl+Enter to commit the changes.

4.4. The status icons displayed in the lower left corner of the editor indicate that there are
changes ready to push to the remote Git repository. Click Synchronize Changes to push

DO417-RHAE2.8-en-1-20200106 571
Chapter 12 | Comprehensive Review

your local changes to the remote repository, and retrieve any new changes from the
repository.

5. From workstation, access your Ansible Tower instance available at http://


tower.example.com. Connect as the student user with RedHat123@! as the password.
6. Use the Run compreview project job template to test your playbook.

6.1. In the navigation pane, click Templates.

6.2. Click the Run compreview project job template.

6.3. Select the lab4.yml playbook from the PLAYBOOK list.

6.4. Select Default inventory from the INVENTORY list.

6.5. If you completed Chapter 8: Interacting with Users and Domains, select the AD
Administrator credential from the CREDENTIAL list and update the EXTRA
VARIABLES text field to match the following:

---
ansible_winrm_transport: kerberos

6.6. Click SAVE to update the template, and then click LAUNCH to run the job.

7. After all tasks have completed, verify that the status in the DETAILS pane shows
Successful. If the job is not successful, compare your playbook with the solutions/
lab4.sol solution file in the compreview Git repository.
8. From workstation, use the RDP client to connect to win1.example.com. Use devops as
the user and RedHat123@! as the password. Use the snmpb tool to walk the MIB for win2.

8.1. The snmpb tool does not create menu entries; browse to C:\Program Files
(x86)\SnmpB using Windows Explorer, and then start the snmpb tool.

8.2. Click Options → Manage Agent Profiles..., and then right-click in the left pane and
select New agent profile. Set the name to win2, and the Agent Address/Name to
win2.example.com. Check all SNMP versions, and then click OK.

8.3. From the Remote SNMP Agent list, switch the host from localhost to win2.
Select SNMPv2c as the SNMP version.

8.4. Right-click the MIB Tree top-level folder, and then select Walk. The query results
appear in the right pane.
Scroll up to the top of the results to see the values defined in the playbook.

-----SNMP query started-----


1: sysDescr.0 Hardware: Intel64 Family 6 Model 85 Stepping 4 AT/AT COMPATIBLE -
Software: Windows Version 6.3 (Build 17763 Multiprocessor Free)
2: sysObjectID.0 enterprises.311.1.1.3.1.2
3: sysUpTime.0 0:06:43.47
4: sysContact.0 Adam Admin
5: sysName.0 win2
6: sysLocation.0 Arizona
7: sysServices.0 79
...output omitted...

572 DO417-RHAE2.8-en-1-20200106
Chapter 12 | Comprehensive Review

Note
If the SNMP query displays a Timeout message, then a restart of the
win2.example.com host may be required.

8.5. Disconnect from win1.example.com when testing is complete.

This concludes the lab.

DO417-RHAE2.8-en-1-20200106 573
574 DO417-RHAE2.8-en-1-20200106
Appendix A

Supplementary Topics
Goal Investigate supplementary topics not included in
the official course.

DO417-RHAE2.8-en-1-20200106 575
Appendix A | Supplementary Topics

Managing Red Hat Ansible Tower User


Roles

Objectives
After completing this section, you should be able to apply user roles to control access to
credentials, projects, and job templates in Red Hat Ansible Tower.

Managing Inventory Roles


Users and teams can be assigned the ability to read, use, or manage an inventory by assigning
appropriate roles for that inventory. In some cases, instead of directly assigning a role to the user
or team, a role granting permissions to work with an inventory indirectly may be inherited.

The following is a list of available roles for an inventory:

Admin
The inventory Admin role grants users full permissions over an inventory. These permissions
include deletion and modification of the inventory. In addition, this role also grants permissions
associated with the inventory roles Use, Ad Hoc, and Update.

Use
The inventory Use role grants users the ability to use an inventory in a job template resource.
This controls which inventory is used to launch jobs using the job template's playbook.

Ad Hoc
The inventory Ad Hoc role grants users the ability to use the inventory to execute ad hoc
commands. Using Ansible Tower for ad hoc command execution is discussed in detail in
Ansible Tower User Guide.

Update
The inventory Update role grants users the ability to update a dynamic inventory from its
external data source.

Read
The inventory Read role grants users the ability to view the contents of an inventory.

Configuring Access for Inventories


When an inventory is first created, it is only accessible by users who have the Admin, Inventory
Admin, or Auditor roles for the organization to which the inventory belongs. All other access
must be specifically configured.

This is done by assigning users and teams appropriate roles as discussed above. The inventory
must be created and saved before users and teams can be assigned roles on it.

Roles are assigned through the PERMISSIONS section of the inventory's editor screen
(accessible through the pencil icon next to its name). The following procedure details the steps to
assign users and teams roles on an inventory:

1. Log in as a user with Admin role on the organization in which the inventory was created.

2. Click Inventories in the navigation pane to display the organization's inventory list.

3. Click the pencil icon for the inventory to enter the inventory's editor screen.

576 DO417-RHAE2.8-en-1-20200106
Appendix A | Supplementary Topics

4. On the inventory's editor screen, click the PERMISSIONS button to enter the permissions
editor.
A list appears, naming users and teams, with their assigned roles. If there is an X next to a
role, click it to remove that role from the user.

5. Click the + button to add permissions.

6. In the ADD USERS / TEAMS selection screen, click either USERS or TEAMS. Select the
check boxes next to the users or teams to be assigned new roles.

7. Under Please assign roles to the selected users/teams, click the SELECT ROLES list.
Select the desired inventory role for each user or team.
Click KEY for a list of inventory roles and their definitions.

8. Click SAVE to finalize the new roles.

Managing Machine Credential Roles


Private machine credentials (credentials that are not assigned to an organization) are only
accessible to their creators or to users that have the System Administrator or System
Auditor user type. Other users cannot be assigned roles on private machine credentials.

To assign roles to machine credentials, the machine credential must be assigned to an Ansible
Tower organization. Then users and teams in that organization can share that credential through
role assignments.

The following is the list of available credential roles.

Admin
The Admin role grants users full permissions for a machine credential. These permissions
include deletion and modification of the credential, as well as the ability to use the credential
in a job template.

Use
The Use role grants users the ability to use a machine credential in a job template.

Read
The Read role grants users the ability to view the details of a machine credential. This still
does not allow them to decrypt the secrets which belong to that machine credential through
the web interface.

Configuring Access for Machine Credentials


When a machine credential assigned to an organization is first created, it is only accessible by the
owner and users with either the Admin or Auditor role in the organization in which the machine
credential was created. Additional access, if desired, must be specifically configured.

Additional roles cannot be assigned until it is first saved, after which they can be set by editing the
machine credential.

Roles are assigned through the PERMISSIONS section of the machine credential editor screen.

The following procedure details the steps for granting permissions to a machine credential which
belongs to an organization after its creation.

1. Log in as a user with Admin role on the organization in which the machine credential was
created.

2. Click Credentials to enter the credentials management interface.

DO417-RHAE2.8-en-1-20200106 577
Appendix A | Supplementary Topics

3. Click the name of the machine credential to edit in order to enter the credential editor
screen.

4. On the credential editor screen, click the PERMISSIONS button to enter the permissions
editor.

5. Click the + button to add permissions.

6. On the user and team selection screen, click either USERS or TEAMS and then select the
check boxes for the users or teams to be assigned roles.

7. Under Please assign roles for the selected users/teams, click KEY to display the list of
credential roles and their definitions.

8. Click the SELECT ROLES list and select the desired credential role for each user or team.

9. Click SAVE to finalize the changes to permissions.

Important
Permissions for credentials can also be added through either the user or team
management screens.

Managing SCM Credential Roles


Just like machine credentials, private SCM credentials are only usable by their creators and
System Administrator and System Auditor users. You can share SCM Credentials that are
assigned to an organization with other users by assigning either users or teams the appropriate
roles for that credential.

The following is the list of roles available for providing users access to SCM credentials:

Admin
The Admin role grants you full permissions for an SCM credential. These permissions include
deletion and modification of the credential. This role also grants to the user the permissions
associated with the credential, which are Use and Read roles.

Use
The Use role grants you the ability to associate an SCM credential with a project. This role also
grants you the permissions associated with the credential Read role.

The Use role does not control whether a user can themselves use the SCM credential to
update a project, only whether they can assign that SCM credential so that it can then be used
by someone who has the Update role for a project.

For example, if you associate an SCM credential with a project, any user with the Update role
on the project can use the associated SCM credential without being granted Use role that
credential.

Read
The Read role grants you the ability to view the details of an SCM credential.

Configuring Access for SCM Credentials


When you first create an SCM Credential, it is only accessible by users with either the Admin or
Auditor role in the organization to which the credential belongs. You must explicitly configure any
additional access for other users.

578 DO417-RHAE2.8-en-1-20200106
Appendix A | Supplementary Topics

The assignment of SCM credential roles to users or teams dictates who has permissions to that
credential. You cannot assign these permissions when creating the SCM credential for the first
time. You can manage the permissions by editing the credential after its creation.

Roles are assigned through the PERMISSIONS section of the credential editor screen. The
following list details the steps for granting permissions to an SCM credential that belongs to an
organization.

1. Log in as a user with Admin role in the organization that the SCM credential belongs to.

2. Click Credentials in the navigation pane to enter the credential management interface.

3. Select the SCM credential to edit it.

4. Select PERMISSIONS to manage the permissions for the credential.

5. Click + to add a new permission.

6. In the user and team selection screen, select either a team or a user for which you want to
create a new permission.

7. Click KEY to display the list of credential roles and their definitions.

Select a role from the SELECT ROLES list and select the desired role for the user or the
team.

Figure A.1: Managing credential roles in Ansible Tower

Important
You can also manage permissions for SCM credentials through either the user or
team management screens available under Ansible Tower's Settings interface.

DO417-RHAE2.8-en-1-20200106 579
Appendix A | Supplementary Topics

Managing Project Roles


You can assign project roles to users or to the team they belong to. For example, if a user requires
permissions for a specific project you can configure the project permission individually for the user,
or for their team.

The following are the list of available project roles:

Admin
The Admin role grants you full access to the project. With this role, users can delete the
project or modify its properties, including its permissions. In addition, this role also grants you
the Use, Update, and Read roles, which are discussed later in this section.

Use
The Use role grants you the ability to use a project with a job template. This role also grants
you the permissions associated with the project Read role.

Update
The Update role grants you the ability to manually update or schedule an update to the
project's materials from its SCM source. This role also grants you the permissions associated
with the Project Read role.

Read
The Read role grants you the ability to view the details, permissions, and notifications
associated with the project.

Configuring Access for Projects


After creating a project it is only accessible by users with the Admin or Auditor role in the
organization that the project belongs to.

You must explicitly configure any other access for other users. You cannot assign roles when you
define the project for the first time, only by editing the project after creation.

You can review roles by accessing the PERMISSIONS section of the project. The following
procedure details the steps to assign roles for a project:

1. Ensure you log in as a user that has the Admin role for the project.

2. Click Projects in the navigation pane to display the list of projects.

Click the pencil icon for the row of the project that you want to update.

3. On the Project editor screen, select PERMISSIONS to manages the permissions for the
project.

4. Click + to create a new permission.

5. In the user and team selection screen, select either a team or a user.

Select KEY to display the list of project roles and their definition.

6. Click the SELECT ROLES list and select the desired project role for each user or team.

580 DO417-RHAE2.8-en-1-20200106
Appendix A | Supplementary Topics

Figure A.2: Managing project roles

Note
You can also manage roles for projects from either the user or team management
screens.

Managing Job Template Roles


Ansible Tower uses three roles to control who can access job templates.

Admin
The Admin role gives you the permission to delete a job template or edit its properties,
including its associated permissions. This role also grants you the permissions that are
associated with the Execute and Read roles of the job template.

Execute
The Execute role permits you to execute a job using the job template. It also grants you the
permission to schedule a job from a job template but also the permissions that are associated
with the Read role of the job template.

Important
To be able to run a job from a job template, you only need the Execute role of
the job template; you do not need the Use role for any of the resources that are
associated with the job template.

Read
The Read role grants you read-only access to view the properties of a job template. It also
grants access to view other information related to the job template, such as the list of jobs
that run using the job template, as well as its associated permissions and notifications.

DO417-RHAE2.8-en-1-20200106 581
Appendix A | Supplementary Topics

Configuring Access for Job Templates


When you first create a job template, it is only accessible by you or by users with either an Admin
or Auditor role in the organization that owns the project. You must explicitly configure any
additional access.

The assignment of the previously discussed job template roles to users or teams, dictates who
has permissions on a job template. You cannot assign these permissions when you create the job
template; you can configure these options by editing the job template after its creation.

Roles are available from the PERMISSIONS section of the job template editor screen. The
following procedure describes the steps for granting permissions to a job template after its
creation.

1. Log in as a user with Admin role on the organization that owns the job template or as the user
that created it.

2. Click TEMPLATES in the navigation pane to display the list of templates.

Click the pencil icon for the job template to edit.

3. Select PERMISSIONS to manage the permissions for the job template.

Click + to add permissions.

4. From the user and team selection screen, select a user or a team that requires permissions for
the job template.

5. Click KEY to display the list of job template roles and their definitions.

6. Select the role for user or the team from the SELECT ROLES list.

Figure A.3: Managing roles for job templates

References
Ansible Tower User Guide
http://docs.ansible.com/ansible-tower/latest/html/userguide/index.html

582 DO417-RHAE2.8-en-1-20200106
Appendix B

Legal Notices

DO417-RHAE2.8-en-1-20200106 583
Appendix B | Legal Notices

arillso.chocolatey Role License


The arillso.chocolatey role from Ansible Galaxy (at https://galaxy.ansible.com/arillso/
chocolatey) was used in one or more exercises in this course. The original material for that role is
available from https://github.com/arillso/ansible.chocolatey under the following MIT license:

Copyright (c) 2019 Arillso

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.

584 DO417-RHAE2.8-en-1-20200106

You might also like