Skip to content

Annual Update for Bullseye#2

Closed
NickJLange wants to merge 261 commits intoNickJLange:masterfrom
DataDog:main
Closed

Annual Update for Bullseye#2
NickJLange wants to merge 261 commits intoNickJLange:masterfrom
DataDog:main

Conversation

@NickJLange
Copy link
Copy Markdown
Owner

@NickJLange NickJLange commented Jan 1, 2022

Catching up on upstream

Summary by CodeRabbit

  • New Features

    • macOS and Windows install/handler flows, APM single‑step instrumentation, enhanced network/service/runtime‑security and system‑probe config options, integration install/remove support, and Ansible lint/CI helpers.
  • Improvements

    • Raised Ansible baseline to 2.10+, expanded OS/version coverage, many new defaults and flags, safer repo/GPG key handling, Windows reinstall/downgrade handling, and greatly expanded CI matrix/testing.
  • Documentation

    • Revised README, CONTRIBUTING and CHANGELOG with macOS/Windows examples and testing guidance.
  • Chores

    • Updated .gitignore, Dependabot config, and CODEOWNERS.

albertvaka and others added 30 commits January 11, 2021 14:12
Use the dnf task instead of yum when we detect that a Python 3 interpreter is used on a target host.
Add CentOS 8 tests to the CI.
Add Python 2 / Python 3 tests to the CI.

Co-authored-by: Pablo Baeyens <pablo.baeyens@datadoghq.com>
* update readme to reflect changes

* Update README.md

Co-authored-by: Lee Avital <lee.avital@datadoghq.com>

* Update README.md

Co-authored-by: Lee Avital <lee.avital@datadoghq.com>

* Update README.md

Co-authored-by: ruthnaebeck <19349244+ruthnaebeck@users.noreply.github.com>

* Update README.md

Co-authored-by: ruthnaebeck <19349244+ruthnaebeck@users.noreply.github.com>

* Update tasks/pkg-windows-opts.yml

Co-authored-by: ruthnaebeck <19349244+ruthnaebeck@users.noreply.github.com>

* Update templates/system-probe.yaml.j2

Co-authored-by: ruthnaebeck <19349244+ruthnaebeck@users.noreply.github.com>

* Update templates/system-probe.yaml.j2

Co-authored-by: ruthnaebeck <19349244+ruthnaebeck@users.noreply.github.com>

* Update README.md

Co-authored-by: ruthnaebeck <19349244+ruthnaebeck@users.noreply.github.com>

* Update tasks/pkg-windows-opts.yml

Co-authored-by: Albert Vaca Cintora <albert.vaca@datadoghq.com>

Co-authored-by: Lee Avital <lee.avital@datadoghq.com>
Co-authored-by: ruthnaebeck <19349244+ruthnaebeck@users.noreply.github.com>
Co-authored-by: Albert Vaca Cintora <albert.vaca@datadoghq.com>
Redo of #326, with fixes to avoid undefined variable problems on Windows.

Co-authored-by: Derek Brown <derek.brown@datadoghq.com>
Co-authored-by: Lee Avital <lee.avital@datadoghq.com>
Co-authored-by: ruthnaebeck <19349244+ruthnaebeck@users.noreply.github.com>
Co-authored-by: Albert Vaca Cintora <albert.vaca@datadoghq.com>
Fixes the logic around starting / stopping the system-probe service, with different paths depending on the Agent version:
- before 6/7.18.0: the datadog-agent-sysprobe service is independent from the datadog-agent service and is started / stopped / restarted by the role, depending on the system_probe_config.enabled variable
- between 6/7.18.0 and 6/7.24.0: the datadog-agent-sysprobe service depends on datadog-agent, therefore only the datadog-agent service needs to be restarted on configuration changes. The system_probe_config.enabled variable still defines that behavior.
- since 6/7.24.1: the network_config.enabled variable defines if the service should be started or not. The system_probe_config.enabled variable is still supported for backwards compatibility, but is not recommended in the documentation anymore.

Makes sure the role doesn't crash when system_probe_config has a None or empty value.
- Update lint job
- Fix file permissions
- Add role_name and namespace to galaxy_info
- Remove pre/post tasks
- Add a note about the dependency on ansible.windows since Ansible 2.10. This is because some tasks have been moved from base Ansible into separate collections.
-  Split Windows handler into its own file, so we don't include anything from ansible.windows on non-Windows (so we don't have to add the ansible.windows dependency on Linux as well).
- Split "Gather Ansible Facts" task in two files for different Ansible versions, prefixed or unprefixed (for some reason in 2.10 it tried to run Powershell on Linux without this when using the task unprefixed as it was before).
…dog_enabled false (#338)

This includes several proposed modifications:

Reorder the services in the stop_services task so that when they are shut down, they don't have dependency issues due to shutdown order of operations
Disable services rather than stopping them when datadog_enabled is false
Ensure services are not set to disabled when datadog_enabled is true
Resolve/compute datadog_tracked_checks within the task sequence as set_fact rather than only with the default vars so that its variable precedence is higher than include_vars. Also address null/none dictionary during this step. Propose calling it sanitize-checks.

Co-authored-by: Kylian Serrania <kylian.serrania@datadoghq.com>
* Release version 4.8.0

Co-authored-by: Pablo Baeyens <pablo.baeyens@datadoghq.com>
Fixes a typo when including the main-win.yml file.

This is causing errors when the role tries to notify a restart on Windows.
Dynamically includes the Windows Agent restart handler to make it work as expected.
* By default, get keys from keys.datadoghq.com, not Ubuntu keyserver
* Always add the DATADOG_APT_KEY_CURRENT.public key (contains key used to sign current repodata)
* Add 'signed-by' option to all sources list lines
* On Debian >= 9 and Ubuntu >= 16, only add keys to /usr/share/keyrings/datadog-archive-keyring.gpg
* On older systems, also add the same keyring to /etc/apt/trusted.gpg.d

Co-authored-by: Kylian Serrania <kylian.serrania@datadoghq.com>
Co-authored-by: Kylian Serrania <kylian.serrania@datadoghq.com>
* This will make it compatible with Jinja2 <2.10, and Jinja2 >=3
swang392 and others added 4 commits October 8, 2025 14:57
* update windows tasks and conf

* add file permissions for lint

* revert granular agent restart

* nit

* use ansible.builtin.template w/o local tmp

* add file perms

* Delete .lock
The Rosetta 2 translation is no longer required for running Agent 7 in
CI, since Agent 7.70+ is built "natively" for each of the 2 supported
macOS architectures (`x86_64`, and now `arm64`).
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Oct 20, 2025

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Large refactor converting many datadog variables to an agent_datadog_* surface, reorganizing OS-specific install/restart flows (Linux, macOS, Windows), centralizing package/key management, adding APM single-step installer and ansible-lint CI/CircleCI matrix additions; extensive template and test/playbook updates.

Changes

Cohort / File(s) Summary
CI & Lint
​.circleci/config.yml, ci_test/ansible_lint.sh, requirements-ansible-lint.txt, requirements.txt
Add ansible-lint script, pinned lint deps, and large CircleCI workflow/matrix changes; thread python, jinja2_native, and inventory through CI jobs.
Repo metadata & tooling
.github/CODEOWNERS, .github/dependabot.yml, .gitignore, Gemfile, chefignore
Update CODEOWNERS, add Dependabot config, modify .gitignore, remove development gems from Gemfile, adjust chefignore.
Docs & changelog
README.md, CONTRIBUTING.md, CHANGELOG.md, manual_tests/readme.md
Major README rewrite (role vs collection, new variables/examples), trim CONTRIBUTING, expand CHANGELOG, update manual test docs including Windows/WSL guidance.
Defaults & metadata
defaults/main.yml, meta/main.yml
Add extensive agent_datadog_* defaults (enable/manage flags, repo/GPG/proxy, macOS/Windows paths, network/runtime_security/service_monitoring, flavor/version scaffolding); raise min Ansible to 2.10; expand Galaxy platforms.
Handlers
handlers/main.yml, handlers/main-macos.yml, handlers/main-win.yml
Split restart logic by OS, add macOS launchctl handlers and Windows restart include.
Agent tasks & shared config
tasks/agent-linux.yml, tasks/agent-macos.yml, tasks/agent-win.yml, tasks/_agent-linux-macos-shared.yml, tasks/agent5-linux.yml
Refactor install/config flows, consolidate Linux/macOS shared config, add macOS LaunchDaemon flow, enhance Windows installer/service flow, remove legacy Agent5 tasks.
Package & repo management
tasks/_apt-key-import.yml, tasks/_remove_rpm_keys.yml, tasks/pkg-debian*.yml, tasks/pkg-redhat*.yml, tasks/pkg-suse*.yml, tasks/pkg-macos*.yml, tasks/pkg-windows*.yml
Centralize key import/dearmor logic, multi-key RPM/Yum/Zypper handling, migrate to dnf/ansible.builtin where appropriate, implement macOS DMG and Windows MSI flows.
Version parsing & discovery
tasks/parse-version*.yml, tasks/set-parse-version.yml, tasks/win_agent_*.yml
Standardize/rename version vars to agent_datadog_*, add OS-specific discovery/parsing and install guards.
Templates & rendering
templates/datadog.yaml.j2, templates/datadog.conf.j2, templates/system-probe.yaml.j2, templates/checks.yaml.j2, templates/install.json.j2, templates/security-agent.yaml.j2, templates/com.datadoghq.agent.plist.j2, templates/zypper.repo.j2
Migrate templates to new vars, add network/runtime_security/service_monitoring blocks, Jinja indent compatibility fixes, macOS plist and install.json additions.
Integrations & checks
tasks/integration.yml, tasks/integration/*, tasks/sanitize-checks.yml, tasks/check-removed-config.yml
Split integration management into OS-specific includes, add shared Linux/macOS and Windows flows, sanitize check vars, and add failures for removed GPG variables.
APM & utilities
tasks/apm-single-step-instrumentation.yml, tasks/remove-legacy-installer.yml, tasks/main.yml, tasks/os-check.yml
Add APM single-step installer flow, legacy installer cleanup, reorganize main task flow (sanitization and API-key enforcement), and broaden OS-family checks.
CI & manual playbooks / inventories
ci_test/*.yaml, ci_test/inventory/*, manual_tests/*, manual_tests/Vagrantfile
Add many CI playbooks (install/downgrade/APM/pinned), macOS inventory, update manual Vagrant/inventories and manual test playbooks.
Tests removed
test/integration/default/*, test/integration/default/serverspec/*, manual_tests/test_5_*.yml
Remove default integration playbook and related Serverspec tests and some manual test playbooks.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant CI as CI/Invoker
    participant Role as Ansible Role (tasks/main.yml)
    participant Facts as Ansible Facts
    participant PKG as Package Manager (apt/dnf/zypper/win_package)
    participant OS as Target OS (Linux/macOS/Windows)
    participant Handler as OS Handlers (handlers/*.yml)

    CI->>Role: invoke playbook / include_role
    Role->>Facts: gather facts
    Role->>Role: sanitize checks, parse version, set agent_datadog_* facts
    Role->>PKG: include OS-specific pkg tasks (deb/rpm/dmg/msi)
    PKG->>OS: download/install package
    OS-->>PKG: return install result
    PKG-->>Role: register install state
    Role->>Handler: notify restart (OS-specific)
    Handler->>OS: perform service/launchctl/win_service actions
    OS-->>CI: report final state/result
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Poem

🐇 I hopped through vars both old and new,
agent_datadog now leads the crew.
DMG, MSI, and launchd too—
CI matrices helped us through.
A carrot cheer for code refreshed and true! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Title check ⚠️ Warning The title 'Annual Update for Bullseye' is vague and does not reflect the actual scope of changes. The PR makes extensive updates across CI/CD, defaults, templates, and tasks—far beyond a simple Bullseye platform update. Revise the title to accurately describe the primary changes, such as 'Refactor agent installation, configuration management, and CI workflows' or 'Add macOS/Windows support and restructure agent deployment logic'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 33

🧹 Nitpick comments (38)
.github/dependabot.yml (1)

1-6: Solid Dependabot configuration.

The configuration correctly enables monthly Bundler updates with a sensible setup: v2 schema is current, the root directory is appropriate, and the monthly interval strikes a good balance between staying current and avoiding update fatigue.

Consider: Expanding to other package managers (optional).

If this repository uses Python, JavaScript, or other dependencies, you may want to add additional package ecosystems (e.g., pip, npm, github-actions) to the same configuration file in a follow-up PR. This keeps dependency updates centralized and maintainable.

requirements.txt (1)

1-1: Consider updating to galaxy-importer 0.4.33 for the latest improvements and fixes.

Version 0.4.29 is not vulnerable to the known path-traversal advisory (CVE-2023-5189) which affects only versions up to 0.4.16. However, the latest version is 0.4.33 (released August 27, 2025), so consider upgrading to benefit from intervening patches and features unless there are breaking changes that prevent it.

tasks/parse-version-macos.yml (1)

2-10: Consider more robust version parsing.

The grep and awk pipeline is fragile and will fail silently if the agent's version output format changes. While failed_when: false prevents task failure, it may lead to empty or incorrect version detection.

Consider using a more robust approach:

-- name: Get macOS Agent version
-  ansible.builtin.shell:
-    cmd: set -o pipefail && {{ datadog_agent_binary_path_macos }} version | grep 'Agent ' | awk '{print $2}'
-    executable: /bin/bash
+- name: Get macOS Agent version
+  ansible.builtin.shell:
+    cmd: set -o pipefail && {{ datadog_agent_binary_path_macos }} version --json | jq -r '.version'
+    executable: /bin/bash

Alternatively, if JSON output isn't available, add a validation step to check if the parsed version is non-empty.

templates/com.datadoghq.agent.plist.j2 (1)

19-25: Consider templating hard-coded paths.

The binary path /opt/datadog-agent/bin/agent/agent and log path /opt/datadog-agent/logs/launchd.log are hard-coded. If these paths might vary across deployments or versions, consider using Jinja2 variables similar to the approach used for agent_username and agent_groupname.

Example:

         <key>ProgramArguments</key>
         <array>
-            <string>/opt/datadog-agent/bin/agent/agent</string>
+            <string>{{ datadog_agent_binary_path_macos }}</string>
             <string>run</string>
         </array>
         <key>StandardOutPath</key>
-        <string>/opt/datadog-agent/logs/launchd.log</string>
+        <string>{{ datadog_agent_log_path_macos }}/launchd.log</string>
         <key>StandardErrorPath</key>
-        <string>/opt/datadog-agent/logs/launchd.log</string>
+        <string>{{ datadog_agent_log_path_macos }}/launchd.log</string>
tasks/pkg-debian/install-installer.yml (1)

2-9: Add comment explaining the ignore_errors: true rationale to match the RedHat variant.

The ignore_errors: true is intentional and properly validated. The registered variable is checked in subsequent tasks with when: not ansible_check_mode and not datadog_installer_install_result.failed, and the result is used to send telemetry including installation status and error information. However, the Debian task lacks the explanatory comment present in the RedHat variant. Add a comment documenting that errors are intentionally ignored to allow telemetry collection and dependent task skipping, matching the existing documentation in tasks/pkg-redhat/install-installer-dnf.yml.

templates/install.json.j2 (1)

1-1: Consider adding variable validation and improving readability.

The template references install_signature.install_id, install_signature.install_time, and datadog_apm_instrumentation_enabled without checking if they're defined, which could lead to template rendering errors if these variables are missing.

Additionally, the single-line JSON format may reduce readability for future maintenance.

Consider applying this diff for better error handling and readability:

-{"install_id": "{{ install_signature.install_id }}", "install_type": {% if datadog_apm_instrumentation_enabled | length > 0 %}"ansible_single_step"{% else %}"ansible_manual"{% endif %}, "install_time": {{ install_signature.install_time }}}
+{
+  "install_id": "{{ install_signature.install_id | default('') }}",
+  "install_type": {% if (datadog_apm_instrumentation_enabled | default([])) | length > 0 %}"ansible_single_step"{% else %}"ansible_manual"{% endif %},
+  "install_time": {{ install_signature.install_time | default(0) }}
+}
tasks/parse-version-windows.yml (2)

2-2: Document the rc/beta limitation in user-facing documentation.

The comment notes that this task won't work with rc/beta builds. If this limitation impacts users, ensure it's documented in the role's main documentation or README.


21-21: Consider removing redundant conditional.

The when: ansible_facts.os_family == "Windows" condition is redundant since ansible.windows.win_shell can only execute on Windows hosts. The task will already fail gracefully on non-Windows systems.

If you want to keep the explicit guard for clarity, the current implementation is acceptable. Otherwise, consider:

-  when: ansible_facts.os_family == "Windows"
tasks/check-removed-config.yml (2)

2-5: Consider safer type handling for the deprecation check.

The condition datadog_yum_gpgkey|length > 0 will raise an error if datadog_yum_gpgkey is defined but not a string or sequence (e.g., if a user sets it to a number or boolean).

Consider a more defensive check:

- name: Ensure datadog_yum_gpgkey is not used
  ansible.builtin.fail:
    msg: datadog_yum_gpgkey configuration value was removed.
-  when: datadog_yum_gpgkey is defined and datadog_yum_gpgkey|length > 0
+  when: datadog_yum_gpgkey is defined and datadog_yum_gpgkey is not none and datadog_yum_gpgkey != ''

Or use:

  when: datadog_yum_gpgkey is defined and datadog_yum_gpgkey

This will catch any truthy value without type-specific operations.


7-10: Consider safer type handling for the deprecation check.

Same issue as with datadog_yum_gpgkey above—the length filter may fail on non-sequence types.

Apply the same defensive check pattern:

- name: Ensure datadog_zypper_gpgkey is not used
  ansible.builtin.fail:
    msg: datadog_zypper_gpgkey configuration value was removed.
-  when: datadog_zypper_gpgkey is defined and datadog_zypper_gpgkey|length > 0
+  when: datadog_zypper_gpgkey is defined and datadog_zypper_gpgkey is not none and datadog_zypper_gpgkey != ''

Or simply:

  when: datadog_zypper_gpgkey is defined and datadog_zypper_gpgkey
CONTRIBUTING.md (2)

5-5: Modernize CI badge (Travis org is deprecated).

While updating badges, consider replacing/removing the Travis badge (next line) in favor of your current CI (e.g., GitHub Actions).


66-66: Public support channel link.

If the Slack workspace isn’t publicly accessible, consider pointing contributors to GitHub Discussions/Issues instead.

tasks/sanitize-checks.yml (1)

6-13: Clarify precedence and dedupe tracked checks; assert input type.

Parenthesize to make intent explicit, dedupe, and validate that datadog_additional_checks is a sequence.

-    agent_datadog_tracked_checks: "{{ agent_datadog_checks | list + datadog_additional_checks | default([], true) }}"
+    agent_datadog_tracked_checks: "{{ ((agent_datadog_checks | list) + (datadog_additional_checks | default([], true))) | unique }}"

Optionally extend asserts:

   ansible.builtin.assert:
     that:
       - agent_datadog_checks is mapping
+      - datadog_additional_checks | default([]) is sequence
ci_test/downgrade_to_6.yaml (1)

5-5: Avoid absolute role path in shared examples.

If not strictly CI-only, prefer a relative role reference to improve portability.

templates/zypper.repo.j2 (2)

1-7: Guard undefined datadog_zypper_repo.

Safer when var is absent.

-{% if datadog_zypper_repo | length > 0 %}
+{% if datadog_zypper_repo is defined and datadog_zypper_repo | length > 0 %}

16-17: Align variable naming.

Mixing datadog_zypper_gpgcheck and agent_do_zypper_repo_gpgcheck is inconsistent. Consider consistent prefixes.

tasks/agent-macos.yml (1)

32-37: Consider making service check more robust.

The task uses failed_when: false to handle cases where the service isn't running. Consider adding explicit error message handling to distinguish between "service not found" vs. other launchctl failures.

tasks/integration/_linux-macos-shared.yml (1)

33-42: Consider using argv format for consistency.

Lines 18-23 use argv format for the remove command, but line 34 uses string interpolation for the install command. For consistency and to avoid potential shell injection issues, consider using argv format here as well.

Apply this diff:

-- name: Installing pinned version of integration, integration={{ item.key }}
-  ansible.builtin.command: "{{ datadog_agent_binary_path }} integration install {{ third_party }} {{ item.key }}=={{ item.value.version }}"
+- name: Installing pinned version of integration, integration={{ item.key }}
+  ansible.builtin.command:
+    argv:
+      - "{{ datadog_agent_binary_path }}"
+      - integration
+      - install
+      - "{{ third_party }}"
+      - "{{ item.key }}=={{ item.value.version }}"
   become: true
   become_user: "{{ integration_command_user }}"
   vars:

Note: You'll need to adjust the third_party variable handling to work with argv (possibly empty string vs flag).

tasks/installer-setup.yml (1)

6-9: Unusual use of changed_when: true for a read-only command.

The date command is read-only but marked with changed_when: true. While this ensures the task always runs and appears in change reports, it inflates the change count. Consider using changed_when: false with check_mode: false if the goal is to always execute without reporting changes.

Apply this diff if you want to avoid inflating change counts:

 - name: Start duration measurements
   ansible.builtin.command: "date +%s%N"
   register: datadog_installer_start_time
-  changed_when: true
+  changed_when: false
+  check_mode: false
manual_tests/test_7_full.yml (1)

3-3: Remove outdated Ansible version comment.

The comment referencing Ansible < 1.9 is no longer relevant. Modern playbooks only need become: yes.

Apply this diff:

-    - { role: ../../ansible-datadog, become: yes }  # On Ansible < 1.9, use `sudo: yes` instead of `become: yes`
+    - { role: ../../ansible-datadog, become: yes }
tasks/integration/windows.yml (1)

6-8: Fix typo in task name comment.

The comment has a typo: "commmand" should be "command".

Apply this diff:

- name: Set Agent user for integration commmand
+ name: Set Agent user for integration command
tasks/integration/macos.yml (1)

6-8: Fix typo in task name comment.

The comment has a typo: "commmand" should be "command" (same as Windows integration file).

Apply this diff:

- name: Set Agent user for integration commmand
+ name: Set Agent user for integration command
ci_test/install_agent_7_macos.yaml (1)

10-11: Remove or update inconsistent CentOS comment in macOS test.

This macOS test includes a comment about avoiding CentOS checks, which is out of place. Either remove the comment or clarify its relevance to macOS.

Apply this diff:

-    # avoid checking that the agent is stopped for centos
+    # avoid checking that the agent is stopped for macOS (no pre-existing service)
tasks/pkg-redhat/install-installer-dnf.yml (1)

9-11: Minor typo in comment.

Line 11 has "depedency" which should be "dependency". While not a functional issue, it should be corrected for code quality.

Apply this diff to fix the typo:

  # Since we want to send telemetry including when the installation failed,
-  # we need to explicitely ignore failures and skip dependent task when one
-  # of its depedency failed
+  # we need to explicitly ignore failures and skip dependent tasks when one
+  # of its dependencies failed
tasks/set-parse-version.yml (1)

4-4: Update to modern Ansible filter syntax.

The default filter's second boolean parameter can now be expressed with the named parameter syntax, which is clearer and more maintainable. Lines 4 and 12 use the positional boolean parameter true.

Consider updating to the more idiomatic named parameter approach:

- agent_datadog_agent_major_version: "{{ datadog_agent_major_version | default('', true) | string }}"
+ agent_datadog_agent_major_version: "{{ datadog_agent_major_version | default('', boolean=true) | string }}"

This change improves readability without affecting functionality.

Also applies to: 12-12

tasks/pkg-redhat/install-pinned.yml (1)

2-5: Make disablerepo conditional to avoid harmless/noisy dnf warnings on non-AppStream hosts.

On RHEL-like distros lacking an “appstream” repo id, dnf prints “No matching repo to disable”. Keep current behavior but omit the param when not applicable.

Apply this diff:

-  ansible.builtin.dnf:
+  ansible.builtin.dnf:
     name: "{{ datadog_agent_flavor }}-{{ agent_datadog_agent_redhat_version }}"
     update_cache: true
     state: present
     allow_downgrade: "{{ datadog_agent_allow_downgrade }}"
-    disablerepo: "appstream"
+    disablerepo: "{{ (ansible_facts.os_family == 'RedHat' and (ansible_facts.distribution_major_version | int) >= 8) | ternary('appstream', omit) }}"

Also applies to: 8-9

templates/security-agent.yaml.j2 (1)

1-23: LGTM; optional: simplify indentation via to_nice_yaml(indent=2).

Current indent filter is fine and compatible. You could avoid Jinja indent quirks by using the filter’s built-in indent parameter instead.

Example:

runtime_security_config:
{{ runtime_security_config | to_nice_yaml(indent=2) }}
handlers/main-macos.yml (1)

10-22: Remove redundant check_mode and unused register; keep handler semantics clean.

Tasks already gated by “when: not ansible_check_mode”; the explicit check_mode: false is redundant. Also, command_result is registered but unused.

Apply this diff:

   ansible.builtin.command: "launchctl unload -wF {{ datadog_macos_system_plist_file_path }}"
   become: true
-  check_mode: false
   when: datadog_enabled and not ansible_check_mode and ansible_facts.os_family == "Darwin"
   changed_when: true
@@
   ansible.builtin.command: "launchctl load -wF {{ datadog_macos_system_plist_file_path }}"
   become: true
-  check_mode: false
   when: datadog_enabled and not ansible_check_mode and ansible_facts.os_family == "Darwin"
   changed_when: true
@@
   ansible.builtin.command: "launchctl kickstart -k system/{{ datadog_macos_service_name }}"
   become: true
-  register: command_result
-  check_mode: false
   when: datadog_enabled and not ansible_check_mode and ansible_facts.os_family == "Darwin"
   changed_when: true

Also applies to: 24-30

tasks/installer-config.yml (2)

2-5: Guard against undefined variables.

If datadog_apm_instrumentation_enabled is undefined, the length filter will fail. Consider adding a default value or using a defined check.

Apply this diff:

-  when: datadog_apm_instrumentation_enabled | length > 0
+  when: datadog_apm_instrumentation_enabled | default('') | length > 0

7-19: Guard against undefined variables.

The length checks on lines 16-19 will fail if the variables are undefined. Add default values to prevent errors.

Apply this diff:

   when: >
-    datadog_installer_registry | length > 0 or
-    datadog_installer_auth | length > 0 or
-    datadog_installer_version | length > 0 or
-    datadog_apm_inject_version | length > 0
+    datadog_installer_registry | default('') | length > 0 or
+    datadog_installer_auth | default('') | length > 0 or
+    datadog_installer_version | default('') | length > 0 or
+    datadog_apm_inject_version | default('') | length > 0
ci_test/ansible_lint.sh (1)

45-64: Consider using a more robust find pattern.

Line 48 uses a for loop over find output, which can be fragile with special characters in filenames. While this is likely acceptable for Ansible role files, consider using find -exec or a while-read loop for better robustness.

Alternative approach:

-for file in $(find . -type f -and \( -path '*defaults*' -or -path '*tasks*' -or -path '*templates*' -or -path '*handlers*' -or -name '.gitkeep' -or -path '*meta*' -or -name 'README.md' \));
-do
+find . -type f -and \( -path '*defaults*' -or -path '*tasks*' -or -path '*templates*' -or -path '*handlers*' -or -name '.gitkeep' -or -path '*meta*' -or -name 'README.md' \) -print0 | while IFS= read -r -d '' file; do
     echo "Create ansible_collections/datadog/roles/agent/${file:2}"
     mkdir -p "$(dirname "ansible_collections/datadog/roles/agent/${file:2}")"
     cp -r "$file" "ansible_collections/datadog/roles/agent/${file:2}"
 done
defaults/main.yml (2)

261-261: Confirm ansible_user is safe to use as default for macOS user.

Line 261 sets datadog_macos_user: "{{ ansible_user }}". The ansible_user variable is a runtime fact that may not exist in all execution contexts. Consider whether this should default to a fixed value (e.g., "dd-agent" for consistency with Linux) or include a fallback. This affects macOS agent configuration correctness.

# Current (line 261):
datadog_macos_user: "{{ ansible_user }}"

# Consider a safer default:
datadog_macos_user: "{{ ansible_user | default('dd-agent') }}"

78-117: Review RPM GPG key management strategy for expiry handling.

Lines 78-117 define multiple RPM/Zypper GPG keys with expiry date comments (2022, 2024, 2028, 2033). Confirm that:

  1. Key rotation/removal is tracked as keys expire
  2. The comment on lines 101-102 about SNI and older Python is still relevant and not outdated
  3. Removal of expired keys (e.g., 2022 key) is handled in a migration path
tasks/agent-win.yml (1)

82-86: Verify custom checks source paths are accessible and validated.

Lines 82-86 copy custom check files from datadog_custom_checks[item] to the Windows checks directory. Confirm:

  1. The source paths in datadog_custom_checks are valid and accessible from the Ansible controller
  2. These paths are validated before reaching this task
  3. Error handling is in place if source files don't exist
tasks/pkg-windows.yml (1)

2-5: Verify agent_datadog_sysprobe_enabled is correctly initialized for Windows.

Line 2-5 sets agent_datadog_sysprobe_enabled from network_config before including Windows opts tasks. Confirm:

  1. This initial value is appropriate (only network_config, not other probe configs like service_monitoring_config)
  2. The comment "must be prior to pkg-windows-opts.yml" indicates a dependency—verify pkg-windows-opts.yml doesn't override this incorrectly
  3. This pattern aligns with Linux initialization (if present in agent-linux.yml)
.circleci/config.yml (3)

12-13: Verify Python path is correct for all CI environments.

Lines 12-13 use -e 'ansible_python_interpreter=/usr/bin/<<parameters.python>>'. This assumes Python is located at /usr/bin/, which may not be true for all distributions or CI images. For example:

  • Alpine Linux: /usr/local/bin/python3
  • Homebrew on macOS: /opt/homebrew/bin/python3.11

Consider using a more flexible approach, or ensure all CI images have Python at /usr/bin/.


207-262: Verify APM injection test setup and dependencies.

Lines 207-262 define new APM injection tests that:

  1. Clone the DataDog system-tests repository from GitHub (line 223)
  2. Build a Docker image (line 224)
  3. Run a test application (line 225)
  4. Verify traces are emitted (lines 228-239)

Confirm:

  1. The system-tests repository is publicly available and won't be rate-limited
  2. The docker build and run steps are properly integrated into CI
  3. The trace verification logic (jq query) is correct
  4. Network connectivity from CI to public repos is allowed

263-299: Verify installer test setup with fake systemctl is appropriate.

Lines 263-299 (test_installer job) use a fake systemctl script to simulate systemd in a Docker container (lines 285-286). Verify:

  1. This approach doesn't mask real systemd-related bugs
  2. The datadog-installer actually needs systemctl and won't fail on the fake version
  3. The /etc/systemd/system/ directory creation is sufficient for the installer
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2e01bf3 and b4ccfcd.

⛔ Files ignored due to path filters (1)
  • Gemfile.lock is excluded by !**/*.lock
📒 Files selected for processing (97)
  • .ansible-lint (1 hunks)
  • .circleci/config.yml (3 hunks)
  • .github/CODEOWNERS (1 hunks)
  • .github/dependabot.yml (1 hunks)
  • .gitignore (1 hunks)
  • CHANGELOG.md (4 hunks)
  • CONTRIBUTING.md (3 hunks)
  • Gemfile (0 hunks)
  • README.md (16 hunks)
  • chefignore (0 hunks)
  • ci_test/ansible_lint.sh (1 hunks)
  • ci_test/downgrade_to_6.yaml (1 hunks)
  • ci_test/install_agent_6.yaml (2 hunks)
  • ci_test/install_agent_6_macos.yaml (2 hunks)
  • ci_test/install_agent_7.yaml (2 hunks)
  • ci_test/install_agent_7_apm_all.yaml (1 hunks)
  • ci_test/install_agent_7_apm_python.yaml (1 hunks)
  • ci_test/install_agent_7_macos.yaml (2 hunks)
  • ci_test/install_agent_7_pinned.yaml (1 hunks)
  • ci_test/install_installer.yaml (1 hunks)
  • ci_test/install_installer_air_gapped.yaml (1 hunks)
  • ci_test/install_installer_over_pinned.yaml (1 hunks)
  • ci_test/inventory/ci_macos.ini (1 hunks)
  • defaults/main.yml (4 hunks)
  • handlers/main-macos.yml (1 hunks)
  • handlers/main-win.yml (1 hunks)
  • handlers/main.yml (1 hunks)
  • kitchen.yml (0 hunks)
  • manual_tests/.gitignore (1 hunks)
  • manual_tests/Vagrantfile (1 hunks)
  • manual_tests/inventory (1 hunks)
  • manual_tests/inventory_win (1 hunks)
  • manual_tests/readme.md (1 hunks)
  • manual_tests/test_5_default.yml (0 hunks)
  • manual_tests/test_5_full.yml (0 hunks)
  • manual_tests/test_6_default.yml (1 hunks)
  • manual_tests/test_6_full.yml (2 hunks)
  • manual_tests/test_7_default.yml (1 hunks)
  • manual_tests/test_7_full.yml (1 hunks)
  • meta/main.yml (1 hunks)
  • requirements-ansible-lint.txt (1 hunks)
  • requirements.txt (1 hunks)
  • tasks/_agent-linux-macos-shared.yml (1 hunks)
  • tasks/_apt-key-import.yml (1 hunks)
  • tasks/_remove_rpm_keys.yml (1 hunks)
  • tasks/agent-linux.yml (1 hunks)
  • tasks/agent-macos.yml (1 hunks)
  • tasks/agent-win.yml (1 hunks)
  • tasks/agent5-linux.yml (0 hunks)
  • tasks/check-removed-config.yml (1 hunks)
  • tasks/installer-config.yml (1 hunks)
  • tasks/installer-setup.yml (1 hunks)
  • tasks/integration.yml (1 hunks)
  • tasks/integration/_linux-macos-shared.yml (1 hunks)
  • tasks/integration/_windows-integration-update.yml (1 hunks)
  • tasks/integration/linux.yml (1 hunks)
  • tasks/integration/macos.yml (1 hunks)
  • tasks/integration/windows.yml (1 hunks)
  • tasks/main.yml (1 hunks)
  • tasks/os-check.yml (1 hunks)
  • tasks/parse-version-macos.yml (1 hunks)
  • tasks/parse-version-windows.yml (1 hunks)
  • tasks/parse-version.yml (1 hunks)
  • tasks/pkg-debian.yml (1 hunks)
  • tasks/pkg-debian/install-installer.yml (1 hunks)
  • tasks/pkg-debian/install-latest.yml (1 hunks)
  • tasks/pkg-debian/install-pinned.yml (1 hunks)
  • tasks/pkg-macos.yml (1 hunks)
  • tasks/pkg-macos/macos_agent_latest.yml (1 hunks)
  • tasks/pkg-macos/macos_agent_version.yml (1 hunks)
  • tasks/pkg-redhat.yml (1 hunks)
  • tasks/pkg-redhat/install-installer-dnf.yml (1 hunks)
  • tasks/pkg-redhat/install-latest.yml (1 hunks)
  • tasks/pkg-redhat/install-pinned.yml (1 hunks)
  • tasks/pkg-suse.yml (1 hunks)
  • tasks/pkg-suse/install-installer-zypper.yml (1 hunks)
  • tasks/pkg-suse/install-latest.yml (1 hunks)
  • tasks/pkg-suse/install-pinned.yml (1 hunks)
  • tasks/pkg-windows-opts.yml (1 hunks)
  • tasks/pkg-windows.yml (2 hunks)
  • tasks/sanitize-checks.yml (1 hunks)
  • tasks/set-parse-version.yml (1 hunks)
  • tasks/win_agent_latest.yml (1 hunks)
  • tasks/win_agent_version.yml (1 hunks)
  • templates/checks.yaml.j2 (1 hunks)
  • templates/com.datadoghq.agent.plist.j2 (1 hunks)
  • templates/datadog.conf.j2 (1 hunks)
  • templates/datadog.yaml.j2 (1 hunks)
  • templates/install.json.j2 (1 hunks)
  • templates/installer-logs.j2 (1 hunks)
  • templates/installer-telemetry.j2 (1 hunks)
  • templates/security-agent.yaml.j2 (1 hunks)
  • templates/system-probe.yaml.j2 (1 hunks)
  • templates/zypper.repo.j2 (2 hunks)
  • test/integration/default/default.yml (0 hunks)
  • test/integration/default/serverspec/localhost/default_spec.rb (0 hunks)
  • test/integration/default/serverspec/spec_helper.rb (0 hunks)
💤 Files with no reviewable changes (9)
  • tasks/agent5-linux.yml
  • manual_tests/test_5_default.yml
  • test/integration/default/default.yml
  • Gemfile
  • chefignore
  • test/integration/default/serverspec/localhost/default_spec.rb
  • test/integration/default/serverspec/spec_helper.rb
  • manual_tests/test_5_full.yml
  • kitchen.yml
🧰 Additional context used
🪛 Checkov (3.2.334)
tasks/pkg-macos/macos_agent_latest.yml

[medium] 7-22: Ensure that HTTPS url is used with uri

(CKV2_ANSIBLE_1)

🪛 LanguageTool
requirements-ansible-lint.txt

[grammar] ~1-~1: Hier könnte ein Fehler sein.
Context: ansible-lint==25.1.2

(QB_NEW_DE)

CHANGELOG.md

[uncategorized] ~9-~9: The operating system from Apple is written “macOS”.
Context: ...tation [DataDog#676] * [IMPROVEMENT] Simplify MacOS version architecture [DataDog#677] * [IMPROVEM...

(MAC_OS)


[grammar] ~21-~21: Ensure spelling is correct
Context: ...MENT] Only gather facts and services if notd done already [DataDog#659] [Thanks @POIFischba...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[uncategorized] ~53-~53: The operating system from Apple is written “macOS”.
Context: ...eb/rpms [DataDog#624] * [IMPROVEMENT] [CI] Fix MacOS CI [DataDog#630] * [BUGFIX] Fix Ansible check ...

(MAC_OS)


[grammar] ~86-~86: Ensure spelling is correct
Context: ...ll.json file related to apm single step instrumation [DataDog#572] * [FEATURE] add support for data...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~150-~150: Use a hyphen to join words.
Context: ...ng includepkgs in repofiles on Red Hat compatible platforms. See [DataDog#443]. Thanks...

(QB_NEW_EN_HYPHEN)


[grammar] ~155-~155: Use a hyphen to join words.
Context: ...ing role multiple times in a row on SUSE compatible platforms. See [DataDog#453]. * [DOC...

(QB_NEW_EN_HYPHEN)

README.md

[style] ~112-~112: ‘Whether or not’ might be wordy. Consider a shorter alternative.
Context: ...og_apply_windows_614_fix` | Whether or not to download and apply file referenced b...

(EN_WORDINESS_PREMIUM_WHETHER_OR_NOT)


[uncategorized] ~113-~113: The operating system from Apple is written “macOS”.
Context: ...ren't running Datadog Agent 6.14.*.| | datadog_macos_user | The name...

(MAC_OS)


[uncategorized] ~114-~114: The operating system from Apple is written “macOS”.
Context: ...ults to ansible_user (macOS only).| | datadog_macos_download_url | Override...

(MAC_OS)


[grammar] ~122-~122: Use a hyphen to join words.
Context: ... the datadog_checks section. The first level key is the name of the check, and ...

(QB_NEW_EN_HYPHEN)


[uncategorized] ~330-~330: The operating system from Apple is written “macOS”.
Context: ... string. #### macOS When the variable datadog_macos_download_url is not set, the official ...

(MAC_OS)


[grammar] ~358-~358: Use a hyphen to join words.
Context: ...e`: Removes an integration. ##### Third party integrations [Datadog community][...

(QB_NEW_EN_HYPHEN)


[style] ~580-~580: ‘prior to’ might be wordy. Consider a shorter alternative.
Context: ...rmation applies to versions of the role prior to 4.9.0. Since 4.9.0, the apt_key modul...

(EN_WORDINESS_PREMIUM_PRIOR_TO)

🪛 markdownlint-cli2 (0.18.1)
CHANGELOG.md

32-32: Bare URL used

(MD034, no-bare-urls)

README.md

112-112: Bare URL used

(MD034, no-bare-urls)


315-315: Bare URL used

(MD034, no-bare-urls)


323-323: Bare URL used

(MD034, no-bare-urls)


324-324: Bare URL used

(MD034, no-bare-urls)


334-334: Bare URL used

(MD034, no-bare-urls)


335-335: Bare URL used

(MD034, no-bare-urls)


336-336: Bare URL used

(MD034, no-bare-urls)


337-337: Bare URL used

(MD034, no-bare-urls)


347-347: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


628-628: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


646-646: Link and image reference definitions should be needed
Unused link or image reference definition: "2"

(MD053, link-image-reference-definitions)

🪛 Shellcheck (0.11.0)
ci_test/ansible_lint.sh

[warning] 12-12: Quote this to prevent word splitting.

(SC2046)


[warning] 48-48: For loops over find output are fragile. Use find -exec or a while read loop.

(SC2044)

Comment thread .circleci/config.yml Outdated
Comment thread .circleci/config.yml
Comment on lines +469 to +503
- test_install:
matrix:
parameters:
ansible_version: ["2_10", "3_4", "4_10", "9_4"]
agent_version: ["6", "7"]
jinja2_native: ["true", "false"]
os: ["rocky8"]
python: ["python3"]

- test_install:
matrix:
parameters:
ansible_version: ["12_0"]
agent_version: ["6", "7"]
jinja2_native: ["true", "false"]
os: ["rocky9", "suse", "amazonlinux2023"]
python: ["python3.11"]

# Newer suse images only have Python 3 installed
- test_install:
matrix:
parameters:
ansible_version: ["2_8", "2_9", "2_10"]
ansible_version: ["2_10", "3_4", "4_10", "9_4"]
agent_version: ["6", "7"]
os: ["suse"]
python: ["python3"]

- test_install:
matrix:
parameters:
ansible_version: ["2_10", "3_4", "4_10"]
agent_version: ["6", "7"]
os: ["amazonlinux2023"]
python: ["python3"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Review test matrix coverage and Python version consistency.

Lines 469-503 expand the test matrices to include multiple Ansible versions, agent versions, distributions, and Python versions. Verify that:

  1. Python versions align with distribution capabilities (python3 for older Debian, python3.11 for newer)
  2. Ansible versions support the Python versions they're paired with (Ansible 5.x requires Python >= 3.8)
  3. The jinja2_native parameter is tested across a representative sample of combinations
  4. macOS tests are included (line 504+)

🏁 Script executed:

#!/bin/bash
# Count matrix combinations to ensure coverage is reasonable
echo "Test matrix combinations:"
rg -o 'parameters:.*python: .*' .circleci/config.yml | wc -l

Length of output: 27


I need to examine the actual file structure more carefully, as the regex pattern didn't work with the YAML format.


---

🏁 Script executed:

```shell
#!/bin/bash
# Extract the relevant section of the config file with better context
echo "=== Lines 465-510 of .circleci/config.yml ==="
sed -n '465,510p' .circleci/config.yml

Length of output: 1449


🏁 Script executed:

#!/bin/bash
# Search for macOS test configurations
echo "=== Checking for macOS test references ==="
rg -n "macos|darwin" .circleci/config.yml -i

Length of output: 349


🏁 Script executed:

#!/bin/bash
# Search for all test_install matrix definitions to understand structure
echo "=== All test_install matrix blocks ==="
rg -n "test_install:" .circleci/config.yml -A 10

Length of output: 1589


🏁 Script executed:

#!/bin/bash
# Check what comes after line 503
echo "=== Lines 500-520 of config ==="
sed -n '500,520p' .circleci/config.yml

Length of output: 613


🏁 Script executed:

#!/bin/bash
# Look for ansible version definitions and python compatibility info
echo "=== Checking ansible_version parameter usage ==="
rg -n "ansible_version" .circleci/config.yml -C 3

Length of output: 9461


🏁 Script executed:

#!/bin/bash
# Search for jinja2_native usage
echo "=== jinja2_native parameter coverage ==="
rg -n "jinja2_native" .circleci/config.yml -C 2

Length of output: 4286


🏁 Script executed:

#!/bin/bash
# Check python version specifications
echo "=== Python version parameters ==="
rg -n "python.*:" .circleci/config.yml | head -30

Length of output: 1248


🏁 Script executed:

#!/bin/bash
# Get file length and overall structure
echo "=== File statistics ==="
wc -l .circleci/config.yml
echo ""
echo "=== Test matrix sections ==="
rg -n "- test_install:" .circleci/config.yml

Length of output: 483


I need to verify the Ansible version compatibility claims:

I need to check if Rocky Linux and SUSE default Python versions could support Ansible 9.4:<!-- [scratchpad_update]
[task verify_review_comment_1/1 COMPLETE]
[observations]
Key findings from web searches:

  • Rocky Linux 8: No default version of Python on Rocky Linux 8, but Python 3.6.8 if installed seems to take precedence. Available versions are 3.6, 3.8, 3.9, 3.12 (from source 21-15, 28-1, 28-4)
  • Ansible 9 removed Python 3.9 support; Python 3.10 or newer is required
  • SUSE: SUSE Linux Enterprise Server 15 uses Python 3.6 by default, Python 3.9 added in SP3 but no longer supported as of SP4 (sources 32-1, 32-2, 32-3, 35-1)

Issues identified:

  1. Ansible 9.4 (9_4 notation) is tested with generic "python3" on rocky8 (line 472) and suse (line 491)

    • Rocky8 default is 3.6.8, which is below Ansible 9's 3.10+ requirement
    • SUSE default is 3.6, also insufficient for Ansible 9.4
    • This is a CRITICAL issue
  2. jinja2_native coverage incomplete:

    • Only tested in 2 of 4 matrices (rocky8 and ansible 12.0 combination)
    • NOT tested for suse standalone or amazonlinux2023
    • Partial coverage issue
  3. macOS tests present and correct format with all Ansible versions

    • But also uses generic "python3" (though brew installs 3.11)
      [analysis]
      Review comment concerns are partially valid:
  • Issue 1 (Python alignment): INCORRECT for Ansible 9.4 - python3 on rocky8/suse insufficient
  • Issue 2 (Ansible compatibility): CRITICAL ISSUE FOUND - Ansible 9.4 requires Python 3.10+
  • Issue 3 (jinja2_native coverage): VALID but partial - not all combinations tested
  • Issue 4 (macOS tests): VALID - tests present

The review comment is asking for verification, but actual code issues exist that need to be flagged.
[actions]

  • Generate rewritten comment highlighting the Ansible 9.4 Python version issue
  • Flag jinja2_native coverage gaps
  • Confirm macOS tests are present
    [scratchpad_end] -->

Ansible 9.4 Python version incompatibility detected. Consider explicit Python 3.10+ for affected tests.

The test matrices reveal a compatibility issue: Ansible 9 requires Python 3.10 or newer on the controller, but lines 472 and 491 pair ansible_version "9_4" with generic python: ["python3"] on rocky8 and suse. Rocky Linux 8's python3 link defaults to Python 3.6.8, and SUSE Linux Enterprise Server 15 uses Python 3.6 by default—both insufficient.

Additionally, jinja2_native parameter testing is incomplete: it's tested with Ansible 2_10–9_4 on rocky8 and with Ansible 12_0 across rocky9/suse/amazonlinux2023, but not for suse or amazonlinux2023 in standalone matrices (lines 488–502).

Confirm: Upgrade python specification for Ansible 9.4 tests, or skip those combinations on distributions with Python < 3.10. macOS tests (line 504+) are included as expected.

Comment thread CHANGELOG.md
* [IMPROVEMENT] Remove pycache directory during upgrades [#673]
* [IMPROVEMENT] Prepare deployment of Agent v7.70+ for macOS (arm64/x86_64) [664]
* [DOCUMENTATION] Adjust misleading macOS Agent version documentation [#676]
* [IMPROVEMENT] Simplify MacOS version architecture [#677]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix capitalization: use "macOS" instead of "MacOS".

The operating system from Apple is written as "macOS" (lowercase 'm').

Apply this diff:

-* [IMPROVEMENT] Simplify MacOS version architecture [#677]
+* [IMPROVEMENT] Simplify macOS version architecture [#677]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
* [IMPROVEMENT] Simplify MacOS version architecture [#677]
* [IMPROVEMENT] Simplify macOS version architecture [#677]
🧰 Tools
🪛 LanguageTool

[uncategorized] ~9-~9: The operating system from Apple is written “macOS”.
Context: ...tation [DataDog#676] * [IMPROVEMENT] Simplify MacOS version architecture [DataDog#677] * [IMPROVEM...

(MAC_OS)

🤖 Prompt for AI Agents
In CHANGELOG.md around line 9, the entry uses the incorrect capitalization
"MacOS"; change it to the correct Apple branding "macOS" so the line reads "*
[IMPROVEMENT] Simplify macOS version architecture [#677]". Ensure only the
capitalization of "macOS" is updated and nothing else in the line is modified.

Comment thread CHANGELOG.md
# 5.2.1 / 2025-05-22
* [IMPROVEMENT] Provide bootstrap environment variables to installer only if not empty strings [#655]
* [IMPROVEMENT] Remove community.general.zypper reference [#658]
* [IMPROVEMENT] Only gather facts and services if notd done already [#659] [Thanks @POIFischbacher]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix typo: "notd" should be "not".

Apply this diff:

-* [IMPROVEMENT] Only gather facts and services if notd done already [#659] [Thanks @POIFischbacher]
+* [IMPROVEMENT] Only gather facts and services if not done already [#659] [Thanks @POIFischbacher]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
* [IMPROVEMENT] Only gather facts and services if notd done already [#659] [Thanks @POIFischbacher]
* [IMPROVEMENT] Only gather facts and services if not done already [#659] [Thanks @POIFischbacher]
🧰 Tools
🪛 LanguageTool

[grammar] ~21-~21: Ensure spelling is correct
Context: ...MENT] Only gather facts and services if notd done already [DataDog#659] [Thanks @POIFischba...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🤖 Prompt for AI Agents
In CHANGELOG.md around line 21, there's a typo: the word "notd" should be
corrected to "not"; update the line so it reads "Only gather facts and services
if not done already" preserving the rest of the entry and formatting.

Comment thread CHANGELOG.md
* [IMPROVEMENT] Provide bootstrap environment variables to installer only if not empty strings [#655]
* [IMPROVEMENT] Remove community.general.zypper reference [#658]
* [IMPROVEMENT] Only gather facts and services if notd done already [#659] [Thanks @POIFischbacher]
* [IMROVEMENT] [CI] Remove role prefix lint warnings [#660]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix typo: "IMROVEMENT" should be "IMPROVEMENT".

Apply this diff:

-* [IMROVEMENT] [CI] Remove role prefix lint warnings [#660]
+* [IMPROVEMENT] [CI] Remove role prefix lint warnings [#660]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
* [IMROVEMENT] [CI] Remove role prefix lint warnings [#660]
* [IMPROVEMENT] [CI] Remove role prefix lint warnings [#660]
🤖 Prompt for AI Agents
In CHANGELOG.md around line 22, the word "IMROVEMENT" is misspelled; change
"IMROVEMENT" to the correct "IMPROVEMENT" so the entry reads "* [IMPROVEMENT]
[CI] Remove role prefix lint warnings [#660]". Ensure only the typo is fixed and
keep the rest of the line intact.

Comment on lines +8 to +11
ansible.builtin.set_fact:
agent_dd_download_url: "{% if agent_datadog_agent_major_version
| int == 7 %}{{ datadog_windows_agent7_latest_url }} {% else %}{{ datadog_windows_agent6_latest_url }}{% endif %}"
when: datadog_windows_download_url | default('', true) | length == 0
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Trailing space in Jinja URL (version==7) can break downloads.

There’s a literal space after datadog_windows_agent7_latest_url. Remove it or switch to ternary.

Apply one of the following:

-    agent_dd_download_url: "{% if agent_datadog_agent_major_version
-      | int == 7 %}{{ datadog_windows_agent7_latest_url }} {% else %}{{ datadog_windows_agent6_latest_url }}{% endif %}"
+    agent_dd_download_url: "{% if (agent_datadog_agent_major_version | int) == 7 %}{{ datadog_windows_agent7_latest_url }}{% else %}{{ datadog_windows_agent6_latest_url }}{% endif %}"

Or:

-    agent_dd_download_url: "{% if agent_datadog_agent_major_version
-      | int == 7 %}{{ datadog_windows_agent7_latest_url }} {% else %}{{ datadog_windows_agent6_latest_url }}{% endif %}"
+    agent_dd_download_url: "{{ ((agent_datadog_agent_major_version | int) == 7)
+      | ternary(datadog_windows_agent7_latest_url, datadog_windows_agent6_latest_url) }}"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ansible.builtin.set_fact:
agent_dd_download_url: "{% if agent_datadog_agent_major_version
| int == 7 %}{{ datadog_windows_agent7_latest_url }} {% else %}{{ datadog_windows_agent6_latest_url }}{% endif %}"
when: datadog_windows_download_url | default('', true) | length == 0
ansible.builtin.set_fact:
agent_dd_download_url: "{% if (agent_datadog_agent_major_version | int) == 7 %}{{ datadog_windows_agent7_latest_url }}{% else %}{{ datadog_windows_agent6_latest_url }}{% endif %}"
when: datadog_windows_download_url | default('', true) | length == 0
Suggested change
ansible.builtin.set_fact:
agent_dd_download_url: "{% if agent_datadog_agent_major_version
| int == 7 %}{{ datadog_windows_agent7_latest_url }} {% else %}{{ datadog_windows_agent6_latest_url }}{% endif %}"
when: datadog_windows_download_url | default('', true) | length == 0
ansible.builtin.set_fact:
agent_dd_download_url: "{{ ((agent_datadog_agent_major_version | int) == 7)
| ternary(datadog_windows_agent7_latest_url, datadog_windows_agent6_latest_url) }}"
when: datadog_windows_download_url | default('', true) | length == 0
🤖 Prompt for AI Agents
In tasks/win_agent_latest.yml around lines 8 to 11, the Jinja expression sets
agent_dd_download_url with a literal trailing space after {{
datadog_windows_agent7_latest_url }} which can break downloads; remove the
trailing space (i.e., change the template so the version==7 branch has no
trailing space) or replace the if/else block with a ternary expression such as
{{ (agent_datadog_agent_major_version | int == 7) |
ternary(datadog_windows_agent7_latest_url, datadog_windows_agent6_latest_url) }}
to ensure no accidental whitespace is included.

Comment thread templates/datadog.yaml.j2
Comment on lines +13 to 15
{% if agent_datadog_config is not defined or agent_datadog_config["api_key"] is not defined -%}
api_key: {{ datadog_api_key }}
{% endif %}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Guard api_key emission; current block fails when datadog_api_key is undefined.

If api_key isn’t set in agent_datadog_config and datadog_api_key is not defined, templating errors out. Add a defined check.

Apply this diff:

-{% if agent_datadog_config is not defined or agent_datadog_config["api_key"] is not defined -%}
-api_key: {{ datadog_api_key }}
+{% if (agent_datadog_config is not defined or agent_datadog_config["api_key"] is not defined)
+      and (datadog_api_key is defined) -%}
+api_key: "{{ datadog_api_key }}"
 {% endif %}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{% if agent_datadog_config is not defined or agent_datadog_config["api_key"] is not defined -%}
api_key: {{ datadog_api_key }}
{% endif %}
{% if (agent_datadog_config is not defined or agent_datadog_config["api_key"] is not defined)
and (datadog_api_key is defined) -%}
api_key: "{{ datadog_api_key }}"
{% endif %}
🤖 Prompt for AI Agents
In templates/datadog.yaml.j2 around lines 13 to 15, the current conditional
emits api_key when agent_datadog_config is missing or lacks api_key but assumes
datadog_api_key exists, causing template errors if datadog_api_key is undefined;
update the if condition to also check that datadog_api_key is defined (e.g., add
"and datadog_api_key is defined") so the api_key line is only rendered when
datadog_api_key is present.

Comment thread templates/installer-logs.j2 Outdated
Comment on lines +1 to +36
{
"api_version": "v2",
"request_type": "logs",
"tracer_time": "{{ stop_time }}",
"runtime_id": "{{ trace_id }}",
"seq_id": 2,
"origin": "ansible",
"host": {
"hostname": "{{ hostname }}",
"os": "{{ system }}",
"distribution": "{{ os_family }}",
"architecture": "{{ arch }}",
"kernel_version": "{{ kernel }}",
"kernel_release": "{{ kernel_version }}"
},
"application": {
"service_name": "datadog-ansible",
"service_version": "{{ role_version }}",
"language_name": "UNKNOWN",
"language_version": "n/a",
"tracer_version": "n/a"
},
"payload": {
"logs": [{
"message": "{{ stdout }}",
"level": "DEBUG",
"trace_id": {{ datadog_installer_trace_id }},
"span_id": {{ datadog_installer_trace_id }}
},{
"message": "{{ stderr }}",
"level": "ERROR",
"trace_id": {{ datadog_installer_trace_id }},
"span_id": {{ datadog_installer_trace_id }}
}]
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Escape strings and cast numbers to produce valid JSON (and reduce PII risk).

Use tojson for strings and int casts for IDs/timestamps; optionally redact secrets in stderr.

-    "tracer_time": "{{ stop_time }}",
-    "runtime_id": "{{ trace_id }}",
+    "tracer_time": {{ stop_time | int }},
+    "runtime_id": {{ (trace_id | string) | tojson }},
@@
-        "hostname": "{{ hostname }}",
-        "os": "{{ system }}",
-        "distribution": "{{ os_family }}",
-        "architecture": "{{ arch }}",
-        "kernel_version": "{{ kernel }}",
-        "kernel_release": "{{ kernel_version }}"
+        "hostname": {{ hostname | tojson }},
+        "os": {{ system | tojson }},
+        "distribution": {{ os_family | tojson }},
+        "architecture": {{ arch | tojson }},
+        "kernel_version": {{ kernel | tojson }},
+        "kernel_release": {{ kernel_version | tojson }}
@@
-            "message": "{{ stdout }}",
+            "message": {{ stdout | tojson }},
             "level": "DEBUG",
-            "trace_id": {{ datadog_installer_trace_id }},
-            "span_id": {{ datadog_installer_trace_id }}
+            "trace_id": {{ datadog_installer_trace_id | int }},
+            "span_id": {{ datadog_installer_trace_id | int }}
@@
-            "message": "{{ stderr }}",
+            "message": {{ (stderr
+                           | regex_replace('(?i)apikey\\s*[:=]\\s*\\S+', 'apikey=***REDACTED***')
+                           | tojson) }},
             "level": "ERROR",
-            "trace_id": {{ datadog_installer_trace_id }},
-            "span_id": {{ datadog_installer_trace_id }}
+            "trace_id": {{ datadog_installer_trace_id | int }},
+            "span_id": {{ datadog_installer_trace_id | int }}

Please validate payloads with jq:


🏁 Script executed:

#!/bin/bash
jq empty templates/installer-logs.j2 >/dev/null || echo "Template contains non-JSON constructs; test via render-in-play."

Length of output: 122



---

🏁 Script executed:

```shell
#!/bin/bash
# Inspect the actual template file to confirm current state and line numbers
cat -n templates/installer-logs.j2

Length of output: 1339



---

🌐 Web query:

```web
Ansible Jinja2 filters tojson int regex_replace

💡 Result:

Here are the Ansible/Jinja2 filter usages and short examples.

  1. regex_replace — replace using a regular expression. Use either short name or FQCN ansible.builtin.regex_replace. Example:

    • "{{ 'localhost:80' | regex_replace('^(?P.+):(?P\d+)$', '\g, \g') }}" — yields "localhost, 80". [1]
  2. tojson / to_json — serialize a variable to a JSON string (marks safe for HTML in Jinja2). Example:

    • "{{ myvar | tojson }}" or "{{ myvar | to_json }}". [2]
  3. int — convert a value to an integer. Example:

    • "{{ '42' | int }}" yields integer 42. [3]
  4. Chaining example (common pattern): extract digits with regex_replace then convert to int:

    • "{{ 'size=42MB' | regex_replace('.?(\d+).','\1') | int }}" — yields 42. [1][3]

Notes:

  • Escape backslashes in YAML/Jinja strings (\1, \g) as shown above. [1]
  • Use FQCNs (ansible.builtin.) if you want unambiguous references in docs/playbooks. [1][2][3]

Sources: Ansible docs for regex_replace, tojson/to_json and int. [1][2][3]


Fix invalid JSON by escaping strings and casting numeric fields.

The template currently produces invalid JSON due to unescaped strings and untyped numeric fields. Apply the following:

  • Cast tracer_time and datadog_installer_trace_id values to integers using | int
  • Escape all string interpolations (hostname, system, os_family, etc.) and log messages using | tojson
  • Optionally redact API keys from stderr using | regex_replace('(?i)apikey\\s*[:=]\\s*\\S+', 'apikey=***REDACTED***')
-    "tracer_time": "{{ stop_time }}",
-    "runtime_id": "{{ trace_id }}",
+    "tracer_time": {{ stop_time | int }},
+    "runtime_id": {{ (trace_id | string) | tojson }},
@@
-        "hostname": "{{ hostname }}",
-        "os": "{{ system }}",
-        "distribution": "{{ os_family }}",
-        "architecture": "{{ arch }}",
-        "kernel_version": "{{ kernel }}",
-        "kernel_release": "{{ kernel_version }}"
+        "hostname": {{ hostname | tojson }},
+        "os": {{ system | tojson }},
+        "distribution": {{ os_family | tojson }},
+        "architecture": {{ arch | tojson }},
+        "kernel_version": {{ kernel | tojson }},
+        "kernel_release": {{ kernel_version | tojson }}
@@
-            "message": "{{ stdout }}",
+            "message": {{ stdout | tojson }},
             "level": "DEBUG",
-            "trace_id": {{ datadog_installer_trace_id }},
-            "span_id": {{ datadog_installer_trace_id }}
+            "trace_id": {{ datadog_installer_trace_id | int }},
+            "span_id": {{ datadog_installer_trace_id | int }}
@@
-            "message": "{{ stderr }}",
+            "message": {{ (stderr
+                           | regex_replace('(?i)apikey\\s*[:=]\\s*\\S+', 'apikey=***REDACTED***')
+                           | tojson) }},
             "level": "ERROR",
-            "trace_id": {{ datadog_installer_trace_id }},
-            "span_id": {{ datadog_installer_trace_id }}
+            "trace_id": {{ datadog_installer_trace_id | int }},
+            "span_id": {{ datadog_installer_trace_id | int }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{
"api_version": "v2",
"request_type": "logs",
"tracer_time": "{{ stop_time }}",
"runtime_id": "{{ trace_id }}",
"seq_id": 2,
"origin": "ansible",
"host": {
"hostname": "{{ hostname }}",
"os": "{{ system }}",
"distribution": "{{ os_family }}",
"architecture": "{{ arch }}",
"kernel_version": "{{ kernel }}",
"kernel_release": "{{ kernel_version }}"
},
"application": {
"service_name": "datadog-ansible",
"service_version": "{{ role_version }}",
"language_name": "UNKNOWN",
"language_version": "n/a",
"tracer_version": "n/a"
},
"payload": {
"logs": [{
"message": "{{ stdout }}",
"level": "DEBUG",
"trace_id": {{ datadog_installer_trace_id }},
"span_id": {{ datadog_installer_trace_id }}
},{
"message": "{{ stderr }}",
"level": "ERROR",
"trace_id": {{ datadog_installer_trace_id }},
"span_id": {{ datadog_installer_trace_id }}
}]
}
}
{
"api_version": "v2",
"request_type": "logs",
"tracer_time": {{ stop_time | int }},
"runtime_id": {{ (trace_id | string) | tojson }},
"seq_id": 2,
"origin": "ansible",
"host": {
"hostname": {{ hostname | tojson }},
"os": {{ system | tojson }},
"distribution": {{ os_family | tojson }},
"architecture": {{ arch | tojson }},
"kernel_version": {{ kernel | tojson }},
"kernel_release": {{ kernel_version | tojson }}
},
"application": {
"service_name": "datadog-ansible",
"service_version": "{{ role_version }}",
"language_name": "UNKNOWN",
"language_version": "n/a",
"tracer_version": "n/a"
},
"payload": {
"logs": [{
"message": {{ stdout | tojson }},
"level": "DEBUG",
"trace_id": {{ datadog_installer_trace_id | int }},
"span_id": {{ datadog_installer_trace_id | int }}
},{
"message": {{ (stderr
| regex_replace('(?i)apikey\\s*[:=]\\s*\\S+', 'apikey=***REDACTED***')
| tojson) }},
"level": "ERROR",
"trace_id": {{ datadog_installer_trace_id | int }},
"span_id": {{ datadog_installer_trace_id | int }}
}]
}
}
🤖 Prompt for AI Agents
In templates/installer-logs.j2 around lines 1 to 36, the template emits invalid
JSON because string interpolations are not JSON-escaped and numeric fields are
left untyped; fix it by casting tracer_time and all trace/span id interpolations
to integers with |int, wrap every string interpolation (hostname, system,
os_family, arch, kernel, kernel_version, role_version, stdout, stderr, etc.)
with |tojson to ensure proper escaping, and for stderr optionally pipe through
|regex_replace('(?i)apikey\\s*[:=]\\s*\\S+', 'apikey=***REDACTED***') before
tojson to redact API keys; ensure trace_id/span_id fields remain unquoted
numeric values after casting.

Comment thread templates/installer-telemetry.j2 Outdated
Comment on lines +1 to +50
{
"api_version": "v2",
"request_type": "traces",
"tracer_time": {{ stop_time }},
"runtime_id": "{{ trace_id }}",
"seq_id": 1,
"origin": "ansible",
"host": {
"hostname": "{{ hostname }}",
"os": "{{ system }}",
"distribution": "{{ os_family }}",
"architecture": "{{ arch }}",
"kernel_version": "{{ kernel }}",
"kernel_release": "{{ kernel_version }}"
},
"application": {
"service_name": "datadog-ansible",
"service_version": "{{ role_version }}",
"language_name": "UNKNOWN",
"language_version": "n/a",
"tracer_version": "n/a"
},
"payload": {
"traces": [[{
"service": "datadog-ansible",
"name": "install_installer",
"resource": "install_installer",
"trace_id": {{ trace_id }},
"span_id": {{ trace_id }},
"parent_id": 0,
"start": {{ start_time }},
"duration": {{ stop_time - start_time }},
"error": {{ rc }},
"meta": {
"language": "yaml",
"exit_code": {{ rc }},
"error": {
"message": "{{ stderr }}"
},
"version": "{{ role_version }}"
},
"metrics": {
"_trace_root": 1,
"_top_level": 1,
"_dd.top_level": 1,
"_sampling_priority_v1": 2
}
}]]
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Harden JSON: escape strings and cast numerics; redact stderr.

Apply tojson for strings and int casts for numbers to avoid invalid JSON; redact obvious secrets in stderr.

-    "tracer_time": {{ stop_time }},
-    "runtime_id": "{{ trace_id }}",
+    "tracer_time": {{ stop_time | int }},
+    "runtime_id": {{ (trace_id | string) | tojson }},
@@
-        "hostname": "{{ hostname }}",
-        "os": "{{ system }}",
-        "distribution": "{{ os_family }}",
-        "architecture": "{{ arch }}",
-        "kernel_version": "{{ kernel }}",
-        "kernel_release": "{{ kernel_version }}"
+        "hostname": {{ hostname | tojson }},
+        "os": {{ system | tojson }},
+        "distribution": {{ os_family | tojson }},
+        "architecture": {{ arch | tojson }},
+        "kernel_version": {{ kernel | tojson }},
+        "kernel_release": {{ kernel_version | tojson }}
@@
-            "trace_id": {{ trace_id }},
-            "span_id": {{ trace_id }},
+            "trace_id": {{ trace_id | int }},
+            "span_id": {{ trace_id | int }},
@@
-            "start": {{ start_time }},
-            "duration": {{ stop_time - start_time }},
-            "error": {{ rc }},
+            "start": {{ start_time | int }},
+            "duration": {{ (stop_time - start_time) | int }},
+            "error": {{ rc | int }},
@@
-                    "message": "{{ stderr }}"
+                    "message": {{ (stderr
+                                   | regex_replace('(?i)apikey\\s*[:=]\\s*\\S+', 'apikey=***REDACTED***')
+                                   | tojson) }}

Render a sample payload and validate with jq:


🏁 Script executed:

#!/bin/bash
ansible -m template -a 'src=templates/installer-telemetry.j2 dest=/tmp/payload.json' localhost -e '{"trace_id":123,"start_time":1,"stop_time":2,"rc":0,"hostname":"h","system":"s","os_family":"f","arch":"a","kernel":"k","kernel_version":"kv","role_version":"v","stderr":""}' -c local
jq empty /tmp/payload.json && echo "OK"

Length of output: 121


I'll verify the template file and confirm the Jinja2 filters suggested in the review.


---

🏁 Script executed:

```shell
#!/bin/bash
# Read the template file to check current content
if [ -f "templates/installer-telemetry.j2" ]; then
  cat "templates/installer-telemetry.j2"
else
  echo "File not found"
fi

Length of output: 1509


🌐 Web query:

Jinja2 tojson filter regex_replace string int filters

💡 Result:

Short summary + examples.

Key points

  • You can chain Jinja2 filters left→right; the output of one is input to the next. [1]
  • tojson serializes a value to JSON and marks it safe for HTML/script contexts (escapes <, >, &, '). It accepts an optional indent. [2]
  • regex_replace is available (or can be added as a custom filter) to run a Python regex replacement; use \1 for backreferences in the replacement string. [3]
  • string and int are built‑in cast filters to convert types. [1][3]

Examples

  • Remove non-digits, cast to int:
    {{ val|regex_replace('[^0-9]', '')|int }}

  • Cast to string then JSON-encode (safe for embedding in <script>):

    <script>const data = {{ value|string|tojson }};</script>
  • Replace prefix with nothing, then JSON:
    {{ mystr|regex_replace('^prefix-', '')|tojson }}

  • Use capture groups in replacement:
    {{ text|regex_replace('([a-z]+)-([0-9]+)', '\2-\1') }}

Notes

  • If your environment lacks regex_replace you can register a custom filter or use replace for simple literal replaces. [3]
  • tojson is intended for HTML/script output; for non-HTML contexts use a normal JSON dump in your backend if needed. [2]

Sources

  1. Jinja2 filters reference (built-ins, casting, chaining). [1]
  2. tojson description/behavior (escaping, indent). [2]
  3. regex/regex_replace usage and examples (including backreferences / custom filter guidance). [3]

Would you like a concrete example using your actual template data?


Apply suggested JSON hardening filters to all template variables.

The template file matches the review snippet and all identified issues are valid:

  • String variables (hostname, system, etc.) and stderr are unescaped and unquoted, risking JSON breakage if they contain special characters.
  • Numeric variables (trace_id, start_time, stop_time, rc) lack int casting, risking type coercion.
  • The stderr field should be redacted to prevent API key leakage.

All suggested Jinja2 filters (tojson, int, string, regex_replace) are valid and available. Apply the provided diffs to harden JSON output.

Comment thread templates/zypper.repo.j2
Comment on lines +22 to +26
gpgkey={{ datadog_zypper_gpgkey_current }}
{{ datadog_zypper_gpgkey_20280418 }}
{{ datadog_zypper_gpgkey_20200908 }}
{{ datadog_zypper_gpgkey_e09422b3 }}
{% endif %}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

gpgkey must be a single logical line; join keys for SUSE ≥ 15.

Multiple physical lines under one key likely won’t parse. Join with spaces.

-{% else %}
-gpgkey={{ datadog_zypper_gpgkey_current }}
-       {{ datadog_zypper_gpgkey_20280418 }}
-       {{ datadog_zypper_gpgkey_20200908 }}
-       {{ datadog_zypper_gpgkey_e09422b3 }}
+{% else %}
+gpgkey={{ [datadog_zypper_gpgkey_current,
+           datadog_zypper_gpgkey_20280418,
+           datadog_zypper_gpgkey_20200908,
+           datadog_zypper_gpgkey_e09422b3] | join(' ') }}
 {% endif %}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
gpgkey={{ datadog_zypper_gpgkey_current }}
{{ datadog_zypper_gpgkey_20280418 }}
{{ datadog_zypper_gpgkey_20200908 }}
{{ datadog_zypper_gpgkey_e09422b3 }}
{% endif %}
{% else %}
gpgkey={{ [datadog_zypper_gpgkey_current,
datadog_zypper_gpgkey_20280418,
datadog_zypper_gpgkey_20200908,
datadog_zypper_gpgkey_e09422b3] | join(' ') }}
{% endif %}
🤖 Prompt for AI Agents
In templates/zypper.repo.j2 around lines 22 to 26, the gpgkey entries are split
across multiple physical lines which breaks parsing; replace the multiple gpgkey
lines with a single gpgkey= line that concatenates all possible key variables
separated by spaces, using Jinja to filter out empty values and join them (e.g.
build a list of the key variables, select non-empty entries, then join with a
space) so the repo file emits one logical gpgkey line for SUSE ≥ 15.

…sing `install-ssi.sh` script (#682)

* Remove legacy installer package and unit files

* Stop legacy installer systemd services and reload systemd graph

* Remove configuration and installation of datadog-installer

* Remove leftover from pr #624 installer/apm packages from pkg-redhat

* Remove air-gapped installer doc and some installer-specific tests

* First APM SSI iteration downloading and running the script

* fix env placement + correct yaml

* fix legacy installer removal task

* Remove installer tests

* Fix legacy installer removal conditionals

* Only create install.json file if apm_instrumentation enabled is set

* Use specific package built-in to avoid erroring out on AL2023

* Do not fail when trying to remove the package

* Change logic for APM SSI to determine installation instead of weird skipping logic

* Check apm status from installer + add .ansible to gitignore
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (6)
tasks/agent-linux.yml (2)

13-16: CRITICAL: Variable naming inconsistency breaks system-probe version-gating.

Lines 14–16 reference datadog_major, datadog_minor, and datadog_bugfix (the old variable names), but the PR renames these to agent_datadog_major, agent_datadog_minor, and agent_datadog_bugfix. Since these old variables are not defined, the agent_datadog_before_7610 flag will always evaluate to false, breaking version-gated logic for system-probe and security-agent on versions below 7.61.0. This is a blocker that must be fixed before merge.

Apply this diff to use the renamed variables:

- name: Set before 6/7.61.0 flag
  ansible.builtin.set_fact:
-   agent_datadog_before_7610: "{{ datadog_major is defined and datadog_minor is defined and datadog_bugfix is defined
+   agent_datadog_before_7610: "{{ agent_datadog_major is defined and agent_datadog_minor is defined and agent_datadog_bugfix is defined
-     and datadog_major | int < 8
-     and (datadog_minor | int < 61) }}"
+     and agent_datadog_major | int < 8
+     and (agent_datadog_minor | int < 61) }}"

53-87: CRITICAL: System-probe enablement conditions overlap, causing multiple set_fact executions.

Lines 53–87 contain four "Set system probe enabled" tasks with overlapping when conditions. For Agent version 7.50.0:

  • Line 57: agent_datadog_before_7241 = false → condition fails ✓
  • Line 66: not agent_datadog_before_7241 = trueexecutes
  • Line 76: not agent_datadog_before_7400 = trueexecutes
  • Line 87: not agent_datadog_before_7610 = trueexecutes

All three tasks (lines 66, 76, 87) execute, and the last one (line 87) overwrites the previous values. This violates the principle of idempotency and produces unpredictable results. The conditions must be mutually exclusive.

Fix the overlapping conditions by adding explicit lower-bound checks:

- name: Set system probe enabled (since 6/7.24.1)
  ansible.builtin.set_fact:
    agent_datadog_sysprobe_enabled: "{{ ((system_probe_config is defined and 'enabled' in (system_probe_config | default({}, true)) and
      system_probe_config['enabled']) or (network_config is defined and 'enabled' in (network_config | default({}, true)) and
      network_config['enabled'])) and agent_datadog_sysprobe_installed }}"
- when: not datadog_skip_running_check and (not agent_datadog_before_7241)
+ when: not datadog_skip_running_check and agent_datadog_before_7400 and (not agent_datadog_before_7241)

- name: Set system probe enabled (since 6/7.40.0)
  ansible.builtin.set_fact:
    agent_datadog_sysprobe_enabled: "{{ ((system_probe_config is defined and 'enabled' in (system_probe_config | default({}, true)) and
      system_probe_config['enabled']) or (network_config is defined and 'enabled' in (network_config | default({}, true)) and
      network_config['enabled']) or (service_monitoring_config is defined and
      'enabled' in (service_monitoring_config | default({}, true)) and service_monitoring_config['enabled'])) and agent_datadog_sysprobe_installed }}"
- when: not datadog_skip_running_check and (not agent_datadog_before_7400)
+ when: not datadog_skip_running_check and agent_datadog_before_7610 and (not agent_datadog_before_7400)

- name: Set system probe enabled (since 6/7.61.0)
  ansible.builtin.set_fact:
    agent_datadog_sysprobe_enabled: "{{ ((system_probe_config is defined and 'enabled' in (system_probe_config | default({}, true)) and
      system_probe_config['enabled']) or (network_config is defined and 'enabled' in (network_config | default({}, true)) and
      network_config['enabled']) or (service_monitoring_config is defined and
      'enabled' in (service_monitoring_config | default({}, true)) and service_monitoring_config['enabled'])) or
      (system_probe_other_config is defined and (system_probe_other_config is mapping | default({}, true)) and
      system_probe_other_config | length > 0) and agent_datadog_sysprobe_installed }}"
- when: not datadog_skip_running_check and (not agent_datadog_before_7610)
+ when: not datadog_skip_running_check and (not agent_datadog_before_7610)
tasks/pkg-debian.yml (4)

28-28: Fix stat mode comparison: use octal format, not string.

Line 28 compares agent_apt_keyring_file.stat.mode (an integer) against the string "0644". This comparison always fails, causing the keyring file to be recreated on every run.

Apply this fix:

- when: not ansible_check_mode and (not agent_apt_keyring_file.stat.exists or not agent_apt_keyring_file.stat.mode == "0644")
+ when: not ansible_check_mode and (not agent_apt_keyring_file.stat.exists or not agent_apt_keyring_file.stat.mode == 0o644)

16-45: Update variable names to new agent_datadog_* naming convention.

Several variables in this section still use the old datadog_ prefix and should follow the new naming scheme introduced in the PR:

  • Lines 16, 18, 23: datadog_apt_usr_share_keyringagent_datadog_apt_usr_share_keyring
  • Line 49 (after fixing YAML): datadog_apt_trusted_d_keyringagent_datadog_apt_trusted_d_keyring
  • Line 32: datadog_apt_default_keysagent_datadog_apt_default_keys
  • Lines 39, 41, 43, 45: datadog_apt_key_url_newagent_datadog_apt_key_url_new

Example:

- when: datadog_apt_key_url_new is not defined and not ansible_check_mode
+ when: agent_datadog_apt_key_url_new is not defined and not ansible_check_mode

48-56: Remove malformed YAML line that breaks task structure.

Line 49 contains invalid YAML syntax (keyring1,keyring2= {{ ... }}) that is not a valid Ansible task attribute. This line should be removed; the task structure is otherwise correct with src, dest, mode, and remote_src attributes.

Apply this fix:

  - name: Ensure keyring1 exists with same contents as keyring2 for older distro versions.
-   keyring1,keyring2= {{ datadog_apt_trusted_d_keyring, datadog_apt_usr_share_keyring }}
    ansible.builtin.copy:

72-81: Update repository variable names and fix type consistency.

Lines 80-81 reference datadog_agent6_apt_repo and datadog_agent7_apt_repo, which should follow the new naming convention. Also, line 76 compares item.key (integer from dict keys) against agent_datadog_agent_major_version | int; cast both to strings for clarity.

Apply these fixes:

  with_dict:
-   6: "{{ datadog_agent6_apt_repo }}"
-   7: "{{ datadog_agent7_apt_repo }}"
+   6: "{{ agent_datadog_agent6_apt_repo }}"
+   7: "{{ agent_datadog_agent7_apt_repo }}"

And update the state condition:

- state: "{% if item.key == agent_datadog_agent_major_version | int and datadog_apt_repo | length == 0 %}present{% else %}absent{% endif %}"
+ state: "{% if item.key | string == agent_datadog_agent_major_version | string and agent_datadog_apt_repo | length == 0 %}present{% else %}absent{% endif %}"
🧹 Nitpick comments (6)
tasks/_agent-linux-macos-shared.yml (1)

126-129: Consider gating debug output to verbosity levels.

The debug task at lines 126–129 prints the full install.json content unconditionally whenever it exists. For production deployments, consider adding verbosity: 2 to reduce log clutter.

Apply this diff to make the debug task conditional:

- name: Debug print install.json content
  ansible.builtin.debug:
    msg: "install.json content : {{ install_json_value.content }}"
+ verbosity: 2
  when: install_file.stat.exists
README.md (1)

336-372: Minor: Add hyphen to "third party" compound adjective (line 337).

Per Markdown best practices and grammar, "third party" should be "third-party" when used as a compound adjective modifying "integrations".

Apply this diff:

-##### Third party integrations~
+##### Third-party integrations~
tasks/apm-single-step-instrumentation.yml (2)

38-45: Add timeout to prevent hanging on failed downloads.

The get_url task should include a timeout parameter to prevent indefinite hangs if the download server is unresponsive.

Apply this diff:

- name: Download datadog-installer install-ssi.sh script
  ansible.builtin.get_url:
    url: "{{ datadog_installer_install_ssi_script_url }}"
    dest: /tmp/datadog-installer/install-ssi.sh
    mode: "0750"
+   timeout: 30
    # Always overwrite the file to ensure we have the latest version.
    force: true
  register: install_ssi_script_result

47-52: Improve error handling for script execution; reconsider changed_when logic.

Line 51's guard (when: install_ssi_script_result.status_code == 200) is overly specific—get_url doesn't set status_code on successful downloads; it only fails if the download fails. Line 52's changed_when: true assumes the script always modifies state, which may not be accurate. Consider registering the result and checking for success more robustly.

Apply this diff to improve error handling:

- name: Run datadog-installer install-ssi.sh script
  ansible.builtin.command:
    cmd: /tmp/datadog-installer/install-ssi.sh
  environment: "{{ datadog_apm_single_step_instrumentation_environment }}"
- when: install_ssi_script_result.status_code == 200
- changed_when: true
+ register: ssi_script_result
+ changed_when: ssi_script_result.rc == 0
+ failed_when: ssi_script_result.rc != 0
tasks/pkg-redhat.yml (1)

87-95: GPG key list should be filtered to only include necessary keys per version.

Lines 106–111 and similar blocks include all five GPG keys for every repository configuration (Agent 6, 7, custom), but not all keys are needed for all versions. For example, the E09422B3 key is only imported conditionally (lines 40, 46) based on minor version. Including unused keys in the repo configuration is redundant and may cause unnecessary warnings.

Consider filtering the gpgkey list to include only keys that are actually imported for the target version.

tasks/pkg-suse.yml (1)

80-86: Add force: true to key downloads for consistency with other distributions.

Across pkg-redhat.yml and pkg-suse.yml, some get_url tasks for key downloads include force: true to ensure the latest version is always fetched, but lines 80–86 and 108–114 in pkg-suse.yml omit this parameter. For consistency and to ensure up-to-date keys are always used, add force: true to these tasks.

Apply this diff:

- name: Download 20200908 key (Expires 2024) RPM key
  ansible.builtin.get_url:
    url: "{{ datadog_zypper_gpgkey_20200908 }}"
    dest: /tmp/DATADOG_RPM_KEY_20200908.public
    checksum: sha256:{{ datadog_zypper_gpgkey_20200908_sha256sum }}
    mode: '600'
+   force: true
  when: ansible_distribution_version|int >= 12

- name: Download 20280418 key (Expires 2028) RPM key
  ansible.builtin.get_url:
    url: "{{ datadog_zypper_gpgkey_20280418 }}"
    dest: /tmp/DATADOG_RPM_KEY_20280418.public
    checksum: "sha256:{{ datadog_zypper_gpgkey_20280418_sha256sum }}"
    mode: '600'
+   force: true
  when: ansible_distribution_version|int >= 12

Also applies to: 108-114

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 107a632 and 8218ea5.

📒 Files selected for processing (13)
  • .circleci/config.yml (3 hunks)
  • .gitignore (1 hunks)
  • README.md (16 hunks)
  • defaults/main.yml (4 hunks)
  • handlers/main.yml (1 hunks)
  • tasks/_agent-linux-macos-shared.yml (1 hunks)
  • tasks/agent-linux.yml (1 hunks)
  • tasks/apm-single-step-instrumentation.yml (1 hunks)
  • tasks/main.yml (1 hunks)
  • tasks/pkg-debian.yml (1 hunks)
  • tasks/pkg-redhat.yml (1 hunks)
  • tasks/pkg-suse.yml (1 hunks)
  • tasks/remove-legacy-installer.yml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .gitignore
🧰 Additional context used
🪛 Gitleaks (8.29.0)
tasks/pkg-debian.yml

[high] 38-38: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 40-40: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 42-42: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 44-44: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

defaults/main.yml

[high] 106-106: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 109-109: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 112-112: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 115-115: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 128-128: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 130-130: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 132-132: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 134-134: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 216-216: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 218-218: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 220-220: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 222-222: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🪛 LanguageTool
README.md

[style] ~91-~91: Consider shortening this phrase to just ‘whether’, unless you mean ‘regardless of whether’.
Context: ...og_apply_windows_614_fix` | Whether or not to download and apply file referenced b...

(WHETHER)


[uncategorized] ~92-~92: The operating system from Apple is written “macOS”.
Context: ...ren't running Datadog Agent 6.14.*.| | datadog_macos_user | The name...

(MAC_OS)


[uncategorized] ~93-~93: The operating system from Apple is written “macOS”.
Context: ...ults to ansible_user (macOS only).| | datadog_macos_download_url | Override...

(MAC_OS)


[uncategorized] ~309-~309: The operating system from Apple is written “macOS”.
Context: ... string. #### macOS When the variable datadog_macos_download_url is not set, the official ...

(MAC_OS)


[uncategorized] ~337-~337: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...remove`: Removes an integration. ##### Third party integrations [Datadog community][20] a...

(EN_COMPOUND_ADJECTIVE_INTERNAL)


[style] ~559-~559: ‘prior to’ might be wordy. Consider a shorter alternative.
Context: ...rmation applies to versions of the role prior to 4.9.0. Since 4.9.0, the apt_key modul...

(EN_WORDINESS_PREMIUM_PRIOR_TO)

🪛 markdownlint-cli2 (0.18.1)
README.md

91-91: Bare URL used

(MD034, no-bare-urls)


294-294: Bare URL used

(MD034, no-bare-urls)


302-302: Bare URL used

(MD034, no-bare-urls)


303-303: Bare URL used

(MD034, no-bare-urls)


313-313: Bare URL used

(MD034, no-bare-urls)


314-314: Bare URL used

(MD034, no-bare-urls)


315-315: Bare URL used

(MD034, no-bare-urls)


316-316: Bare URL used

(MD034, no-bare-urls)


326-326: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


607-607: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


625-625: Link and image reference definitions should be needed
Unused link or image reference definition: "2"

(MD053, link-image-reference-definitions)

🔇 Additional comments (18)
tasks/remove-legacy-installer.yml (1)

1-36: ✓ Solid best-effort legacy cleanup implementation.

The use of failed_when: false throughout is appropriate for removing legacy components that may not exist on all systems. The coverage of multiple systemd paths ensures compatibility across RHEL/Debian/SUSE distributions.

tasks/_agent-linux-macos-shared.yml (1)

107-172: Install.json lifecycle management is sound but relies on implicit facts.

The install.json management (lines 115–172) correctly handles both new and existing installations by parsing existing signatures or generating new UUIDs. The UUID fallback chain (cat /proc/sys/kernel/random/uuid → uuidgen) is resilient. However, line 172 creates the install.json only when datadog_apm_instrumentation_enabled is defined—ensure all paths that depend on install.json account for this conditional creation.

Please verify that install.json is created in all necessary contexts:

  • Is datadog_apm_instrumentation_enabled always defined when install.json is needed?
  • If not, consider unconditionally creating install.json as part of the shared configuration path for consistency.
README.md (4)

5-18: ✓ Clear and helpful role vs. collection documentation.

The distinction between the Datadog collection (datadog.dd) and standalone role (datadog.datadog) is well explained, with links to both Galaxy pages and a note on shared configuration variables.


49-97: ✓ Comprehensive role variables table with clear descriptions.

The variables table is well-organized and includes all key configuration options. Mandatory fields (e.g., datadog_api_key) are clearly marked, and deprecation notices are included for removed variables (e.g., datadog_yum_gpgkey).


208-254: ✓ System probe and NPM configuration documentation is accurate and well-structured.

The updates reflect the shift from system_probe_config to network_config and introduce system_probe_other_config for additional configuration. The Windows NPM note (line 223) is helpful. Example configuration is clear and accurate.


536-553: ✓ Windows uninstallation guidance is practical and well-documented.

The script to locate and uninstall the Datadog Agent on Windows is clear, with proper error handling for cases where the Agent is not installed.

tasks/pkg-redhat.yml (1)

116-158: ✓ Repository configuration guards are correct and mutually exclusive.

The three yum_repository tasks (Agent 6, Agent 7, custom) are properly guarded:

  • Agent 6: agent_datadog_agent_major_version | int == 6 and datadog_yum_repo | length == 0
  • Agent 7: agent_datadog_agent_major_version | int == 7 and datadog_yum_repo | length == 0
  • Custom: datadog_yum_repo | length > 0

These conditions ensure exactly one repository is configured.

handlers/main.yml (2)

10-12: ✓ Service facts gathering and restart logic correctly gate on OS type.

The service facts are gathered only on Linux/macOS (excluding Windows), which avoids unnecessary operations on Windows. The main restart handler then checks ansible_facts.services for the presence and state of the exp service, preventing conflicts between experimental and production agents. This is a clean approach to handling multiple service variants.

Also applies to: 14-20


22-38: ✓ Excellent use of include_tasks to avoid unnecessary collection dependencies.

The Windows and macOS restart handlers use include_tasks to load OS-specific logic only when needed, avoiding the requirement for the ansible.windows collection on Linux hosts. This is the correct pattern for modular, platform-specific Ansible code. The comments clearly explain the rationale.

tasks/agent-linux.yml (1)

99-156: ✓ Service lifecycle management is well-structured and idempotent.

The main agent service orchestration correctly uses ansible.builtin.service with explicit enabled and use semantics. The guards prevent operations on disabled/check modes, and the exp service check avoids conflicts with experimental agents. The inclusion of older agent services (datadog-agent-process, datadog-agent-trace) ensures clean lifecycle management across versions.

tasks/pkg-suse.yml (1)

52-58: Fix incomplete task definition: add missing url: keyword.

Line 53–55 is missing the url: keyword before the URL value. This will cause a YAML parsing error.

Apply this diff to fix the syntax:

- name: Download E09422B3 key (Expires 2022) RPM key
  ansible.builtin.get_url:
-   url: "{{ datadog_zypper_gpgkey_e09422b3 }}"
+   url: "{{ datadog_zypper_gpgkey_e09422b3 }}"
    dest: /tmp/DATADOG_RPM_KEY_E09422B3.public
     checksum: sha256:{{ datadog_zypper_gpgkey_e09422b3_sha256sum }}
    mode: '600'
   when: ansible_distribution_version|int >= 12 and agent_datadog_minor is defined and agent_datadog_minor | int < 36

Wait, looking at the code again, line 54 shows url: is present. Let me re-check. The issue is that lines 52-58 in the code block show:

- name: Download E09422B3 key (Expires 2022) RPM key
  ansible.builtin.get_url:
    url: "{{ datadog_zypper_gpgkey_e09422b3 }}"  # line 54
    dest: /tmp/DATADOG_RPM_KEY_E09422B3.public  # line 55
     checksum: sha256:...  # line 56 - extra space?

Actually, re-reading the annotation, lines 52-58 appear correctly formatted. Let me reconsider.

Actually, I see line 54 doesn't have "url:" label in the original:

- name: Download E09422B3 key (Expires 2022) RPM key
  ansible.builtin.get_url:
    url: "{{ datadog_zypper_gpgkey_e09422b3 }}"  # This IS line 54 in the display
    dest: /tmp/DATADOG_RPM_KEY_E09422B3.public

Wait, looking more carefully at the formatting, I see the code is properly structured. Let me re-examine if there's actually an issue...

Actually, the code provided shows the full task and it looks correct. Let me revise my comment.

Likely an incorrect or invalid review comment.

.circleci/config.yml (2)

88-88: Approve: parameter threading and jinja2_native propagation.

The addition of jinja2_native parameter (lines 21-23) and threading it through install_agent command invocation (line 88) is correct. The YAML environment variable setup at line 28 (ANSIBLE_JINJA2_NATIVE="<<parameters.jinja2_native>>") properly passes the value to ansible-playbook.


173-205: Approve: macOS job structure and Python setup.

The new test_install_macos job correctly:

  • Installs Rosetta 2 for ARM64 compatibility (lines 193-194)
  • Installs Python 3.11 via Homebrew (lines 196-197)
  • Uses the full path to installed Python in the test command (line 203: /opt/homebrew/bin/python3.11)
  • Properly passes parameters through the command invocation

The setup aligns with the explicit Python version in the install_agent command invocation at line 28, which expects a full path like /usr/bin/python3 or /opt/homebrew/bin/python3.11.

tasks/main.yml (3)

2-8: Approve: ansible.builtin.setup with gather_subset parameter.

The explicit ansible.builtin.setup module invocation with gather_subset parameter is correct. The comment on line 5 correctly notes that the full prefix is necessary to avoid Ansible picking the wrong module on Windows systems.


17-20: Approve: API key validation for managed config.

The fail task correctly enforces datadog_api_key presence when datadog_manage_config is enabled, preventing silent configuration failures. This is a good defensive check.


93-112: Approve: APM Single Step Instrumentation validation.

The implementation correctly:

  1. Sets a fact to determine if instrumentation should be installed (lines 95-100)
  2. Validates the configuration value against allowed options (lines 102-107)
  3. Conditionally includes the instrumentation task (lines 109-112) with check_mode guard

The inline validation prevents misconfiguration errors early.

defaults/main.yml (2)

2-2: Approve: comprehensive role expansion for version 5.4.1.

The defaults file reflects a well-structured expansion of the Datadog Ansible role:

  1. Version and feature flags (lines 2-8): Version 5.4.1 with explicit datadog_enabled and datadog_manage_config flags provide clear configuration control.

  2. System probe and integration surface (lines 14-17, 22-35): New config blocks for system-probe, network monitoring, and service monitoring expand the role's capabilities.

  3. Package flavor (line 65): Introduction of datadog_agent_flavor allows support for alternative agent builds (e.g., IoT Agent).

  4. APM instrumentation (lines 182-198): Structured APM configuration with optional library pinning supports host and Docker injection modes.

  5. macOS support (lines 237-265): Comprehensive macOS additions including DMG URLs, user/service paths, and architecture-specific downloads align with the PR's macOS expansion goals.

  6. Repository and key management (lines 208-235): Centralized GPG key definitions and repository configuration with signed-by options modernize package verification.

Also applies to: 65-65, 182-198, 237-265


226-227: Verify defaults align with updated variable names in task files.

The repository definitions at lines 226-227 (apt), 230-231 (yum), and 234-235 (zypper) use the agent_datadog_agent6_apt_repo, agent_datadog_agent6_yum_repo, and agent_datadog_agent6_zypper_repo naming. Verify that:

  1. All task files (pkg-debian.yml, pkg-redhat.yml, pkg-suse.yml, pkg-windows.yml) reference these exact variable names.
  2. The variables in pkg-debian.yml have been updated (past review flagged inconsistencies; current code still shows old names).

This is a precondition for the role to function correctly after the migration.

Also applies to: 230-231, 234-235

Comment thread .circleci/config.yml
Comment on lines +345 to +349
ansible_version: ["2_10", "3_4", "4_10", "9_4"]
agent_version: ["6", "7"]
jinja2_native: ["true", "false"]
os: ["rocky8"]
python: ["python3"]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

❓ Verification inconclusive

Ansible 9.4 incompatible with Rocky Linux 8's default Python 3.6.

Line 345 tests Ansible 9.4 with python: ["python3"] on rocky8, but Ansible 9 requires Python 3.10 or newer. Rocky Linux 8's python3 link defaults to Python 3.6.8. This combination will fail at runtime.

Options:

  1. Upgrade to Python 3.10+: specify python: ["python3.10"] or python: ["python3.11"] for this matrix.
  2. Remove Ansible 9.4 from rocky8 tests if Python 3.10+ is unavailable on that distribution.
  3. Use a newer Rocky version (e.g., rocky9) which has Python 3.9+ available.

I'll verify the claims in the review comment by checking the Ansible compatibility requirements and examining the actual configuration file.Now let me search for Ansible 9.4 specific requirements:

Now let me examine the actual CircleCI config file to verify the specific issue at lines 345-349:

Based on my web search verification, I have confirmed all the key facts in the review comment:

  1. Ansible 9 removed support for Python 3.9 and requires Python 3.10 or newer on the controller

  2. Rocky Linux 8's python3 link defaults to Python 3.6.8, which takes precedence over other installed versions

The review comment accurately identifies a critical compatibility issue that will cause runtime failures when testing Ansible 9.4 with the default Rocky Linux 8 Python. The suggestions provided are all valid and appropriate.

Ansible 9.4 incompatible with Rocky Linux 8's default Python 3.6.

Line 345 tests Ansible 9.4 with python: ["python3"] on rocky8, but Ansible 9 requires Python 3.10 or newer on the control node. Rocky Linux 8's python3 defaults to Python 3.6.8. This combination will fail at runtime.

Options:

  1. Upgrade to Python 3.10+: specify python: ["python3.10"] or python: ["python3.11"] for this matrix.
  2. Remove Ansible 9.4 from rocky8 tests if Python 3.10+ is unavailable on that distribution.
  3. Use a newer Rocky version (e.g., rocky9) which has Python 3.9+ available.
🤖 Prompt for AI Agents
.circleci/config.yml lines 345-349: the matrix tests Ansible 9.4 on rocky8 with
python: ["python3"], but Ansible 9 requires Python >=3.10 while Rocky Linux 8's
python3 points to 3.6.8, so update the matrix to ensure Python >=3.10 for
Ansible 9.4 (e.g., set python: ["python3.10"] or ["python3.11"] for entries that
use ansible_version "9_4"), or remove the "9_4" ansible entry for rocky8, or
change the os to a newer distribution (rocky9) that provides Python 3.10+; apply
the chosen change consistently in the matrix so CI runs use a compatible Python
for Ansible 9.4.

Comment thread .circleci/config.yml
Comment thread .circleci/config.yml
Comment thread tasks/pkg-debian.yml
set_fact:
datadog_remove_custom_repo_file: "{{ datadog_repo_file_contents != datadog_apt_repo }}"
ansible.builtin.set_fact:
agent_datadog_remove_custom_repo_file: "{{ agent_datadog_repo_file_contents != datadog_apt_repo }}"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Update datadog_apt_repo references to new naming convention.

Lines 100, 109, 114, and 117 use datadog_apt_repo, which should be agent_datadog_apt_repo per the PR's variable migration:

- when: (datadog_apt_repo | length == 0) or agent_datadog_remove_custom_repo_file and (not ansible_check_mode)
+ when: (agent_datadog_apt_repo | length == 0) or agent_datadog_remove_custom_repo_file and (not ansible_check_mode)
  repo: "{{ datadog_apt_repo }}"
+ repo: "{{ agent_datadog_apt_repo }}"
- when: (datadog_apt_repo | length > 0) and (not ansible_check_mode)
+ when: (agent_datadog_apt_repo | length > 0) and (not ansible_check_mode)

Also applies to: 109-109, 114-114, 117-117

🤖 Prompt for AI Agents
In tasks/pkg-debian.yml around lines 100, 109, 114 and 117, update uses of the
old variable datadog_apt_repo to the new name agent_datadog_apt_repo; replace
each occurrence (including in expressions like
agent_datadog_remove_custom_repo_file) so the playbook references the migrated
variable, then run a lint/ansible-playbook --syntax-check to confirm no other
references remain.

…all of Datadog Agent (#683)

* [AGENTONB-2680][Windows] Provide users a way to skip and force reinstall of Datadog Agent

* Change how we uninstall by looking for the installed productcode instead of msi to allow downgrades

* clarify the precedence of the option

* whitespace trim
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (7)
tasks/pkg-windows.yml (2)

2-20: Variable naming convention inconsistency throughout Windows flow.

The file mixes datadog_windows_* (legacy) and agent_datadog_* (new) naming styles. Input flags use the old convention, then map to the new convention internally. This pattern repeats throughout the file (e.g., datadog_windows_614_fix_script_url is later referenced in lines 24–27, while agent_dd_download_url is used in lines 45, 56). While the mapping is explicit, this hybrid approach complicates variable tracking and increases maintenance burden.

Consider:

  • Standardizing on a single naming convention across the role (either commit to agent_datadog_* throughout or stick with datadog_windows_*).
  • Documenting the mapping clearly if both styles must coexist.
  • Adding a centralized variable mapping layer if this pattern appears elsewhere.

110-120: Password handling approach is reasonable but has limitations.

The password is appended to agent_win_install_args with no_log: true on the task. This prevents the task itself from being logged but does not protect the variable if it's:

  • Referenced or inspected by other tasks
  • Dumped in error messages or debug output
  • Included in playbook/facts output

For maximum security, consider:

  • Storing the password separately from agent_win_install_args and injecting it only at the final install command.
  • Documenting that the agent_win_install_args variable must be treated as sensitive throughout subsequent tasks.
  • Using Ansible's vault or external secret management if this role will run in sensitive environments.

Current approach is acceptable for typical use cases but should be documented.

defaults/main.yml (1)

76-135: Repository and GPG key management is comprehensive but shows DRY violations.

The configuration provides good forward planning with multiple GPG keys tracked by expiration date (2022, 2024, 2028, 2033). However, datadog_yum_gpgkey_* definitions (lines 103–116) are duplicated identically in datadog_zypper_gpgkey_* (lines 126–134).

Consider:

  • Extracting common key definitions to reduce duplication.
  • Adding comments explaining each key's expiration date and rotation plan.
  • Documenting the process for adding/retiring GPG keys.
README.md (4)

53-100: Variable documentation is comprehensive but has minor grammar issues.

The table clearly documents new variables with platform tags and external documentation references. However, Line 103 has a grammar issue: "first level key" should be "first-level key" (hyphenated as a compound modifier). Additionally, verify that example configurations in the "Playbooks" section (lines ~388–463) accurately reflect these variable names and usage patterns.

Verify that all code examples later in the README use the correct variable names and structure, particularly:

  • Line 461: network_config example
  • Line 95–96: datadog_macos_user default to ansible_user (confirm this works correctly in macOS tasks)

101-225: Integration and system probe documentation clearly explains new configuration structure.

The restructuring from system_probe_config to separate network_config, runtime_security_config, service_monitoring_config, and system_probe_other_config is well-explained with clear examples. The new Custom Python Checks subsection (lines 141–157) and Autodiscovery section provide good guidance. The Windows NPM note (line 225) properly flags that NPM is optional and may require reinstall.

Minor grammar issue at line 339: "Third party integrations" should be "third-party integrations" (hyphenated).


283-320: Repository and version documentation is comprehensive and well-organized.

The addition of Windows and macOS repository sections with per-major-version defaults, architecture-aware URLs, and clear tables helps users understand installation sources across platforms.

Minor formatting issue: Lines 296, 304–305, and 315–318 contain bare URLs that should be wrapped in markdown link syntax [text](url) for consistency and validation (flagged by markdownlint-cli2 as MD034).


538-625: Windows uninstallation and troubleshooting sections are comprehensive.

The new Uninstallation section (lines 538–555) provides helpful guidance for Windows users. The Troubleshooting section appropriately marks deprecated information with version numbers (e.g., "versions of the role prior to 4.9.0," "version 5+") and explains critical issues like the Windows 6.14 Agent bug and missing API key requirement.

Minor issues:

  • Line 609: Fenced code block should specify language (e.g., ```json or ```text) (flagged by MD040).
  • Line 627: Unused link reference [2] should be removed (flagged by MD053).
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8218ea5 and d529ede.

📒 Files selected for processing (3)
  • README.md (16 hunks)
  • defaults/main.yml (4 hunks)
  • tasks/pkg-windows.yml (2 hunks)
🧰 Additional context used
🪛 LanguageTool
README.md

[style] ~91-~91: ‘Whether or not’ might be wordy. Consider a shorter alternative.
Context: ...og_apply_windows_614_fix` | Whether or not to download and apply file referenced b...

(EN_WORDINESS_PREMIUM_WHETHER_OR_NOT)


[uncategorized] ~94-~94: The operating system from Apple is written “macOS”.
Context: ...indows_skip_install(Windows only).| |datadog_macos_user` | The name...

(MAC_OS)


[uncategorized] ~95-~95: The operating system from Apple is written “macOS”.
Context: ...ults to ansible_user (macOS only).| | datadog_macos_download_url | Override...

(MAC_OS)


[grammar] ~103-~103: Use a hyphen to join words.
Context: ... the datadog_checks section. The first level key is the name of the check, and ...

(QB_NEW_EN_HYPHEN)


[uncategorized] ~311-~311: The operating system from Apple is written “macOS”.
Context: ... string. #### macOS When the variable datadog_macos_download_url is not set, the official ...

(MAC_OS)


[grammar] ~339-~339: Use a hyphen to join words.
Context: ...e`: Removes an integration. ##### Third party integrations [Datadog community][...

(QB_NEW_EN_HYPHEN)


[style] ~561-~561: ‘prior to’ might be wordy. Consider a shorter alternative.
Context: ...rmation applies to versions of the role prior to 4.9.0. Since 4.9.0, the apt_key modul...

(EN_WORDINESS_PREMIUM_PRIOR_TO)

🪛 markdownlint-cli2 (0.18.1)
README.md

91-91: Bare URL used

(MD034, no-bare-urls)


296-296: Bare URL used

(MD034, no-bare-urls)


304-304: Bare URL used

(MD034, no-bare-urls)


305-305: Bare URL used

(MD034, no-bare-urls)


315-315: Bare URL used

(MD034, no-bare-urls)


316-316: Bare URL used

(MD034, no-bare-urls)


317-317: Bare URL used

(MD034, no-bare-urls)


318-318: Bare URL used

(MD034, no-bare-urls)


328-328: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


609-609: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


627-627: Link and image reference definitions should be needed
Unused link or image reference definition: "2"

(MD053, link-image-reference-definitions)

🔇 Additional comments (11)
tasks/pkg-windows.yml (4)

35-46: Gate logic for version handling is well-structured.

The conditional includes for latest vs. pinned versions are mutually exclusive and properly gated. No concerns with this section.


54-60: MSI download and result registration look correct.

The variable agent_download_msi_result is properly registered and consistently referenced in subsequent tasks (lines 134, 141, 143).


62-91: Product ID lookup logic is defensive and comprehensive.

The PowerShell script properly handles both 64-bit and 32-bit registry paths, gracefully handles missing paths, and deduplicates results. The caching logic correctly filters for non-empty matches before setting the fact. The changed_when: false and check_mode: false settings are appropriate here.

Verify that line 125 (uninstall loop) safely handles the case where agent_datadog_windows_installed_product_ids may not be defined if no product IDs were found or if force reinstall was not set.


121-143: Uninstall, install, and cleanup logic is well-gated and consistent.

Uninstall runs only when force-reinstalling, install uses registered download result properly, and cleanup checks for successful download before removing temporary files. All gates are appropriate.

defaults/main.yml (5)

2-48: Version bump and new basic flags are appropriate.

The addition of datadog_enabled, datadog_manage_config, and check management flags provides fine-grained control. New macOS binary path and integration user variables complete platform coverage consistently with existing Linux/Windows patterns.


152-188: Windows installation defaults are comprehensive with good control flags.

The MSI URLs, fix script handling, and skip/force-reinstall flags provide appropriate control. However, note that win_install_args defaults to a single space (line 188). Verify in tasks that this is safely concatenated—if other args are appended without care, spacing could be incorrect.

Verify that win_install_args (line 188) is correctly used in task concatenation, particularly when the password arg is appended in tasks/pkg-windows.yml line 117.


190-207: Advanced installer and APM configuration variables are well-structured.

The addition of APM instrumentation, remote updates, and installer customization options provides the flexibility needed for advanced scenarios. Default for datadog_apm_instrumentation_libraries as an empty list is appropriate—users enable via configuration.


216-243: Internal repository defaults are well-structured with modern security practices.

The use of signed-by with APT keyrings, architecture-aware repo URLs for yum/zypper, and clear "internal use only" comments are all appropriate. Architecture substitution properly uses ansible_facts.architecture.


245-272: macOS defaults and Ansible facts configuration are well-designed.

Architecture-aware URLs for Agent 7.70+ (separate arm64/x86_64 packages), standard macOS paths, and minimal facts gathering (!all, !any, min, env) are all appropriate. Service name, plist file paths, and log directories follow macOS conventions correctly.

README.md (2)

1-48: Documentation introduction and prerequisites are clear and comprehensive.

The distinction between Ansible role and collection channels is well-explained, prerequisite for ansible.windows collection is clearly documented with installation instructions, and the API key requirement is appropriately explained with a workaround option.


388-463: Playbook examples are clear and appropriately use updated variables.

The main sample playbook correctly uses network_config and demonstrates integration installation. Examples for Agent v6, site configuration, and Windows-specific deployments provide good coverage for different scenarios.

* [AGENTONB-2680][Windows] Provide users a way to skip and force reinstall of Datadog Agent

* Change how we uninstall by looking for the installed productcode instead of msi to allow downgrades

* [AGENTONB-2711] Allow Agent downgrades on Windows by uninstalling first
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tasks/pkg-windows-opts.yml (1)

60-85: Validation logic is correct but hard to read.

The path validation properly handles upgrade scenarios by comparing registry values against provided config/install directories. However, the multi-line when conditions are difficult to parse. Consider extracting the conditions to variables for clarity.

Example refactor for readability:

+ - name: Set config validation conditions
+   ansible.builtin.set_fact:
+     agent_config_mismatch: >-
+       (agent_config_root_from_registry.exists) and
+       (datadog_windows_config_files_dir | length > 0) and
+       (agent_config_root_from_registry.value | regex_replace('\\\\$','') | lower !=
+        datadog_windows_config_files_dir | lower)
+
  - name: Validate config path
    ansible.builtin.fail:
      msg: "Incompatible configuration option {{ agent_config_root_from_registry.value }} != {{ datadog_windows_config_files_dir }}"
-   when: ( (agent_config_root_from_registry.exists) and (datadog_windows_config_files_dir | length > 0 ) and (agent_config_root_from_registry.value
-     | regex_replace('\\\\$','') | lower != datadog_windows_config_files_dir | lower ) )
+   when: agent_config_mismatch
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d529ede and de89c3a.

📒 Files selected for processing (2)
  • tasks/parse-version-windows.yml (1 hunks)
  • tasks/pkg-windows-opts.yml (1 hunks)
🔇 Additional comments (10)
tasks/pkg-windows-opts.yml (7)

19-35: PowerShell feature discovery logic looks sound.

The script correctly discovers installed Datadog Agent features via COM/registry inspection, filters appropriately, and outputs results for consumption by downstream tasks.


42-55: Registry queries are properly structured.

The use of win_reg_stat to query ConfigRoot and InstallPath is appropriate, and registering both the result and .exists flag enables proper conditional handling downstream.


87-108: Directory setup correctly handles upgrade and new install paths.

The logic properly distinguishes between providing custom paths via install arguments and detecting existing registry-based paths during upgrades.


111-114: NPM flag setup is correct.

The use of ADDLOCAL=MainApplication,NPM syntax is appropriate for Windows Installer feature selection when sysprobe is enabled.


129-163: Downgrade detection logic is sound and well-guarded.

The three-part version comparison correctly identifies downgrades, properly guards against undefined version variables, and appropriately triggers both skip_install disable and force_reinstall enable for downgrade scenarios.


10-12: The repository clone operation failed, preventing me from searching the codebase for the win_install_args variable definition. Without access to the repository structure, I cannot verify whether:

  1. win_install_args is defined in defaults files
  2. The variable is set in earlier tasks or playbooks
  3. The variable scope and execution order are correct

Since the verification could not be completed and the information remains inconclusive, I'll provide the rewritten review comment with this limitation noted:


Verify win_install_args variable is defined before this task execution.

This task initializes agent_win_install_args from win_install_args (line 12), but the source variable's origin cannot be confirmed due to verification limitations. Ensure win_install_args is defined in defaults, vars files, or earlier in the playbook execution flow before this task runs.


117-127: I'm unable to clone the repository in the sandbox environment to verify the concern. Let me provide the rewritten review comment based on the analysis I can perform with the provided code snippet:


Verify the logic of the when condition that checks agent_datadog_skip_install before setting it to false.

The when condition (line 126) checks if agent_datadog_skip_install is true, but the task body (line 119) sets it to false. This appears contradictory and suggests one of the following:

  1. The condition should check not agent_datadog_skip_install instead of agent_datadog_skip_install
  2. The variable semantics are inverted from their name (i.e., skip_install: true means "do install")
  3. There is a logical error in the condition

Confirm the intended behavior: should this task execute when the agent installation should be skipped, or when it should not be skipped? Review the preceding tasks to understand what state agent_datadog_skip_install has when this task is reached.

tasks/parse-version-windows.yml (3)

33-38: Safe fallback handling for version component facts.

The use of default('', true) on lines 35-37 provides a graceful fallback if regex parsing fails or returns incomplete results. The conversion to string is explicit and appropriate. The logic here handles the edge case where regex_search returns fewer than three groups.


23-31: The regex_search syntax is correct and produces the expected list output.

The Ansible documentation confirms that regex_search with multiple named group backreferences ('\\g<name>') returns a list of the captured values. The syntax in the code—regex_search(installed_agent_regexp, '\\g<major>', '\\g<minor>', '\\g<bugfix>') —is the standard Ansible approach and will correctly produce a list ['major_value', 'minor_value', 'bugfix_value'] that can be accessed via .0, .1, .2 indexing.


3-21: Based on my verification, I have a critical finding: The Datadog Agent's Windows DisplayVersion in the registry is always 4 components (major.minor.patch.build), e.g., "7.69.1.0". This means the edge case described in the original review—where the version string has fewer than 3 components—will never occur in practice.

The original concern about malformed output like "7.43." was theoretically valid for arbitrary version strings, but is not applicable to the Datadog Agent, which always provides exactly 4 numeric components in the registry's DisplayVersion field.

Additionally, I confirmed that:

  • The Ansible regex_search() syntax with multiple named groups using '\\g<name>' is correct and valid
  • The code gracefully handles any failures with failed_when: false

The review comment's primary concern is not applicable to Datadog Agent versioning; the code is adequate as-is.

The PowerShell script correctly parses the guaranteed 4-part Datadog Agent version string from the Windows registry and outputs the 3-part semantic version. The subsequent regex parsing and fact assignment work as intended. No changes are required.

Comment on lines 1 to +17
- name: Set DD Username Arg
set_fact:
win_install_args: "{{ win_install_args }} DDAGENTUSER_NAME={{ datadog_windows_ddagentuser_name }}"
when: datadog_windows_ddagentuser_name | length > 0
ansible.builtin.set_fact:
agent_win_install_args: "{{ win_install_args }} DDAGENTUSER_NAME={{ datadog_windows_ddagentuser_name }}"
when: datadog_windows_ddagentuser_name | default('', true) | length > 0
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Inconsistent variable reference breaks DD username argument.

Line 16 references win_install_args instead of agent_win_install_args. This breaks the DD username argument since later tasks (lines 88–89, 93–94, 112–113) all append to agent_win_install_args, which won't include the username set here.

Apply this diff to fix the variable reference:

- name: Set DD Username Arg
  ansible.builtin.set_fact:
-   agent_win_install_args: "{{ win_install_args }} DDAGENTUSER_NAME={{ datadog_windows_ddagentuser_name }}"
+   agent_win_install_args: "{{ agent_win_install_args }} DDAGENTUSER_NAME={{ datadog_windows_ddagentuser_name }}"
  when: datadog_windows_ddagentuser_name | default('', true) | length > 0
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Set DD Username Arg
set_fact:
win_install_args: "{{ win_install_args }} DDAGENTUSER_NAME={{ datadog_windows_ddagentuser_name }}"
when: datadog_windows_ddagentuser_name | length > 0
ansible.builtin.set_fact:
agent_win_install_args: "{{ win_install_args }} DDAGENTUSER_NAME={{ datadog_windows_ddagentuser_name }}"
when: datadog_windows_ddagentuser_name | default('', true) | length > 0
- name: Set DD Username Arg
ansible.builtin.set_fact:
agent_win_install_args: "{{ agent_win_install_args }} DDAGENTUSER_NAME={{ datadog_windows_ddagentuser_name }}"
when: datadog_windows_ddagentuser_name | default('', true) | length > 0
🤖 Prompt for AI Agents
In tasks/pkg-windows-opts.yml around lines 14 to 17, the set_fact uses the wrong
variable name (win_install_args) so the DDAGENTUSER_NAME is not appended to the
shared agent_win_install_args used later; update the set_fact to append
DDAGENTUSER_NAME to agent_win_install_args instead of win_install_args so
subsequent tasks that extend agent_win_install_args include the username
(preserve the when condition and formatting).

* [AGENTONB-2680][Windows] Provide users a way to skip and force reinstall of Datadog Agent

* Change how we uninstall by looking for the installed productcode instead of msi to allow downgrades

* [AGENTONB-2711] Allow Agent downgrades on Windows by uninstalling first

* Do not install/restart Agent when remote update is happening

* Remove trailing space

* Init remote update flag to false to simplify approach
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
tasks/pkg-windows-opts.yml (1)

14-17: 🔴 CRITICAL: Unresolved bug—inconsistent variable reference breaks argument accumulation.

This issue was flagged in past review and remains unfixed.

Line 16 references win_install_args (the base input) instead of agent_win_install_args (the accumulator). This breaks consistency and may cause issues if additional setup tasks are added between line 12 and line 16, or if line 16 is conditionally executed after other modifications.

All subsequent append operations (lines 89, 94, 113) correctly append to agent_win_install_args. Line 16 should do the same for consistency and safety.

Apply this diff to fix the variable reference:

  - name: Set DD Username Arg
    ansible.builtin.set_fact:
-     agent_win_install_args: "{{ win_install_args }} DDAGENTUSER_NAME={{ datadog_windows_ddagentuser_name }}"
+     agent_win_install_args: "{{ agent_win_install_args }} DDAGENTUSER_NAME={{ datadog_windows_ddagentuser_name }}"
    when: datadog_windows_ddagentuser_name | default('', true) | length > 0
🧹 Nitpick comments (1)
tasks/agent-win.yml (1)

27-28: Complex filter chains—ensure Windows path handling is robust.

The filter chains using win_dirname, win_basename, and regex replacements across multiple lines are complex. Verify:

  • These filters exist in the Jinja2 environment (or are Ansible built-ins)
  • Paths with backslashes and dots are handled correctly (e.g., C:\path\check.d\conf.yamlcheck)
  • Edge cases (empty paths, malformed extensions) don't cause silent failures

Consider breaking these into intermediate variables for readability:

paths: "{{ agent_datadog_conf_paths.files | map(attribute='path') | select('match', '.*\\conf\\.yaml$') | list }}"
dirnames: "{{ paths | map('win_dirname') | map('win_basename') | list }}"
checks: "{{ dirnames | map('regex_replace', '^(.*).d$', '\\1') | list }}"

Also applies to: 39-40, 51-52

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between de89c3a and fbed756.

📒 Files selected for processing (6)
  • handlers/main-win.yml (1 hunks)
  • tasks/agent-win.yml (1 hunks)
  • tasks/main.yml (1 hunks)
  • tasks/pkg-windows-opts.yml (1 hunks)
  • tasks/pkg-windows.yml (2 hunks)
  • tasks/windows_remote_update_check.yml (1 hunks)
🔇 Additional comments (14)
tasks/windows_remote_update_check.yml (1)

1-27: LGTM!

The remote update detection logic is sound. The PowerShell CIM query correctly identifies ongoing updates, and the flag initialization/setting/messaging flow integrates well with the downstream handler and task logic.

handlers/main-win.yml (1)

1-11: LGTM!

The Windows handler-like task is well-documented and appropriately conditioned. The force_dependent_services flag and the datadog_remote_update_in_progress gate are correct safeguards for Windows service restarts.

tasks/agent-win.yml (2)

18-18: Verify variable registration consistency.

Lines 18 and 61 register agent_datadog_conf_paths, but line 18 is inside a conditional and line 61 references it unconditionally. Ensure that any downstream task referencing agent_datadog_conf_paths is also gated by the same condition or provides a default.

[scratchpad_end] -->

Also applies to: 61-61


88-95: LGTM!

The trace and process agent service management with the datadog_remote_update_in_progress gate is correct. The start_mode: manual preserves their enabled state without forcing immediate startup.

tasks/main.yml (3)

17-20: LGTM!

The Windows remote update check include is correctly conditioned and positioned before the Windows install tasks. This ensures the flag is initialized before being checked in other Windows flows.


53-56: Verify that datadog_rpm_remove_keys loop is properly initialized.

Line 56 loops over datadog_rpm_remove_keys, which is not initialized in this file. Ensure:

  • This variable is defined in defaults/main.yml with a safe default (e.g., empty list)
  • The loop will not fail if the variable is undefined

If the variable may be undefined, add a fallback:

loop: "{{ datadog_rpm_remove_keys | default([], true) }}"

108-127: Verify APM instrumentation validation and integration.

The APM Single Step Instrumentation logic introduces three separate blocks (lines 108-127):

  1. Determining if instrumentation should be installed (lines 108-115)
  2. Explicit validation for invalid values (lines 117-122)
  3. Inclusion of instrumentation tasks (lines 124-127)

Verify:

  • The apm-single-step-instrumentation.yml include file exists and is properly structured.
  • If datadog_apm_instrumentation_enabled is not set, the flow gracefully skips (which it does).
  • The three blocks are sequenced correctly (determine → validate → include).

Otherwise, the logic is sound.

tasks/pkg-windows-opts.yml (4)

19-35: LGTM!

The Windows Installer feature discovery via PowerShell is robust. It safely handles missing registry keys and filter results to installed features only. The changed_when: false is appropriate for a read-only discovery task.


87-95: LGTM!

The directory creation and permission setting logic for custom Program Files and Config Files directories is sound. Conditions and formatting are correct.


100-108: LGTM!

The config root resolution logic correctly prioritizes explicit configuration over registry detection, and the regex to strip trailing backslashes is appropriate.


129-148: LGTM!

The downgrade detection logic is comprehensive, correctly comparing major, minor, and bugfix versions in a logical order. The version comparison chain is well-structured.

tasks/pkg-windows.yml (3)

28-34: Verify that included version tasks set agent_dd_download_url.

Lines 28 and 32 include win_agent_latest.yml and win_agent_version.yml, which are not provided in this review. These tasks must set agent_dd_download_url, which is referenced on line 49. Verify:

  • Both include files exist and are syntactically correct.
  • Both files set agent_dd_download_url under all relevant execution paths.
  • No code paths skip setting agent_dd_download_url before line 49.

103-105: Verify Jinja2 ternary syntax for conditional password display.

Line 105 uses a complex Jinja2 ternary condition to conditionally append DDAGENTUSER_PASSWORD=<REDACTED> to the debug message. Verify the syntax is correctly recognized by Ansible:

msg: "{{ agent_win_install_args }}{% if datadog_windows_ddagentuser_password | default('', true) | length > 0 %} DDAGENTUSER_PASSWORD=<REDACTED>{% endif %}"

This should work, but confirm that the filter chain and conditional render as expected in your Ansible version.


114-123: LGTM!

The uninstall logic correctly gates the uninstall on the agent_datadog_force_reinstall flag and verifies that product IDs are available. The loop and conditions are sound.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
CHANGELOG.md (1)

18-18: Multiple spelling and typographical errors persist from previous reviews.

These issues were previously flagged but remain unfixed in the current code:

  • Line 18: "MacOS" → "macOS" (Apple OS branding)
  • Line 30: "notd" → "not" (typo)
  • Line 31: "IMROVEMENT" → "IMPROVEMENT" (typo)
  • Line 62: "MacOS" → "macOS" (Apple OS branding)
  • Line 95: "instrumation" → "instrumentation" (typo)

Apply these diffs to fix all spelling errors:

-* [IMPROVEMENT] Simplify MacOS version architecture [#677]
+* [IMPROVEMENT] Simplify macOS version architecture [#677]
-* [IMPROVEMENT] Only gather facts and services if notd done already [#659] [Thanks @POIFischbacher]
+* [IMPROVEMENT] Only gather facts and services if not done already [#659] [Thanks @POIFischbacher]
-* [IMROVEMENT] [CI] Remove role prefix lint warnings [#660]
+* [IMPROVEMENT] [CI] Remove role prefix lint warnings [#660]
-* [IMPROVEMENT] [CI] Fix MacOS CI [#630]
+* [IMPROVEMENT] [CI] Fix macOS CI [#630]
-* [FEATURE] creating install.json file related to apm single step instrumation [#572]
+* [FEATURE] creating install.json file related to apm single step instrumentation [#572]

Also applies to: 30-30, 31-31, 62-62, 95-95

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fbed756 and c0edebf.

📒 Files selected for processing (2)
  • CHANGELOG.md (4 hunks)
  • defaults/main.yml (4 hunks)
🧰 Additional context used
🪛 Gitleaks (8.30.0)
defaults/main.yml

[high] 106-106: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 109-109: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 112-112: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 115-115: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 128-128: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 130-130: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 132-132: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 134-134: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 224-224: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 226-226: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 228-228: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 230-230: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🪛 LanguageTool
CHANGELOG.md

[uncategorized] ~18-~18: The operating system from Apple is written “macOS”.
Context: ...tation [DataDog#676] * [IMPROVEMENT] Simplify MacOS version architecture [DataDog#677] * [IMPROVEM...

(MAC_OS)


[grammar] ~30-~30: Ensure spelling is correct
Context: ...MENT] Only gather facts and services if notd done already [DataDog#659] [Thanks @POIFischba...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[uncategorized] ~62-~62: The operating system from Apple is written “macOS”.
Context: ...eb/rpms [DataDog#624] * [IMPROVEMENT] [CI] Fix MacOS CI [DataDog#630] * [BUGFIX] Fix Ansible check ...

(MAC_OS)


[grammar] ~95-~95: Ensure spelling is correct
Context: ...ll.json file related to apm single step instrumation [DataDog#572] * [FEATURE] add support for data...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~164-~164: Use a hyphen to join words.
Context: ...ing role multiple times in a row on SUSE compatible platforms. See [DataDog#453]. * [DOC...

(QB_NEW_EN_HYPHEN)

🪛 markdownlint-cli2 (0.18.1)
CHANGELOG.md

4-4: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


13-13: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


21-21: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


24-24: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


27-27: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


34-34: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


38-38: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


43-43: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


49-49: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


56-56: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


60-60: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


68-68: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


78-78: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


81-81: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


85-85: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


94-94: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


105-105: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


119-119: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


123-123: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


134-134: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


137-137: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


147-147: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


152-152: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


156-156: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


168-168: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


173-173: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


178-178: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


187-187: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


192-192: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


201-201: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


208-208: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


214-214: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


226-226: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


230-230: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


234-234: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


243-243: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


247-247: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


255-255: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


263-263: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)


542-542: Link and image reference definitions should be needed
Unused link or image reference definition: "DataDog#362"

(MD053, link-image-reference-definitions)


659-659: Link and image reference definitions should be needed
Unused link or image reference definition: "DataDog#664"

(MD053, link-image-reference-definitions)


667-667: Link and image reference definitions should be needed
Duplicate link or image reference definition: "DataDog#677"

(MD053, link-image-reference-definitions)


724-724: Link and image reference definitions should be needed
Unused link or image reference definition: "@POIFischbacher"

(MD053, link-image-reference-definitions)

🔇 Additional comments (4)
defaults/main.yml (4)

4-8: Well-structured addition of role enablement controls.

The new top-level flags datadog_enabled and datadog_manage_config provide clear control over service state and configuration management. Comments are precise and helpful.


44-44: Good expansion of macOS and multi-platform support.

New variables for macOS integration (integration_command_user_macos, datadog_agent_binary_path_macos) and agent flavor selection (datadog_agent_flavor) follow existing conventions and enable cleaner multi-platform support.

Also applies to: 47-47, 65-65


82-135: Comprehensive RPM/Zypper repository and GPG key configuration.

Extensive additions for yum and zypper repository management, including proxy support, GPG key rotation, and architecture-aware repo URLs. All variables are properly documented with expiration dates and checksums for transparency.


216-272: Well-organized internal variables for platform-specific defaults.

Clear separation of public (lines 4–209) from internal (lines 216–272) variables. Internal macOS defaults, APT keyring paths, and architecture-specific repo URLs are properly documented as "for internal use only."

Comment thread CHANGELOG.md
# 5.4.1 / 2025-10-08
* [IMPROVEMENT] Disable appstream install as its not used [#674]
* [IMPROVEMENT] Remove pycache directory during upgrades [#673]
* [IMPROVEMENT] Prepare deployment of Agent v7.70+ for macOS (arm64/x86_64) [664]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix missing "#" in pull request reference.

Line 16 lacks the "#" prefix in the PR reference, which breaks the link definition pattern used throughout the file:

-* [IMPROVEMENT] Prepare deployment of Agent v7.70+ for macOS (arm64/x86_64) [664]
+* [IMPROVEMENT] Prepare deployment of Agent v7.70+ for macOS (arm64/x86_64) [#664]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
* [IMPROVEMENT] Prepare deployment of Agent v7.70+ for macOS (arm64/x86_64) [664]
* [IMPROVEMENT] Prepare deployment of Agent v7.70+ for macOS (arm64/x86_64) [#664]
🤖 Prompt for AI Agents
In CHANGELOG.md around line 16, the pull request reference is missing the "#"
prefix causing the link pattern to break; update the line to include a "#"
before the PR number so it matches the file's link reference format (e.g.,
change "[664]" to "[#664]") to restore the correct link behavior.

Comment thread CHANGELOG.md
[#609]: https://github.com/DataDog/ansible-datadog/pull/609
[#611]: https://github.com/DataDog/ansible-datadog/pull/611
[#612]: https://github.com/DataDog/ansible-datadog/pull/612
[#618]: https://github.com/DataDog/ansible-datadog/pull/619
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix incorrect and duplicate link reference definitions.

Two critical link reference errors will cause broken navigation:

Line 635: Incorrect target PR number—should reference PR DataDog#618, not DataDog#619:

-[#618]: https://github.com/DataDog/ansible-datadog/pull/619
+[#618]: https://github.com/DataDog/ansible-datadog/pull/618

Lines 666–667: Duplicate definition for [#677]—the second definition (line 667) is incorrect and should be removed:

 [#677]: https://github.com/DataDog/ansible-datadog/pull/677
-[#677]: https://github.com/DataDog/ansible-datadog/pull/679

Also applies to: 666-667

🤖 Prompt for AI Agents
In CHANGELOG.md around lines 635 and 666–667, fix two link-reference issues:
update the link target on line 635 to reference PR #618 (replace any occurrence
of "#619" with "#618" for that link definition), and remove the
duplicate/incorrect second definition of [#677] at line 667 (leave the first
definition intact at line 666). Ensure there are no other duplicate
link-reference definitions for these PR numbers elsewhere in the file.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tasks/agent-linux.yml (1)

98-98: Duplicated notify handler logic across multiple tasks.

Lines 98, 109, 168, and 178 all contain the same complex inline Jinja2 conditional to determine which handler to notify:

{% if agent_datadog_before_7180 %}restart datadog-agent-sysprobe{% else %}restart datadog-agent{% endif %}

This violates DRY (Don't Repeat Yourself) and makes future maintenance harder if the handler selection logic changes.

🔎 Recommended refactor

Extract the handler name as a fact early in the playbook:

- name: Set appropriate restart handler for system probe changes
  ansible.builtin.set_fact:
    agent_datadog_sysprobe_restart_handler: "{{ 'restart datadog-agent-sysprobe' if agent_datadog_before_7180 else 'restart datadog-agent' }}"

Then simplify all notify statements:

- notify: "{% if agent_datadog_before_7180 %}restart datadog-agent-sysprobe{% else %}restart datadog-agent{% endif %}"
+ notify: "{{ agent_datadog_sysprobe_restart_handler }}"
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c0edebf and da06f98.

📒 Files selected for processing (1)
  • tasks/agent-linux.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: cubic · AI code reviewer
🔇 Additional comments (1)
tasks/agent-linux.yml (1)

117-118: Clarify the purpose of the experimental service check.

Line 118 includes a condition that prevents starting datadog-agent if datadog-agent-exp.service is running. This experimental service variant is not documented in comments or elsewhere in the file.

Please clarify:

  • What is the datadog-agent-exp.service?
  • Under what circumstances is it used?
  • Should this condition be documented in a comment?

Comment thread tasks/agent-linux.yml
Comment on lines +81 to +86
agent_datadog_sysprobe_enabled: "{{ ((system_probe_config is defined and 'enabled' in (system_probe_config | default({}, true)) and
system_probe_config['enabled']) or (network_config is defined and 'enabled' in (network_config | default({}, true)) and
network_config['enabled']) or (service_monitoring_config is defined and
'enabled' in (service_monitoring_config | default({}, true)) and service_monitoring_config['enabled'])) or
(system_probe_other_config is defined and (system_probe_other_config is mapping | default({}, true)) and
system_probe_other_config | length > 0) and agent_datadog_sysprobe_installed }}"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

CRITICAL: Logic error in system probe enablement condition due to parenthesis mismatch.

Lines 81-86 have two critical issues:

  1. Parenthesis mismatch: The closing )) on line 84 followed by or and then and agent_datadog_sysprobe_installed at the end creates incorrect precedence. Currently evaluates as:

    ((A or B or C)) or ((D and E and F) and G)
    

    This means if any of the first three conditions (system_probe_config, network_config, or service_monitoring_config) is enabled, agent_datadog_sysprobe_enabled will be true even if the service is not installed, breaking the installation check.

  2. Malformed expression on line 85: (system_probe_other_config is mapping | default({}, true)) attempts to apply a default filter to a boolean result from the is mapping test, which is invalid Jinja2 syntax.

🔎 Proposed fix
 - name: Set system probe enabled (since 6/7.61.0)
   ansible.builtin.set_fact:
     agent_datadog_sysprobe_enabled: "{{ ((system_probe_config is defined and 'enabled' in (system_probe_config | default({}, true)) and
       system_probe_config['enabled']) or (network_config is defined and 'enabled' in (network_config | default({}, true)) and
       network_config['enabled']) or (service_monitoring_config is defined and
-      'enabled' in (service_monitoring_config | default({}, true)) and service_monitoring_config['enabled'])) or
-      (system_probe_other_config is defined and (system_probe_other_config is mapping | default({}, true)) and
-      system_probe_other_config | length > 0) and agent_datadog_sysprobe_installed }}"
+      'enabled' in (service_monitoring_config | default({}, true)) and service_monitoring_config['enabled']) or
+      (system_probe_other_config is defined and system_probe_other_config is mapping and
+      system_probe_other_config | length > 0)) and agent_datadog_sysprobe_installed }}"
   when: not datadog_skip_running_check and (not agent_datadog_before_7610)

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

28 issues found across 91 files

Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed.

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name=".circleci/config.yml">

<violation number="1" location=".circleci/config.yml:269">
P0: Invalid bash array syntax. `[&quot;java&quot;, &quot;js&quot;, ...]` is not valid bash - it will be interpreted as a glob pattern, not iterate over the list. Use `for tracer in java js dotnet python ruby; do` instead.</violation>

<violation number="2" location=".circleci/config.yml:316">
P3: Typo: &quot;Pythpn&quot; should be &quot;Python&quot;.</violation>
</file>

<file name="README.md">

<violation number="1" location="README.md:646">
P2: URL uses `docs.datadog.com` instead of `docs.datadoghq.com`. This is inconsistent with all other Datadog documentation links in this file and may result in a broken link.</violation>
</file>

<file name="tasks/integration/linux.yml">

<violation number="1" location="tasks/integration/linux.yml:6">
P3: Typo in task name: &quot;commmand&quot; should be &quot;command&quot; (has 3 m&#39;s instead of 2).</violation>
</file>

<file name="tasks/integration/macos.yml">

<violation number="1" location="tasks/integration/macos.yml:6">
P3: Typo in task name: &quot;commmand&quot; should be &quot;command&quot; (has three &#39;m&#39;s instead of two).</violation>
</file>

<file name="tasks/windows_remote_update_check.yml">

<violation number="1" location="tasks/windows_remote_update_check.yml:6">
P2: Add `changed_when: false` since this shell task only reads process information and doesn&#39;t modify the system. Without this, Ansible will always report this task as &quot;changed&quot; even on subsequent runs.</violation>
</file>

<file name="tasks/win_agent_latest.yml">

<violation number="1" location="tasks/win_agent_latest.yml:10">
P1: Trailing space introduced in URL. There&#39;s a space after `{{ datadog_windows_agent7_latest_url }}` before `{% else %}` which will be included in the resulting URL when major version is 7, potentially causing download failures.</violation>
</file>

<file name="CONTRIBUTING.md">

<violation number="1" location="CONTRIBUTING.md:55">
P2: Referenced script `ci_test/collection-structure-setup.sh` does not exist. The `ci_test/` directory contains `ansible_lint.sh` instead. This will cause contributors to fail when following the documentation.</violation>
</file>

<file name="manual_tests/Vagrantfile">

<violation number="1" location="manual_tests/Vagrantfile:3">
P2: Ubuntu 14.04 Trusty reached End of Life in April 2019. For an &quot;Annual Update,&quot; consider using a currently supported Ubuntu LTS version like `ubuntu/jammy64` (22.04) or `ubuntu/focal64` (20.04).</violation>

<violation number="2" location="manual_tests/Vagrantfile:7">
P2: CentOS 8 reached End of Life in December 2021. Consider using `rockylinux/9` or `almalinux/9` as actively maintained RHEL-compatible alternatives.</violation>
</file>

<file name=".github/dependabot.yml">

<violation number="1" location=".github/dependabot.yml:3">
P2: Incorrect package ecosystem: `bundler` is for Ruby projects, but this repository has no Gemfile. Consider using `pip` for the Python requirements.txt files, or `github-actions` for workflow dependencies instead.</violation>
</file>

<file name="ci_test/install_agent_7_macos.yaml">

<violation number="1" location="ci_test/install_agent_7_macos.yaml:10">
P3: Misleading comment: This file is specifically for macOS (`install_agent_7_macos.yaml`), but the comment references CentOS. Consider updating the comment to reflect the actual reason for skipping the running check on macOS, or remove it if not applicable.</violation>
</file>

<file name="tasks/pkg-suse/install-pinned.yml">

<violation number="1" location="tasks/pkg-suse/install-pinned.yml:3">
P1: The `oldpackage` parameter is not supported by `ansible.builtin.package` - it&#39;s a zypper-specific option. This task will fail or the downgrade logic won&#39;t work. Consider using `ansible.builtin.zypper` instead to retain the `oldpackage` functionality.</violation>
</file>

<file name="tasks/parse-version-macos.yml">

<violation number="1" location="tasks/parse-version-macos.yml:4">
P2: Shell variable should use the `quote` filter for paths that may contain spaces or special characters. macOS paths commonly contain spaces, and without proper quoting the command will fail.</violation>
</file>

<file name="CHANGELOG.md">

<violation number="1" location="CHANGELOG.md:16">
P3: Missing `#` in link reference: `[664]` should be `[#664]` for consistent markdown link formatting.</violation>

<violation number="2" location="CHANGELOG.md:31">
P3: Typo: `[IMROVEMENT]` should be `[IMPROVEMENT]`.</violation>

<violation number="3" location="CHANGELOG.md:635">
P2: Incorrect URL: Link reference `[#618]` points to `/pull/619` instead of `/pull/618`. The reference number should match the pull request number.</violation>

<violation number="4" location="CHANGELOG.md:667">
P2: Duplicate link reference: `[#677]` is defined twice. This second definition should be `[#679]` to match its URL.</violation>
</file>

<file name="tasks/pkg-windows-opts.yml">

<violation number="1" location="tasks/pkg-windows-opts.yml:126">
P1: Version comparison logic is incorrect for major versions less than 7. For example, version 6.50 would fail the check `agent_datadog_minor | int &lt; 45` (50 &lt; 45 is false), even though 6.50 is definitely before 7.45. The condition should be `(agent_datadog_major | int &lt; 7) or (agent_datadog_major | int == 7 and agent_datadog_minor | int &lt; 45)`.</violation>
</file>

<file name="tasks/agent-linux.yml">

<violation number="1" location="tasks/agent-linux.yml:14">
P1: Inconsistent variable names used in version check. This task uses `datadog_major`/`datadog_minor`/`datadog_bugfix` while all other similar flag tasks use `agent_datadog_major`/`agent_datadog_minor`/`agent_datadog_bugfix`. This will likely cause the check to always be undefined/false.</violation>

<violation number="2" location="tasks/agent-linux.yml:85">
P1: Invalid Jinja2 syntax: `is mapping | default({}, true)` is incorrect. The `is mapping` test returns a boolean which cannot be piped to `default()`. Should be `(system_probe_other_config | default({}, true)) is mapping` to first apply the default and then test if it&#39;s a mapping.</violation>

<violation number="3" location="tasks/agent-linux.yml:85">
P1: Operator precedence bug: `agent_datadog_sysprobe_installed` only applies to the last OR clause due to missing parentheses. The system probe could be marked as enabled even when not installed if `system_probe_config`, `network_config`, or `service_monitoring_config` are enabled. The entire expression should be wrapped with `and agent_datadog_sysprobe_installed` at the end.</violation>
</file>

<file name="tasks/pkg-debian.yml">

<violation number="1" location="tasks/pkg-debian.yml:48">
P1: Invalid YAML multi-line string syntax for task name. Without using `&gt;` or `|` operators, the second line is not properly parsed as part of the `name` value, which may cause YAML parsing errors or unexpected behavior. Consider using folded style or keeping the name on a single line.</violation>
</file>

<file name="tasks/main.yml">

<violation number="1" location="tasks/main.yml:8">
P1: The `when` conditions use AND logic (list format) but this will error if `ansible_facts` is undefined because `ansible_facts.system` cannot be accessed on an undefined variable. This should use OR logic instead.</violation>

<violation number="2" location="tasks/main.yml:27">
P3: Typo in task name: &#39;presidence&#39; should be &#39;precedence&#39;.</violation>
</file>

<file name=".ansible-lint">

<violation number="1" location=".ansible-lint:8">
P2: Inconsistent rule naming: `var_naming` uses underscore but ansible-lint canonical rule names use hyphens. This should be `var-naming` to match the format used in `skip_list` and ensure the warning is properly configured.</violation>
</file>

<file name="tasks/pkg-macos/macos_agent_latest.yml">

<violation number="1" location="tasks/pkg-macos/macos_agent_latest.yml:16">
P2: `retries: 2` has no effect without an `until` condition. In Ansible, retries only work when combined with `until`. Without it, the task runs exactly once regardless of the `retries` value. Consider adding `until` and `delay` parameters, e.g.:
```yaml
retries: 2
delay: 3
until: datadog_macos_agent7_latest_arch_check.status is defined
```</violation>
</file>

<file name="tasks/agent-win.yml">

<violation number="1" location="tasks/agent-win.yml:137">
P1: The `retries` and `delay` parameters have no effect without an `until` condition. This task will only run once, not retry 3 times as intended. Add an `until` condition and `register` to enable actual retry behavior.</violation>
</file>

Reply to cubic to teach it or ask questions. Tag @cubic-dev-ai to re-run a review.

Comment thread .circleci/config.yml
os: ["rocky9", "debian"]
python: ["python3.11"]

# Newer debian images only have Pythpn 3 installed
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Dec 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Typo: "Pythpn" should be "Python".

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .circleci/config.yml, line 316:

<comment>Typo: &quot;Pythpn&quot; should be &quot;Python&quot;.</comment>

<file context>
@@ -90,28 +138,269 @@ jobs:
+              os: [&quot;rocky9&quot;, &quot;debian&quot;]
+              python: [&quot;python3.11&quot;]
+
+      # Newer debian images only have Pythpn 3 installed
+      - test_install_downgrade:
+          matrix:
</file context>
Suggested change
# Newer debian images only have Pythpn 3 installed
# Newer debian images only have Python 3 installed
Fix with Cubic

Comment thread .circleci/config.yml
- run: sudo datadog-agent status || true
- run: ps aux | grep -v grep | grep datadog-agent
- run: >
bash -c 'for tracer in ["java", "js", "dotnet", "python", "ruby"]; do
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Dec 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0: Invalid bash array syntax. ["java", "js", ...] is not valid bash - it will be interpreted as a glob pattern, not iterate over the list. Use for tracer in java js dotnet python ruby; do instead.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .circleci/config.yml, line 269:

<comment>Invalid bash array syntax. `[&quot;java&quot;, &quot;js&quot;, ...]` is not valid bash - it will be interpreted as a glob pattern, not iterate over the list. Use `for tracer in java js dotnet python ruby; do` instead.</comment>

<file context>
@@ -90,28 +138,269 @@ jobs:
+      - run: sudo datadog-agent status || true
+      - run: ps aux | grep -v grep | grep datadog-agent
+      - run: &gt;
+          bash -c &#39;for tracer in [&quot;java&quot;, &quot;js&quot;, &quot;dotnet&quot;, &quot;python&quot;, &quot;ruby&quot;]; do
+            sudo datadog-installer is-installed datadog-apm-library-$tracer;
+          done&#39;
</file context>
Suggested change
bash -c 'for tracer in ["java", "js", "dotnet", "python", "ruby"]; do
bash -c 'for tracer in java js dotnet python ruby; do
Fix with Cubic

Comment thread README.md
[18]: https://docs.datadoghq.com/security/cspm/setup/?tab=docker
[19]: https://github.com/DataDog/integrations-core
[20]: https://github.com/DataDog/integrations-extras
[21]: https://docs.datadog.com/tracing/trace_collection/library_injection_local
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Dec 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: URL uses docs.datadog.com instead of docs.datadoghq.com. This is inconsistent with all other Datadog documentation links in this file and may result in a broken link.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At README.md, line 646:

<comment>URL uses `docs.datadog.com` instead of `docs.datadoghq.com`. This is inconsistent with all other Datadog documentation links in this file and may result in a broken link.</comment>

<file context>
@@ -505,15 +600,47 @@ If you are updating from **6.14.0 or 6.14.1 on Windows**, use the following step
+[18]: https://docs.datadoghq.com/security/cspm/setup/?tab=docker
+[19]: https://github.com/DataDog/integrations-core
+[20]: https://github.com/DataDog/integrations-extras
+[21]: https://docs.datadog.com/tracing/trace_collection/library_injection_local
</file context>
Suggested change
[21]: https://docs.datadog.com/tracing/trace_collection/library_injection_local
[21]: https://docs.datadoghq.com/tracing/trace_collection/library_injection_local
Fix with Cubic

ansible.builtin.set_fact:
datadog_agent_binary_path: "{{ datadog_agent_binary_path_linux }}"

- name: Set Agent user for integration commmand
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Dec 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Typo in task name: "commmand" should be "command" (has 3 m's instead of 2).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tasks/integration/linux.yml, line 6:

<comment>Typo in task name: &quot;commmand&quot; should be &quot;command&quot; (has 3 m&#39;s instead of 2).</comment>

<file context>
@@ -0,0 +1,12 @@
+  ansible.builtin.set_fact:
+    datadog_agent_binary_path: &quot;{{ datadog_agent_binary_path_linux }}&quot;
+
+- name: Set Agent user for integration commmand
+  ansible.builtin.set_fact:
+    integration_command_user: &quot;{{ integration_command_user_linux }}&quot;
</file context>
Fix with Cubic

ansible.builtin.set_fact:
datadog_agent_binary_path: "{{ datadog_agent_binary_path_macos }}"

- name: Set Agent user for integration commmand
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Dec 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Typo in task name: "commmand" should be "command" (has three 'm's instead of two).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tasks/integration/macos.yml, line 6:

<comment>Typo in task name: &quot;commmand&quot; should be &quot;command&quot; (has three &#39;m&#39;s instead of two).</comment>

<file context>
@@ -0,0 +1,12 @@
+  ansible.builtin.set_fact:
+    datadog_agent_binary_path: &quot;{{ datadog_agent_binary_path_macos }}&quot;
+
+- name: Set Agent user for integration commmand
+  ansible.builtin.set_fact:
+    integration_command_user: &quot;{{ integration_command_user_macos }}&quot;
</file context>
Fix with Cubic

Comment thread tasks/main.yml
msg: "datadog_api_key is mandatory when using managed config"
when: datadog_api_key is not defined and datadog_manage_config

- name: Resolve datadog_tracked_checks later to defend against variable presidence issues arising from dynamically included null datadog_checks
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Dec 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Typo in task name: 'presidence' should be 'precedence'.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tasks/main.yml, line 27:

<comment>Typo in task name: &#39;presidence&#39; should be &#39;precedence&#39;.</comment>

<file context>
@@ -1,47 +1,128 @@
+    msg: &quot;datadog_api_key is mandatory when using managed config&quot;
+  when: datadog_api_key is not defined and datadog_manage_config
 
+- name: Resolve datadog_tracked_checks later to defend against variable presidence issues arising from dynamically included null datadog_checks
+  ansible.builtin.include_tasks: sanitize-checks.yml
+
</file context>
Suggested change
- name: Resolve datadog_tracked_checks later to defend against variable presidence issues arising from dynamically included null datadog_checks
- name: Resolve datadog_tracked_checks later to defend against variable precedence issues arising from dynamically included null datadog_checks
Fix with Cubic

Comment thread tasks/main.yml
# If the full prefix isn't specified in Ansible 2.10+, we might end up running `ansible.windows.setup` instead.
when:
- ansible_facts is undefined
- ansible_facts.system is undefined
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Dec 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: The when conditions use AND logic (list format) but this will error if ansible_facts is undefined because ansible_facts.system cannot be accessed on an undefined variable. This should use OR logic instead.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tasks/main.yml, line 8:

<comment>The `when` conditions use AND logic (list format) but this will error if `ansible_facts` is undefined because `ansible_facts.system` cannot be accessed on an undefined variable. This should use OR logic instead.</comment>

<file context>
@@ -1,47 +1,128 @@
+    # If the full prefix isn&#39;t specified in Ansible 2.10+, we might end up running `ansible.windows.setup` instead.
+  when:
+    - ansible_facts is undefined
+    - ansible_facts.system is undefined
+
+- name: Initialize internal datadog_config variable
</file context>
Fix with Cubic

Comment thread .ansible-lint
- fqcn[action]

warn_list:
- var_naming
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Dec 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Inconsistent rule naming: var_naming uses underscore but ansible-lint canonical rule names use hyphens. This should be var-naming to match the format used in skip_list and ensure the warning is properly configured.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .ansible-lint, line 8:

<comment>Inconsistent rule naming: `var_naming` uses underscore but ansible-lint canonical rule names use hyphens. This should be `var-naming` to match the format used in `skip_list` and ensure the warning is properly configured.</comment>

<file context>
@@ -0,0 +1,12 @@
+  - fqcn[action]
+
+warn_list:
+  - var_naming
+  - idiom
+
</file context>
Fix with Cubic

status_code: 200
register: datadog_macos_agent7_latest_arch_check
failed_when: false
retries: 2
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Dec 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: retries: 2 has no effect without an until condition. In Ansible, retries only work when combined with until. Without it, the task runs exactly once regardless of the retries value. Consider adding until and delay parameters, e.g.:

retries: 2
delay: 3
until: datadog_macos_agent7_latest_arch_check.status is defined
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tasks/pkg-macos/macos_agent_latest.yml, line 16:

<comment>`retries: 2` has no effect without an `until` condition. In Ansible, retries only work when combined with `until`. Without it, the task runs exactly once regardless of the `retries` value. Consider adding `until` and `delay` parameters, e.g.:
```yaml
retries: 2
delay: 3
until: datadog_macos_agent7_latest_arch_check.status is defined
```</comment>

<file context>
@@ -0,0 +1,30 @@
+    status_code: 200
+  register: datadog_macos_agent7_latest_arch_check
+  failed_when: false
+  retries: 2
+  when:
+    - datadog_macos_download_url | default(&#39;&#39;, true) | length == 0
</file context>
Fix with Cubic

Comment thread tasks/agent-win.yml
- (datadog_start_result.failed | default(false))
- not datadog_remote_update_in_progress
delay: 10
retries: 3
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Dec 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: The retries and delay parameters have no effect without an until condition. This task will only run once, not retry 3 times as intended. Add an until condition and register to enable actual retry behavior.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tasks/agent-win.yml, line 137:

<comment>The `retries` and `delay` parameters have no effect without an `until` condition. This task will only run once, not retry 3 times as intended. Add an `until` condition and `register` to enable actual retry behavior.</comment>

<file context>
@@ -1,48 +1,154 @@
+    - (datadog_start_result.failed | default(false))
+    - not datadog_remote_update_in_progress
+  delay: 10
+  retries: 3
+
+- name: Ensure datadog-agent is disabled
</file context>
Suggested change
retries: 3
retries: 3
until: datadog_retry_result.state == 'started'
register: datadog_retry_result
Fix with Cubic

ian28223 and others added 2 commits January 19, 2026 00:21
Update CHANGELOG.md

Fix link to PR related to 5.4.0

Co-authored-by: ian.bucad <ian.bucad@datadoghq.com>
* update datadog_agent_binary_path_linux to new path

* update macos ci runner to xcode 26.2.0

* detect which path to use instead

* fix tests

* allow integration install to fail, just checking binary path

* fix binary path detection logic

* clean up tests

* datadog_agent_binary_path falls back to datadog_agent_binary_path_linux
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In @.circleci/config.yml:
- Line 342: Fix the typo "Pythpn" to "Python" in the comments that mention
Python in the CI config; locate the comment lines containing the exact
misspelling "Pythpn" (both occurrences referenced in the diff) and replace them
with "Python" so the documentation comments read correctly.
- Around line 268-271: The bash for-loop uses JSON-style array syntax which is
invalid; edit the run command so the loop header uses a bash space-separated
list (java js dotnet python ruby) instead of ["java", "js", "dotnet", "python",
"ruby"] and ensure the loop uses the proper bash structure (for tracer in ...;
do ...; done) while leaving the body invocation sudo datadog-installer
is-installed datadog-apm-library-$tracer unchanged.

In `@ci_test/install_agent_7_with_integration_fleet.yaml`:
- Around line 7-15: Add the missing Datadog control vars to the playbook's vars
block: set datadog_enabled: false and datadog_skip_running_check: true so the
agent does not start during CI; update the vars alongside
datadog_agent_major_version, datadog_api_key,
datadog_apm_instrumentation_enabled, datadog_apm_instrumentation_libraries and
datadog_integration (e.g., next to datadog_agent_major_version) to match the
other test playbooks.
🧹 Nitpick comments (1)
ci_test/install_agent_7_with_integration_fleet.yaml (1)

24-24: Missing trailing newline.

YAML files should end with a newline character for POSIX compliance and to avoid potential issues with some tools.

Add trailing newline
       always:
         - name: Verify Fleet path was detected
           ansible.builtin.assert:
             that: datadog_agent_binary_path == "/bin/datadog-agent"
             fail_msg: "Wrong path: {{ datadog_agent_binary_path }}"
+

Comment thread .circleci/config.yml
Comment on lines +268 to +271
- run: >
bash -c 'for tracer in ["java", "js", "dotnet", "python", "ruby"]; do
sudo datadog-installer is-installed datadog-apm-library-$tracer;
done'
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Invalid bash for-loop syntax will cause job failure.

The loop syntax for tracer in ["java", "js", "dotnet", "python", "ruby"] is incorrect. Bash does not use JSON-style array notation for iteration.

🐛 Proposed fix
       - run: >
-          bash -c 'for tracer in ["java", "js", "dotnet", "python", "ruby"]; do
+          bash -c 'for tracer in java js dotnet python ruby; do
             sudo datadog-installer is-installed datadog-apm-library-$tracer;
           done'
🤖 Prompt for AI Agents
In @.circleci/config.yml around lines 268 - 271, The bash for-loop uses
JSON-style array syntax which is invalid; edit the run command so the loop
header uses a bash space-separated list (java js dotnet python ruby) instead of
["java", "js", "dotnet", "python", "ruby"] and ensure the loop uses the proper
bash structure (for tracer in ...; do ...; done) while leaving the body
invocation sudo datadog-installer is-installed datadog-apm-library-$tracer
unchanged.

Comment thread .circleci/config.yml
os: ["rocky9", "debian"]
python: ["python3.11"]

# Newer debian images only have Pythpn 3 installed
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Typo: "Pythpn" should be "Python".

Lines 342 and 351 both contain the typo "Pythpn" instead of "Python" in the comments.

📝 Proposed fix
-      # Newer debian images only have Pythpn 3 installed
+      # Newer debian images only have Python 3 installed
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Newer debian images only have Pythpn 3 installed
# Newer debian images only have Python 3 installed
🤖 Prompt for AI Agents
In @.circleci/config.yml at line 342, Fix the typo "Pythpn" to "Python" in the
comments that mention Python in the CI config; locate the comment lines
containing the exact misspelling "Pythpn" (both occurrences referenced in the
diff) and replace them with "Python" so the documentation comments read
correctly.

Comment on lines +7 to +15
vars:
datadog_agent_major_version: 7
datadog_api_key: "11111111111111111111111111111111"
datadog_apm_instrumentation_enabled: "host"
datadog_apm_instrumentation_libraries: ["python"]
datadog_integration:
test-integration:
action: install
version: 1.0.0
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check other test files for these settings patterns
echo "=== All test files in ci_test directory ==="
ls -la ci_test/*.yaml 2>/dev/null | head -20

echo -e "\n=== Checking for datadog_enabled and datadog_skip_running_check in all test files ==="
rg -n 'datadog_enabled|datadog_skip_running_check' ci_test/ --color=never

echo -e "\n=== Checking Fleet-related test files specifically ==="
rg -l 'fleet|Fleet' ci_test/ --color=never

echo -e "\n=== Content of install_agent_7_with_integration.yaml for comparison ==="
cat ci_test/install_agent_7_with_integration.yaml

echo -e "\n=== Checking trailing newline in the Fleet file ==="
tail -c 20 ci_test/install_agent_7_with_integration_fleet.yaml | od -c

Repository: NickJLange/ansible-datadog

Length of output: 3205


🏁 Script executed:

#!/bin/bash
# Verify trailing newline more reliably
echo "=== Checking trailing newline status ==="
echo "Fleet file ends with newline:"
tail -1 ci_test/install_agent_7_with_integration_fleet.yaml | wc -l

echo -e "\nComparison file (install_agent_7_with_integration.yaml) ends with newline:"
tail -1 ci_test/install_agent_7_with_integration.yaml | wc -l

echo -e "\n=== File sizes and last few bytes ==="
echo "Fleet file:"
wc -l ci_test/install_agent_7_with_integration_fleet.yaml
tail -c 30 ci_test/install_agent_7_with_integration_fleet.yaml | xxd

echo -e "\nComparison file:"
wc -l ci_test/install_agent_7_with_integration.yaml
tail -c 30 ci_test/install_agent_7_with_integration.yaml | xxd

echo -e "\n=== Full content of Fleet file ==="
cat -n ci_test/install_agent_7_with_integration_fleet.yaml

Repository: NickJLange/ansible-datadog

Length of output: 1601


Add datadog_enabled: false and datadog_skip_running_check: true for consistency.

This playbook is the only test file missing these settings, which are present in all other test files (install_agent_7.yaml, install_agent_7_with_integration.yaml, install_agent_7_pinned.yaml, etc.). Without them, the Datadog agent service may start during CI tests. Add these settings to the vars block to match the established test pattern.

🤖 Prompt for AI Agents
In `@ci_test/install_agent_7_with_integration_fleet.yaml` around lines 7 - 15, Add
the missing Datadog control vars to the playbook's vars block: set
datadog_enabled: false and datadog_skip_running_check: true so the agent does
not start during CI; update the vars alongside datadog_agent_major_version,
datadog_api_key, datadog_apm_instrumentation_enabled,
datadog_apm_instrumentation_libraries and datadog_integration (e.g., next to
datadog_agent_major_version) to match the other test playbooks.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 5 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name=".circleci/config.yml">

<violation number="1" location=".circleci/config.yml:316">
P2: The `run: >` folded block collapses newlines, so the first `#` comment causes the rest of the `bash -c` script to be commented out and skipped. Use a literal block (`|`) or remove comments/insert semicolons so the checks actually execute.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread .circleci/config.yml
- run: sudo datadog-agent status || true
- run: ps aux | grep -v grep | grep datadog-agent
# Verify that SSI was installed with custom directory
- run: >
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The run: > folded block collapses newlines, so the first # comment causes the rest of the bash -c script to be commented out and skipped. Use a literal block (|) or remove comments/insert semicolons so the checks actually execute.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .circleci/config.yml, line 316:

<comment>The `run: >` folded block collapses newlines, so the first `#` comment causes the rest of the `bash -c` script to be commented out and skipped. Use a literal block (`|`) or remove comments/insert semicolons so the checks actually execute.</comment>

<file context>
@@ -296,6 +296,45 @@ jobs:
+      - run: sudo datadog-agent status || true
+      - run: ps aux | grep -v grep | grep datadog-agent
+      # Verify that SSI was installed with custom directory
+      - run: >
+          bash -c '
+          # Check that datadog-installer is present
</file context>
Suggested change
- run: >
- run: |
Fix with Cubic

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="defaults/main.yml">

<violation number="1" location="defaults/main.yml:208">
P1: Defaulting the SSI script directory to /tmp introduces a local privilege escalation risk: an unprivileged user can pre-create /tmp/datadog-installer and keep ownership since the role doesn’t set owner/group, then swap the installer script before it runs. Use a root-owned runtime directory by default (or set owner/group explicitly in the tasks).</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread defaults/main.yml
# Directory where the Single Step Instrumentation (SSI) script will be downloaded and executed.
# Default uses /tmp/datadog-installer.
# Override this if /tmp/datadog-installer is not suitable in your environment.
datadog_ssi_script_dir: "/tmp/datadog-installer"
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Defaulting the SSI script directory to /tmp introduces a local privilege escalation risk: an unprivileged user can pre-create /tmp/datadog-installer and keep ownership since the role doesn’t set owner/group, then swap the installer script before it runs. Use a root-owned runtime directory by default (or set owner/group explicitly in the tasks).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At defaults/main.yml, line 208:

<comment>Defaulting the SSI script directory to /tmp introduces a local privilege escalation risk: an unprivileged user can pre-create /tmp/datadog-installer and keep ownership since the role doesn’t set owner/group, then swap the installer script before it runs. Use a root-owned runtime directory by default (or set owner/group explicitly in the tasks).</comment>

<file context>
@@ -203,9 +203,9 @@ datadog_apm_inject_version: ""
-datadog_ssi_script_dir: "/var/run/datadog-ssi"
+# Default uses /tmp/datadog-installer.
+# Override this if /tmp/datadog-installer is not suitable in your environment.
+datadog_ssi_script_dir: "/tmp/datadog-installer"
 
 # Enable remote updates through datadog-installer
</file context>
Suggested change
datadog_ssi_script_dir: "/tmp/datadog-installer"
datadog_ssi_script_dir: "/var/run/datadog-installer"
Fix with Cubic

@NickJLange
Copy link
Copy Markdown
Owner Author

Closing stale PR on inactive fork

@NickJLange NickJLange closed this Feb 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.