6. Ansible Foundations and Inventory ManagementIntroduction and ContextInfrastructure as Code (IaC) treats infrastructure configuration as a form of executable, reviewable, and version-controlled code. Terraform is primarily concerned with provisioning and managing infrastructure resources, whereas Ansible is commonly used to configure operating systems, deploy applications, enforce desired state, and orchestrate operational procedures. In a DevOps environment, the two technologies are often complementary: Terraform may create virtual machines and networks, while Ansible prepares those machines for service. Ansible is an agentless automation platform. A central control node connects to managed nodes, usually through SSH for Linux and WinRM or PSRP for Windows, and executes modules remotely. This architecture reduces the software that must be installed on target systems, although it places responsibility for connectivity, credentials, interpreter availability, and execution control on the automation environment. The effectiveness of Ansible depends not only on writing playbooks. Practitioners must understand inventories, variable resolution, facts, modules, connection methods, execution models, idempotence, security, and precedence. Poorly designed inventory or variable structures can make an apparently simple automation project difficult to test, audit, and operate. This chapter develops these foundations and relates them to professional infrastructure management. Learning ObjectivesAfter studying this chapter, the learner should be able to: 1. Describe Ansible’s architecture, agentless model, and principal execution stages. 2. Configure a basic Ansible control node and validate connectivity to managed hosts. 3. Design static and dynamic inventories using groups, variables, and host patterns. 4. Explain facts, modules, ad hoc commands, playbooks, tasks, handlers, and idempotence. 5. Select appropriate connection methods for Linux, Windows, network, and local targets. 6. Apply Ansible variable precedence and troubleshoot unexpected values. 7. Evaluate security, governance, reliability, and maintainability risks in Ansible automation. 8. Develop an inventory and automation approach suitable for a multi-environment organization. Ansible’s Operating ModelAnsible uses a control-node model. The control node contains the Ansible executable, configuration, inventories, credentials or credential references, roles, collections, and playbooks. Managed nodes are the systems on which actions occur. A control node may be a developer workstation, a dedicated automation server, a CI/CD runner, or an execution environment managed through an automation platform. The usual execution sequence is as follows. Ansible first parses configuration and inventory data, resolves the hosts selected by a play, loads variables, establishes connections, gathers facts if requested, and then executes tasks. Each task normally invokes a module. The module performs an operation on the managed node and returns structured output, including whether the system changed. Ansible uses this result to determine whether later tasks, handlers, or failure controls should be triggered. Unlike traditional management systems that require a persistent agent on every server, Ansible generally transfers a temporary module to the target, executes it, collects the result, and removes temporary files. For many Unix-like systems, the target needs SSH access and a suitable Python interpreter for most modules. Some modules and connection plugins have different requirements. Agentless does not mean dependency-free: network access, authentication, privilege escalation, interpreters, and compatible modules remain essential. Control Nodes and Managed NodesA control node should be treated as a production automation component rather than merely a command-line workstation. It requires controlled software versions, protected credentials, reliable access to target systems, and a directory structure that supports review and testing. Organizations commonly place playbooks in a Git repository and execute them through a controlled pipeline rather than allowing arbitrary manual changes. Managed nodes may include virtual machines, physical servers, containers, network devices, cloud instances, and application hosts. Their connection requirements differ. Linux systems often use SSH; Windows systems commonly use WinRM or PSRP; network devices may use network-specific connection plugins and do not necessarily provide a conventional shell; and local execution can be used for a control node or development environment. Installing and Validating a Control NodeAnsible is generally installed through Python package management or an operating-system package manager. In professional settings, the installation method should be reproducible. A virtual environment, pinned dependency versions, and a documented supported version reduce the risk that an update changes module behavior or parsing rules. A basic validation sequence might include: ```bash python3 -m venv .venv source .venv/bin/activate python -m pip install --upgrade pip python -m pip install ansible ansible --version ``` The exact installation command depends on the chosen Ansible distribution and organizational standards. The important principle is that the executable and its dependencies should be identifiable and repeatable. Ansible searches for configuration in defined locations, with the active configuration commonly selected through the `ANSIBLE_CONFIG` environment variable or a project-local `ansible.cfg`. A minimal configuration may contain: ```ini [defaults] inventory = ./inventory host_key_checking = True retry_files_enabled = False interpreter_python = auto_silent [ssh_connection] pipelining = True ``` Configuration should not be copied without analysis. Host-key checking improves protection against impersonation, while pipelining can improve performance but may interact with privilege escalation policies. Security and operational decisions should be explicit rather than hidden in a shared file. Connectivity can be tested with an ad hoc command: ```bash ansible all -m ansible.builtin.ping ``` The `ping` module does not test the ICMP protocol. It verifies that Ansible can connect, execute the module, and obtain a valid response. A successful result indicates functional automation connectivity, not that an application is healthy. Inventory as a Model of the EnvironmentAn inventory identifies managed hosts and organizes them into groups. It is also a source of host and group variables. Inventory therefore serves two purposes: it describes where automation should run and supplies context about those targets. A simple INI inventory is easy to read: ```ini [web] web01 ansible_host=192.0.2.21 web02 ansible_host=192.0.2.22 [database] db01 ansible_host=192.0.2.31 [production:children] web database [production:vars] environment=production ``` The host name used in a play is the inventory alias, while `ansible_host` identifies the actual network address. This distinction is useful when DNS names, cloud instance identifiers, and operational names differ. YAML inventory is more structured and can represent nested variables clearly: ```yaml all: children: web: hosts: web01: ansible_host: 192.0.2.21 web02: ansible_host: 192.0.2.22 vars: service_name: nginx database: hosts: db01: ansible_host: 192.0.2.31 vars: environment: production ``` The special `all` group contains every host, while `ungrouped` contains hosts not assigned to another explicitly defined group. Groups can represent technical roles, environments, geographical locations, ownership, compliance boundaries, or combinations of these. However, excessive overlapping groups can make host selection and variable inheritance difficult to understand. Inventory design should reflect stable operational concepts rather than every possible classification. Static and Dynamic InventoriesA static inventory is maintained as a file. It is suitable for environments whose membership changes slowly or for controlled laboratory systems. A dynamic inventory obtains hosts from an external source such as a cloud provider, virtualization platform, configuration database, or service catalog. It may be implemented by an inventory plugin or an executable inventory script, although modern practice favors supported inventory plugins. Dynamic inventory reduces the risk of configuring obsolete hosts, but it introduces dependencies on APIs, permissions, tags, and data quality. A cloud inventory may group machines by region, account, environment, or resource tags. If tags are inconsistent, the resulting automation scope may be incorrect. Therefore, dynamic inventory is not automatically more accurate; it is only as reliable as the source data and filtering rules. Inventory can be inspected with: ```bash ansible-inventory --graph ansible-inventory --list ansible-inventory --host web01 ``` These commands are valuable for troubleshooting group membership and variable sources before a playbook is executed. Variables, Facts, and PrecedenceVariables allow one playbook to operate across hosts that differ in names, ports, packages, paths, environments, or operational policies. They can be defined in inventory, group and host variable directories, playbooks, roles, extra variables, and other sources. A typical project might use: ```text project/ ├── ansible.cfg ├── inventory/ │ ├── production/ │ │ ├── hosts.yml │ │ ├── group_vars/ │ │ │ └── web.yml │ │ └── host_vars/ │ │ └── web01.yml │ └── staging/ ├── playbooks/ │ └── site.yml └── roles/ ``` Group variables express common properties, while host variables should be reserved for genuine exceptions. Sensitive values should not be stored as unencrypted plain text. Ansible Vault can encrypt files or variables, but Vault is a mechanism for protecting stored data, not a replacement for access control, secret rotation, or a dedicated secrets manager. Facts are information gathered from managed nodes, such as operating-system family, processor architecture, memory, network interfaces, mount points, and discovered addresses. Fact gathering is enabled by default in ordinary plays unless disabled. Facts are accessed through the `ansible_facts` namespace, for example: ```yaml - name: Display operating system family
ansible.builtin.debug: var: ansible_facts.os_family ``` Facts support conditional logic and portable roles, but fact gathering consumes time and may expose information that should be handled carefully. Fact caching can improve performance for large environments, but stale cached facts can produce incorrect decisions. Cache duration and invalidation should therefore be managed deliberately. Understanding PrecedenceAnsible has a detailed variable precedence model. In broad terms, values supplied explicitly at execution time, particularly through `-e` or `--extra-vars`, override many other definitions. Role and task variables, block and play variables, host and group variables, and inventory defaults operate at different levels. The exact ordering depends on the variable source and context. The practical rule is not to memorize an isolated list but to design for clarity: - Use inventory variables for target-specific data.
- Use role defaults for values intended to be easily overridden.
- Use role variables for internal role behavior that should be less easily overridden.
- Use play or task variables for limited execution context.
- Use extra variables for deliberate, auditable overrides rather than routine configuration.
Unexpected values should be investigated using `ansible-inventory`, carefully scoped debug tasks, and documentation of the intended source. Variable names should be specific enough to avoid collisions, especially in collections and reusable roles. Modules, Tasks, Plays, and PlaybooksA module is a unit of Ansible functionality. Modules manage packages, files, services, users, cloud resources, databases, templates, and many other objects. A task invokes one module with arguments: ```yaml - name: Ensure web package is installed
ansible.builtin.package: name: nginx state: present ``` A play maps a set of tasks to selected hosts: ```yaml - name: Configure web servers
hosts: web become: true tasks: ansible.builtin.package: name: nginx state: present ``` A playbook is a YAML document containing one or more plays. It represents a repeatable operational procedure. Tasks should use fully qualified collection names such as `ansible.builtin.copy`, improving readability and reducing ambiguity. Modules differ in quality and behavior. A module should be selected according to the desired state of a resource rather than merely the command that can produce an outcome. For example, the `service` or `systemd` module communicates the desired service state more clearly than a shell command such as `systemctl start nginx`. Ad Hoc CommandsAd hoc commands are useful for exploration, diagnostics, and small one-time actions: ```bash ansible web -m ansible.builtin.command -a 'uname -a' ansible web -m ansible.builtin.setup ansible db -b -m ansible.builtin.service -a 'name=postgresql state=started' ``` They are not a substitute for playbooks in controlled production work. Commands executed ad hoc are harder to review, reproduce, test, and audit. A useful professional pattern is to use an ad hoc command to investigate a problem, then encode the durable correction in a playbook. Templates, Handlers, and LoopsThe `template` module renders a Jinja2 template using variables and facts. It is suitable for configuration files whose contents vary by environment or host. When a configuration change requires a service restart, the task should notify a handler: ```yaml - name: Deploy application configuration
ansible.builtin.template: src: app.conf.j2 dest: /etc/example/app.conf mode: '0644' notify: Restart application handlers: - name: Restart application
ansible.builtin.service: name: example-app state: restarted ``` Handlers run when notified and normally execute at the end of a play. This avoids restarting a service unnecessarily when the configuration has not changed. Loops allow a task to apply an operation to multiple items, but loop data should be structured clearly and should not conceal substantially different operations in one task. Idempotence and Execution StrategyIdempotence means that applying the same intended configuration repeatedly produces the same final state without unnecessary additional changes. In Ansible, idempotence is expressed through module parameters such as `state: present`, `enabled: true`, or a declarative file resource. It is a property of the operation and its implementation, not a guarantee that every Ansible task is automatically idempotent. A shell or command task may be necessary, but it requires safeguards. The `creates`, `removes`, or `changed_when` controls can help Ansible determine whether an operation should run or whether it changed the system. Poorly written command tasks may report changes on every run, conceal failures, or apply destructive actions repeatedly. Ansible’s default linear strategy processes task progression across hosts in coordinated batches, although the exact behavior includes forks and synchronization points. The `serial` keyword limits the number of hosts updated at once, which is important for rolling deployments. `max_fail_percentage` and related controls can stop a rollout when too many hosts fail. Delegation can execute a task on another host, while `run_once` restricts a task to one selected host; both require careful reasoning about data and failure scope. Check mode, invoked with `--check`, estimates changes without applying them where modules support that capability. Diff mode can show file differences, though sensitive content must be protected. These features improve review but cannot perfectly predict operations involving external systems or arbitrary commands. Connection Methods and Privilege EscalationThe connection plugin determines how Ansible reaches a target. Common methods include: - SSH for Unix-like systems.
- Local execution when no remote connection is required.
- WinRM or PSRP for Windows systems.
- Network-specific plugins for routers, switches, and appliances.
- Container or virtualization connections in specialized environments.
SSH configuration may specify an alternate user, port, private key, proxy jump, or bastion host: ```yaml web01: ansible_host: 192.0.2.21 ansible_user: deployer ansible_ssh_private_key_file: ~/.ssh/automation_ed25519 ``` Privilege escalation is separate from connection. The `become` mechanism allows a connection user to obtain additional privileges, commonly through `sudo`: ```yaml become: true become_method: sudo tasks: ansible.builtin.package: name: nginx state: present ``` The connection account should receive only the privileges required for its tasks. Passwordless privilege escalation may simplify automation but increases the impact of stolen credentials. Organizations should use narrowly scoped sudo policies, short-lived credentials where possible, centralized logging, and approval controls for sensitive operations. A Detailed Applied Case: Standardizing a Three-Tier PlatformBackgroundConsider Meridian Services, a fictional organization operating a customer portal with web, application, and database tiers. The company has separate staging and production environments. Systems were provisioned by different teams, resulting in inconsistent package versions, manually edited configuration files, and uncertain service startup behavior. Situation and ProblemA release succeeded in staging but failed in production because one application host used a different runtime version and a database host had a disabled service. The operations team also maintained a spreadsheet of server addresses, which was frequently outdated. Management required repeatable configuration, controlled production rollout, and an auditable record of changes. AnalysisThe problem was not simply the absence of scripts. It involved three forms of drift: infrastructure membership drift, configuration drift, and process drift. A static list could not reliably identify current cloud instances. Shell scripts lacked consistent change reporting. Finally, no clear boundary existed between environment-specific data and reusable configuration logic. Approach and SolutionThe team implemented a dynamic inventory based on cloud resource tags. Hosts were grouped by environment and service role, such as `staging_web`, `production_web`, and `production_database`. Group variables defined non-sensitive settings, while encrypted variables and a secrets manager supplied credentials. Reusable roles were created for the operating-system baseline, runtime installation, web service configuration, and database service management. Role defaults contained safe baseline values. Environment-specific variables changed only the required parameters. Tasks used fully qualified module names and declarative states. Configuration templates notified handlers only when files changed. Production deployment used `serial` to update a small number of web hosts at a time. Health checks were executed between batches, and the playbook stopped if the failure threshold was exceeded. The database role was applied separately because database changes had a different risk profile. Check mode and review of the proposed diff were incorporated into the change process. OutcomeThe organization obtained a reproducible configuration baseline and a clearer separation between inventory data, reusable roles, and environment policy. New hosts entered the correct automation scope through tags. Re-running the playbooks produced no changes on compliant systems, while drift was reported through normal change results. The team also discovered that some application settings had never been documented; these were resolved as part of the design process. Learning PointsThe case demonstrates that Ansible’s value is organizational as well as technical. Inventory is a governance boundary, not merely a host list. Idempotent roles reduce operational uncertainty, but they do not eliminate the need for testing, staged rollout, access control, and human review. Dynamic discovery improves freshness only when resource metadata is governed. Finally, the safest automation separates stable reusable logic from environment-specific data and secrets. Risks, Limitations, and Common MistakesAnsible can produce large-scale changes quickly, which makes incorrect host patterns particularly dangerous. A play intended for `staging_web` may affect production if group names or inventory sources are wrong. Explicit inventory selection, environment protections, approval gates, and limited concurrency reduce this risk. Common technical mistakes include using shell commands where a module exists, storing secrets in plain text, relying on implicit variable names, ignoring failed tasks with `ignore_errors`, disabling host-key checking without compensating controls, and testing only on one distribution. Another mistake is treating successful task execution as proof of application correctness. Configuration management verifies selected resource states; it does not automatically validate end-to-end business behavior. YAML syntax can also create errors through indentation, implicit data typing, or ambiguous values. Fully qualified module names, linting, syntax checks, and automated tests help identify problems early. Roles and collections should be versioned and reviewed because a dependency update can alter behavior. Large inventories may create performance challenges. Fact gathering, API calls, forks, network latency, and controller capacity all affect execution time. Fact caching, appropriate forks, batching, and specialized execution environments can help, but performance tuning should not weaken auditability or safety. Governance, Security, and Professional PracticeAnsible automation frequently operates with elevated privileges and access to sensitive systems. Governance should therefore cover identity, authorization, code review, credential management, logging, change approval, and separation of duties. Automation repositories should be protected like production code. Branch controls and peer review are particularly important for changes involving destructive modules, firewall rules, user accounts, or secret distribution. Secrets should be supplied through protected mechanisms such as Vault, an enterprise secrets manager, or a secured automation platform. Encryption at rest is insufficient if playbook output exposes a secret; `no_log: true` may be needed for sensitive tasks, although excessive use can reduce diagnostic value. Logs should be retained according to organizational and regulatory requirements while avoiding unnecessary personal or confidential data. Compliance automation should be transparent and evidence-oriented. A role that enforces password policy or file permissions should document the intended control, its scope, exceptions, and verification method. Automation should not silently remediate systems where legal, safety, or business requirements demand approval. Current Developments and Emerging DirectionsAnsible is increasingly used through automation platforms that provide web-based inventories, role-based access control, job templates, scheduling, credentials, workflow approval, and centralized execution logs. Execution environments package Ansible, collections, and Python dependencies into reproducible containers, reducing differences between developer machines and CI runners. Collections provide modular distribution of modules, plugins, and roles. Their use increases reuse but also introduces supply-chain concerns. Organizations should select trusted sources, pin versions, scan dependencies, and test upgrades. Event-driven automation is another developing direction. Monitoring events can trigger controlled Ansible actions, such as remediation or scaling, but automatic response must include safeguards against alert storms, repeated remediation, and malicious or corrupted event data. AI-assisted operations may help suggest playbooks, interpret failures, or generate task drafts; nevertheless, generated automation requires human review, testing, least-privilege execution, and explicit validation of its assumptions. Best-Practice Framework for Ansible ProjectsA maintainable Ansible implementation generally follows these principles: 1. Keep inventories, playbooks, roles, and configuration under version control. 2. Separate environments and make the selected inventory explicit at execution time. 3. Prefer idempotent modules over unstructured shell commands. 4. Use meaningful groups based on stable operational responsibilities. 5. Keep secrets outside ordinary source files and protect task output. 6. Use role defaults for safe, documented customization points. 7. Validate syntax, lint code, test roles, and use check mode where appropriate. 8. Stage high-risk changes with `serial`, health checks, and rollback planning. 9. Pin important collection and dependency versions. 10. Document privilege requirements, exceptions, ownership, and expected outcomes. 11. Treat dynamic inventory metadata as governed configuration data. 12. Measure success through drift reduction, change reliability, recovery time, and audit quality rather than task count alone. Chapter SummaryAnsible is an agentless automation platform in which a control node connects to managed systems and executes modules to achieve a desired state. Its practical foundation consists of a reproducible control-node environment, accurate inventories, well-structured variables, facts, connection plugins, privilege escalation, and declarative modules. Inventories identify hosts and organize them into meaningful groups; dynamic inventories can improve freshness but depend on reliable external metadata. Modules, tasks, plays, and playbooks provide progressively larger units of automation. Idempotence is central because repeated execution should converge systems toward the intended state without unnecessary changes. Ad hoc commands are useful for investigation, while durable operational knowledge should be encoded in tested playbooks and roles. Variable precedence must be managed through disciplined design rather than accidental overrides. Finally, professional Ansible practice requires security controls, governance, staged execution, dependency management, testing, and awareness of the limitations of automation. Key TermsControl node: The system from which Ansible commands, playbooks, inventories, and plugins are executed. Managed node: A target system on which Ansible performs automation tasks. Agentless automation: Automation that generally does not require a persistent management agent on each target. Inventory: A collection of managed hosts, groups, and associated variables. Static inventory: An inventory maintained directly in a file or set of files. Dynamic inventory: Inventory generated from an external source such as a cloud API or service catalog. Host pattern: An expression used to select hosts for a command or play. Module: A reusable unit of Ansible functionality that performs an operation on a target. Task: A named invocation of a module with specified arguments. Play: A mapping of tasks to a selected group of hosts. Playbook: A YAML document containing one or more plays. Fact: Information automatically gathered about a managed host. Variable precedence: The ordering rules that determine which variable value overrides another. Handler: A special task executed when notified, usually after a configuration change. Idempotence: The property that repeated application of an operation converges on the same desired state. Connection plugin: The mechanism Ansible uses to communicate with a managed node. Privilege escalation: A controlled method, such as `sudo`, for obtaining higher permissions. Ansible Vault: An Ansible feature for encrypting sensitive data used by automation. Execution strategy: The method governing how tasks progress across multiple hosts. Drift: Divergence between the actual configuration of a system and its intended configuration. Review QuestionsShort Answer Questions1. What distinguishes an Ansible control node from a managed node? 2. Why is the Ansible `ping` module not an ICMP connectivity test? 3. What are the principal purposes of an inventory? 4. Define idempotence in the context of configuration management. 5. What is the role of an Ansible handler? Long Answer Questions1. Explain Ansible’s agentless architecture and describe the principal stages of playbook execution. 2. Compare static and dynamic inventories, including their benefits, dependencies, and risks. 3. Explain how facts, variables, and variable precedence influence playbook behavior. 4. Discuss the relationship among modules, tasks, plays, playbooks, roles, and handlers. 5. Explain how security, governance, and least privilege should shape an enterprise Ansible implementation. Analytical / Application Questions1. An organization has separate staging and production cloud accounts, but resource tags are inconsistent. Design an inventory and governance approach that reduces the risk of applying a production play to staging or vice versa. 2. A playbook reports a configuration file as changed on every run and restarts the application each time. Diagnose the likely design problem and propose an idempotent correction. 3. During a rolling production deployment, two of ten web servers fail configuration. Explain which Ansible execution controls and operational safeguards could limit impact and support recovery. 22. Multiple Choice Questions with AnswersQuestion 1Which statement best describes Ansible’s agentless operating model? A. Every managed host must run a continuously active Ansible daemon. B. The control node connects to targets and executes modules without normally requiring a persistent agent. C. Ansible can configure only systems that expose a cloud-provider API. D. Managed hosts must be rebuilt after every playbook execution. Correct Answer: B. The control node connects to targets and executes modules without normally requiring a persistent agent. Question 2In an inventory, what is the principal purpose of ansible_host when used with an inventory alias such as web01? A. It defines the operating-system family of web01. B. It identifies the actual network address to which Ansible connects. C. It assigns web01 to the production group. D. It specifies the module used for web01. Correct Answer: B. It identifies the actual network address to which Ansible connects. Question 3Which approach most directly supports idempotent package configuration? A. Running a shell command that always installs the package again. B. Using the package module with state: present. C. Using debug to print the package name. D. Disabling change reporting for the task. Correct Answer: B. Using the package module with state: present. Question 4What is the main operational purpose of an Ansible handler? A. To execute a task only when it has been notified, commonly after a change. B. To define a permanent connection to every managed host. C. To override all inventory variables. D. To gather facts before every task. Correct Answer: A. To execute a task only when it has been notified, commonly after a change. Question 5An administrator wants to identify the groups and variables associated with a host before running a playbook. Which command is most appropriate? A. ansible-inventory --host web01 B. ansible-playbook --syntax-check web01 C. ansible-galaxy --graph web01 D. ansible-config --remove web01 Correct Answer: A. ansible-inventory --host web01 Question 6A value supplied with extra variables conflicts with a value in group_vars. What should generally be expected? A. The group_vars value always overrides the extra variable. B. Both values are merged randomly. C. The explicitly supplied extra variable generally has higher precedence. D. The playbook fails before variable resolution. Correct Answer: C. The explicitly supplied extra variable generally has higher precedence. Question 7A team wants to update production web servers gradually and stop if failures exceed an acceptable threshold. Which combination is most relevant? A. serial and failure-threshold controls such as max_fail_percentage B. debug and gather_facts: false only C. local connection and ignore_errors D. An ad hoc command and no inventory groups Correct Answer: A. serial and failure-threshold controls such as max_fail_percentage Question 8Why can dynamic inventory still produce an incorrect automation scope? A. Dynamic inventory never supports grouping. B. It depends on the accuracy of external metadata, filters, permissions, and API data. C. It always ignores cloud resource tags. D. It can contain only one managed host. Correct Answer: B. It depends on the accuracy of external metadata, filters, permissions, and API data. Question 9Which practice best protects sensitive information in an Ansible project? A. Store passwords in ordinary group variables and print them for testing. B. Use protected secret mechanisms, restrict access, and prevent sensitive task output where necessary. C. Disable host-key checking for every environment. D. Place credentials in shell commands so they are not in YAML. Correct Answer: B. Use protected secret mechanisms, restrict access, and prevent sensitive task output where necessary. Question 10A command task reports changed on every execution even though the target state is already correct. What is the most appropriate response? A. Accept the behavior because all command tasks are inherently idempotent. B. Replace it with a suitable declarative module or add carefully justified change and execution conditions. C. Add more forks to make the changes faster. D. Move the command into inventory variables. Correct Answer: B. Replace it with a suitable declarative module or add carefully justified change and execution conditions.
|