Courseiva

CCNA Manage task execution and roles Questions

60 questions · Manage task execution and roles · All types, answers revealed

1
MCQmedium

An administrator runs a playbook with the serial keyword set to 2. The playbook targets 6 hosts and contains a task that runs a rolling update. During execution, the administrator notices that the task is executed on only 2 hosts at a time, but the playbook waits for all tasks to complete on those 2 hosts before moving to the next 2. What is the primary effect of the serial keyword in this scenario?

A.It limits the number of hosts that execute each task concurrently, processing hosts in batches.
B.It ensures that only 2 tasks are executed at a time on each host.
C.It sets the maximum number of forks used for parallel task execution across all hosts.
D.It restricts the play to run on only 2 hosts total, ignoring the rest.
AnswerA

The serial keyword defines the number of hosts to manage in each batch. With serial: 2, Ansible runs the entire play on 2 hosts, then the next 2, and so on, ensuring tasks complete on one batch before proceeding to the next. This is correct because it controls batch size and provides rolling updates.

Why this answer

The serial keyword controls how many hosts are included in each batch of a play. When set to 2, Ansible completes the entire play on the first 2 hosts before moving to the next 2. This provides rolling updates and limits the impact of failures.

It does not affect parallelism within a batch or limit the total number of hosts.

Exam trap

The trap here is confusing serial with forks or throttle, which control parallelism and task concurrency rather than host batching.

2
MCQhard

An administrator is designing a role that needs to execute a set of tasks conditionally based on whether a package is installed. Which approach is best practice?

A.Use the stat module to check package file existence
B.Use the command module to check package status
C.Use ansible_facts.packages
D.Use the package_facts module
AnswerD

package_facts gathers installed package information into the package_facts variable, letting subsequent tasks evaluate conditions against actual system state. This avoids shelling out to rpm or dpkg and keeps the check idempotent and portable across distributions.

Why this answer

The `package_facts` module is the best practice for gathering package installation status in Ansible. It populates the `ansible_facts.packages` variable with structured data about installed packages, allowing you to conditionally execute tasks using `when` statements without relying on external commands or file checks. This approach is idempotent, efficient, and aligns with Ansible's declarative philosophy.

Exam trap

The trap here is that candidates confuse `ansible_facts.packages` (which is a variable that must be populated by `package_facts`) with a pre-existing fact, leading them to choose option C without realizing the module is required first.

How to eliminate wrong answers

Option A is wrong because the `stat` module checks file existence, not package installation status; a package may be installed without its files in a predictable location, or files may exist from a different source. Option B is wrong because the `command` module is not idempotent and requires parsing command output (e.g., `rpm -q`), which is fragile, platform-specific, and violates Ansible's best practices of using dedicated modules. Option C is wrong because `ansible_facts.packages` is not automatically populated; it is only available after running the `package_facts` module or if the `gather_subset` includes `packages`, which is not the default and not a direct method to check package status.

3
MCQmedium

A team is writing an Ansible role to configure a web server. They want to include default variables that can be easily overridden by playbook variables. Which directory and file should they use to define these variables?

A.vars/defaults.yml
B.defaults/main.yml
C.default_vars/main.yml
D.vars/main.yml
AnswerB

Placing variables in defaults/main.yml gives them the lowest precedence in Ansible's variable hierarchy, so playbook vars, host vars and role params all override them automatically. This satisfies the stem's requirement for easily overridden role defaults, unlike vars/main.yml, whose higher precedence resists such overrides.

Why this answer

In Ansible roles, default variables are defined in the `defaults/main.yml` file. These variables have the lowest precedence, meaning they can be easily overridden by playbook variables, inventory variables, or any other variable source with higher precedence. This design allows role authors to provide sensible defaults while giving users the flexibility to customize behavior without modifying the role itself.

Exam trap

The trap here is that candidates confuse the `defaults/` directory (lowest precedence) with the `vars/` directory (higher precedence), or they invent non-standard directory names like `default_vars/`, because the exam tests precise knowledge of the Ansible role directory structure and variable precedence rules.

How to eliminate wrong answers

Option A is wrong because `vars/defaults.yml` is not a standard Ansible role directory structure; Ansible expects default variables in a `defaults` directory, not a `vars` directory. Option C is wrong because `default_vars/main.yml` uses an incorrect directory name; the correct directory is `defaults`, not `default_vars`. Option D is wrong because `vars/main.yml` is used for role variables that have higher precedence and are not intended to be easily overridden by playbook variables; placing defaults in `vars/` would make them harder to override, defeating the purpose of easily overridable defaults.

4
MCQeasy

An administrator wants to run a specific set of tasks only on hosts that are members of the 'webservers' group. Which Ansible construct should be used to conditionally execute those tasks based on group membership?

A.Use the 'delegate_to' keyword to run tasks on a representative host from the group.
B.Use the 'when' condition with the 'group_names' variable.
C.Use the 'hosts' keyword in the play to target the 'webservers' group.
D.Use the 'when' condition with the inventory_hostname variable.
AnswerB

The group_names variable is a list of all groups the current host belongs to. A condition such as "'webservers' in group_names" will evaluate to true only on hosts in that group. This is the standard, dynamic way to conditionally run tasks based on inventory group membership without hardcoding hostnames.

Why this answer

The group_names variable contains the list of groups the current host belongs to. Using a when condition like "'webservers' in group_names" ensures the tasks run only on hosts in that group, regardless of the play's target. This is dynamic and adapts to inventory changes.

Exam trap

The trap here is confusing play-level targeting with task-level conditionals; targeting a group in the play runs all tasks on those hosts, but conditional execution requires a when clause.

5
MCQmedium

An administrator wants to run a playbook that executes tasks in parallel across multiple hosts but wants to limit the number of simultaneous hosts to 5. Which directive should be set?

A.poll
B.serial
C.throttle
D.forks
AnswerB

The serial directive controls how many hosts Ansible targets per play iteration, so setting serial: 5 runs tasks across at most five hosts simultaneously. It bounds parallelism while still completing all hosts in successive batches.

Why this answer

The `serial` directive in Ansible controls the number of hosts that execute a play at a time, allowing you to limit concurrency. Setting `serial: 5` ensures that only 5 hosts run tasks simultaneously, with the playbook completing in batches of 5 until all hosts are processed.

Exam trap

The trap here is confusing `forks` (which controls connection parallelism) with `serial` (which controls play-level batch execution), leading candidates to incorrectly choose `forks` when they need to limit simultaneous host execution per play.

How to eliminate wrong answers

Option A is wrong because `poll` is used with asynchronous tasks to set the interval for checking job status, not to limit simultaneous host execution. Option C is wrong because `throttle` limits the number of concurrent task executions per task or block, but it does not control the batch size of hosts across an entire play; it applies at a finer granularity. Option D is wrong because `forks` defines the maximum number of parallel connections Ansible makes to hosts, but it does not enforce a strict batch limit; with `forks` set to 5, Ansible could still start tasks on more than 5 hosts if the play has multiple tasks, as it controls parallelism at the connection level, not the play-level batch size.

6
MCQhard

Refer to the exhibit. An administrator runs the playbook but the wait_for task fails. What is the most likely cause?

A.The ansible_facts variable may not be available because fact gathering is disabled.
B.The http_port variable is misspelled.
C.The wait_for module requires the 'port' parameter to be an integer.
D.The delegate_to should be set to the remote host.
AnswerA

Correct: without gather_facts: yes, ansible_facts is empty.

Why this answer

The playbook uses `ansible_facts['ansible_tcpip_socket']['port']` to supply the port number to the `wait_for` module. If fact gathering is disabled (e.g., via `gather_facts: no` at the play level or `ANSIBLE_GATHERING=explicit`), the `ansible_facts` dictionary is empty, so the variable resolves to `None` or an undefined value, causing the task to fail. The error is not a syntax or type issue but a missing fact dependency.

Exam trap

The EX294 exam often tests the dependency between fact gathering and fact-based variables, trapping candidates who assume the error is a simple type mismatch or misspelling rather than a missing fact collection step.

How to eliminate wrong answers

Option B is wrong because the variable name `http_port` is not used in the playbook; the task references `ansible_facts['ansible_tcpip_socket']['port']`, so a misspelling of `http_port` is irrelevant. Option C is wrong because the `wait_for` module does accept the `port` parameter as a string (e.g., `'80'`) and will convert it internally; the error is not due to type mismatch. Option D is wrong because `delegate_to` is used to run a task on a different host, but the `wait_for` task is already targeting the remote host via `hosts: all`; delegating to the remote host would be redundant and not fix the missing fact issue.

7
Matchingmedium

Match each systemd unit type to its description.

Drag a concept onto its matching description — or click a concept then click the description.

Concepts
Matches

Background daemon or process

IPC or network socket

Time-based activation

Filesystem mount point

Group of units for synchronization

Why these pairings

Common systemd unit types include service (manages daemons), socket (manages IPC/network sockets), timer (schedules events), and mount (controls mount points). Be careful not to confuse timer with service.

8
Multi-Selecthard

An administrator is debugging a playbook that uses multiple roles and wants to limit execution to a specific set of tasks. Which three methods can be used to filter task execution? (Choose three.)

Select 3 answers
A.Use the '--tags' command-line option.
B.Use the '--skip-tags' command-line option.
C.Use the '--check' command-line option.
D.Use the '--step' command-line option.
E.Use the '--start-at-task' command-line option.
AnswersA, B, E

The --tags option restricts execution to tasks and roles carrying the named tags, so only those tagged tasks run. This filters execution without editing the playbook, satisfying the requirement to limit a multi-role playbook to a specific set of tasks.

Why this answer

Option A is correct because the '--tags' command-line option filters execution so that only tasks (and roles) tagged with the specified tag names are run, which directly limits a playbook to a specific set of tasks. Option B is correct because '--skip-tags' performs the inverse filtering, excluding tasks carrying the given tags while running everything else, another valid way to narrow execution. Option E is correct because '--start-at-task' begins execution at the first task whose name matches the given value, effectively limiting the run to that task and those following it.

Option C is not a filtering method: '--check' runs the playbook in dry-run/check mode, reporting changes without applying them. Option D is also not a filter: '--step' prompts interactively before each task, allowing the operator to confirm or skip tasks one at a time rather than selecting a task set.

Exam trap

The trap here is confusing options that control execution flow (like '--step' or '--check') with options that actually filter which tasks are included or excluded from the run, leading candidates to select non-filtering options.

9
MCQhard

A playbook includes a long-running task that should not block the rest of the playbook. The administrator wants to start the task and later check its status. Which method should be used?

A.Use the 'async' keyword with 'poll: 0' and then use async_status module.
B.Use 'delegate_to: localhost' and 'run_once'.
C.Use a separate playbook invoked with 'ansible-playbook' via command module.
D.Use 'throttle' to limit execution.
AnswerA

Fire-and-forget execution requires async with poll: 0, which returns immediately without blocking subsequent tasks. The async_status module then queries the job by its async job ID to retrieve completion state, satisfying the requirement to start the task and check its status later.

Why this answer

Setting `poll: 0` with the `async` keyword launches the task in the background without waiting for it to complete, and the `async_status` module can then be used later to check the task's status by referencing its job ID. This allows the playbook to continue executing other tasks while the long-running task runs asynchronously.

Exam trap

The trap here is that candidates confuse `async` with `throttle` or `delegate_to`, thinking any concurrency-related keyword will make a task non-blocking, when only `async` with `poll: 0` achieves true background execution.

How to eliminate wrong answers

Option B is wrong because `delegate_to: localhost` and `run_once` control where a task runs and how many times it executes, but they do not prevent a long-running task from blocking the playbook; the task still runs synchronously. Option C is wrong because using a separate playbook invoked via the `command` module with `ansible-playbook` is an anti-pattern that bypasses Ansible's built-in async support, adds unnecessary complexity, and still blocks until the subprocess finishes unless manually backgrounded. Option D is wrong because `throttle` limits the number of concurrent task executions but does not make a task non-blocking; the task still runs synchronously within its throttle slot.

10
MCQmedium

An administrator is writing a role where a task should only execute when the variable `web_package` is defined and its value is `httpd`. The role must not fail if the variable is undefined. Which task condition is correct?

A.when: web_package is defined and web_package == "httpd"
B.when: web_package == "httpd"
C.when: web_package | default("httpd") == "httpd"
D.when: web_package is defined or web_package == "httpd"
AnswerA

This condition first checks if the variable is defined, short-circuiting safely if it is not, then compares its value. Because Ansible evaluates conditions with Jinja2 and short-circuiting, referencing an undefined variable in the second part is avoided. This meets the requirement of not failing when the variable is missing and only running when the value is exactly httpd.

Why this answer

The task must run only when web_package is defined and its value is httpd, without failing if undefined. The condition using 'is defined' followed by 'and' correctly short-circuits so that the variable is only compared when it exists. The other conditions either fail on undefined variables, run when the variable is missing, or use incorrect logic.

Exam trap

The trap here is assuming that a simple equality check or a default filter safely handles undefined variables, but only the defined test with and short-circuits to prevent errors.

11
Multi-Selecteasy

Which two statements are true regarding Ansible roles? (Choose two.)

Select 2 answers
A.Role handlers are shared across all roles in the play.
B.A role can have a meta/main.yml file to define dependencies.
C.Role variables in vars/main.yml can be overridden by playbook vars.
D.Role default variables in defaults/main.yml have the lowest priority.
E.Roles can only be used in a playbook's roles section.
AnswersB, D

The meta/main.yml file within a role directory accepts a dependencies list, letting Ansible resolve and run prerequisite roles before the role's own tasks. This satisfies the scenario's need to declare role dependencies in a structured, supported location.

Why this answer

Option B is correct because a role's meta/main.yml file is exactly where role dependencies are declared under the dependencies key, allowing Ansible to automatically pull in and run other roles before the current one. Option D is correct because variables defined in defaults/main.yml have the lowest precedence in Ansible's variable hierarchy, meaning almost any other variable source (inventory, play vars, role vars, extra vars, etc.) will override them. Option A is wrong because handlers are scoped to the role or play that defines them, not shared globally across all roles.

Option C is wrong because vars/main.yml role variables have higher precedence than playbook vars, so playbook vars cannot override them. Option E is wrong because roles can also be included dynamically with include_role or imported with import_role, not only via the roles section.

Exam trap

The trap here is that candidates often confuse the priority of role variables (vars/main.yml) with default variables (defaults/main.yml), mistakenly thinking playbook vars can override role vars, when in fact defaults have the lowest priority and role vars are higher than playbook vars.

12
Multi-Selecthard

An administrator needs to ensure that a set of tasks runs only when a specific condition is met, and that the tasks are skipped without error otherwise. The condition depends on a variable that may be undefined. Which TWO approaches will safely evaluate the condition without causing an undefined variable error? (Choose two.)

Select 2 answers
A.Use the 'when' keyword with the 'is defined' test, such as "when: my_var is defined and my_var == 'value'".
B.Use the 'ignore_errors' keyword on the task and check the variable in a subsequent task.
C.Use the 'failed_when' keyword to define a custom failure condition based on the variable.
D.Use the 'when' keyword with the 'default' filter, such as "when: my_var | default(false)".
E.Use the 'when' keyword with the variable directly, such as "when: my_var == 'value'".
AnswersA, D

The 'is defined' test checks whether a variable exists before evaluating it. By combining it with 'and', the second part of the condition is only evaluated if the variable is defined, preventing an undefined variable error. This is a standard pattern for safely referencing potentially undefined variables in conditions.

Why this answer

Both the default filter and the 'is defined' test allow safe evaluation of potentially undefined variables in when conditions. The default filter supplies a fallback value, while 'is defined' short-circuits the condition to avoid evaluating the variable if it does not exist. Either approach prevents undefined variable errors and ensures tasks are skipped cleanly.

Exam trap

The trap here is assuming that Ansible treats undefined variables as false in when conditions, but it actually raises an error unless you explicitly guard against undefined values.

13
Multi-Selecthard

Which TWO statements about Ansible role defaults are true?

Select 2 answers
A.Defaults are only loaded if no vars are defined.
B.Defaults are loaded from the defaults/main.yml file.
C.Defaults have higher priority than variables defined in the playbook.
D.Defaults cannot be overridden.
E.Defaults have the lowest priority of all variables.
AnswersB, E

Defaults are loaded from `defaults/main.yml` within a role's directory structure, giving them the lowest precedence of any role variable. This satisfies the scenario's requirement by ensuring these values are easily overridden by inventory variables, playbook vars, or `--extra-vars`, making roles reusable across environments without editing role files.

Why this answer

Option B is correct because Ansible automatically loads role default variables from the defaults/main.yml file inside the role's directory structure, making it the standard location for defining fallback values. Option E is correct because defaults have the lowest precedence in Ansible's variable priority hierarchy, meaning nearly any other variable source (inventory vars, play vars, host vars, extra vars, etc.) will override them. Option A is incorrect because defaults are always loaded, not conditionally based on whether other vars exist; they simply get overridden when higher-priority variables are present.

Option C is incorrect because defaults have lower priority than playbook vars, not higher. Option D is incorrect because defaults are specifically designed to be easily overridden by higher-precedence variable sources.

Exam trap

The EX294 exam often tests the distinction between role defaults and role vars, where candidates mistakenly think defaults have higher priority or cannot be overridden, but in reality defaults are the lowest priority and designed to be overridden by any other variable source.

14
MCQhard

An Ansible playbook fails intermittently due to a service not starting in time. The administrator wants to configure a task to retry until the service confirms it is running. Which Ansible feature should be used?

A.Until loop with retries and delay.
B.Failed_when with conditional retry.
C.Block and rescue to catch failure.
D.Async with poll interval.
AnswerA

An until loop with retries and delay repeatedly runs the task until its condition evaluates true, pausing between attempts. This directly satisfies the intermittent-startup constraint: the service check is re-evaluated after each delay, so transient timing failures no longer abort the playbook.

Why this answer

The 'until' loop in Ansible repeatedly retries a task until a specified condition evaluates to true, and it can be combined with 'retries' and 'delay' to control how many attempts are made and how long to wait between them. This is the idiomatic way to handle a service that takes time to start, such as waiting for a port to open or a status command to succeed. It directly addresses intermittent timing failures without failing the playbook prematurely.

Exam trap

EX294 often tests the difference between retry mechanisms ('until' with retries/delay) and error-handling constructs ('block'/'rescue', 'failed_when'), so candidates who pick a recovery construct instead of a polling loop get it wrong.

How to eliminate wrong answers

Option B is wrong because 'failed_when' only redefines what constitutes a failure — it does not provide a retry mechanism by itself, so it cannot wait for a service to come up. Option C is wrong because 'block' and 'rescue' handle error recovery after a failure, not repeated polling until success; they are for exception handling, not retry loops. Option D is wrong because 'async' with a poll interval runs a task asynchronously and checks on it, but it is designed for long-running tasks, not for condition-based retries of a service check.

15
MCQhard

An administrator has a requirements.yml file specifying roles from multiple sources: a public Galaxy server, a private Git repository, and a local path. They want to install all roles into the roles directory of the current project. Which command will achieve this?

A.ansible-galaxy collection install -r requirements.yml
B.ansible-galaxy install -r requirements.yml --roles-path ./roles
C.ansible-galaxy install -r requirements.yml -p .
D.ansible-galaxy role install --force -r requirements.yml
AnswerB

The `-r` flag reads every entry in requirements.yml, resolving Galaxy, Git and local sources in one pass, while `--roles-path ./roles` overrides the default install location so roles land in the project's own roles directory rather than the user-level path — satisfying the stem's requirement to install all roles locally.

Why this answer

The command 'ansible-galaxy install -r requirements.yml --roles-path ./roles' installs roles from a requirements file into the specified roles directory. The '--roles-path' option (or '-p') sets the destination, and '-r' specifies the requirements file. This meets the requirement to install all roles into the roles directory of the current project.

Exam trap

EX294 often tests the distinction between 'ansible-galaxy install' and 'ansible-galaxy collection install', and the correct use of '--roles-path' versus '-p' with the right directory, causing candidates to choose commands that install to the wrong location.

How to eliminate wrong answers

Option A is wrong because 'ansible-galaxy collection install' is for collections, not roles, and it does not use '--roles-path'. Option C is wrong because '-p .' sets the roles path to the current directory, not the 'roles' subdirectory, so roles would be installed in the project root, not in 'roles'. Option D is wrong because 'ansible-galaxy role install --force -r requirements.yml' lacks the '--roles-path' option, so it installs to the default system roles path, not the project's roles directory.

16
MCQeasy

What is the purpose of the 'meta: flush_handlers' task?

A.Restart services immediately
B.Clear the handler queue
C.Wait for handlers to complete
D.Force handlers to run immediately
AnswerD

The meta: flush_handlers task interrupts the current play and executes all handlers notified so far, rather than waiting until the end of the play. This forces immediate handler execution at that point in the task sequence.

Why this answer

The 'meta: flush_handlers' task in Ansible is used to force any pending handler notifications to run immediately at that point in the play, rather than waiting until the end of the play. This is correct because it ensures that handlers triggered by earlier tasks execute right away, which is essential when subsequent tasks depend on the state changes those handlers make (e.g., restarting a service before configuring it further).

Exam trap

The trap here is that candidates confuse 'flush_handlers' with simply waiting for handlers to complete (Option C), not realizing that flush_handlers actively forces immediate execution of the handler queue, rather than passively waiting for the default end-of-play execution.

How to eliminate wrong answers

Option A is wrong because 'restart services immediately' is not a direct purpose of flush_handlers; handlers may include restarts, but flush_handlers forces all pending handlers to run, not just restarts. Option B is wrong because 'clear the handler queue' is the opposite of what flush_handlers does—it executes the queue, not empties it without execution. Option C is wrong because 'wait for handlers to complete' describes a passive behavior, whereas flush_handlers actively triggers execution of pending handlers at that point in the play.

17
MCQeasy

What is the purpose of the 'vars' keyword under the httpd role inclusion?

A.Set variables for the common role
B.Define new variables for the playbook
C.Set variables for all roles in the play
D.Override default variables for that role
AnswerD

Passing `vars` under a role inclusion overrides that role's default variables for the current play only, without editing the role's `defaults/main.yml`. This satisfies the scenario's need to customise role behaviour per host or play while keeping the role reusable and unmodified.

Why this answer

The 'vars' keyword under a role inclusion in Ansible allows you to override the default variables defined within that specific role. This is done at the point of inclusion, providing role-specific variable overrides without affecting other roles or the playbook's global variable scope.

Exam trap

The trap here is that candidates often confuse the 'vars' keyword under a role inclusion with setting global playbook variables, but it only overrides variables for that specific role instance.

How to eliminate wrong answers

Option A is wrong because 'vars' under a role inclusion does not set variables for the common role; it only affects the specific role being included. Option B is wrong because 'vars' does not define new variables for the playbook as a whole; it only provides variables to the included role. Option C is wrong because 'vars' under a single role inclusion does not set variables for all roles in the play; each role inclusion can have its own 'vars' block, and they are isolated to that role.

18
MCQhard

An administrator wants to define role dependencies. In which file should they place the dependencies declaration?

A.vars/main.yml
B.defaults/main.yml
C.tasks/main.yml
D.meta/main.yml
AnswerD

Role dependencies are declared under the dependencies key inside meta/main.yml within the role directory. Ansible reads this file during role loading and runs each listed dependency before the role's own tasks, satisfying the declaration requirement.

Why this answer

Role dependencies in Ansible are declared in the `meta/main.yml` file using the `dependencies` key. This allows you to specify other roles that must be executed before the current role, ensuring prerequisite tasks are run automatically.

Exam trap

The trap here is that candidates often confuse `meta/main.yml` with `tasks/main.yml` or variable files, assuming dependencies are defined in the task list or variable defaults, but Ansible specifically reserves `meta/main.yml` for role metadata including dependencies, author info, and supported platforms.

How to eliminate wrong answers

Option A is wrong because `vars/main.yml` is used to define variables for the role, not dependencies. Option B is wrong because `defaults/main.yml` is used to set default variable values, which have the lowest precedence and are not for dependencies. Option C is wrong because `tasks/main.yml` contains the main list of tasks to execute in the role, not dependency declarations.

19
MCQhard

An administrator is using a role that includes a task file conditionally with 'include_tasks' inside a loop. The task file contains a handler notification. The administrator notices that the handler is not being triggered for each iteration. What is the most likely reason?

A.The handler is notified only once per host, regardless of how many times it is notified.
B.The handler must be defined inside the included task file, not in the main role.
C.Handlers cannot be notified from tasks included with 'include_tasks'.
D.The 'include_tasks' module does not support loops; 'import_tasks' must be used instead.
AnswerA

Handlers in Ansible are designed to run only once per host, even if notified multiple times. This is intentional to avoid redundant service restarts. In a loop with 'include_tasks', each iteration may notify the handler, but it will only be triggered once at the end of the play. This explains why the handler is not triggered for each iteration, as the administrator might expect.

Why this answer

Handlers run only once per host per play, even if notified multiple times. In a loop with 'include_tasks', each iteration may notify the handler, but it will execute only once at the end of the play. This is by design to prevent multiple restarts.

The other options misstate limitations or requirements that do not exist.

Exam trap

The trap here is assuming handlers run once per notification, when they actually run once per host per play.

20
MCQmedium

Refer to the exhibit. The administrator wants to run a playbook that installs a package on all webservers. Which command will use the existing configuration and inventory correctly?

A.ansible-playbook -e 'ansible_python_interpreter=/usr/bin/python3' site.yml
B.ansible-playbook site.yml
C.ansible webservers -m package -a 'name=httpd state=present'
D.ansible-playbook -i inventory site.yml
AnswerB

ansible-playbook site.yml runs the playbook using the default ansible.cfg and inventory already present in the working directory, so existing host groupings such as webservers are honoured without extra flags. This matches the requirement to use the existing configuration and inventory correctly.

Why this answer

The command 'ansible-playbook site.yml' uses the default Ansible configuration file (ansible.cfg) and the default inventory location defined there. If the administrator has already configured the inventory and other settings in ansible.cfg, this command will correctly target the webservers group as defined in the playbook. No extra flags are needed because the existing configuration is assumed to be in place.

Exam trap

The trap is that candidates may think they need to specify the inventory explicitly with '-i' or provide interpreter variables, but the question states 'existing configuration and inventory correctly,' implying the default configuration already handles it.

How to eliminate wrong answers

Option A is wrong because it passes an extra variable for the Python interpreter, which is unnecessary if the inventory or ansible.cfg already specifies it, and it does not address inventory selection. Option C is wrong because it uses an ad-hoc ansible command rather than running the playbook, and it does not execute the playbook's tasks or use the playbook's logic. Option D is wrong because it explicitly specifies '-i inventory', which may override the configured inventory path and cause the playbook to use a different inventory than intended, potentially missing the webservers group.

21
MCQmedium

An administrator maintains a role named 'webserver' that is used by several teams. The role must run a handler named 'restart httpd' after a configuration file is changed, but only when the role is included with a variable 'notify_handler' set to true. The role's tasks/main.yml currently has a task that copies httpd.conf with 'notify: restart httpd'. Which change should the administrator make in the role to ensure the handler is notified only when 'notify_handler' is true?

A.Add 'run_once: true' to the handler and set 'notify_handler' in the role's defaults/main.yml.
B.Add 'listen: "{{ notify_handler }}"' to the handler and notify the handler with 'notify: "{{ notify_handler }}"'.
C.Add 'when: notify_handler | bool' to the handler definition in handlers/main.yml.
D.Add 'when: notify_handler | bool' to the task that copies httpd.conf in tasks/main.yml.
AnswerD

Placing the conditional on the task that copies the configuration file ensures the task only runs when 'notify_handler' is true. Because notification occurs only when a task reports 'changed', the handler will be notified only if the copy task actually executes and changes the file. This directly meets the requirement and is the standard Ansible pattern for conditionally notifying handlers from within a role.

Why this answer

The handler is notified only when a task reports a change. To make notification conditional, the condition must be applied to the task that performs the change and notifies the handler. Adding a 'when' clause to the copy task ensures the task runs only when 'notify_handler' is true, so the handler is queued only in that case.

Conditions on handlers themselves do not prevent notification from being queued.

Exam trap

The trap here is assuming that a 'when' condition on a handler prevents the handler from being notified, when in fact it only controls whether the handler runs after being queued.

22
MCQeasy

Which directive in an Ansible playbook ensures that a task runs only on the first host in a batch, and results are applied to all hosts?

A.run_once
B.any_errors_fatal
C.throttle
D.delegate_to: localhost
AnswerA

`run_once` executes the task on a single host — the first in the batch — while its results are applied to every host in the play. This satisfies the stem's constraint of limiting execution to one host yet propagating outcomes to all, avoiding redundant operations across the batch.

Why this answer

The run_once directive ensures that a task is executed only on the first host in the current batch of hosts. The results of that task are then applied to all hosts in the play. This is useful for tasks that should only be performed once, such as database migrations or generating a shared token, while still making the outcome available to all hosts.

Exam trap

EX294 often tests the distinction between run_once and other execution control directives like throttle and any_errors_fatal, and candidates may confuse run_once with delegate_to when both are used together.

How to eliminate wrong answers

Option B is wrong because any_errors_fatal causes the entire play to abort if any host fails a task, which is unrelated to running a task on a single host. Option C is wrong because throttle limits the number of hosts that execute a task concurrently, but it does not restrict execution to only the first host. Option D is wrong because delegate_to: localhost runs the task on the control node instead of the target hosts, but it does not ensure that the task runs only once; it would run for each host unless combined with other directives like run_once.

23
MCQhard

An administrator is building a role whose task list must run a platform-specific set of tasks: one file for Red Hat Enterprise Linux hosts and another for Debian hosts, with the choice made at runtime based on gathered facts. The role must remain readable and avoid loading the wrong file even partially. Which approach should the administrator use?

A.Place both platform task files in the role and rely on the role's meta/main.yml dependencies to select one.
B.Put the platform-specific tasks directly in tasks/main.yml and use tags to select which ones run.
C.Use ansible.builtin.include_tasks with a filename built from ansible_facts, so only the matching file is loaded at runtime.
D.Use ansible.builtin.import_tasks for both platform files and wrap each in a when condition.
AnswerC

include_tasks is processed dynamically during execution, so a filename assembled from a fact such as ansible_facts['os_family'] is evaluated when the task is reached and only the selected file is read. This keeps platform logic readable and avoids parsing the non-matching file entirely.

Why this answer

Dynamic inclusion through include_tasks evaluates the filename expression when the task executes, after facts are available, so exactly one platform file is loaded. Static import_tasks resolves at parse time and cannot branch on facts, and tags or meta dependencies are selected by the operator or parse order rather than by host platform.

Exam trap

The trap here is assuming that a when condition on an imported task file prevents that file from being parsed, when imports are resolved before facts exist.

24
MCQmedium

A team develops a custom Ansible role 'webserver' that depends on another role 'common'. They want to ensure that when 'webserver' is used, 'common' is automatically installed from the same Galaxy server. Which approach should they use?

A.Add a requirements.yml file in the role's root directory specifying common.
B.Add a dependencies: ['common'] to the role's meta/main.yml file.
C.Use ansible-galaxy install webserver --with-dependencies to install common separately.
D.Include the 'common' role in the playbook before 'webserver'.
AnswerB

Correct: Role dependencies in meta/main.yml are automatically installed.

Why this answer

Ansible roles can declare dependencies in the `meta/main.yml` file using the `dependencies` key. When the 'webserver' role is installed via `ansible-galaxy install`, Ansible automatically resolves and installs all listed dependencies from the same Galaxy server, ensuring 'common' is present without manual intervention.

Exam trap

The trap here is that candidates confuse role dependencies (declared in `meta/main.yml`) with playbook-level role ordering or external requirements files, leading them to choose options that manage execution order or manual installation instead of automatic dependency resolution.

How to eliminate wrong answers

Option A is wrong because a `requirements.yml` file in the role's root directory is not automatically processed by Ansible when installing a role; it is used at the project or playbook level to define external role collections for `ansible-galaxy install -r`. Option C is wrong because `--with-dependencies` is not a valid flag for `ansible-galaxy install`; dependencies are resolved automatically from `meta/main.yml` without requiring a separate flag. Option D is wrong because including 'common' in the playbook before 'webserver' only controls execution order at runtime, not installation; it does not ensure 'common' is installed from Galaxy automatically.

25
MCQhard

An administrator is using a role named 'app' that contains a task file 'install.yml' and a handler 'restart app'. The role is included in a playbook with 'include_role' and a variable 'app_version' set to '2.0'. The task file 'install.yml' includes a task that notifies the handler. During execution, the handler runs immediately after the task, before other tasks in the play. Which action should the administrator take to ensure the handler runs only at the end of the play?

A.Add 'meta: flush_handlers' after the role inclusion.
B.Set 'force_handlers: false' in the play to prevent handlers from running until the end.
C.Check the role for a 'meta: flush_handlers' task and remove it, because it forces handlers to run prematurely.
D.Ensure that the handler is not notified until the end of the play by moving the notification to a task that runs last.
AnswerC

Handlers normally run at the end of a play. If a handler runs immediately after the notifying task, the most likely cause is a 'meta: flush_handlers' task within the role or play that forces handlers to run at that point. Removing that task will restore the default behavior, where handlers run at the end of the play. This is the correct action to ensure the handler runs only at the end.

Why this answer

Handlers are designed to run at the end of a play. If a handler runs immediately after being notified, it is typically because a 'meta: flush_handlers' task is present, which explicitly forces handlers to run at that point. Removing that task restores the default behavior.

The other options either do not address the cause or would force handlers to run even earlier.

Exam trap

The trap here is confusing 'force_handlers' with handler timing; 'force_handlers' controls running handlers after failures, not when they run during a successful play.

26
Multi-Selectmedium

Which TWO of the following statements about Ansible roles are correct?

Select 2 answers
A.Role names must be prefixed with 'ansible-role-' when published to Ansible Galaxy.
B.Variables in 'defaults/main.yml' have the lowest precedence and can be overridden by inventory variables.
C.Role dependencies are defined in the 'meta/main.yml' file.
D.The 'include_role' module can only be used for static imports.
E.A role's tasks are executed before any 'pre_tasks' defined in the playbook.
AnswersB, C

Variables in `defaults/main.yml` sit at the bottom of Ansible's precedence order, below inventory group_vars, host_vars and play vars. This satisfies the stem's requirement that role defaults remain overridable, letting consumers customise a role without editing its files.

Why this answer

Option B is correct because variables defined in a role's defaults/main.yml have the lowest precedence in Ansible's variable hierarchy, meaning they can be overridden by inventory variables (host_vars, group_vars), play vars, and virtually any other variable source. Option C is correct because role dependencies are declared in the meta/main.yml file under the 'dependencies' key, which Ansible reads to automatically pull in and execute dependent roles before the current role. Option A is incorrect because the 'ansible-role-' prefix is only a naming convention recommended for Galaxy, not a mandatory requirement.

Option D is incorrect because include_role performs dynamic inclusion at runtime, whereas import_role is used for static imports. Option E is incorrect because pre_tasks in a playbook always run before the roles section, not after.

Exam trap

The trap is mixing up defaults vs vars precedence and static vs dynamic role inclusion; candidates often assume defaults override inventory variables or that include_role is static, both of which are backwards.

27
MCQeasy

An administrator wants to apply a role to a subset of hosts based on a condition. The condition should be evaluated for each host individually. Which approach is correct?

A.Use the 'tags' directive on the role and run the playbook with '--tags'.
B.Use the 'become' directive on the role to control privilege escalation.
C.Use the 'delegate_to' directive on the role to target specific hosts.
D.Use the 'when' directive on the role inclusion in the play.
AnswerD

Applying 'when' to a role inclusion (e.g., 'roles: - role: myrole when: condition') evaluates the condition per host. If true, the role is applied to that host. This is the standard way to conditionally apply roles on a per-host basis, ensuring the role's tasks run only where the condition is met.

Why this answer

The 'when' directive on a role inclusion evaluates the condition for each host, applying the role only where the condition is true. This is the correct method for per-host conditional role application. Tags, become, and delegate_to serve different purposes and do not provide conditional execution based on host-specific variables.

Exam trap

The trap here is thinking that tags or other directives can conditionally apply roles per host, when 'when' is the correct mechanism.

28
MCQhard

What is the most likely cause of the failure?

A.The --check flag prevents role variable resolution.
B.The nginx role's defaults or vars do not define 'nginx_version'.
C.The host web1 is not configured to use the nginx role.
D.The nginx role was not included in the playbook correctly.
AnswerB

The role references nginx_version, but neither defaults nor vars supply it. Ansible resolves variables from role defaults, vars, inventory, or playbook; with none defining nginx_version, the variable is undefined and templating fails during the play.

Why this answer

The error indicates that Ansible cannot resolve the variable 'nginx_version' during the playbook run. Since the `--check` flag only simulates changes and does not affect variable resolution, the most likely cause is that the nginx role's `defaults/main.yml` or `vars/main.yml` does not define this variable, leaving it undefined and causing the failure.

Exam trap

The trap here is that candidates often assume the `--check` flag is the culprit for any failure during a dry run, but Ansible's check mode still resolves all variables and validates templates, so a missing variable error is not caused by the check flag itself.

How to eliminate wrong answers

Option A is wrong because the `--check` flag does not prevent role variable resolution; it only skips the execution of modules that would make changes, while variable resolution still occurs normally. Option C is wrong because the host web1 does not need to be 'configured to use the nginx role' in a separate step; roles are applied via the playbook's `roles:` directive or `include_role`, and the error is about a missing variable, not role assignment. Option D is wrong because the error message does not indicate a syntax or inclusion issue with the role; it specifically points to an undefined variable, meaning the role was included but its variable definitions are incomplete.

29
MCQmedium

Refer to the exhibit. The playbook fails with an error. What is the most likely cause?

A.import_tasks cannot be used with a loop.
B.import_tasks must be placed in a role.
C.The loop variable should be referenced as '{{ item }}' without quotes.
D.The file names must be literal without templates.
AnswerA

The failure stems from `import_tasks` being static: it is parsed at playbook load time, so it cannot accept a `loop`, which is evaluated at runtime. The stem's error arises because the task file is imported before loop items exist. Switching to `include_tasks`, which is dynamic, resolves this constraint.

Why this answer

`import_tasks` is a static import that is processed at playbook parse time, before any variables or loops are evaluated. Ansible does not support using `import_tasks` inside a loop (`loop:` or `with_items:`) because the import occurs once during parsing, not dynamically per iteration. To run tasks repeatedly, you must use `include_tasks`, which is processed dynamically at runtime and supports loops.

Exam trap

Red Hat often tests the distinction between static (`import_tasks`) and dynamic (`include_tasks`) includes, and the trap here is that candidates confuse the two, thinking any include can be used with a loop, when only dynamic includes support iteration.

How to eliminate wrong answers

Option B is wrong because `import_tasks` does not need to be placed in a role; it can be used in any playbook or task file to import a list of tasks from another file. Option C is wrong because referencing the loop variable as `'{{ item }}'` with quotes is valid in Ansible; the error is not caused by quoting but by the static import limitation. Option D is wrong because file names in `import_tasks` can be templates (e.g., `{{ var }}.yml`) as long as they resolve to a valid file at parse time; the issue is not with templating but with the loop construct.

30
MCQeasy

A playbook includes multiple roles. The administrator wants to skip a specific role during execution. Which technique should they use?

A.Add a condition to each task in the role
B.Use the '--limit' option to exclude hosts
C.Use tags on the role and run with --tags
D.Use tags on the role and run with --skip-tags
AnswerD

Tags applied to a role let you selectively control execution; running ansible-playbook with --skip-tags excludes any role carrying that tag. This satisfies the requirement to skip one specific role while the remaining roles in the playbook still run.

Why this answer

Ansible roles support tagging, and the `--skip-tags` option allows you to exclude all tasks within a role that share a specific tag. By assigning a unique tag to the role (e.g., `tags: skip_me`) and running the playbook with `--skip-tags skip_me`, the entire role is skipped without modifying individual tasks or hosts.

Exam trap

Candidates often confuse --tags and --skip-tags, mistakenly choosing --tags when the goal is to skip a role.

How to eliminate wrong answers

Option A is wrong because adding a condition to each task in the role is inefficient, error-prone, and violates DRY principles; it requires modifying every task and does not leverage Ansible's built-in role-skipping mechanisms. Option B is wrong because `--limit` filters hosts, not roles or tasks; it cannot skip a specific role within a playbook that targets multiple hosts. Option C is wrong because using `--tags` includes only tagged items, but the question asks to skip a specific role, not to include only certain roles; `--tags` would require tagging all other roles and tasks, which is impractical and opposite to the goal.

31
MCQeasy

An Ansible playbook needs to ensure a service is enabled and running on boot. Which combination of parameters should be used with the 'systemd' module?

A.enabled: yes, state: reloaded
B.enabled: yes, state: started
C.enabled: yes, daemon_reload: yes
D.enabled: yes, state: restarted
AnswerB

Setting enabled: yes registers the unit for start on boot, while state: started ensures it is running now. Together they satisfy both halves of the stem's requirement, unlike state alone or enabled alone, which leave one condition unmet.

Why this answer

The 'systemd' module in Ansible requires both 'enabled: yes' to set the service to start on boot and 'state: started' to ensure the service is currently running. This combination directly fulfills the requirement of ensuring a service is enabled and running on boot.

Exam trap

The trap here is that candidates often confuse 'enabled' with 'state' or assume 'daemon_reload' or 'reloaded' can substitute for starting the service, but only the combination of 'enabled: yes' and 'state: started' fully satisfies the requirement for both boot persistence and current running state.

How to eliminate wrong answers

Option A is wrong because 'state: reloaded' only reloads the service's configuration without starting it if it is not running, and it does not guarantee the service is enabled on boot. Option C is wrong because 'daemon_reload: yes' only reloads the systemd manager configuration (e.g., after adding new unit files) but does not start the service or enable it on boot. Option D is wrong because 'state: restarted' restarts the service if it is running but does not ensure it is enabled to start on boot, and it will fail if the service is not already running.

32
Drag & Dropmedium

Drag and drop the steps to configure a logical volume (LV) using LVM on a new disk in the correct order.

Drag or tap steps into the slots.

Steps
Order
1Step 1
2Step 2
3Step 3
4Step 4

Why this order

The correct sequence for configuring a logical volume using LVM on a new disk is: first create a physical volume from the disk, then create a volume group from that physical volume, then create a logical volume from the volume group, then format the logical volume with a filesystem, and finally mount the filesystem to make it accessible. This order ensures that each step builds upon the previous one, following the LVM hierarchy of PV -> VG -> LV -> filesystem -> mount.

33
MCQhard

Refer to the exhibit. An administrator runs a playbook in check mode and receives the shown output. What should be done to fix the failure while maintaining idempotency?

A.Modify the deploy role to use the force parameter when copying files.
B.Add a task in the apache role to create the /var/www/html directory using the file module.
C.Run the playbook without check mode to force the deployment.
D.Add a pre_task in the playbook to create /var/www/html before roles execute.
AnswerB

Creating the directory with the file module declares the desired state, so repeated runs report no change and idempotency holds. The failure stems from httpd's document root being absent before the copy task runs; the file module with state: directory satisfies that prerequisite declaratively rather than through an imperative shell command.

Why this answer

The failure in check mode indicates that the /var/www/html directory does not exist, and the apache role's copy task cannot write to it. The correct fix is to add a task in the apache role that uses the file module to create the directory with the desired state (e.g., state: directory), ensuring idempotency because the task will only create it if absent. This keeps the role self-contained and maintains idempotent behavior.

Exam trap

EX294 often tests the misconception that running without check mode or using force parameters resolves missing directory issues, but the real fix is to ensure the role itself creates required directories idempotently.

How to eliminate wrong answers

Option A is wrong because using the force parameter on the copy module only overwrites existing files; it does not create missing parent directories and would still fail. Option C is wrong because running without check mode does not fix the underlying missing directory; it would still fail unless the directory is created, and it breaks idempotency by potentially making changes without proper state management. Option D is wrong because adding a pre_task in the playbook creates the directory outside the role, which reduces role reusability and may not be idempotent if the pre_task is not properly written; it also violates the principle of keeping role dependencies within the role.

34
MCQmedium

An administrator is writing a playbook that must execute a task only when a specific variable is defined. The variable may be set in the inventory, group_vars, or host_vars. Which conditional ensures the task runs only if the variable 'app_port' is defined?

A.when: app_port is exists
B.when: app_port is not undefined
C.when: app_port
D.when: app_port is defined
AnswerD

The 'is defined' test is the correct Ansible conditional to check if a variable exists in the current host's context. It evaluates to true if 'app_port' is set from any source, including inventory, group_vars, or host_vars. This directly satisfies the requirement without erroring if the variable is missing, unlike a direct truthiness check.

Why this answer

The 'is defined' test is the standard way to check if a variable exists in Ansible. It correctly handles variables set from any source and avoids errors when the variable is missing. The other options either test truthiness, use invalid syntax, or confuse file existence with variable definition.

Only the correct option reliably ensures the task runs when 'app_port' is defined.

Exam trap

The trap here is confusing variable existence with truthiness or using an invalid test like 'is not undefined' or 'is exists'.

35
MCQhard

Refer to the exhibit. An administrator runs an Ansible playbook and receives the error shown. The playbook uses a variable 'vault_httpd_port' that should be stored in an encrypted vault file. Which step should the administrator take first to resolve the issue?

A.Re-encrypt the vault file with a different password.
B.Add 'vault_httpd_port' to the group_vars/all.yml file without encryption.
C.Use the --ask-vault-pass option again with a different password.
D.Ensure the vault file is referenced in the playbook using include_vars or vars_files, and that the vault password is correct.
AnswerD

Referencing the vault file via `vars_files` or `include_vars` is what actually loads `vault_httpd_port` into the play's variable scope; without that, Ansible cannot decrypt or resolve it, producing the undefined-variable error. Supplying the correct vault password then allows decryption to succeed, satisfying the stem's encrypted-vault constraint.

Why this answer

The error indicates Ansible cannot find the variable 'vault_httpd_port' because the encrypted vault file containing it is not being loaded into the playbook's variable scope. The administrator must first verify that the vault file is properly referenced via include_vars or vars_files in the playbook, and that the correct vault password is supplied (e.g., via --ask-vault-pass or a vault password file). Without loading the vault file, the variable remains undefined regardless of encryption password changes.

Exam trap

EX294 often tests the misconception that simply re-encrypting or changing the vault password resolves variable loading issues, when the real problem is that the vault file is not referenced in the playbook.

How to eliminate wrong answers

Option A is wrong because re-encrypting the vault file with a different password does not address the missing variable reference or loading mechanism. Option B is wrong because storing the variable unencrypted in group_vars/all.yml defeats the purpose of vault encryption and does not resolve the underlying issue of the vault file not being loaded. Option C is wrong because using --ask-vault-pass with a different password is only relevant if the vault file is already referenced; the primary issue is that the vault file is not being included or referenced in the playbook.

36
MCQeasy

In an Ansible playbook, the 'strategy' parameter is set to 'free'. What behavior does this strategy produce?

A.Playbook runs tasks on hosts in batches of 1.
B.Strategy is deprecated and replaced by 'linear'.
C.All hosts run the same task at the same time, then move to the next task.
D.Each host runs through the playbook independently of other hosts.
AnswerD

The free strategy lets each host proceed through the play at its own pace without waiting at task barriers for other hosts, so hosts complete independently. This differs from linear, which synchronises hosts at each task.

Why this answer

The 'free' strategy in Ansible allows each host to run through the playbook independently, without waiting for other hosts to finish the current task. This means a faster host can proceed to subsequent tasks while slower hosts are still working on earlier tasks, maximizing parallelism and reducing overall execution time.

Exam trap

The trap here is confusing the 'free' strategy with the 'serial' parameter or the default 'linear' strategy, leading candidates to incorrectly associate batching or synchronized task execution with 'free'.

How to eliminate wrong answers

Option A is wrong because the 'free' strategy does not run tasks in batches of 1; that behavior is achieved by setting the 'serial' parameter to 1, which controls batch size, not the strategy. Option B is wrong because the 'free' strategy is not deprecated and is still fully supported; the 'linear' strategy is the default, not a replacement for 'free'. Option C is wrong because it describes the 'linear' strategy, where all hosts execute the same task simultaneously before moving to the next task; the 'free' strategy allows hosts to proceed independently.

37
Multi-Selecteasy

Which TWO elements can be used to include external task files in a playbook?

Select 2 answers
A.import_tasks
B.include_tasks
C.include_vars
D.add_host
E.include_role
AnswersA, B

import_tasks is processed statically at playbook parse time, splicing the external task file into the play before execution. This makes it one of the two valid elements for including external task files in a playbook.

Why this answer

Both A. import_tasks and B. include_tasks are the two Ansible directives designed to bring external task files into a playbook, which is exactly what the scenario asks for. import_tasks is processed statically at playbook parse time, so the referenced YAML file's tasks are inserted before execution begins, making it suitable for fixed, always-included task lists. include_tasks is processed dynamically at runtime, allowing the included file to be chosen conditionally or looped over, which is useful when the task file depends on variables or facts. The other options do not belong: include_vars loads variables from an external file rather than tasks, add_host dynamically adds a host to the in-memory inventory, and include_role imports a role (which may contain tasks) but is not the directive for including a standalone external task file.

Exam trap

The trap here is that candidates often confuse `include_tasks` and `import_tasks` with variable-loading or inventory-modifying modules, or they mistakenly think `include_role` can be used to include arbitrary task files instead of entire roles.

38
MCQmedium

An administrator has a role named 'web' that must run a package installation task before any other tasks in the role. The role contains a tasks/main.yml file and a meta/main.yml file. The administrator wants the package installation to be a separate role named 'common' that is always executed first when the 'web' role is applied. Which approach should the administrator use?

A.Add the 'common' role to the roles list in the play before the 'web' role.
B.Add a dependencies section to meta/main.yml in the 'web' role listing the 'common' role.
C.Use include_role with a when condition in tasks/main.yml of the 'web' role.
D.Use import_tasks in tasks/main.yml to import a tasks file from the 'common' role.
AnswerB

Role dependencies defined in meta/main.yml cause the listed roles to execute before the current role. This ensures the 'common' role runs first, installing packages before any 'web' tasks. Dependencies are resolved at playbook parse time and are the standard mechanism for ordering role execution without modifying the play itself.

Why this answer

Role dependencies declared in meta/main.yml cause the dependent role to execute before the current role. This ensures the 'common' role's package installation runs first whenever 'web' is applied, regardless of the playbook. It is the intended way to express that one role requires another, keeping the relationship self-contained within the role.

Exam trap

The trap here is assuming that listing roles in a play is equivalent to defining a dependency, but a play-level list only orders roles for that specific play and does not enforce the dependency for other playbooks.

39
MCQmedium

An administrator needs to ensure that a task runs only on the first host in a batch and that its result is applied to all hosts in the batch. Which Ansible directive should be used?

A.run_once: true
B.delegate_to: localhost
C.serial: 1
D.any_errors_fatal: true
AnswerA

'run_once: true' forces the task to execute on only one host (the first host in the current batch) and applies the results to all hosts in the play. This is exactly the requirement. It is commonly used for tasks like database migrations or cluster initialization that should happen only once, with the outcome affecting all hosts.

Why this answer

The 'run_once: true' directive ensures a task runs only on the first host in the batch and that the results are applied to all hosts. This is ideal for one-time operations. The other options either delegate to the control node, change batching, or affect error handling, none of which satisfy the specific requirement.

Exam trap

The trap here is confusing 'run_once' with delegation or serial batching, which control different aspects of execution.

40
MCQeasy

You are managing a web application deployment using Ansible. The application requires a specific version of a library (libapp) to be installed on all web servers. Your current playbook uses the role 'web' which includes a task to install libapp version 1.2. However, after a recent update, the role's defaults now specify libapp version 2.0, but you must keep version 1.2 for compatibility. You have defined a variable 'lib_version' in the playbook's vars section with value '1.2'. The role's task uses the variable 'libapp_version' (not 'lib_version'). The play fails because 'libapp_version' is undefined. What is the best way to resolve this issue without modifying the role?

A.Modify the role's defaults/main.yml to set libapp_version to 1.2.
B.Use the playbook to set libapp_version as a variable for the role: either in the play vars section or by passing it as a role parameter.
C.Rename your playbook variable from lib_version to libapp_version in the play vars.
D.Create a file roles/web/vars/main.yml with libapp_version: 1.2.
AnswerB

The role reads libapp_version, so supplying that exact variable name overrides the role default of 2.0 while leaving the role untouched. Setting it in play vars or as a role parameter satisfies the requirement to keep libapp version 1.2.

Why this answer

It allows you to set the variable `libapp_version` that the role expects without modifying the role itself. By defining `libapp_version` in the playbook's vars section or passing it as a role parameter, you override the role's default value (2.0) with the required version 1.2, ensuring the task uses the correct library version while preserving role integrity.

Exam trap

The trap here is that candidates may confuse variable names (lib_version vs libapp_version) and attempt to rename variables or modify role defaults, rather than understanding that the correct solution is to set the exact variable expected by the role at the playbook level.

How to eliminate wrong answers

Option A is wrong because modifying the role's defaults/main.yml directly changes the role, which violates the requirement to not modify the role. Option C is wrong because renaming the playbook variable from `lib_version` to `libapp_version` does not address the issue; the role's task uses `libapp_version`, and simply renaming the variable in the playbook's vars section would still leave `libapp_version` undefined unless the variable is explicitly set. Option D is wrong because creating a file roles/web/vars/main.yml modifies the role's internal structure, which is not allowed per the requirement to not modify the role.

41
MCQhard

A developer wants to reuse a set of tasks that conditionally include other task files based on variables defined per host. Which method should be used to ensure the included tasks are evaluated per host at runtime?

A.include_tasks
B.include_role
C.import_role
D.import_tasks
AnswerA

`include_tasks` is processed dynamically at runtime for each host, so conditional expressions and variables are evaluated per host as the play executes. This satisfies the requirement that included task files be selected based on host-specific variables, unlike static `import_tasks`, which resolves everything when the playbook is parsed.

Why this answer

Include_tasks, because it dynamically loads and evaluates task files at runtime, allowing conditional logic and per-host variables to be resolved when the tasks are executed. This is essential for reusing a set of tasks that conditionally include other task files based on variables defined per host, as include_tasks processes the included file fresh each time it is encountered, respecting any host-specific variable context.

Exam trap

The trap here is that candidates confuse static imports (import_tasks, import_role) with dynamic includes (include_tasks, include_role), not realizing that static imports are resolved at parse time and cannot handle per-host conditional logic at runtime.

How to eliminate wrong answers

Option B (include_role) is wrong because it dynamically includes an entire role at runtime, not a set of tasks that conditionally include other task files; it is designed for role reuse, not granular task file inclusion based on per-host variables. Option C (import_role) is wrong because it statically imports a role at playbook parse time, meaning all tasks and dependencies are pre-processed and cannot be conditionally evaluated per host at runtime. Option D (import_tasks) is wrong because it statically imports task files at parse time, so any conditional logic or variable-based inclusion is resolved before the playbook runs, preventing per-host runtime evaluation.

42
MCQeasy

An administrator wants to ensure a role's tasks are executed only on certain hosts. Which approach should they use?

A.Set host_vars for each target host
B.Set group_vars for the target group
C.Use a 'when' condition in the role's tasks
D.Use tags on the role
AnswerC

A 'when' condition evaluates host facts or variables at runtime, so tasks run only where the predicate is true. This satisfies the stem's constraint of restricting a role's tasks to certain hosts, though it filters per task rather than limiting which hosts the role targets.

Why this answer

Ansible's 'when' clause allows conditional execution of tasks based on variables such as inventory hostname, group membership, or custom facts. By using a 'when' condition that checks the target host's identity (e.g., 'ansible_hostname' or 'inventory_hostname'), the administrator can ensure that the role's tasks run only on specific hosts, without modifying inventory structure or using separate variable files.

Exam trap

The trap here is that candidates often confuse variable scoping (host_vars/group_vars) with conditional execution, assuming that setting variables for a host or group inherently limits task execution to those hosts, when in fact variables only provide data and do not control task flow without an explicit 'when' condition.

How to eliminate wrong answers

Option A is wrong because setting host_vars for each target host defines variables per host but does not control task execution; tasks will still run on all hosts unless a 'when' condition references those variables. Option B is wrong because group_vars define variables for all hosts in a group, but tasks will execute on every host in that group unless a 'when' condition is added; group_vars alone cannot restrict execution to a subset of hosts within the group. Option D is wrong because tags on a role are used to selectively include or exclude tasks during playbook runs via the '--tags' or '--skip-tags' options, but they do not enforce host-based restrictions; tags control which tasks run globally, not which hosts they run on.

43
MCQeasy

You need to run an Ansible playbook every hour to update a dynamic inventory file from a CMDB API. The playbook is stored in /opt/ansible/update_inventory.yml. You want to schedule the execution using a cron job on the control node. The control node runs Red Hat Enterprise Linux 9. The playbook uses Ansible Vault to decrypt API credentials, and the vault password is stored in /etc/ansible/.vault_pass. Which cron entry will execute the playbook hourly?

A.0 * * * * /usr/bin/ansible-playbook --vault-password-file ~/.vault_pass /opt/ansible/update_inventory.yml
B.* * * * * /usr/bin/ansible-playbook --vault-password-file /etc/ansible/.vault_pass /opt/ansible/update_inventory.yml
C.0 * * * * /usr/bin/ansible --vault-password-file /etc/ansible/.vault_pass /opt/ansible/update_inventory.yml
D.0 * * * * /usr/bin/ansible-playbook --vault-password-file /etc/ansible/.vault_pass /opt/ansible/update_inventory.yml
AnswerD

The cron field '0 * * * *' runs the job at minute zero of every hour, satisfying the hourly requirement. Supplying --vault-password-file lets ansible-playbook decrypt the API credentials non-interactively, which is essential because cron has no TTY for the vault prompt.

Why this answer

It specifies the correct cron schedule (0 * * * * for hourly), uses the correct command (ansible-playbook), and points to the correct vault password file (/etc/ansible/.vault_pass) as specified in the stem. Option A uses the wrong vault password file path (~/.vault_pass). Option B uses the wrong schedule (every minute).

Option C uses the wrong command (ansible instead of ansible-playbook).

44
MCQeasy

An administrator needs to execute a role named `common` on all hosts in the play, but only for hosts that are members of the `webservers` group. Which playbook construct achieves this?

A.Apply the role under a play with hosts: webservers.
B.Add a task with delegate_to: webservers before including the role.
C.Set a variable in group_vars/webservers.yml and use it in the role's tasks.
D.Use the roles keyword with a when condition on the group name.
AnswerA

Defining the play with hosts: webservers ensures the role only runs on hosts in that group. Roles applied in a play are executed on all hosts targeted by the play. This is the standard and simplest way to restrict role execution to a specific host group.

Why this answer

The most direct way to run a role only on a specific group is to target that group in the play's hosts directive. Roles run on all hosts in the play, so restricting the play's hosts restricts the role. Other options either do not filter hosts or misuse Ansible features.

Exam trap

The trap here is overcomplicating host targeting with conditions or variables when the play's hosts directive is the correct and simplest mechanism.

45
Multi-Selectmedium

An administrator is building a reusable role and must decide how to structure variables so that callers can override values while the role still ships sensible starting values. Which TWO practices are appropriate for this role design? (Choose two.)

Select 2 answers
A.Place values that must not be changed by callers in vars/main.yml so they outrank most other sources.
B.Store role variables in the inventory host file so each host can be tuned individually.
C.Place starting values in defaults/main.yml so they have low precedence and are easily overridden.
D.Require callers to pass every value as an extra variable with -e on the command line.
E.Define all role variables in the play's vars section so they are inherited by every role in the play.
AnswersA, C

Variables in vars/main.yml carry high precedence, above inventory and play variables, so they resist accidental overrides by callers. This makes them suitable for internal constants the role depends on, while still allowing extra variables or role parameters to take precedence when a deliberate change is required.

Why this answer

A well-designed role separates low-precedence starting values from high-precedence internal constants. Defaults give callers an easy override path, while vars/main.yml protects values the role must control. Play vars, inventory host data, and mandatory extra variables all bind the role to a specific context and undermine reuse.

Exam trap

The trap here is treating defaults and vars as interchangeable, when their precedence difference is what makes one overridable and the other protected.

46
MCQmedium

An Ansible role has a complex dependency tree. The administrator wants to ensure that dependencies are installed before the main role tasks. Which file should be used to define dependencies?

A.meta/main.yml
B.defaults/main.yml
C.tasks/main.yml
D.vars/main.yml
AnswerA

Dependencies declared in meta/main.yml are processed by Ansible before the role's tasks execute, guaranteeing prerequisite roles run first. This satisfies the constraint of ensuring dependencies install ahead of the main role in a complex dependency tree.

Why this answer

In Ansible, role dependencies are defined in the `meta/main.yml` file using the `dependencies` key. This ensures that any listed roles are executed before the main role's tasks, providing a controlled execution order. The `meta/main.yml` file is specifically designed for metadata such as dependencies, author information, and supported platforms.

Exam trap

The trap here is that candidates often confuse `meta/main.yml` with `tasks/main.yml` or `vars/main.yml`, mistakenly thinking dependencies can be defined in the same file as tasks or variables, when in fact only `meta/main.yml` supports the `dependencies` directive.

How to eliminate wrong answers

Option B is wrong because `defaults/main.yml` is used to define default variable values for the role, not dependencies. Option C is wrong because `tasks/main.yml` contains the main list of tasks to execute for the role, but it does not support dependency declarations. Option D is wrong because `vars/main.yml` is used to define variables with higher precedence than defaults, but it cannot define role dependencies.

47
MCQhard

A role's tasks/main.yml contains a task that uses `notify: restart service`. The handler is defined in handlers/main.yml. During a playbook run, the task reports 'changed' but the handler does not run until the end of the play. The administrator wants the handler to run immediately after the task, before any subsequent tasks. Which action should be taken?

A.Change the handler to use listen: restart service and set run_once: true.
B.Set force_handlers: true in the play and use serial: 1.
C.Move the handler definition into the same tasks/main.yml file and rename it.
D.Add a task using meta: flush_handlers immediately after the notifying task.
AnswerD

Handlers run at the end of each play by default, or when explicitly flushed. Inserting a meta: flush_handlers task right after the notifying task forces all pending handlers to execute at that point, before any later tasks. This fulfills the requirement to run the handler immediately after the task that notified it.

Why this answer

Handlers by default execute at the end of the play after all tasks complete. To run them earlier, a meta: flush_handlers task must be inserted at the desired point. Other options either change failure behavior, batching, or definition location, none of which alter the execution timing of handlers.

Exam trap

The trap here is thinking that handler options like run_once or force_handlers change when handlers execute, but only explicit flushing or play end triggers them.

48
MCQhard

Refer to the exhibit. The administrator runs the playbook with the 'deploy' tag, but all tasks are skipped. What is the most likely reason?

A.The --tags option filters tasks; only tasks with the 'deploy' tag run, but none of the role tasks have that tag.
B.The role 'database' is not found in the roles_path.
C.The inventory host db1.example.com is not in the dbservers group.
D.The tags in the role tasks conflict with the play tags, causing a syntax error.
AnswerA

The `--tags deploy` filter runs only tasks carrying that tag, so untagged role tasks are skipped entirely. Since Ansible applies tag filtering at task level and roles do not inherit tags from the play, every task lacking an explicit `deploy` tag is excluded, producing the all-skipped output described in the stem.

Why this answer

Ansible's --tags option filters task execution so that only tasks tagged with the specified tag(s) run. If the playbook is executed with '--tags deploy' but none of the tasks inside the 'database' role have the 'deploy' tag applied, all tasks are skipped. This is the most likely reason given the symptom that all tasks are skipped rather than an error being raised.

Exam trap

EX294 often tests the misconception that tags applied at the play or role-inclusion level automatically propagate to all tasks inside a role — they do not unless 'apply' or explicit task tags are used, leading to silent skips.

How to eliminate wrong answers

Option B is wrong because if the role 'database' were not found in roles_path, Ansible would raise a fatal error ('role not found') rather than silently skipping all tasks. Option C is wrong because if the host were not in the 'dbservers' group, the play would simply have no hosts to run against (or skip the host), but the symptom described is that tasks are skipped, which points to tag filtering. Option D is wrong because tag conflicts do not cause syntax errors — tags are additive and non-conflicting; Ansible would not fail with a syntax error due to tag mismatches.

49
MCQmedium

An administrator maintains a role named 'webserver' whose tasks reference the variable 'http_port'. The playbook calls the role twice within the same play, first with http_port set to 8080 and then with http_port set to 8443, expecting two differently configured deployments. After the run, both deployments use port 8443. Which change to the role invocation should the administrator make so each invocation uses its own value?

A.Define http_port in group_vars for every managed host in the inventory.
B.Pass the variable with the 'vars' keyword on the 'roles' entry for each invocation.
C.Declare http_port in the role's defaults/main.yml and override it with set_fact before each role entry.
D.Add 'allow_duplicates: true' to the role's meta/main.yml file and pass the variable on the command line with -e.
AnswerB

Variables supplied through the 'vars' keyword on a role entry are scoped to that individual role invocation, so the first call receives 8080 and the second receives 8443 independently. This is the documented way to parameterize the same role multiple times inside one play without the values bleeding between invocations.

Why this answer

Each entry in the 'roles' list is a separate role invocation, and the 'vars' keyword attached to that entry scopes the supplied variables to that invocation only. This lets one role run twice in the same play with different parameter values. Inventory variables, defaults, extra variables, or persistent facts all resolve at host or play scope, so they cannot differentiate the two calls.

Exam trap

The trap here is believing that adding allow_duplicates alone gives each role call its own variables, when it only permits the duplicate role to run.

50
MCQeasy

Refer to the exhibit. An Ansible playbook task fails with 'Missing sudo password'. The playbook runs against a server where the remote user 'admin' has sudo privileges but requires a password. Which configuration change would resolve this issue?

A.Set ansible_become_password or use the -K flag when running the playbook.
B.Change become_method to su to avoid password prompts.
C.Remove the become_user line and rely on default root.
D.Change become_user to root.
AnswerA

Supplying the sudo password via `ansible_become_password` or the `-K` prompt lets Ansible satisfy the privilege-escalation credential the remote user requires. The stem's constraint is that `admin` holds sudo rights but sudo demands a password; without that secret, become fails with 'Missing sudo password'. This directly resolves it.

Why this answer

The error 'Missing sudo password' occurs because Ansible needs the sudo password for the remote user. Option A provides the password either by setting ansible_become_password in inventory or using the -K flag to prompt for it. Option B is incorrect because switching to su does not solve the password issue and is unnecessary.

Option C is incorrect because removing become_user doesn't address the password requirement. Option D is incorrect because changing become_user to root doesn't provide the needed password.

51
MCQeasy

Which ansible.cfg setting controls the number of parallel forks for task execution?

A.parallel
B.max_parallel
C.forks
D.threads
AnswerC

The forks directive in the [defaults] section sets how many hosts Ansible configures concurrently, each fork being a separate worker process. Raising it increases parallelism across the inventory; leaving it at the default of five limits throughput on large host counts.

Why this answer

The `forks` setting in `ansible.cfg` (or the `ANSIBLE_FORKS` environment variable) controls the maximum number of parallel processes Ansible uses when executing tasks on remote hosts. By default, this value is 5, meaning Ansible will manage up to 5 hosts concurrently per playbook run. Increasing this value allows Ansible to operate on more hosts simultaneously, improving throughput in larger environments.

Exam trap

The trap here is that candidates may confuse Ansible's `forks` with generic terms like `parallel` or `threads`, or with similar settings from other configuration management tools, leading them to select a plausible-sounding but incorrect option.

How to eliminate wrong answers

Option A is wrong because `parallel` is not a valid Ansible configuration setting; Ansible uses the `forks` parameter to control parallelism. Option B is wrong because `max_parallel` does not exist in Ansible's configuration; it may be confused with a similar concept in other tools like Puppet or SaltStack. Option D is wrong because `threads` is not an Ansible configuration key; Ansible uses multiprocessing (fork-based) rather than threading for parallel execution, and `threads` is unrelated to the number of concurrent hosts.

52
MCQeasy

Which best practice should be followed when using Ansible to manage task execution across multiple hosts?

A.Use 'ignore_errors: yes' on all tasks to prevent playbook failures.
B.Ensure tasks are idempotent so they can be run multiple times without changing the system state beyond the desired state.
C.Always use serial execution to avoid race conditions.
D.Write tasks that rely on the previous task's output to ensure correct order.
AnswerB

Idempotence means repeated runs converge on the same desired state without side effects, which is essential when a play targets many hosts and some tasks may be retried or partially applied. It keeps multi-host execution predictable and safe.

Why this answer

Idempotency is a core principle of Ansible: running the same playbook multiple times should produce the same desired state without unintended side effects. This ensures predictable, safe task execution across multiple hosts, as Ansible modules are designed to check the current state before making changes.

Exam trap

The trap here is that candidates confuse 'ignore_errors' with a valid error-handling strategy, or assume serial execution is always safer, when in fact idempotency is the fundamental best practice that Ansible's design revolves around.

How to eliminate wrong answers

Option A is wrong because 'ignore_errors: yes' on all tasks would suppress legitimate failures, making debugging impossible and potentially leaving systems in an inconsistent or broken state. Option C is wrong because serial execution is not always necessary; Ansible's default parallel execution (via forks) is efficient and safe for idempotent tasks, and serial is only used for specific rolling-update scenarios. Option D is wrong because relying on previous task output creates tight coupling and non-idempotent workflows; Ansible encourages using facts, registered variables, and idempotent modules to maintain order without hard dependencies.

53
MCQeasy

A playbook targets a group of database servers and must run a backup task only on one host at a time, waiting for each host to finish before starting the next, so that a shared storage array is not saturated. Which play keyword should the administrator set to achieve this serialized behavior?

A.serial: 1
B.throttle: 1
C.order: sequential
D.strategy: host_pinned
AnswerA

The serial keyword controls how many hosts are taken from the play's host list and processed as a batch. Setting it to 1 makes Ansible complete the entire play on one host before moving to the next, which serializes execution and prevents simultaneous load on the shared storage array.

Why this answer

The serial keyword defines the batch size for a play, and a value of 1 forces Ansible to finish all tasks on one host before selecting the next host from the group. This produces strictly sequential execution across the targeted database servers, which is the desired protection for shared storage.

Exam trap

The trap here is confusing task-level concurrency controls such as throttle with play-level batching controlled by serial.

54
MCQeasy

A systems administrator needs to run a playbook that installs packages on a group of managed nodes. The playbook should run only on nodes that are part of the 'web_servers' group in the inventory. Which approach is best practice?

A.Set 'hosts: web_servers' in the play.
B.Set 'hosts: all' and use '--limit web_servers' when running ansible-playbook.
C.Set 'hosts: localhost' and delegate tasks to web_servers.
D.Set 'hosts: all' and use a 'when' condition to check if the node is in the web_servers group.
AnswerA

Setting `hosts: web_servers` scopes the play directly to the inventory group, so Ansible targets only those managed nodes and skips all others. This satisfies the constraint that execution must be limited to the 'web_servers' group, using Ansible's native group pattern matching rather than conditional logic or delegation.

Why this answer

Setting 'hosts: web_servers' in the play directly targets only the nodes in that inventory group, which is the simplest and most maintainable approach. This follows Ansible's best practice of declaring the target group explicitly in the playbook rather than relying on runtime flags or conditional logic, ensuring the playbook's intent is clear and portable.

Exam trap

The trap here is that candidates may overcomplicate the solution by choosing runtime flags or conditional logic, forgetting that Ansible's simplest and most explicit targeting method—setting 'hosts' to the group name—is both best practice and the most reliable for clarity and execution.

How to eliminate wrong answers

Option B is wrong because using '--limit web_servers' with 'hosts: all' is a runtime override that can be forgotten or misapplied, making the playbook less self-documenting and error-prone; it also requires the operator to remember the flag each time. Option C is wrong because setting 'hosts: localhost' and delegating tasks to web_servers is unnecessary complexity—delegation is meant for tasks that must run on the control node (e.g., fetching files), not for targeting a group of managed nodes. Option D is wrong because using a 'when' condition to check group membership (e.g., 'when: "web_servers" in group_names') still runs the play on all nodes, wasting resources and potentially causing failures on non-target nodes if tasks are not idempotent.

55
MCQmedium

An administrator is writing a role that must execute a handler only if a configuration file changes. The handler is defined in handlers/main.yml. The task that modifies the configuration file uses the copy module. Which keyword must be used on the task to trigger the handler?

A.changed_when
B.when
C.notify
D.listen
AnswerC

The notify keyword on a task specifies one or more handlers to run when the task reports a changed state. When the copy module writes a new configuration file, it returns changed: true, which triggers the handler. Handlers run once at the end of the play, or when flushed. This is the standard way to restart services after configuration updates.

Why this answer

Handlers are triggered by the notify keyword on a task. When the task's state is changed, Ansible adds the handler to a list of handlers to run at the end of the play. The copy module will report changed when it updates the file, thus notifying the handler to restart the service.

Without notify, the handler never runs.

Exam trap

The trap here is thinking that a handler runs automatically when its associated file changes, but Ansible requires an explicit notify declaration on the task that makes the change.

56
MCQhard

Refer to the exhibit. The playbook uses the 'yum' module to install 'httpd' on a RHEL 8 system. Which of the following is the most likely cause of the failure?

A.The 'yum' module is deprecated for RHEL 8; must use 'dnf'.
B.The AppStream repository is not enabled on the target host.
C.The remote host does not have subscription-manager access.
D.The package name is misspelled; it should be 'apache2'.
AnswerB

On RHEL 8, httpd ships in the AppStream repository rather than BaseOS. If AppStream is disabled, the yum module cannot resolve the package and the task fails, so enabling that repository is the required fix.

Why this answer

On RHEL 8, the `yum` command is a symbolic link to `dnf`, and the `yum` Ansible module internally uses `dnf` as the backend. The most common cause of failure when installing a package like `httpd` on RHEL 8 is that the AppStream repository (which contains `httpd`) is not enabled or available on the target host. Without an enabled repository containing the package, the module cannot resolve and install it, leading to a failure.

Exam trap

The trap here is that candidates assume the `yum` module is deprecated or incompatible with RHEL 8, but the actual failure is almost always a repository availability issue, not the module itself.

How to eliminate wrong answers

Option A is wrong because the `yum` module is not deprecated for RHEL 8; it is fully functional and internally delegates to `dnf` on RHEL 8 systems, so using the `yum` module is valid. Option C is wrong because subscription-manager access is not required for installing `httpd`; the package is available from standard repositories (e.g., AppStream) and does not require a Red Hat subscription to be accessed. Option D is wrong because the package name `httpd` is correct for RHEL 8; `apache2` is the package name used on Debian-based systems, not on RHEL.

57
MCQhard

A team has developed several roles that share common variables. They want to organize these variables in a central file. Where should they place this file so it is automatically loaded by all roles?

A.In the inventory directory as host_vars/localhost.yml
B.In a common role's vars/main.yml
C.In a common role's defaults/main.yml
D.In the playbook directory as group_vars/all.yml
AnswerD

Variables in group_vars/all.yml, relative to the playbook directory, are automatically loaded for every host in every play, giving all roles centralised access without explicit includes. This satisfies the requirement that the file load automatically for all roles.

Why this answer

Placing a file in the playbook directory as group_vars/all.yml makes it automatically loaded by all roles. Ansible automatically includes any YAML files in the group_vars directory that match group names, and the special group 'all' applies to every host. This centralizes shared variables without requiring explicit imports in each role.

Exam trap

Red Hat often tests the distinction between role-level variable files (vars/main.yml and defaults/main.yml) and global variable files (group_vars/all.yml), trapping candidates who think a common role's vars/main.yml is automatically loaded by all roles when in fact it requires explicit role dependencies or includes.

How to eliminate wrong answers

Option A is wrong because host_vars/localhost.yml applies only to the localhost host, not to all hosts targeted by roles. Option B is wrong because vars/main.yml in a common role would require every other role to explicitly depend on or include that role, which is not automatic. Option C is wrong because defaults/main.yml in a common role defines default variables with the lowest precedence, which can be overridden by any higher-precedence variable source, making it unsuitable for central shared variables that should be consistently applied.

58
Multi-Selectmedium

An Ansible playbook uses the 'block' and 'rescue' directives. Which two statements are true about this construct? (Choose two.)

Select 2 answers
A.Rescue tasks are executed on all hosts in the play.
B.A rescue section executes only if the block tasks fail.
C.Blocks cannot be nested.
D.The 'always' section runs regardless of success or failure.
E.A block can have multiple rescue sections.
AnswersB, D

The rescue section is bound to its enclosing block: it runs only when a task inside that block returns a failure, allowing recovery or rollback. Successful block execution skips rescue entirely, so it never triggers on unrelated task failures elsewhere in the play.

Why this answer

Option B is correct because the 'rescue' section of a block is executed only when a task inside the corresponding 'block' fails, allowing error handling and recovery logic to run conditionally. Option D is correct because the 'always' section is guaranteed to run whether the block tasks succeed, fail, or are rescued, making it suitable for cleanup or finalization steps. Option A is incorrect because rescue tasks run only on hosts where the block failed, not on all hosts in the play.

Option C is incorrect because blocks can be nested inside other blocks. Option E is incorrect because a block can contain only one 'rescue' section.

Exam trap

The trap here is that candidates often think 'rescue' runs on all hosts or that multiple rescue sections are allowed, confusing Ansible's block/rescue/always pattern with exception handling in programming languages like try-catch-finally.

59
MCQhard

A playbook contains a task that uses the 'until' keyword with a retry count of 5 and a delay of 10. The task fails on all 5 attempts. What is the default behavior of Ansible regarding this task and subsequent tasks?

A.The task is skipped, and the playbook continues with subsequent tasks.
B.The task failure is ignored, and the playbook continues.
C.The task fails, and the playbook stops executing on that host by default.
D.The task is retried indefinitely until it succeeds.
AnswerC

When a task with 'until' exhausts all retries, it is marked as failed. By default, Ansible stops executing further tasks on that host, unless ignore_errors or failed_when is used. This prevents subsequent tasks from running on a host where a critical operation did not succeed. The play continues on other hosts unless any_errors_fatal is set.

Why this answer

When a task with 'until' exhausts its retries, it fails. Ansible's default behavior is to stop executing further tasks on that host, preventing subsequent actions that might depend on the failed task's success. The play continues on other hosts unless any_errors_fatal is set.

Exam trap

The trap here is assuming that retries imply eventual success or that a failed retry loop is automatically ignored, but Ansible treats exhausted retries as a standard task failure.

60
Multi-Selectmedium

Which TWO statements about Ansible roles are correct?

Select 2 answers
A.Roles must follow a specific directory structure.
B.Roles can be shared via Ansible Galaxy.
C.Ansible Galaxy is a continuous integration tool for testing roles.
D.Role dependencies must be defined in a file named dependencies.yml.
E.Role names must have a .role extension.
AnswersA, B

Ansible roles enforce a defined directory hierarchy — tasks, handlers, defaults, vars, files, templates and meta — so the role loader can locate content automatically. This structure satisfies the stem's requirement that roles follow a specific layout, since deviating from these conventional paths prevents Ansible from resolving tasks and variables correctly.

Why this answer

Option A is correct because Ansible roles rely on a defined directory layout (e.g., tasks/, handlers/, defaults/, vars/, files/, templates/, meta/, and the main.yml entry files) so that Ansible can automatically load each component without explicit includes. Option B is correct because Ansible Galaxy is the public repository and CLI for packaging, downloading, and sharing roles, so roles can indeed be distributed and installed via Galaxy (e.g., ansible-galaxy install). Option C is wrong because Ansible Galaxy is a role/content distribution hub, not a CI tool; CI for roles would be handled by tools like Jenkins, GitLab CI, or Molecule.

Option D is wrong because role dependencies are declared in meta/main.yml under the dependencies key, not in a file named dependencies.yml. Option E is wrong because role names are plain directory names and do not use a .role extension.

Exam trap

The trap here is that candidates confuse Ansible Galaxy as a CI tool because it has 'Galaxy' in its name, or assume role dependencies require a separate file like dependencies.yml, when in fact they must be placed in meta/main.yml.

Ready to test yourself?

Try a timed practice session using only Manage task execution and roles questions.