diff --git a/.ansible-lint b/.ansible-lint new file mode 100644 index 00000000..cb1fa021 --- /dev/null +++ b/.ansible-lint @@ -0,0 +1,12 @@ +--- +enable_list: + - empty-string-compare + - fqcn-builtins + - fqcn[action] + +warn_list: + - var_naming + - idiom + +skip_list: + - var-naming[no-role-prefix] diff --git a/.circleci/config.yml b/.circleci/config.yml index 76b656da..e4aa189c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -6,66 +6,111 @@ commands: parameters: version: type: string + python: + type: string steps: - - run: ansible-playbook -i ./ci_test/inventory/ci.ini "./ci_test/install_agent_<>.yaml" --check - - run: ansible-playbook -i ./ci_test/inventory/ci.ini "./ci_test/downgrade_to_5.yaml" --check - - install_agent_5: - steps: - - run: ansible-playbook -i ./ci_test/inventory/ci.ini "./ci_test/install_agent_5.yaml" - - run: dd-agent info || true - - run: ps aux | grep -v grep | grep datadog-agent + - run: ansible-playbook -i ./ci_test/inventory/ci.ini "./ci_test/install_agent_<>.yaml" -e 'ansible_python_interpreter=/usr/bin/<>' --check + - run: ansible-playbook -i ./ci_test/inventory/ci.ini "./ci_test/downgrade_to_6.yaml" -e 'ansible_python_interpreter=/usr/bin/<>' --check install_agent: parameters: version: type: string + python: + type: string + jinja2_native: + type: string + default: "false" + inventory: + type: string + default: "ci.ini" steps: - - run: ansible-playbook -i ./ci_test/inventory/ci.ini "./ci_test/install_agent_<>.yaml" + - run: ANSIBLE_JINJA2_NATIVE="<>" ansible-playbook -i ./ci_test/inventory/<> "./ci_test/install_agent_<>.yaml" -e 'ansible_python_interpreter=<>' - run: datadog-agent version - downgrade_agent_5_23_0: + test_install_no_manage_config: + parameters: + version: + type: string + python: + type: string steps: - - run: ansible-playbook -i ./ci_test/inventory/ci.ini "./ci_test/downgrade_to_5.yaml" - - run: dd-agent info || true - - run: ps aux | grep -v grep | grep datadog-agent + - run: ansible-playbook -i ./ci_test/inventory/ci.ini "./ci_test/install_agent_<>.yaml" -e '{"ansible_python_interpreter":"/usr/bin/<>","datadog_manage_config":false}' + - run: bash -c '[ -f /etc/datadog-agent/datadog.yaml.example ] || [ -f /etc/dd-agent/datadog.conf.example ]' + - run: bash -c '[ ! -f /etc/datadog-agent/datadog.yaml ] && [ ! -f /etc/datadog-agent/system-probe.yaml ] && [ ! -f /etc/datadog-agent/security-agent.yaml ] && [ ! -f /etc/dd-agent/datadog.conf ]' + + downgrade_agent_6_28: + parameters: + python: + type: string + steps: + - run: ansible-playbook -i ./ci_test/inventory/ci.ini "./ci_test/downgrade_to_6.yaml" -e 'ansible_python_interpreter=/usr/bin/<>' + - run: datadog-agent version + - run: datadog-agent status || true test_agent_install_downgrade: parameters: version: type: string + python: + type: string + jinja2_native: + type: string + default: "false" steps: - checkout - dry_run: version: "<>" - - install_agent_5 - - when: - condition: - not: - equal: [<>, "5"] - steps: - - install_agent: - version: <> - - downgrade_agent_5_23_0 + python: "<>" + # install agent version corresponding to parameters.version + - install_agent: + version: "<>" + python: "<>" + - downgrade_agent_6_28: + python: "<>" + # Verify the downgrade worked + - run: datadog-agent version test_agent_install: parameters: version: type: string + python: + type: string + jinja2_native: + type: string + default: "false" steps: - checkout - install_agent: - version: <> + version: "<>" + python: "<>" + jinja2_native: "<>" + + test_agent_install_macos: + parameters: + version: + type: string + python: + type: string + jinja2_native: + type: string + default: "false" + steps: + - checkout + - install_agent: + version: "<>" + python: "<>" + jinja2_native: "<>" + inventory: "ci_macos.ini" jobs: - # TODO: Use 2.10 image, fix file permission errors (E208) that arise. ansible_lint: docker: - - image: datadog/docker-library:ansible_debian_2_7 + - image: datadog/docker-library:ansible_debian_2_10 steps: - checkout - - run: pip install ansible-lint - - run: ansible-lint -v . + - run: ci_test/ansible_lint.sh test_install_downgrade: parameters: @@ -75,12 +120,15 @@ jobs: type: string os: type: string + python: + type: string docker: - image: datadog/docker-library:ansible_<>_<> steps: - checkout - test_agent_install_downgrade: version: "<>" + python: "<>" test_install: parameters: @@ -90,28 +138,351 @@ jobs: type: string os: type: string + python: + type: string + jinja2_native: + type: string + default: "false" docker: - image: datadog/docker-library:ansible_<>_<> steps: - checkout - test_agent_install: version: "<>" + python: "<>" + jinja2_native: "<>" + + test_install_no_manage_config: + parameters: + ansible_version: + type: string + agent_version: + type: string + os: + type: string + python: + type: string + docker: + - image: datadog/docker-library:ansible_<>_<> + steps: + - checkout + - test_install_no_manage_config: + version: "<>" + python: "<>" + + test_install_macos: + parameters: + ansible_version: + type: string + agent_version: + type: string + python: + type: string + jinja2_native: + type: string + default: "false" + macos: + xcode: 26.2.0 + steps: + - checkout + - when: + condition: + equal: ["6_macos", << parameters.agent_version >>] + steps: + - run: + name: Install Rosetta 2 + command: printf 'A\n' | sudo softwareupdate --install-rosetta + - run: + name: Install Python3 + command: brew install python@3.11 + - run: + name: Install Ansible + command: /opt/homebrew/bin/pip3.11 install ansible~=<> + - test_agent_install_macos: + version: "<>" + python: "/opt/homebrew/bin/python3.11" + jinja2_native: "<>" + + test_apm_injection: + parameters: + ansible_version: + type: string + + machine: + image: ubuntu-2204:2023.10.1 # includes docker and docker-compose + + steps: + - checkout + # these repos have expired GPG keys and make APT fail (and we don't need them) + - run: sudo rm /etc/apt/sources.list.d/* + - run: pip3 install ansible==<> + - run: ansible-playbook --become -i ./ci_test/inventory/ci.ini "./ci_test/install_agent_7_apm_python.yaml" + - run: sudo datadog-agent status || true + - run: ps aux | grep -v grep | grep datadog-agent + - run: git -C /tmp clone https://github.com/DataDog/system-tests.git + - run: cd /tmp/system-tests/lib-injection/build/docker/python/dd-lib-python-init-test-django && sudo docker build -t system-tests/local . + - run: sudo docker run -d --name test-app-python -p 5985:18080 system-tests/local:latest + - run: curl --retry 10 --retry-max-time 30 --retry-all-errors localhost:5985 + # Verify the instrumentation status from datadog-installer + - run: | + status_json=$(sudo datadog-installer status --json | jq .apm_injection_status) + for key in $(echo "$status_json" | jq -r 'keys[]'); do + value=$(echo "$status_json" | jq -r --arg k "$key" '.[$k]') + if [ "$value" != "true" ]; then + echo "❌ Check failed: $key is not true (value: $value)" + exit 1 + fi + echo "✅ $key is true" + done + echo "🎉 All APM injection checks passed!" + # verify that the emitted traces are received by checking agent status + - run: | + for i in {1..14}; do + echo "Checking for traces (attempt $i/14)..." + if sudo datadog-agent status "apm agent" --json | jq -e '.apmStats.ratebyservice | keys | length > 0' >/dev/null 2>&1; then + echo "✅ Traces found in agent status!" + sudo datadog-agent status "apm agent" --json | jq '.apmStats.ratebyservice' + exit 0 + fi + sleep 5 + done + echo "❌ No traces found after 70 seconds" + exit 1 + + test_apm_injection_all: + parameters: + ansible_version: + type: string + + machine: + image: ubuntu-2204:2023.10.1 # includes docker and docker-compose + + steps: + - checkout + # these repos have expired GPG keys and make APT fail (and we don't need them) + - run: sudo rm /etc/apt/sources.list.d/* + - run: pip3 install ansible==<> + - run: ansible-playbook --become -i ./ci_test/inventory/ci.ini "./ci_test/install_agent_7_apm_all.yaml" + - 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 + sudo datadog-installer is-installed datadog-apm-library-$tracer; + done' + + test_integration_traditional: + parameters: + ansible_version: + type: string + os: + type: string + python: + type: string + docker: + - image: datadog/docker-library:ansible_<>_<> + steps: + - checkout + - run: ansible-playbook -i ./ci_test/inventory/ci.ini "./ci_test/install_agent_7_with_integration.yaml" -e 'ansible_python_interpreter=/usr/bin/<>' + + test_integration_fleet: + parameters: + ansible_version: + type: string + machine: + image: ubuntu-2204:2023.10.1 + steps: + - checkout + - run: sudo rm /etc/apt/sources.list.d/* + - run: pip3 install ansible==<> + - run: ansible-playbook --become -i ./ci_test/inventory/ci.ini "./ci_test/install_agent_7_with_integration_fleet.yaml" + + test_apm_injection_custom_dir: + parameters: + ansible_version: + type: string + + machine: + image: ubuntu-2204:2023.10.1 # includes docker and docker-compose + + steps: + - checkout + # these repos have expired GPG keys and make APT fail (and we don't need them) + - run: sudo rm /etc/apt/sources.list.d/* + - run: pip3 install ansible==<> + - run: ansible-playbook --become -i ./ci_test/inventory/ci.ini "./ci_test/install_agent_7_apm_custom_dir.yaml" + - 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 + sudo datadog-installer --version || exit 1 + # Check that APM libraries were installed + sudo datadog-installer is-installed datadog-apm-library-python || exit 1 + sudo datadog-installer is-installed datadog-apm-library-java || exit 1 + ' + # Verify the custom directory was used and cleaned up + - run: | + if [ -d /opt/datadog-ssi-scripts ]; then + echo "Custom SSI script directory exists" + if [ -f /opt/datadog-ssi-scripts/install-ssi.sh ]; then + echo "ERROR: SSI script was not cleaned up" + exit 1 + fi + echo "SSI script was properly cleaned up" + else + echo "Custom SSI script directory was not created" + exit 1 + fi + + test_incorrect_rhel6_detect: + # Ensure some RHEL derivatives aren't incorrectly detected as RHEL 6 + docker: + - image: datadog/docker-library:ansible_<>_<> + parameters: + jinja2_native: + type: string + default: "false" + os: + type: string + ansible_version: + type: string + python: + type: string + steps: + - checkout + - run: ANSIBLE_JINJA2_NATIVE="<>" ansible-playbook -i ./ci_test/inventory/ci.ini ./ci_test/install_agent_7_pinned.yaml -e 'ansible_python_interpreter=/usr/bin/<>' + - run: datadog-agent version workflows: version: 2 test_datadog_role: + # Note: Ansible 5.* requires Python >= 3.8, which for now we only have on Debian. + # Whenever newer major versions of RHEL and SUSE get released, they should have + # a new enough Python, so we will test on them as well jobs: - ansible_lint - test_install_downgrade: matrix: parameters: - ansible_version: ["2_6", "2_7", "2_8", "2_9", "2_10"] - agent_version: ["5", "6", "7"] - os: ["debian", "centos"] + ansible_version: ["2_10", "3_4", "4_10"] + agent_version: ["6", "7"] + os: ["rocky8"] + python: ["python3"] + + - test_install_downgrade: + matrix: + parameters: + ansible_version: ["12_0"] + agent_version: ["6", "7"] + os: ["rocky9", "debian"] + python: ["python3.11"] + + # Newer debian images only have Pythpn 3 installed + - test_install_downgrade: + matrix: + parameters: + ansible_version: ["2_10", "3_4", "4_10", "5_3", "9_4"] + agent_version: ["6", "7"] + os: ["debian"] + python: ["python3"] + + # Newer debian images only have Pythpn 3 installed + - test_install_no_manage_config: + matrix: + parameters: + ansible_version: ["2_10", "3_4", "4_10"] + agent_version: ["6", "7"] + os: ["debian"] + python: ["python3"] + + - test_install_no_manage_config: + matrix: + parameters: + ansible_version: ["12_0"] + agent_version: ["6", "7"] + os: ["debian"] + python: ["python3.11"] + + - 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: ["2_8", "2_9", "2_10"] + 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_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"] + + - test_install_macos: + matrix: + parameters: + ansible_version: ["2.10", "3.4", "4.10", "12.0"] + agent_version: ["6_macos", "7_macos"] + python: ["python3"] + + - test_apm_injection: + matrix: + parameters: + ansible_version: ["6.7.0", "12.0.0 "] + + - test_apm_injection_all: + matrix: + parameters: + ansible_version: ["6.7.0", "12.0.0"] + + - test_integration_traditional: + matrix: + parameters: + ansible_version: ["4_10"] + os: ["debian"] + python: ["python3"] + + - test_integration_fleet: + matrix: + parameters: + ansible_version: ["12.0.0"] + + - test_apm_injection_custom_dir: + matrix: + parameters: + ansible_version: ["6.7.0", "12.0.0"] + + - test_incorrect_rhel6_detect: + matrix: + parameters: + ansible_version: ["4_10"] + os: ["amazonlinux2023"] + python: ["python3"] + + - test_incorrect_rhel6_detect: + matrix: + parameters: + ansible_version: ["12_0"] + os: ["amazonlinux2023"] + python: ["python3.11"] diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 338fd9f8..aecb092e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,4 +1,4 @@ -* @DataDog/agent-platform +* @DataDog/container-ecosystems # Docs -*README.md @DataDog/agent-platform @DataDog/documentation +*README.md @DataDog/container-ecosystems @DataDog/documentation diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..70a98e6f --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "bundler" + directory: "/" + schedule: + interval: "monthly" diff --git a/.gitignore b/.gitignore index ade095e0..2022cd01 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,20 @@ -.vagrant +.idea/ *.retry .venv +.ansible + +# Vagrant +.vagrant # pre and post tasks folders (user defined) pre_tasks/ post_tasks/ -.kitchen/ -.kitchen.local.yml -.bundle \ No newline at end of file + +# OSX github datastore +**/.DS_Store + +# IDEs +.vscode/ +.idea/ +.cursor/ +.zed/ \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index cd0ffba1..ee49e50f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,278 @@ CHANGELOG ========= +# 5.6.0 / 2026-02-10 +* [IMPROVEMENT] Write system probe config whenever config is defined [#690] +* [IMPROVEMENT] Update Linux Agent CLI path [#693] +* [IMPROVEMENT] Allow configuring the SSI install script download location to ensure it can be executed [#694] + +# 5.5.0 / 2025-12-04 +* [FEATURE] Support Remote updates on Windows [#686] +* [IMPROVEMENT] Add infrastructure_mode variable [#679] +* [IMPROVEMENT] macOS: lift Rosetta 2 translation for Agent 7 in CI [#680] +* [IMPROVEMENT] Remove deprecated deb/rpm installer and support SSI using install-ssi.sh script [#682] +* [IMPROVEMENT] Add IDEs settings to gitignore [#681] +* [IMPROVEMENT] [Windows] Provide users a way to skip and force reinstall of Datadog Agent [#683] +* [IMPROVEMENT] Allow Agent downgrades on Windows [#685] + +# 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] +* [DOCUMENTATION] Adjust misleading macOS Agent version documentation [#676] +* [IMPROVEMENT] Simplify MacOS version architecture [#677] +* [IMPROVEMENT] Update Windows tasks [#675] + +# 5.4.0 / 2025-09-23 +* [IMPROVEMENT] Fix broken conditionals for compatibility with Ansible 2.19 / Ansible 12.0 [#670] + +# 5.3.0 / 2025-09-03 +* [IMPROVEMENT] Support Remote Agent updates through the embedded Datadog Installer (7.69.0+) [#665] + +# 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] +* [IMROVEMENT] [CI] Remove role prefix lint warnings [#660] +* [BUGFIX] [CI] Fix installer tests after 7.66.0 release [#657] + +# 5.2.0 / 2025-05-21 +* [IMPROVEMENT] Add feature to override the Datadog installer default package version [#652] Thanks [@snowman11784] +* [IMPROVEMENT] Add support to override datadog-apm-inject version [#654] + +# 5.1.1 / 2025-05-07 +* [DOCS] Remove centos 6/7 from readme [#647] +* [BUGFIX] Fix typo in fix-parse-version-windows.yml [#648] Thanks [@jacob9423] +* [IMPROVEMENT] [CI] Add FQCN checks to ansible-lint [#650] + +# 5.1.0 / 2025-04-30 +**This role removes support for Ansible Core versions below 2.10.** +* [IMPROVEMENT] Bump ansible-lint to 25.1.2 and fix compatibility issues [#644] +* [IMPROVEMENT] Bump ansible galaxy/lint version [#642] +* [BUGFIX] Fix Windows fqcn error [#645] + +# 5.0.0 / 2025-04-21 +**This role removes support for Python 2 and Agent 5, and bumps the minimum Ansible version for this role to 2.8** Additionally, it no longer supports older versions of Amazon Linux 2 and CentOS. While version 4 of the role will continue to receive backport updates, Ansible collections corresponding to version 4 of this role (Datadog Ansible Collection v5) will not be updated. We recommend upgrading to the latest version for better support and improvements. + +* [MAJOR] Remove support for Python 2 and Agent 5. [#639] +* [IMPROVEMENT] [CI] Explicitly set use: service to ensure compatibility in CI [#640] +* [IMPROVEMENT] [CI] Fix test_install_downgrade ci failures [#638] + +# 4.30.0 / 2025-04-08 +* [IMPROVEMENT] Add system_probe_other_config as catch all [#634] +* [DOCS] Fix typo [#635] + +# 4.29.0 / 2025-03-03 +* [IMPROVEMENT] Remove deprecated APM deb/rpms [#624] +* [IMPROVEMENT] [CI] Fix MacOS CI [#630] +* [BUGFIX] Fix Ansible check mode when installer/apm injection is enabled [#619] +* [DOCS] Add information for air-gapped installation [#622] +* [CHORE] Transfer ownership to container-ecosystems [#618] +* [CHORE] Remove agent-delivery as CODEOWNER [#629] + +# 4.28.0 / 2024-09-24 +* [IMPROVEMENT] Add ansible managed comment to checks.yaml [#602] +* [BUGFIX] Fix default APM setup [#608] +* [BUGFIX] Fix APM injector ownership logic [#604] +* [IMPROVEMENT] Allow pinned version of the agent with the installer [#605] +* [BUGFIX] Fix updated list of APM packages to install [#607] +* [BUGFIX] Fix role crash when pinning the agent version with the installer enabled [#609] +* [BUGFIX] Don't create system-probe config when it is disabled [#611] +* [BUGFIX] Fix distribution version detection on Amazon Linux 2023 [#612] + +# 4.27.0 / 2024-08-26 +* [BUGFIX] Process apm list again [#600] + +# 4.26.0 / 2024-08-19 +* [IMPROVEMENT] datadog-installer registry support [#596] +* [BUGFIX] Fix the datadog-installer on openSUSE [#594] + +# 4.25.0 / 2024-08-06 +* [BUGFIX] Correctly install datadog-installer on RHEL derivatives [#587] +* [BUGFIX] Enable datadog-installer when remote_updates is true [#588] +* [BUGFIX] Fix security-agent.yaml generation [#591] +* [BUGFIX] Don't install datadog-agent when owned by datadog-installer [#589] +* [BUGFIX] Fix APM config when owned by datadog-installer [#590] +* [IMPROVEMENT] Speed up conf.d checks [#584] +* [IMPROVEMENT] Don't sort configuration keys [#577] + +# 4.24.0 / 2024-07-18 +* [FEATURE] creating install.json file related to apm single step instrumation [#572] +* [FEATURE] add support for datadog-installer [#573] +* [FEATURE] add new future GPG key following 2024 GPG key rotation [#568] +* [BUGFIX] Correctly read install.json on remote computer [#575] +* [BUGFIX] Disable logging of datadog_windows_ddagentuser_password [#563]. Thanks [@a-rhodes] +* [BUGFIX] Use install.datadoghq.com instead of the dd-agent bucket link [#576] +* [BUGFIX] Fix ansible-lint warnings on latest version [#578] +* [DOCS] Update broken Ansible Galaxy URLs [#580] Thanks [@kaveet] +* [DOCS] README: fix broken links to ansible-galaxy [#571] + +# 4.23.0 / 2024-06-04 +* [FEATURE] Add version pinning and telemetry for APM tracer libraries [#541] +* [FEATURE] Allow using proxy for Windows downloads [#553] +* [IMPROVEMENT] Restrict the Agent version that can be installed on RHEL (and derivatives) < 7 [#556] +* [IMPROVEMENT] Install old RPM GPG key only when needed on Agent <= 7.35 [#561] +* [BUGFIX] Change `mode` to use string parameters [#528], thanks [@janorn] +* [BUGFIX] Allow 160 character long lines before wrapping [#529], thanks [@janorn] +* [BUGFIX] Properly detect when DEB package is installed [#551] +* [BUGFIX] Fix idempotency molecule test on Windows [#560] +* [BUGFIX] Remove `warn` argument that is not supported in newer Ansible versions [#566] +* [DOCS] Fix inter-readme links for integrations [#546], thanks [@valscion] +* [DOCS] Clarify that role variables are set in the `vars` section of the playbook [#550] +* [DOCS] [DOCS-7475] Replace install command for Windows [#559] + +# 4.22.0 / 2024-01-25 +* [IMPROVEMENT] Use Get-ItemProperty to retrieve Windows Agent version [#536] +* [DOCS] Add a note about required API Key since 4.21 [#538] + +# 4.21.0 / 2023-12-04 +* [FEATURE] [Windows] [AP-1946] Force reinstall if configuration changed [#509] +* [FEATURE] Adding yum repo configuration options [#517] thanks [@chipselden] +* [IMPROVEMENT] Remove usage of datadog-apm-library-all meta package, to make sure Ansible keeps updating the tracer packages if "all" is used in Ansible configuration [#532] +* [IMPROVEMENT] [CI] add call to importer in the role [#515] +* [IMPROVEMENT] [AP-2380] Hard fail if api_key is not provided [#512], [#505] thanks [@gopivalleru] +* [IMPROVEMENT] Bump XCode version from 13.3.0 to 13.4.1 [#511] +* [BUGFIX] correct syntax when checking for config changes [#523] thanks [@TomFromTA] +* [DOCS] [DOCS-6354] Update descriptions for APM role values [#520] +* [DOCS] [README] Add openSUSE/SLES `community.general` install instruction [#513] + +# 4.20.1 / 2023-07-20 +* [CI] Add `empty-string-compare` rule to ansible-lint [#506] + +# 4.20.0 / 2023-07-18 + +* [FEATURE] Add support for configuring APM injection. See [#481]. +* [FEATURE] Add support for `compliance_config`. See [#488]. +* [IMPROVEMENT] Add an option to delete example check configs. See [#459]. Thanks [@rockaut]. +* [IMPROVEMENT] Add new APT and RPM signing keys for the 2024 key rotation. See [#485]. +* [BUGFIX] Make the `ansible.windows` collection optional again by refactoring integration-related tasks. See [#483]. +* [BUGFIX] Modify integration updates task to prevent always changed status. See [#486]. +* [DOCS] Clarifications on downgrade and integrations configuration. See [#501]. + +# 4.19.0 / 2023-05-10 + +* [IMPROVEMENT] Ensure user selected for macOS systemwide installation actually exists. See [#479]. +* [BUGFIX] Refresh Datadog repository cache on Red Hat family systems to ensure DNF properly imports repodata signing keys to its cache. See [#478]. + +# 4.18.0 / 2023-01-12 + +* [DEPRECATION] Remove the old RPM GPG key 4172A230 from hosts that still trust it. This also removes the configuration variables `datadog_yum_gpgkey`, `datadog_zypper_gpgkey` and `datadog_zypper_gpgkey_sha256sum`. See [#466]. + +# 4.17.0 / 2023-01-04 + +* [FEATURE] Add support for Universal Service Monitoring sysprobe configuration. See [#458]. Thanks [@marcus-crane]. +* [IMPROVEMENT] Lock Agent version using `includepkgs` in repofiles on Red Hat compatible platforms. See [#443]. Thanks [@sspans-sbp]. +* [IMPROVEMENT] Prettify and fix yaml indentations. See [#448]. Thanks [@denzhel]. +* [IMPROVEMENT] Add the possibility to prevent the zypper repository installation. See [#452]. Thanks [@jb-mayer]. +* [IMPROVEMENT] Use `ansible_managed` instead of custom hardcoded message in managed files. See [#454]. Thanks [@jlosito]. +* [BUGFIX] Fix version comparison tasks when using ansible-core RC version. See [#446]. +* [BUGFIX] Fix running role multiple times in a row on SUSE compatible platforms. See [#453]. +* [DOCS] Add troubleshooting instructions about `service_facts` breaking Ubuntu 20.04. See [#449]. +* [DOCS] Clarify `datadog_config` behavior. See [#451]. Thanks [@hestonhoffman]. + +# 4.16.0 / 2022-07-11 +* [FEATURE] Add macOS support. See [#437]. Thanks [@lc-applause]. +* [BUGFIX] Remove temporary directory after APT key import. See [#442]. Thanks [@wisnij]. +* [BUGFIX] Prevent security-agent startup if it's not configured. See [#438]. + +# 4.15.0 / 2022-04-20 + +* [IMPROVEMENT] Switch Agent start mode to delayed on Windows. See [#422]. +* [BUGFIX] Fix installation of a newer pinned version by DNF. See [#429]. + +# 4.14.0 / 2022-02-08 + +* [FEATURE] Add tasks for creating custom Python checks. See [#408]. Thanks [@snorlaX-sleeps]. +* [FEATURE] Support Rocky Linux and AlmaLinux. See [#418]. +* [BUGFIX] Fix provisioning on Python 3 / Amazon Linux 2. See [#412]. Thanks [@moleskin-smile]. +* [BUGFIX] Prevent dependency on `ansible.windows` with non-Windows nodes. See [#416]. +* [BUGFIX] Don't display content of `DDAGENTUSER_PASSWORD` for Windows nodes. See [#415]. +* [BUGFIX] Additional fixes for `jinja2_native = True` setting. See [#414]. + +# 4.13.0 / 2022-01-21 + +* [FEATURE] Add datadog_manage_config to disable changing the Agent config files. See [#410]. +* [BUGFIX] Fix error: dict object has no attribute 'system'. See [#409]. Thanks [@stegar123]. + +# 4.12.0 / 2021-11-03 + +* [FEATURE] Add Cloud Workload Security Agent configuration. See [#375]. Thanks [@alsmola]. +* [IMPROVEMENT] Avoid usage of `ansible_lsb` to not depend on `lsb-release` package on Debian. See [#377]. +* [IMPROVEMENT] Check that `datadog_checks` is a mapping to avoid misconfiguration. See [#384]. Thanks [@soar]. +* [IMPROVEMENT] Enable turning off the Agent 6.14 fix for Windows. See [#399]. +* [DOCS] Mention limitations in enabling NPM on Windows. See [#396]. +* [BUGFIX] Fix execution with `jinja2_native = True`. See [#383]. Thanks [@soar]. + +# 4.11.0 / 2021-07-05 + +* [IMPROVEMENT] Install datadog-signing-keys package on Debian/Ubuntu. See [#372]. +* [IMPROVEMENT] Skip install on Linux systems when pinned version is already installed. See [#371]. +* [IMPROVEMENT] Update 'http' URLs to 'https' wherever possible. See [#369].Thanks [@rossigee]. +* [BUGFIX] Detect existing version in check mode on Windows. See [#364]. Thanks [@camjay]. + +# 4.10.0 / 2021-05-25 + +* [IMPROVEMENT] Make Windows package download behavior in check mode consistent with Linux. See [#359]. Thanks [@camjay]. +* [BUGFIX] Remove `indentfirst` in system-probe.yaml.j2, making the role compatible with Jinja2 >= 3. See [#361]. Thanks [@tasktop-teho]. +* [BUGFIX] Ensure gnupg is installed on Debian/Ubuntu. See [#358]. + +# 4.9.0 / 2021-05-06 + +* [IMPROVEMENT] Improvements for APT keys management. See [#351]. + * By default, get keys from keys.datadoghq.com, not the 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`. +* [BUGFIX] Don't set `repo_gpgcheck=1` by default on RHEL/CentOS 8.1 and on custom repos. See [#352]. +* [BUGFIX] Change RPM key URLs to non-SNI versions to ensure the role continues to work with Python <= 2.7.9. See [#353]. +* [DOCS] Add a note about installing marketplace integrations. See [#354]. + +# 4.8.2 / 2021-04-21 + +* [BUGFIX] Another fix for agent not restarting after a configuration change on Windows. See [#349]. + +# 4.8.1 / 2021-04-19 + +* [BUGFIX] Fix Agent not restarting after a configuration change on Windows. See [#347]. + +# 4.8.0 / 2021-04-13 + +* [FEATURE] Add NPM support for Windows. See [#335]. +* [IMPROVEMENT] Split Windows handler into its own file, so we don't include anything from ansible.windows on non-Windows; add a note about the dependency on `ansible.windows`. See [#337]. +* [IMPROVEMENT] Turn on `repo_gpgcheck` on RPM repositories by default. See [#341]. +* [IMPROVEMENT] Align Windows agent to Linux so that service is disabled when `datadog_enabled` is `false`. See [#338]. Thanks [@erikhjensen]. +* [BUGFIX] Fix system-probe enablement conditions. See [#336]. +* [CHORE] Fix issues found by linter (fix file permissions, add `role_name` and `namespace` to `galaxy_info`, remove pre/post tasks). See [#340]. + +# 4.7.1 / 2021-03-23 + +* [BUGFIX] Revert addition of NPM support for Windows, which introduced multiple issues. See [#333]. + +# 4.7.0 / 2021-03-23 + +* [FEATURE] Enable configuring `gpgcheck` option on RPM repofiles. See [#324]. +* [FEATURE] Add NPM support for Windows. See [#326]. +* [IMPROVEMENT] Implement usage of multiple GPG keys in repofiles, use keys from keys.datadoghq.com. See [#325]. +* [BUGFIX] Use the `dnf` task instead of `yum` when we detect that a Python 3 interpreter is used on a target host. See [#301]. +* [DOCS] Lint README for Documentation style. See [#327]. + +# 4.6.0 / 2021-01-11 + +* [FEATURE] Allow removing checks. See [#151] and [#320]. Thanks [@Jno21]. +* [BUGFIX] Make security-agent also affected by datadog_enabled. See [#318]. +* [BUGFIX] Change configuration perms on Linux. See [#313]. Thanks [@loliee]. +* [CHORE] Do not name the RPM repo file differently depending on the Agent version. See [#311]. +* [CHORE] Replace facts from 'ansible_*' to using 'ansible_facts' dictionary. See [#304]. Thanks to [@samasc30]. + +# 4.5.0 / 2020-11-06 + +* [FEATURE] (Windows) Adds support for non-default installation and configuration directories. See [#295][]. +* [BUGFIX] Fixes handling of nil vs. defined but empty variables. See [#303][]. +* [BUGFIX] (Windows) Fixes incorrect service name when validating services. See [#307][]. +* [FEATURE] Adds support for the latest package signing keys. See [#308][]. +* [FEATURE] Adds support for the Datadog IOT agent. See [#309][]. + # 4.4.0 / 2020-09-30 * [BUGFIX] (Windows) Fix compatibility with Ansible 2.10. See [#289][]. @@ -53,7 +325,7 @@ CHANGELOG * [BUGFIX] Fix system-probe.yaml.j2 indent filter. See [#240][] * [BUGFIX] Fix sysprobe service detection for systemd services. See [#242][] * [OTHER] Improve ansible-galaxy score by following best practices. See [#236][] -* [OTHER] Include names for `include_tasks`. See [#226][]. Thanks to [@the-real-cphilips][]. +* [OTHER] Include names for `include_tasks`. See [#226][]. Thanks to [@the-real-cphillips][]. # 4.0.0 / 2019-12-18 @@ -208,6 +480,7 @@ Initial release, compatible with Ansible v1 & v2 [#105]: https://github.com/DataDog/ansible-datadog/issues/105 [#107]: https://github.com/DataDog/ansible-datadog/issues/107 [#116]: https://github.com/DataDog/ansible-datadog/issues/116 +[#151]: https://github.com/DataDog/ansible-datadog/issues/151 [#203]: https://github.com/DataDog/ansible-datadog/issues/203 [#220]: https://github.com/DataDog/ansible-datadog/issues/220 [#224]: https://github.com/DataDog/ansible-datadog/issues/224 @@ -239,24 +512,221 @@ Initial release, compatible with Ansible v1 & v2 [#283]: https://github.com/DataDog/ansible-datadog/issues/283 [#289]: https://github.com/DataDog/ansible-datadog/issues/289 [#291]: https://github.com/DataDog/ansible-datadog/issues/291 +[#295]: https://github.com/DataDog/ansible-datadog/issues/295 [#297]: https://github.com/DataDog/ansible-datadog/issues/297 +[#301]: https://github.com/DataDog/ansible-datadog/issues/301 +[#303]: https://github.com/DataDog/ansible-datadog/issues/303 +[#304]: https://github.com/DataDog/ansible-datadog/issues/304 +[#307]: https://github.com/DataDog/ansible-datadog/issues/307 +[#308]: https://github.com/DataDog/ansible-datadog/issues/308 +[#309]: https://github.com/DataDog/ansible-datadog/issues/309 +[#311]: https://github.com/DataDog/ansible-datadog/issues/311 +[#313]: https://github.com/DataDog/ansible-datadog/issues/313 +[#318]: https://github.com/DataDog/ansible-datadog/issues/318 +[#320]: https://github.com/DataDog/ansible-datadog/issues/320 +[#324]: https://github.com/DataDog/ansible-datadog/issues/324 +[#325]: https://github.com/DataDog/ansible-datadog/issues/325 +[#326]: https://github.com/DataDog/ansible-datadog/issues/326 +[#327]: https://github.com/DataDog/ansible-datadog/issues/327 +[#333]: https://github.com/DataDog/ansible-datadog/issues/333 +[#335]: https://github.com/DataDog/ansible-datadog/issues/335 +[#336]: https://github.com/DataDog/ansible-datadog/issues/336 +[#337]: https://github.com/DataDog/ansible-datadog/issues/337 +[#338]: https://github.com/DataDog/ansible-datadog/issues/338 +[#340]: https://github.com/DataDog/ansible-datadog/issues/340 +[#341]: https://github.com/DataDog/ansible-datadog/issues/341 +[#347]: https://github.com/DataDog/ansible-datadog/issues/347 +[#349]: https://github.com/DataDog/ansible-datadog/issues/349 +[#351]: https://github.com/DataDog/ansible-datadog/issues/351 +[#352]: https://github.com/DataDog/ansible-datadog/issues/352 +[#353]: https://github.com/DataDog/ansible-datadog/issues/353 +[#354]: https://github.com/DataDog/ansible-datadog/issues/354 +[#358]: https://github.com/DataDog/ansible-datadog/issues/358 +[#359]: https://github.com/DataDog/ansible-datadog/issues/359 +[#361]: https://github.com/DataDog/ansible-datadog/issues/361 +[#362]: https://github.com/DataDog/ansible-datadog/issues/362 +[#364]: https://github.com/DataDog/ansible-datadog/issues/364 +[#369]: https://github.com/DataDog/ansible-datadog/issues/369 +[#371]: https://github.com/DataDog/ansible-datadog/issues/371 +[#372]: https://github.com/DataDog/ansible-datadog/issues/372 +[#375]: https://github.com/DataDog/ansible-datadog/issues/375 +[#377]: https://github.com/DataDog/ansible-datadog/issues/377 +[#383]: https://github.com/DataDog/ansible-datadog/issues/383 +[#384]: https://github.com/DataDog/ansible-datadog/issues/384 +[#396]: https://github.com/DataDog/ansible-datadog/issues/396 +[#399]: https://github.com/DataDog/ansible-datadog/issues/399 +[#408]: https://github.com/DataDog/ansible-datadog/issues/408 +[#409]: https://github.com/DataDog/ansible-datadog/issues/409 +[#410]: https://github.com/DataDog/ansible-datadog/issues/410 +[#412]: https://github.com/DataDog/ansible-datadog/issues/412 +[#414]: https://github.com/DataDog/ansible-datadog/issues/414 +[#415]: https://github.com/DataDog/ansible-datadog/issues/415 +[#416]: https://github.com/DataDog/ansible-datadog/issues/416 +[#418]: https://github.com/DataDog/ansible-datadog/issues/418 +[#422]: https://github.com/DataDog/ansible-datadog/issues/422 +[#429]: https://github.com/DataDog/ansible-datadog/issues/429 +[#437]: https://github.com/DataDog/ansible-datadog/issues/437 +[#438]: https://github.com/DataDog/ansible-datadog/issues/438 +[#442]: https://github.com/DataDog/ansible-datadog/issues/442 +[#443]: https://github.com/DataDog/ansible-datadog/issues/443 +[#446]: https://github.com/DataDog/ansible-datadog/issues/446 +[#448]: https://github.com/DataDog/ansible-datadog/issues/448 +[#449]: https://github.com/DataDog/ansible-datadog/issues/449 +[#451]: https://github.com/DataDog/ansible-datadog/issues/451 +[#452]: https://github.com/DataDog/ansible-datadog/issues/452 +[#453]: https://github.com/DataDog/ansible-datadog/issues/453 +[#454]: https://github.com/DataDog/ansible-datadog/issues/454 +[#458]: https://github.com/DataDog/ansible-datadog/issues/458 +[#459]: https://github.com/DataDog/ansible-datadog/pull/459 +[#466]: https://github.com/DataDog/ansible-datadog/issues/466 +[#478]: https://github.com/DataDog/ansible-datadog/issues/478 +[#479]: https://github.com/DataDog/ansible-datadog/issues/479 +[#481]: https://github.com/DataDog/ansible-datadog/pull/481 +[#483]: https://github.com/DataDog/ansible-datadog/pull/483 +[#485]: https://github.com/DataDog/ansible-datadog/pull/485 +[#486]: https://github.com/DataDog/ansible-datadog/pull/486 +[#488]: https://github.com/DataDog/ansible-datadog/pull/488 +[#501]: https://github.com/DataDog/ansible-datadog/pull/501 +[#505]: https://github.com/DataDog/ansible-datadog/pull/505 +[#509]: https://github.com/DataDog/ansible-datadog/pull/509 +[#511]: https://github.com/DataDog/ansible-datadog/pull/511 +[#512]: https://github.com/DataDog/ansible-datadog/pull/512 +[#513]: https://github.com/DataDog/ansible-datadog/pull/513 +[#515]: https://github.com/DataDog/ansible-datadog/pull/515 +[#517]: https://github.com/DataDog/ansible-datadog/pull/517 +[#520]: https://github.com/DataDog/ansible-datadog/pull/520 +[#523]: https://github.com/DataDog/ansible-datadog/pull/523 +[#528]: https://github.com/DataDog/ansible-datadog/pull/528 +[#529]: https://github.com/DataDog/ansible-datadog/pull/529 +[#532]: https://github.com/DataDog/ansible-datadog/pull/532 +[#536]: https://github.com/DataDog/ansible-datadog/issues/536 +[#538]: https://github.com/DataDog/ansible-datadog/issues/538 +[#541]: https://github.com/DataDog/ansible-datadog/pull/541 +[#546]: https://github.com/DataDog/ansible-datadog/pull/546 +[#550]: https://github.com/DataDog/ansible-datadog/pull/550 +[#551]: https://github.com/DataDog/ansible-datadog/pull/551 +[#553]: https://github.com/DataDog/ansible-datadog/pull/553 +[#556]: https://github.com/DataDog/ansible-datadog/pull/556 +[#559]: https://github.com/DataDog/ansible-datadog/pull/559 +[#560]: https://github.com/DataDog/ansible-datadog/pull/560 +[#561]: https://github.com/DataDog/ansible-datadog/pull/561 +[#563]: https://github.com/DataDog/ansible-datadog/pull/563 +[#566]: https://github.com/DataDog/ansible-datadog/pull/566 +[#568]: https://github.com/DataDog/ansible-datadog/pull/568 +[#571]: https://github.com/DataDog/ansible-datadog/pull/571 +[#572]: https://github.com/DataDog/ansible-datadog/pull/572 +[#573]: https://github.com/DataDog/ansible-datadog/pull/573 +[#575]: https://github.com/DataDog/ansible-datadog/pull/575 +[#576]: https://github.com/DataDog/ansible-datadog/pull/576 +[#577]: https://github.com/DataDog/ansible-datadog/pull/577 +[#578]: https://github.com/DataDog/ansible-datadog/pull/578 +[#584]: https://github.com/DataDog/ansible-datadog/pull/584 +[#587]: https://github.com/DataDog/ansible-datadog/pull/587 +[#588]: https://github.com/DataDog/ansible-datadog/pull/588 +[#589]: https://github.com/DataDog/ansible-datadog/pull/589 +[#590]: https://github.com/DataDog/ansible-datadog/pull/590 +[#591]: https://github.com/DataDog/ansible-datadog/pull/591 +[#594]: https://github.com/DataDog/ansible-datadog/pull/594 +[#596]: https://github.com/DataDog/ansible-datadog/pull/596 +[#600]: https://github.com/DataDog/ansible-datadog/pull/600 +[#602]: https://github.com/DataDog/ansible-datadog/pull/602 +[#604]: https://github.com/DataDog/ansible-datadog/pull/604 +[#605]: https://github.com/DataDog/ansible-datadog/pull/605 +[#607]: https://github.com/DataDog/ansible-datadog/pull/607 +[#608]: https://github.com/DataDog/ansible-datadog/pull/608 +[#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 +[#619]: https://github.com/DataDog/ansible-datadog/pull/619 +[#622]: https://github.com/DataDog/ansible-datadog/pull/622 +[#624]: https://github.com/DataDog/ansible-datadog/pull/624 +[#629]: https://github.com/DataDog/ansible-datadog/pull/629 +[#630]: https://github.com/DataDog/ansible-datadog/pull/630 +[#634]: https://github.com/DataDog/ansible-datadog/pull/634 +[#635]: https://github.com/DataDog/ansible-datadog/pull/635 +[#638]: https://github.com/DataDog/ansible-datadog/pull/638 +[#639]: https://github.com/DataDog/ansible-datadog/pull/639 +[#640]: https://github.com/DataDog/ansible-datadog/pull/640 +[#642]: https://github.com/DataDog/ansible-datadog/pull/642 +[#644]: https://github.com/DataDog/ansible-datadog/pull/644 +[#645]: https://github.com/DataDog/ansible-datadog/pull/645 +[#647]: https://github.com/DataDog/ansible-datadog/pull/647 +[#648]: https://github.com/DataDog/ansible-datadog/pull/648 +[#650]: https://github.com/DataDog/ansible-datadog/pull/650 +[#652]: https://github.com/DataDog/ansible-datadog/pull/652 +[#654]: https://github.com/DataDog/ansible-datadog/pull/654 +[#655]: https://github.com/DataDog/ansible-datadog/pull/655 +[#657]: https://github.com/DataDog/ansible-datadog/pull/657 +[#658]: https://github.com/DataDog/ansible-datadog/pull/658 +[#659]: https://github.com/DataDog/ansible-datadog/pull/659 +[#660]: https://github.com/DataDog/ansible-datadog/pull/660 +[#664]: https://github.com/DataDog/ansible-datadog/pull/664 +[#665]: https://github.com/DataDog/ansible-datadog/pull/665 +[#670]: https://github.com/DataDog/ansible-datadog/pull/670 +[#673]: https://github.com/DataDog/ansible-datadog/pull/673 +[#674]: https://github.com/DataDog/ansible-datadog/pull/674 +[#675]: https://github.com/DataDog/ansible-datadog/pull/675 +[#676]: https://github.com/DataDog/ansible-datadog/pull/676 +[#677]: https://github.com/DataDog/ansible-datadog/pull/677 +[#677]: https://github.com/DataDog/ansible-datadog/pull/679 +[#680]: https://github.com/DataDog/ansible-datadog/pull/680 +[#681]: https://github.com/DataDog/ansible-datadog/pull/681 +[#682]: https://github.com/DataDog/ansible-datadog/pull/682 +[#683]: https://github.com/DataDog/ansible-datadog/pull/683 +[#685]: https://github.com/DataDog/ansible-datadog/pull/685 +[#686]: https://github.com/DataDog/ansible-datadog/pull/686 +[#690]: https://github.com/DataDog/ansible-datadog/pull/690 +[#693]: https://github.com/DataDog/ansible-datadog/pull/693 +[#694]: https://github.com/DataDog/ansible-datadog/pull/694 [@DevKyleS]: https://github.com/DevKyleS +[@Jno21]: https://github.com/Jno21 +[@alsmola]: https://github.com/alsmola [@b2jrock]: https://github.com/b2jrock [@brendanlong]: https://github.com/brendanlong +[@camjay]: https://github.com/camjay [@dbr1993]: https://github.com/dbr1993 +[@denzhel]: https://github.com/denzhel [@dv9io0o]: https://github.com/dv9io0o [@enarciso]: https://github.com/enarciso [@eplanet]: https://github.com/eplanet +[@erikhjensen]: https://github.com/erikhjensen [@geoffwright]: https://github.com/geoffwright [@gtrummell]: https://github.com/gtrummell +[@hestonhoffman]: https://github.com/hestonhoffman +[@janorn]: https://github.com/janorn +[@jb-mayer]: https://github.com/jb-mayer [@jeffwidman]: https://github.com/jeffwidman [@jharley]: https://github.com/jharley +[@jlosito]: https://github.com/jlosito [@jpiron]: https://github.com/jpiron [@jstoja]: https://github.com/jstoja [@kanga333]: https://github.com/kanga333 +[@lc-applause]: https://github.com/lc-applause +[@loliee]: https://github.com/loliee +[@marcus-crane]: https://github.com/marcus-crane +[@moleskin-smile]: https://github.com/moleskin-smile [@pdecat]: https://github.com/pdecat [@pmbauer]: https://github.com/pmbauer +[@rockaut]: https://github.com/rockaut +[@rossigee]: https://github.com/rossigee [@rouge8]: https://github.com/rouge8 -[@the-real-cphilips]: https://github.com/the-real-cphilips +[@samasc30]: https://github.com/samasc30 +[@snorlaX-sleeps]: https://github.com/snorlaX-sleeps +[@soar]: https://github.com/soar +[@sspans-sbp]: https://github.com/sspans-sbp +[@stegar123]: https://github.com/stegar123 +[@tasktop-teho]: https://github.com/tasktop-teho +[@the-real-cphillips]: https://github.com/the-real-cphillips [@tomgoren]: https://github.com/tomgoren +[@wisnij]: https://github.com/wisnij [@xp-1000]: https://github.com/xp-1000 +[@TomFromTA]: https://github.com/TomFromTA +[@chipselden]: https://github.com/chipselden +[@gopivalleru]: https://github.com/gopivalleru +[@valscion]: https://github.com/valscion +[@a-rhodes]: https://github.com/a-rhodes +[@kaveet]: https://github.com/kaveet +[@jacob9423]: https://github.com/jacob9423 +[@snowman11784]: https://github.com/snowman11784 +[@POIFischbacher]: https://github.com/POIFischbacher diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f39fdf53..d87884ee 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ The code is licensed under the Apache License 2.0 (see LICENSE for details). -[![Ansible Galaxy](http://img.shields.io/badge/galaxy-Datadog.datadog-660198.svg)](https://galaxy.ansible.com/Datadog/datadog/) +[![Ansible Galaxy](https://img.shields.io/badge/galaxy-Datadog.datadog-660198.svg)](https://galaxy.ansible.com/Datadog/datadog/) [![Build Status](https://travis-ci.org/DataDog/ansible-datadog.svg?branch=master)](https://travis-ci.org/DataDog/ansible-datadog) First of all, thanks for contributing! @@ -52,52 +52,7 @@ To contribute, follow the contributing guidelines above. To test the roles provided by this project, you can follow the instructions in the manual tests [readme.md][tests]. -### Integration testing - -This project uses [Kitchen][kitchen] as an integration tests engine. To verify integration tests, install [Vagrant][vagrant] on your machine. - -Kitchen allows you to test specific recipes described in [kitchen.yml][kitchen_yml]. There is only one basic recipe on ubuntu but that should be enough to develop others or to add features in TDD. - -To list available targets, you can use the `list` command: - -```bash -bundle exec kitchen list -``` - -To test a specific target, you can run: - -```bash -bundle exec kitchen test -``` - -So for example, if you want to test the agent installation, you can run: - -```bash -bundle exec kitchen test default-ubuntu-1810 -``` - -### Development loop - -To develop some fixes or some features, the easiest way is to work on the platform and version of your choice, setting the machine up with the `create` command and applying the recipe with the `converge` command. If you want to explore the machine and try different things, you can also login into the machine with the `login` command. - -```bash -# Create the relevant vagrant virtual machine -bundle exec kitchen create default-ubuntu-1810 - -# Converge to test your recipe -bundle exec kitchen converge default-ubuntu-1810 - -# Login to your machine to check stuff -bundle exec kitchen login default-ubuntu-1810 - -# Verify the integration tests for your machine -bundle exec kitchen verify default-ubuntu-1810 - -# Clean your machine -bundle exec kitchen destroy default-ubuntu-1810 -``` - -It is advised that you work in TDD and that you write tests before making changes so that developing your feature or fix is just making tests pass. +You can also check locally if your changes still validate the ansible collection linter by executing ``ci_test/collection-structure-setup.sh``. ## Author Information @@ -108,8 +63,5 @@ dustinjamesbrown@gmail.com --Forked from brian@akins.org Datadog --Forked from dustinjamesbrown@gmail.com -[kitchen]: https://kitchen.ci -[kitchen_yml]: https://github.com/DataDog/ansible-datadog/blob/master/kitchen.yml -[slack]: http://datadoghq.slack.com +[slack]: https://datadoghq.slack.com [tests]: https://github.com/DataDog/ansible-datadog/blob/master/manual_tests/readme.md -[vagrant]: https://www.vagrantup.com diff --git a/Gemfile b/Gemfile deleted file mode 100644 index 04bbd66b..00000000 --- a/Gemfile +++ /dev/null @@ -1,13 +0,0 @@ -source 'https://rubygems.org' - -group :development do - gem 'rake' - gem 'chef', '= 14.10.9' - gem 'chefspec' - gem 'test-kitchen' - gem 'json_spec', '~> 1.1.0' - gem 'kitchen-ansible' - gem 'kitchen-vagrant' - gem 'rack', '>= 2.1.4' - gem 'serverspec' -end diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index b5df25dc..00000000 --- a/Gemfile.lock +++ /dev/null @@ -1,269 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - addressable (2.7.0) - public_suffix (>= 2.0.2, < 5.0) - bcrypt_pbkdf (1.0.1) - builder (3.2.4) - chef (14.10.9) - addressable - bundler (>= 1.10) - chef-config (= 14.10.9) - chef-zero (>= 13.0) - diff-lcs (~> 1.2, >= 1.2.4) - erubis (~> 2.7) - ffi (~> 1.9, >= 1.9.25) - ffi-yajl (~> 2.2) - highline (~> 1.6, >= 1.6.9) - iniparse (~> 1.4) - mixlib-archive (>= 0.4, < 2.0) - mixlib-authentication (~> 2.1) - mixlib-cli (~> 1.7) - mixlib-log (~> 2.0, >= 2.0.3) - mixlib-shellout (~> 2.4) - net-sftp (~> 2.1, >= 2.1.2) - net-ssh (~> 4.2) - net-ssh-multi (~> 1.2, >= 1.2.1) - ohai (~> 14.0) - plist (~> 3.2) - proxifier (~> 1.0) - rspec-core (~> 3.5) - rspec-expectations (~> 3.5) - rspec-mocks (~> 3.5) - rspec_junit_formatter (~> 0.2.0) - serverspec (~> 2.7) - specinfra (~> 2.10) - syslog-logger (~> 1.6) - uuidtools (~> 2.1.5) - chef-cli (2.0.10) - addressable (>= 2.3.5, < 2.8) - chef (>= 14.0) - cookbook-omnifetch (~> 0.5) - diff-lcs (~> 1.0) - ffi-yajl (>= 1.0, < 3.0) - license-acceptance (~> 1.0, >= 1.0.11) - minitar (~> 0.6) - mixlib-cli (>= 1.7, < 3.0) - mixlib-shellout (>= 2.0, < 4.0) - paint (>= 1, < 3) - solve (> 2.0, < 5.0) - chef-config (14.10.9) - addressable - fuzzyurl - mixlib-config (>= 2.2.12, < 3.0) - mixlib-shellout (~> 2.0) - tomlrb (~> 1.2) - chef-zero (14.0.17) - ffi-yajl (~> 2.2) - hashie (>= 2.0, < 4.0) - mixlib-log (>= 2.0, < 4.0) - rack (~> 2.0, >= 2.0.6) - uuidtools (~> 2.1) - chefspec (9.2.0) - chef (>= 14) - chef-cli - fauxhai-ng (>= 7.5) - rspec (~> 3.0) - cookbook-omnifetch (0.9.1) - mixlib-archive (>= 0.4, < 2.0) - diff-lcs (1.4.4) - ed25519 (1.2.4) - equatable (0.6.1) - erubi (1.9.0) - erubis (2.7.0) - fauxhai-ng (8.2.0) - net-ssh - ffi (1.13.1) - ffi-yajl (2.3.3) - libyajl2 (~> 1.2) - fuzzyurl (0.9.0) - gssapi (1.3.0) - ffi (>= 1.0.1) - gyoku (1.3.1) - builder (>= 2.1.2) - hashie (3.6.0) - highline (1.7.10) - httpclient (2.8.3) - iniparse (1.5.0) - ipaddress (0.8.3) - json_spec (1.1.5) - multi_json (~> 1.0) - rspec (>= 2.0, < 4.0) - kitchen-ansible (0.52.0) - net-ssh (>= 3) - test-kitchen (>= 1.4) - kitchen-vagrant (1.6.1) - test-kitchen (>= 1.4, < 3) - libyajl2 (1.2.0) - license-acceptance (1.0.19) - pastel (~> 0.7) - tomlrb (~> 1.2) - tty-box (~> 0.3) - tty-prompt (~> 0.18) - little-plugger (1.1.4) - logging (2.3.0) - little-plugger (~> 1.1) - multi_json (~> 1.14) - minitar (0.9) - mixlib-archive (1.0.5) - mixlib-log - mixlib-authentication (2.1.1) - mixlib-cli (1.7.0) - mixlib-config (2.2.18) - tomlrb - mixlib-install (3.12.1) - mixlib-shellout - mixlib-versioning - thor - mixlib-log (2.0.9) - mixlib-shellout (2.4.4) - mixlib-versioning (1.2.12) - molinillo (0.6.6) - multi_json (1.14.1) - necromancer (0.5.1) - net-scp (3.0.0) - net-ssh (>= 2.6.5, < 7.0.0) - net-sftp (2.1.2) - net-ssh (>= 2.6.5) - net-ssh (4.2.0) - net-ssh-gateway (2.0.0) - net-ssh (>= 4.0.0) - net-ssh-multi (1.2.1) - net-ssh (>= 2.6.5) - net-ssh-gateway (>= 1.2.0) - net-telnet (0.1.1) - nori (2.6.0) - ohai (14.15.0) - chef-config (>= 12.8, < 15) - ffi (~> 1.9) - ffi-yajl (~> 2.2) - ipaddress - mixlib-cli (>= 1.7.0) - mixlib-config (>= 2.0, < 4.0) - mixlib-log (>= 2.0.1, < 4.0) - mixlib-shellout (>= 2.0, < 4.0) - plist (~> 3.1) - systemu (~> 2.6.4) - wmi-lite (~> 1.0) - paint (2.2.0) - pastel (0.7.4) - equatable (~> 0.6) - tty-color (~> 0.5) - plist (3.5.0) - proxifier (1.0.3) - public_suffix (4.0.5) - rack (2.2.3) - rake (13.0.1) - rspec (3.9.0) - rspec-core (~> 3.9.0) - rspec-expectations (~> 3.9.0) - rspec-mocks (~> 3.9.0) - rspec-core (3.9.2) - rspec-support (~> 3.9.3) - rspec-expectations (3.9.2) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) - rspec-its (1.3.0) - rspec-core (>= 3.0.0) - rspec-expectations (>= 3.0.0) - rspec-mocks (3.9.1) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) - rspec-support (3.9.3) - rspec_junit_formatter (0.2.3) - builder (< 4) - rspec-core (>= 2, < 4, != 2.12.0) - rubyntlm (0.6.2) - rubyzip (2.3.0) - semverse (3.0.0) - serverspec (2.41.5) - multi_json - rspec (~> 3.0) - rspec-its - specinfra (~> 2.72) - sfl (2.3) - solve (4.0.3) - molinillo (~> 0.6) - semverse (>= 1.1, < 4.0) - specinfra (2.82.17) - net-scp - net-ssh (>= 2.7) - net-telnet (= 0.1.1) - sfl - strings (0.1.8) - strings-ansi (~> 0.1) - unicode-display_width (~> 1.5) - unicode_utils (~> 1.4) - strings-ansi (0.2.0) - syslog-logger (1.6.8) - systemu (2.6.5) - test-kitchen (2.5.2) - bcrypt_pbkdf (~> 1.0) - ed25519 (~> 1.2) - license-acceptance (~> 1.0, >= 1.0.11) - mixlib-install (~> 3.6) - mixlib-shellout (>= 1.2, < 4.0) - net-scp (>= 1.1, < 4.0) - net-ssh (>= 2.9, < 7.0) - net-ssh-gateway (>= 1.2, < 3.0) - thor (>= 0.19, < 2.0) - winrm (~> 2.0) - winrm-elevated (~> 1.0) - winrm-fs (~> 1.1) - thor (1.0.1) - tomlrb (1.3.0) - tty-box (0.5.0) - pastel (~> 0.7.2) - strings (~> 0.1.6) - tty-cursor (~> 0.7) - tty-color (0.5.1) - tty-cursor (0.7.1) - tty-prompt (0.21.0) - necromancer (~> 0.5.0) - pastel (~> 0.7.0) - tty-reader (~> 0.7.0) - tty-reader (0.7.0) - tty-cursor (~> 0.7) - tty-screen (~> 0.7) - wisper (~> 2.0.0) - tty-screen (0.8.0) - unicode-display_width (1.7.0) - unicode_utils (1.4.0) - uuidtools (2.1.5) - winrm (2.3.4) - builder (>= 2.1.2) - erubi (~> 1.8) - gssapi (~> 1.2) - gyoku (~> 1.0) - httpclient (~> 2.2, >= 2.2.0.2) - logging (>= 1.6.1, < 3.0) - nori (~> 2.0) - rubyntlm (~> 0.6.0, >= 0.6.1) - winrm-elevated (1.2.1) - erubi (~> 1.8) - winrm (~> 2.0) - winrm-fs (~> 1.0) - winrm-fs (1.3.4) - erubi (~> 1.8) - logging (>= 1.6.1, < 3.0) - rubyzip (~> 2.0) - winrm (~> 2.0) - wisper (2.0.1) - wmi-lite (1.0.5) - -PLATFORMS - ruby - -DEPENDENCIES - chef (= 14.10.9) - chefspec - json_spec (~> 1.1.0) - kitchen-ansible - kitchen-vagrant - rack (>= 2.1.4) - rake - serverspec - test-kitchen - -BUNDLED WITH - 2.1.4 diff --git a/README.md b/README.md index 080f3fdc..f90882da 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,31 @@ -# Ansible Datadog Role +# Datadog Agent Ansible Role -The Ansible Datadog role installs and configures the Datadog Agent and integrations. Version `4` of the role installs the Datadog Agent v7 by default. +The Datadog Agent Ansible role installs and configures the Datadog Agent and integrations. + +## Ansible role versus Ansible collection + +The Datadog Agent Ansible role is available through 2 different channels: + +* As part of the Datadog collection, accessible under the [datadog.dd](https://galaxy.ansible.com/ui/repo/published/datadog/dd/) name on Ansible Galaxy (recommended). +* As a standalone role, accessible under the [datadog.datadog](https://galaxy.ansible.com/ui/standalone/roles/DataDog/datadog/) name on Ansible Galaxy (legacy). + +Version `4` of the role and version `5` of the collection install the Datadog Agent v7 by default. + +Version `5` of the role and version `6` of the collection no longer support Python 2, Agent 5, or Ansible versions below 2.10. It also no longer supports older versions of Amazon Linux 2 and CentOS. ## Setup +Note that the install instructions in this document describe installation of the standalone Datadog role. For installation instructions of the Datadog collection, please refer to [the collection README file](https://github.com/ansible-collections/Datadog/blob/main/README.md). The configuration variables are the same for both the standalone role as well as the role accessed through the collection. + ### Requirements -- Requires Ansible v2.6+. -- Supports most Debian and RHEL-based Linux distributions, and Windows. +- Requires Ansible v2.10+. +- Supports most Debian and RHEL-based Linux distributions, macOS, and Windows. +- Requires the `ansible.windows` collection to be installed: + ```shell + ansible-galaxy collection install ansible.windows + ``` ### Installation Install the [Datadog role][1] from Ansible Galaxy on your Ansible server: @@ -27,46 +44,72 @@ To deploy the Datadog Agent on hosts, add the Datadog role and your API key to y datadog_api_key: "" ``` -#### Role variables - -| Variable | Description | -|--------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `datadog_api_key` | Your Datadog API key. | -| `datadog_site` | The site of the Datadog intake to send Agent data to. Defaults to `datadoghq.com`, set to `datadoghq.eu` to send data to the EU site. This option is only available with Agent version >= 6.6.0. | -| `datadog_agent_version` | The pinned version of the Agent to install (optional, but recommended), for example: `7.16.0`. Setting `datadog_agent_major_version` is not needed if `datadog_agent_version` is used. **Note**: Downgrades are not supported on Windows platforms. | -| `datadog_agent_major_version` | The major version of the Agent to install. The possible values are 5, 6, or 7 (default). If `datadog_agent_version` is set, it takes precedence otherwise the latest version of the specified major is installed. Setting `datadog_agent_major_version` is not needed if `datadog_agent_version` is used. | -| `datadog_checks` | YAML configuration for Agent checks to drop into:
- `/etc/datadog-agent/conf.d/.d/conf.yaml` for Agent v6 and v7,
- `/etc/dd-agent/conf.d` for Agent v5. | -| `datadog_config` | Settings for the main Agent configuration file:
- `/etc/datadog-agent/datadog.yaml` for Agent v6 and v7,
- `/etc/dd-agent/datadog.conf` for Agent v5 (under the `[Main]` section). | -| `datadog_config_ex` | (Optional) Extra INI sections to go in `/etc/dd-agent/datadog.conf` (Agent v5 only). | -| `datadog_apt_repo` | Override the default Datadog `apt` repository. | -| `datadog_apt_cache_valid_time` | Override the default apt cache expiration time (defaults to 1 hour). | -| `datadog_apt_key_url_new` | Override the default URL to Datadog `apt` key (key ID `382E94DE`; the deprecated `datadog_apt_key_url` variable refers to an expired key that's been removed from the role). | -| `datadog_yum_repo` | Override the default Datadog `yum` repository. | -| `datadog_yum_gpgkey` | Override the default URL to the Datadog `yum` key used to verify Agent v5 and v6 (up to 6.13) packages (key ID `4172A230`). | -| `datadog_yum_gpgkey_e09422b3` | Override the default URL to the Datadog `yum` key used to verify Agent v6.14+ packages (key ID `E09422B3`). | -| `datadog_yum_gpgkey_e09422b3_sha256sum` | Override the default checksum of the `datadog_yum_gpgkey_e09422b3` key. | -| `datadog_zypper_repo` | Override the default Datadog `zypper` repository. | -| `datadog_zypper_gpgkey` | Override the default URL to the Datadog `zypper` key used to verify Agent v5 and v6 (up to 6.13) packages (key ID `4172A230`). | -| `datadog_zypper_gpgkey_sha256sum` | Override the default checksum of the `datadog_zypper_gpgkey` key. | -| `datadog_zypper_gpgkey_e09422b3` | Override the default URL to the Datadog `zypper` key used to verify Agent v6.14+ packages (key ID `E09422B3`). | -| `datadog_zypper_gpgkey_e09422b3_sha256sum` | Override the default checksum of the `datadog_zypper_gpgkey_e09422b3` key. | -| `datadog_agent_allow_downgrade` | Set to `yes` to allow Agent downgrades on apt-based platforms (use with caution, see `defaults/main.yml` for details). **Note**: On Centos this only works with Ansible 2.4+. | -| `use_apt_backup_keyserver` | Set to `true` to use the backup keyserver instead of the default one. | -| `datadog_enabled` | Set to `false` to prevent `datadog-agent` service from starting (defaults to `true`). | -| `datadog_additional_groups` | Either a list, or a string containing a comma-separated list of additional groups for the `datadog_user` (Linux only). | -| `datadog_windows_ddagentuser_name` | The name of Windows user to create/use, in the format `\` (Windows only). | -| `datadog_windows_ddagentuser_password` | The password used to create the user and/or register the service (Windows only). | +The API key is required and its absence causes the role to fail. If you want to provide it through another way, outside of Ansible's control, specify a placeholder key and substitute the key at a later point. + +## Role variables + +These variables provide additional configuration during the installation of the Datadog Agent. They should be specified in the `vars` section of your playbook. + +| Variable | Description | +|---------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `datadog_api_key` | Your Datadog API key. **This variable is mandatory starting from 4.21**.| +| `datadog_site` | The site of the Datadog intake to send Agent data to. Defaults to `datadoghq.com`, set to `datadoghq.eu` to send data to the EU site. This option is only available with Agent version >= 6.6.0.| +| `datadog_agent_flavor` | Override the default Debian / RedHat Package for IOT Installations on RPI. Defaults to "datadog-agent" - use "datadog-iot-agent" for RPI.| +| `datadog_agent_version` | The pinned version of the Agent to install (optional, but recommended), for example: `7.16.0`. Setting `datadog_agent_major_version` is not needed if `datadog_agent_version` is used.| +| `datadog_agent_major_version` | The major version of the Agent to install. The possible values are 6 or 7 (default). If `datadog_agent_version` is set, it takes precedence otherwise the latest version of the specified major is installed. Setting `datadog_agent_major_version` is not needed if `datadog_agent_version` is used.| +| `datadog_checks` | YAML configuration for Agent checks to drop into:
- `/etc/datadog-agent/conf.d/.d/conf.yaml` for Agent v6 and v7.| +| `datadog_disable_untracked_checks` | Set to `true` to remove all checks not present in `datadog_checks` and `datadog_additional_checks`.| +| `datadog_additional_checks` | List of additional checks that are not removed if `datadog_disable_untracked_checks` is set to `true`.| +| `datadog_disable_default_checks` | Set to `true` to remove all default checks.| +| `datadog_config` | Set configuration for the Datadog Agent. The role writes the config to the [correct location based on the operating system](https://docs.datadoghq.com/agent/guide/agent-configuration-files/?tab=agentv6v7#agent-main-configuration-file). For a full list of config options, see [the `datadog.yaml` template file in the datadog-agent GitHub repository](https://github.com/DataDog/datadog-agent/blob/main/pkg/config/config_template.yaml).| +| `datadog_config_ex` | (Optional) Extra INI sections to go in `/etc/dd-agent/datadog.conf` (Agent v5 only).| +| `datadog_apt_repo` | Override the default Datadog `apt` repository. Make sure to use the `signed-by` option if repository metadata is signed using Datadog's signing keys: `deb [signed-by=/usr/share/keyrings/datadog-archive-keyring.gpg] https://yourrepo`.| +| `datadog_apt_cache_valid_time` | Override the default apt cache expiration time (defaults to 1 hour).| +| `datadog_apt_key_url_new` | Override the location from which to obtain Datadog `apt` key (the deprecated `datadog_apt_key_url` variable refers to an expired key that's been removed from the role). The URL is expected to be a GPG keyring containing keys `382E94DE`, `F14F620E` and `C0962C7D`.| +| `datadog_yum_repo_config_enabled` | Set to `false` to prevent the configuration of a Datadog `yum` repository (defaults to `true`). WARNING: it deactivates the automatic update of GPG keys.| +| `datadog_yum_repo` | Override the default Datadog `yum` repository.| +| `datadog_yum_repo_proxy` | Set a proxy URL to use in the Datadog `yum` repo configuration.| +| `datadog_yum_repo_proxy_username` | Set a proxy username to use in the Datadog `yum` repo configuration.| +| `datadog_yum_repo_proxy_password` | Set a proxy password to use in the Datadog `yum` repo configuration.| +| `datadog_yum_repo_gpgcheck` | Override the default `repo_gpgcheck` value (empty). If empty, value is dynamically set to `yes` when custom `datadog_yum_repo` is not used and system is not RHEL/CentOS 8.1 (due to [a bug](https://bugzilla.redhat.com/show_bug.cgi?id=1792506) in dnf), otherwise it's set to `no`. | +| `datadog_yum_gpgcheck` | Override the default `gpgcheck` value (`yes`) - use `no` to turn off package GPG signature verification.| +| `datadog_yum_gpgkey` | **Removed in version 4.18.0** Override the default URL to the Datadog `yum` key used to verify Agent v6 (up to 6.13) packages (key ID `4172A230`).| +| `datadog_yum_gpgkey_e09422b3` | Override the default URL to the Datadog `yum` key used to verify Agent v6.14+ packages (key ID `E09422B3`).| +| `datadog_yum_gpgkey_e09422b3_sha256sum` | Override the default checksum of the `datadog_yum_gpgkey_e09422b3` key.| +| `datadog_zypper_repo` | Override the default Datadog `zypper` repository.| +| `datadog_zypper_repo_gpgcheck` | Override the default `repo_gpgcheck` value (empty). If empty, value is dynamically set to `yes` when custom `datadog_zypper_repo` is not used, otherwise it's set to `no`. | +| `datadog_zypper_gpgcheck` | Override the default `gpgcheck` value (`yes`) - use `no` to turn off package GPG signature verification.| +| `datadog_zypper_gpgkey` | **Removed in version 4.18.0** Override the default URL to the Datadog `zypper` key used to verify Agent v6 (up to 6.13) packages (key ID `4172A230`).| +| `datadog_zypper_gpgkey_sha256sum` | **Removed in version 4.18.0** Override the default checksum of the `datadog_zypper_gpgkey` key.| +| `datadog_zypper_gpgkey_e09422b3` | Override the default URL to the Datadog `zypper` key used to verify Agent v6.14+ packages (key ID `E09422B3`).| +| `datadog_zypper_gpgkey_e09422b3_sha256sum` | Override the default checksum of the `datadog_zypper_gpgkey_e09422b3` key.| +| `datadog_agent_allow_downgrade` | Set to `yes` to allow Agent downgrade (use with caution, see `defaults/main.yml` for details). **Note**: Downgrades are not supported on Windows platforms.| +| `datadog_enabled` | Set to `false` to prevent `datadog-agent` service from starting (defaults to `true`).| +| `datadog_additional_groups` | Either a list, or a string containing a comma-separated list of additional groups for the `datadog_user` (Linux only).| +| `datadog_windows_ddagentuser_name` | The name of Windows user to create/use, in the format `\` (Windows only).| +| `datadog_windows_ddagentuser_password` | The password used to create the user and/or register the service (Windows only).| +| `datadog_apply_windows_614_fix` | Whether or not to download and apply file referenced by `datadog_windows_614_fix_script_url` (Windows only). See https://dtdg.co/win-614-fix for more details. You can set this to `false` assuming your hosts aren't running Datadog Agent 6.14.\*.| +| `datadog_windows_skip_install` | Set to `true` to force the role to skip Windows Agent installation even if the role detects that installation is required (Windows only).| +| `datadog_windows_force_reinstall` | Set to `true` to force the role to reinstall the Windows Agent. This option takes precedence over `datadog_windows_skip_install` (Windows only).| +| `datadog_macos_user` | The name of the user to run Agent under. The user has to exist, it won't be created automatically. Defaults to `ansible_user` (macOS only).| +| `datadog_macos_download_url` | Override the URL to download the DMG installer from (macOS only).| +| `datadog_apm_instrumentation_enabled` | Configure APM instrumentation. Possible values are:
- `host`: Both the Agent and your services are running on a host.
- `docker`: The Agent and your services are running in separate Docker containers on the same host.
- `all`: Supports all the previous scenarios for `host` and `docker` at the same time.| +| `datadog_apm_instrumentation_libraries` | List of APM libraries to install if `host` or `docker` injection is enabled (defaults to `["java", "js", "dotnet", "python", "ruby"]`). You can find the available values in [Inject Libraries Locally][21].| +| `datadog_ssi_script_dir` | Directory where the Single Step Instrumentation (SSI) script will be downloaded and executed. Defaults to `/var/run/datadog-ssi`. Override this if the default location has noexec mount restrictions.| +| `datadog_remote_updates` | Enable remote installation and updates through the datadog-installer.| +| `datadog_infrastructure_mode` | Override the default `infrastructure_mode`.| ### Integrations To configure a Datadog integration (check), add an entry to the `datadog_checks` section. The first level key is the name of the check, and the value is the YAML payload to write the configuration file. Examples are provided below. +To install or remove an integration, refer to the `datadog_integration` [paragraph](#integration-installation) + #### Process check To define two instances for the `process` check use the configuration below. This creates the corresponding configuration files: * Agent v6 & v7: `/etc/datadog-agent/conf.d/process.d/conf.yaml` -* Agent v5: `/etc/dd-agent/conf.d/process.yaml` ```yml datadog_checks: @@ -87,7 +130,6 @@ To define two instances for the `process` check use the configuration below. Thi To configure a custom check use the configuration below. This creates the corresponding configuration files: - Agent v6 & v7: `/etc/datadog-agent/conf.d/my_custom_check.d/conf.yaml` -- Agent v5: `/etc/dd-agent/conf.d/my_custom_check.yaml` ```yml datadog_checks: @@ -97,6 +139,24 @@ To configure a custom check use the configuration below. This creates the corres - some_data: true ``` +##### Custom Python Checks + +To pass a Python check to the playbook, use the configuration below. + +This configuration requires the Datadog [play and role][12] to be a part of the larger playbook where the value passed in is the relative file path to the actual task for [Linux][13] or [Windows][14]. + +The key should be the name of the file created in the checks directory `checks.d/{{ item }}.py`: + +```yml + datadog_checks: + my_custom_check: + init_config: + instances: + - some_data: true + datadog_custom_checks: + my_custom_check: '../../../custom_checks/my_custom_check.py' +``` + #### Autodiscovery When using Autodiscovery, there is no pre-processing nor post-processing on the YAML. This means every YAML section is added to the final configuration file, including `autodiscovery identifiers`. @@ -117,7 +177,7 @@ The example below configures the PostgreSQL check through **Autodiscovery**: password: password ``` -Learn more about [Autodiscovery in the Datadog documentation][3]. +Learn more about [Autodiscovery][3] in the Datadog documentation. ### Tracing @@ -129,13 +189,6 @@ datadog_config: enabled: true ``` -To enable trace collection with Agent v5 use the following configuration: - -```yaml -datadog_config: - apm_enabled: "true" # has to be a string -``` - ### Live processes To enable [live process][6] collection with Agent v6 or v7 use the following configuration: @@ -155,11 +208,22 @@ The following variables are available for live processes: * `scrub_args`: Enables the scrubbing of sensitive arguments from a process command line (defaults to `true`). * `custom_sensitive_words`: Expands the default list of sensitive words used by the command line scrubber. -#### System Probe +#### System probe + +The system probe is configured under the `system_probe_config` variable. Any variables nested underneath are written to the `system-probe.yaml`, in the `system_probe_config` section. -The [Network Performance Monitoring][7] (NPM) system probe is configured under the `system_probe_config` variable. Any variables nested underneath are written to the `system-probe.yaml`. +[Network Performance Monitoring][7] (NPM) is configured under the `network_config` variable. Any variables nested underneath are written to the `system-probe.yaml`, in the `network_config` section. -**Note**: The system probe only works on Linux with the Agent v6+. +[Cloud Workload Security][8] is configured under the `runtime_security_config` variable. Any variables nested underneath are written to the `system-probe.yaml` and `security-agent.yaml`, in the `runtime_security_config` section. + +[Universal Service Monitoring][17] (USM) is configured under the `service_monitoring_config` variable. Any variables nested underneath are written to the `system-probe.yaml`, in the `service_monitoring_config` section. + +[Compliance][18] is configured under the `compliance_config` variable. Any variables nested underneath are written to the `security-agent.yaml`, in the `compliance_config` section. + +All other configuration for the system probe that does not live under any of the above keys should be configured under the `system_probe_other_config` variable. Any variables nested underneath are written to the top level +of `system-probe.yaml`. + +**Note for Windows users**: NPM is supported on Windows with Agent v6.27+ and v7.27+. It ships as an optional component that is only installed if `network_config.enabled` is set to true when the Agent is installed or upgraded. Because of this, existing installations might need to do an uninstall and reinstall of the Agent once to install the NPM component, unless the Agent is upgraded at the same time. #### Example configuration @@ -170,36 +234,27 @@ datadog_config: scrub_args: true custom_sensitive_words: ['consul_token','dd_api_key'] system_probe_config: - enabled: true sysprobe_socket: /opt/datadog-agent/run/sysprobe.sock +network_config: + enabled: true +service_monitoring_config: + enabled: true +runtime_security_config: + enabled: true +system_probe_other_config: + traceroute: + enabled: true ``` -Once modification is complete, follow the steps below: +**Note**: This configuration works with Agent 6.24.1+ and 7.24.1+. For older Agent versions, see the [Network Performance Monitoring][9] documentation on how to enable system-probe. + +On Linux, once this modification is complete, follow the steps below if you installed an Agent version older than 6.18.0 or 7.18.0: 1. Start the system-probe: `sudo service datadog-agent-sysprobe start` **Note**: If the service wrapper is not available on your system, run this command instead: `sudo initctl start datadog-agent-sysprobe`. -2. [Restart the Agent][8]: `sudo service datadog-agent restart`. +2. [Restart the Agent][10]: `sudo service datadog-agent restart`. 3. Enable the system-probe to start on boot: `sudo service enable datadog-agent-sysprobe`. -For manual setup, refer to the [NPM][9] documentation. - -#### Agent v5 - -To enable [live process][6] collection with Agent v5, use the following configuration: - -```yml -datadog_config: - process_agent_enabled: true -datadog_config_ex: - process.config: - scrub_args: true - custom_sensitive_words: "," -``` - -### Additional tasks - -`pre_tasks` and `post_tasks` folders are available to run user defined tasks. `pre_tasks` run before executing any tasks from the Datadog Ansible role, and `post_tasks` run after execution of the role. - -Installation tasks on supported platforms register the variable `datadog_agent_install`, which can be used in `post_tasks` to check the installation task's result. `datadog_agent_install.changed` is set to `true` if the installation task did install something, and `false` otherwise (for instance if the requested version was already installed). +For manual setup, see the [NPM][9] documentation. ## Versions @@ -208,7 +263,8 @@ By default, the current major version of the Datadog Ansible role installs Agent For v4+ of this role, when `datadog_agent_version` is used to pin a specific Agent version, the role derives per-OS version names to comply with the version naming schemes of the supported operating systems, for example: - `1:7.16.0-1` for Debian and SUSE based -- `7.16.0-1` for Redhat-based +- `7.16.0-1` for RedHat-based +- `7.16.0-1` for macOS - `7.16.0` for Windows. This makes it possible to target hosts running different operating systems in the same Ansible run, for example: @@ -216,18 +272,15 @@ This makes it possible to target hosts running different operating systems in th | Provided | Installs | System | |-------------------------------------|--------------|-----------------------| | `datadog_agent_version: 7.16.0` | `1:7.16.0-1` | Debian and SUSE-based | -| `datadog_agent_version: 7.16.0` | `7.16.0-1` | Redhat-based | +| `datadog_agent_version: 7.16.0` | `7.16.0-1` | RedHat-based | +| `datadog_agent_version: 7.16.0` | `7.16.0-1` | macOS | | `datadog_agent_version: 7.16.0` | `7.16.0` | Windows | | `datadog_agent_version: 1:7.16.0-1` | `1:7.16.0-1` | Debian and SUSE-based | -| `datadog_agent_version: 1:7.16.0-1` | `7.16.0-1` | Redhat-based | +| `datadog_agent_version: 1:7.16.0-1` | `7.16.0-1` | RedHat-based | | `datadog_agent_version: 1:7.16.0-1` | `7.16.0` | Windows | **Note**: If the version is not provided, the role uses `1` as the epoch and `1` as the release number. -**Agent v5 (older version)**: - -The Datadog Ansible role includes support for Datadog Agent v5 for Linux only. To install Agent v5, use `datadog_agent_major_version: 5` to install the latest version of Agent v5 or set `datadog_agent_version` to a specific version of Agent v5. **Note**: The `datadog_agent5` variable is obsolete and has been removed. - ### Repositories #### Linux @@ -236,46 +289,58 @@ When the variables `datadog_apt_repo`, `datadog_yum_repo`, and `datadog_zypper_r | # | Default apt repository | Default yum repository | Default zypper repository | |---|-------------------------------------------|------------------------------------|-----------------------------------------| -| 5 | deb https://apt.datadoghq.com stable main | https://yum.datadoghq.com/rpm | https://yum.datadoghq.com/suse/rpm | | 6 | deb https://apt.datadoghq.com stable 6 | https://yum.datadoghq.com/stable/6 | https://yum.datadoghq.com/suse/stable/6 | | 7 | deb https://apt.datadoghq.com stable 7 | https://yum.datadoghq.com/stable/7 | https://yum.datadoghq.com/suse/stable/7 | To override the default behavior, set these variables to something else than an empty string. -If you previously used the Agent v5 variables, use the **new** variables below with `datadog_agent_major_version` set to `5` or `datadog_agent_version` pinned to a specific Agent v5 version. - -| Old | New | -|------------------------------|-----------------------| -| `datadog_agent5_apt_repo` | `datadog_apt_repo` | -| `datadog_agent5_yum_repo` | `datadog_yum_repo` | -| `datadog_agent5_zypper_repo` | `datadog_zypper_repo` | +Since version 4.9.0, the `use_apt_backup_keyserver` variable has been removed, as APT keys are obtained from https://keys.datadoghq.com. #### Windows When the variable `datadog_windows_download_url` is not set, the official Windows MSI package corresponding to the `datadog_agent_major_version` is used: -| # | Default Windows MSI package URL | -|---|----------------------------------------------------------------------------------| -| 6 | https://s3.amazonaws.com/ddagent-windows-stable/datadog-agent-6-latest.amd64.msi | -| 7 | https://s3.amazonaws.com/ddagent-windows-stable/datadog-agent-7-latest.amd64.msi | +| Agent version | Default Windows MSI package URL | +|---------------|----------------------------------------------------------------------------------| +| 6 | https://s3.amazonaws.com/ddagent-windows-stable/datadog-agent-6-latest.amd64.msi | +| 7 | https://s3.amazonaws.com/ddagent-windows-stable/datadog-agent-7-latest.amd64.msi | + +To override the default behavior, set this variable to something other than an empty string. -To override the default behavior, set this variable to something else than an empty string. +#### macOS + +When the variable `datadog_macos_download_url` is not set, the official macOS DMG package corresponding to the `datadog_agent_major_version` is used: + +| Agent version | Default macOS DMG package URL | +|---------------|---------------------------------------------------------------------------------------| +| 6 | https://install.datadoghq.com/datadog-agent-6-latest.dmg | +| 7 | https://install.datadoghq.com/datadog-agent-7-latest.dmg (7.69-) | +| | https://install.datadoghq.com/datadog-agent-7-latest.x86_64.dmg (7.70+, Intel Mac) | +| | https://install.datadoghq.com/datadog-agent-7-latest.arm64.dmg (7.70+, Apple Silicon) | + +To override the default behavior, set this variable to something other than an empty string. ### Upgrade To upgrade from Agent v6 to v7, use `datadog_agent_major_version: 7` to install the latest version or set `datadog_agent_version` to a specific version of Agent v7. Use similar logic to upgrade from Agent v5 to v6. -#### Integrations +#### Integration installation **Available for Agent v6.8+** -Use the `datadog_integration` resource to install a specific version of a Datadog integration. Keep in mind, the Agent comes with all the integrations already installed. This command is useful for upgrading a specific integration without upgrading the whole Agent. For more details, see [Integration Management][4]. +Use the `datadog_integration` resource to install a specific version of a Datadog integration. Keep in mind, the Agent comes with the [core integrations][19] already installed. This command is useful for upgrading a specific integration without upgrading the whole Agent. For more details, see [integration management][4]. + +If you want to configure an integration, refer to the `datadog_checks` [paragraph](#integrations) Available actions: - `install`: Installs a specific version of the integration. - `remove`: Removes an integration. +##### Third party integrations + +[Datadog community][20] and [Datadog Marketplace][15] integrations can be installed with the `datadog_integration` resource. **Note**: These integrations are considered to be "third party" and thus need `third_party: true` to be set—see the example below. + ##### Syntax ```yml @@ -308,7 +373,7 @@ This example installs version `1.11.0` of the ElasticSearch integration and remo action: remove ``` -To see the available versions of Datadog integrations, refer to their `CHANGELOG.md` file in the [integrations-core repository][5]. +To see the available versions of Datadog integrations, see their `CHANGELOG.md` file in the [integrations-core repository][5]. ### Downgrade @@ -325,7 +390,7 @@ To downgrade to a prior version of the Agent: Below are some sample playbooks to assist you with using the Datadog Ansible role. -The following example sends data to Datadog US (default), enables logs, and configures a few checks. +The following example sends data to Datadog US (default), enables logs, NPM, and configures a few checks. ```yml - hosts: servers @@ -341,7 +406,6 @@ The following example sends data to Datadog US (default), enables logs, and conf log_level: INFO apm_config: enabled: true - max_traces_per_second: 10 logs_enabled: true # available with Agent v6 and v7 datadog_checks: process: @@ -395,7 +459,7 @@ The following example sends data to Datadog US (default), enables logs, and conf version: 1.11.0 datadog-postgres: action: remove - system_probe_config: + network_config: enabled: true ``` @@ -414,7 +478,7 @@ This example installs the latest Agent v6: ### Configuring the site -If using a site other than the default `datadoghq.com`, set the `datadog_site` var to the appropiate URL (eg: `datadoghq.eu`, `us3.datadoghq.com`). +If using a site other than the default `datadoghq.com`, set the `datadog_site` var to the appropriate URL (eg: `datadoghq.eu`, `us3.datadoghq.com`). This example sends data to the EU site: @@ -429,7 +493,7 @@ This example sends data to the EU site: ### Windows -On Windows, the `become: yes` option should be removed because it will make the role fail. Below are two methods to make the example playbooks work with Windows hosts: +On Windows, remove the `become: yes` option so the role does not fail. Below are two methods to make the example playbooks work with Windows hosts: #### Inventory file @@ -472,10 +536,31 @@ Alternatively, if your playbook **only runs on Windows hosts**, use the followin **Note**: This configuration fails on Linux hosts. Only use it if the playbook is specific to Windows hosts. Otherwise, use the [inventory file method](#inventory-file). +### Uninstallation + +On Windows it's possible to uninstall the Agent by using the following code in your Ansible role: + +```yml +- name: Check If Datadog Agent is installed + win_shell: | + (@(Get-ChildItem -Path "HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" -Recurse) | Where {$_.GetValue("DisplayName") -like "Datadog Agent" }).PSChildName + register: agent_installed_result +- name: Set Datadog Agent installed fact + set_fact: + agent_installed: "{{ agent_installed_result.stdout | trim }}" +- name: Uninstall the Datadog Agent + win_package: + product_id: "{{ agent_installed }}" + state: absent + when: agent_installed != "" +``` + ## Troubleshooting ### Debian stretch +**Note:** this information applies to versions of the role prior to 4.9.0. Since 4.9.0, the `apt_key` module is no longer used by the role. + On Debian Stretch, the `apt_key` module used by the role requires an additional system dependency to work correctly. The dependency (`dirmngr`) is not provided by the module. Add the following configuration to your playbooks to make use of the present role: ```yml @@ -487,16 +572,27 @@ On Debian Stretch, the `apt_key` module used by the role requires an additional apt: name: dirmngr state: present - roles: - { role: datadog.datadog, become: yes } vars: datadog_api_key: "" ``` +### CentOS 6/7 with Python 3 interpreter and Ansible 2.10.x or below + +**DEPRECATED: This section only applies to Ansible role versions 4 or below. Starting with version 5, this role no longer supports CentOS 6/7 and requires Ansible Core 2.10 or higher.** + +The `yum` Python module, which is used in this role to install the Agent on CentOS-based hosts, is only available on Python 2 if Ansible 2.10.x or below is used. In such cases, the `dnf` package manager would have to be used instead. + +However, `dnf` and the `dnf` Python module are not installed by default on CentOS-based hosts before CentOS 8. In this case, it is not possible to install the Agent when a Python 3 interpreter is used. + +This role fails early when this situation is detected to indicate that Ansible 2.11+ or a Python 2 interpreter is needed when installing the Agent on CentOS / RHEL < 8. + +To bypass this early failure detection (for instance, if `dnf` and the `python3-dnf` package are available on your host), set the `datadog_ignore_old_centos_python3_error` variable to `true`. + ### Windows -Due to a critical bug in Agent versions `6.14.0` and `6.14.1` on Windows, installation of these versions is now blocked (starting with version `3.3.0` of this role). +Due to a critical bug in Agent versions `6.14.0` and `6.14.1` on Windows, installation of these versions is blocked (starting with version `3.3.0` of this role). **NOTE:** Ansible fails on Windows if `datadog_agent_version` is set to `6.14.0` or `6.14.1`. Use `6.14.2` or above. @@ -505,15 +601,47 @@ If you are updating from **6.14.0 or 6.14.1 on Windows**, use the following step 1. Upgrade the present `datadog.datadog` Ansible role to the latest version (`>=3.3.0`). 2. Set the `datadog_agent_version` to `6.14.2` or above (defaults to latest). -For more details, see [Critical Bug in Uninstaller for Datadog Agent 6.14.0 and 6.14.1 on Windows][10]. +For more details, see [Critical Bug in Uninstaller for Datadog Agent 6.14.0 and 6.14.1 on Windows][11]. + +### Ubuntu 20.04 broken by service_facts + +Running the `service_facts` module on Ubuntu 20.04 causes the following error: + +``` +localhost | FAILED! => { + "changed": false, + "msg": "Malformed output discovered from systemd list-unit-files: accounts-daemon.service enabled enabled " +} +``` + +To fix this, [update Ansible to `v2.9.8` or above][16]. + +### Missing API key + +Starting from role `4.21` the API key is mandatory for the role to proceed. + +If you need to install the agent through Ansible but don't want to specify an API key (if you are baking it into a container/VM image for instance) you can: +* Specify a dummy API key and replace it afterward +* Disable managed_config (`datadog_manage_config: false`) -[1]: https://galaxy.ansible.com/Datadog/datadog +[1]: https://galaxy.ansible.com/ui/standalone/roles/DataDog/datadog/ [2]: https://github.com/DataDog/ansible-datadog [3]: https://docs.datadoghq.com/agent/autodiscovery [4]: https://docs.datadoghq.com/agent/guide/integration-management/ [5]: https://github.com/DataDog/integrations-core [6]: https://docs.datadoghq.com/infrastructure/process/ [7]: https://docs.datadoghq.com/network_performance_monitoring/ -[8]: https://docs.datadoghq.com/agent/guide/agent-commands/#restart-the-agent +[8]: https://docs.datadoghq.com/security_platform/cloud_workload_security/getting_started/ [9]: https://docs.datadoghq.com/network_performance_monitoring/installation/?tab=agent#setup -[10]: https://app.datadoghq.com/help/agent_fix +[10]: https://docs.datadoghq.com/agent/guide/agent-commands/#restart-the-agent +[11]: https://app.datadoghq.com/help/agent_fix +[12]: https://docs.ansible.com/ansible/latest/reference_appendices/playbooks_keywords.html#playbook-keywords +[13]: https://github.com/DataDog/ansible-datadog/blob/main/tasks/agent-linux.yml +[14]: https://github.com/DataDog/ansible-datadog/blob/main/tasks/agent-win.yml +[15]: https://www.datadoghq.com/blog/datadog-marketplace/ +[16]: https://github.com/ansible/ansible/blob/stable-2.9/changelogs/CHANGELOG-v2.9.rst#id61 +[17]: https://docs.datadoghq.com/tracing/universal_service_monitoring/?tab=configurationfiles#enabling-universal-service-monitoring +[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 diff --git a/chefignore b/chefignore deleted file mode 100644 index 7be3c6df..00000000 --- a/chefignore +++ /dev/null @@ -1 +0,0 @@ -.kitchen diff --git a/ci_test/ansible_lint.sh b/ci_test/ansible_lint.sh new file mode 100755 index 00000000..f899182f --- /dev/null +++ b/ci_test/ansible_lint.sh @@ -0,0 +1,82 @@ +#!/bin/bash -e + +# Install Python 3.10 if not already installed +if ! command -v python3.10 &> /dev/null; then + echo "Installing Python 3.10..." + apt update + apt install -y build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev wget + wget https://www.python.org/ftp/python/3.10.13/Python-3.10.13.tgz + tar -xf Python-3.10.13.tgz + cd Python-3.10.13 + ./configure --enable-optimizations + make -j $(nproc) + make altinstall + cd .. + rm -rf Python-3.10.13 Python-3.10.13.tgz +fi + +# Check Python version +python_version=$(python3.10 -c 'import sys; print(".".join(map(str, sys.version_info[:2])))') +if (( $(echo "$python_version < 3.10" | bc -l) )); then + echo "Error: Python 3.10 or higher is required. Found version $python_version" + exit 1 +fi + +# Create and activate virtual environment +python3.10 -m venv .venv +source .venv/bin/activate + +# galaxy-importer requires ansible-lint https://github.com/ansible/galaxy-importer/blob/master/setup.cfg#L22 +python3.10 -m pip install -r requirements.txt + +# Dry-run of galaxy-importer on legacy-role. +repo_dir=$(pwd) # use of importer must be done from parent repository +pushd .. +echo "Using Python version: $(python3.10 --version)" +echo "Python path: $(which python3.10)" +python3.10 -m galaxy_importer.main --legacy-role "$repo_dir" --namespace datadog 2>&1 | tee tmp_importer.log +# Filter out warnings for roles not found because location differs for macos or manual tests +grep -vq "^WARNING:.*the role '.*' was not found in .*" tmp_importer.log > importer.log +if grep -Eqi "(error|warning)" importer.log; then + exit 1 +fi +popd || exit + +rm -rf ansible_collections +mkdir -p ansible_collections/datadog/dd/roles/agent/ + +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 + 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 +cat << EOF > ansible_collections/datadog/galaxy.yml +namespace: datadog +name: dd +version: 1.2.3 +readme: README.md +authors: + - Datadog +EOF +cat << EOF > ansible_collections/datadog/.ansible-lint-ignore +roles/agent/defaults/main.yml var-naming[no-role-prefix] +EOF + +pushd ansible_collections/datadog/ +ansible-galaxy collection build +popd + +# explicitly install the ansible-lint version we need, despite what ansible-galaxy +# installed as its dependency +pip install -r requirements-ansible-lint.txt + +# Install required collections for linting +ansible-galaxy collection install ansible.windows + +# lint the ansible-role alone +ansible-lint -v --exclude=galaxy.yml --exclude=ci_test/ --exclude=manual_tests/ --exclude=.circleci/ --exclude=ansible_collections/ --exclude=.ansible/ --exclude=.venv/ + +cd ansible_collections/datadog/ || exit +ls -la roles/agent/ +ansible-lint -v --exclude=galaxy.yml --exclude=meta/ --exclude=.ansible/ --exclude=.venv/ diff --git a/ci_test/downgrade_to_6.yaml b/ci_test/downgrade_to_6.yaml new file mode 100644 index 00000000..84c3812a --- /dev/null +++ b/ci_test/downgrade_to_6.yaml @@ -0,0 +1,38 @@ +--- + +- hosts: all + roles: + - { role: '/root/project/'} + vars: + datadog_api_key: "11111111111111111111111111111111" + datadog_enabled: false + datadog_agent_major_version: 6 + datadog_agent_version: "6.28.1" + datadog_agent_allow_downgrade: true + datadog_yum_repo_config_enabled: true + # avoid checking that the agent is stopped for centos + datadog_skip_running_check: true + datadog_config: + tags: "mytag0, mytag1" + log_level: INFO + apm_enabled: "true" # has to be set as a string + datadog_config_ex: + trace.config: + env: dev + trace.concentrator: + extra_aggregators: version + system_probe_config: + sysprobe_socket: /opt/datadog-agent/run/sysprobe.sock + network_config: + enabled: true + service_monitoring_config: + enabled: true + system_probe_other_config: + traceroute: + enabled: true + datadog_checks: + process: + init_config: + instances: + - name: agent + search_string: ['agent', 'sshd' ] diff --git a/ci_test/install_agent_6.yaml b/ci_test/install_agent_6.yaml index 402a91d3..441a28b0 100644 --- a/ci_test/install_agent_6.yaml +++ b/ci_test/install_agent_6.yaml @@ -7,6 +7,7 @@ datadog_api_key: "11111111111111111111111111111111" datadog_enabled: false datadog_agent_major_version: 6 + datadog_yum_repo_config_enabled: true # avoid checking that the agent is stopped for centos datadog_skip_running_check: true datadog_config: @@ -18,6 +19,15 @@ env: dev trace.concentrator: extra_aggregators: version + system_probe_config: + sysprobe_socket: /opt/datadog-agent/run/sysprobe.sock + network_config: + enabled: true + service_monitoring_config: + enabled: true + system_probe_other_config: + traceroute: + enabled: true datadog_checks: process: init_config: diff --git a/ci_test/install_agent_5.yaml b/ci_test/install_agent_6_macos.yaml similarity index 78% rename from ci_test/install_agent_5.yaml rename to ci_test/install_agent_6_macos.yaml index 94362b9a..75f5a660 100644 --- a/ci_test/install_agent_5.yaml +++ b/ci_test/install_agent_6_macos.yaml @@ -2,10 +2,11 @@ - hosts: all roles: - - { role: '/root/project/'} + - {role: '/Users/distiller/project/'} vars: datadog_api_key: "11111111111111111111111111111111" - datadog_agent_major_version: 5 + datadog_enabled: false + datadog_agent_major_version: 6 # avoid checking that the agent is stopped for centos datadog_skip_running_check: true datadog_config: @@ -22,4 +23,4 @@ init_config: instances: - name: agent - search_string: ['agent' ] + search_string: ['agent', 'sshd'] diff --git a/ci_test/install_agent_7.yaml b/ci_test/install_agent_7.yaml index d9cef6ae..afd72c87 100644 --- a/ci_test/install_agent_7.yaml +++ b/ci_test/install_agent_7.yaml @@ -7,6 +7,7 @@ datadog_api_key: "11111111111111111111111111111111" datadog_enabled: false datadog_agent_major_version: 7 + datadog_yum_repo_config_enabled: true # avoid checking that the agent is stopped for centos datadog_skip_running_check: true datadog_config: @@ -18,6 +19,17 @@ env: dev trace.concentrator: extra_aggregators: version + system_probe_config: + sysprobe_socket: /opt/datadog-agent/run/sysprobe.sock + network_config: + enabled: true + service_monitoring_config: + enabled: true + runtime_security_config: + enabled: true + system_probe_other_config: + traceroute: + enabled: true datadog_checks: process: init_config: diff --git a/ci_test/install_agent_7_apm_all.yaml b/ci_test/install_agent_7_apm_all.yaml new file mode 100644 index 00000000..95af73cd --- /dev/null +++ b/ci_test/install_agent_7_apm_all.yaml @@ -0,0 +1,9 @@ +--- + +- hosts: all + roles: + - { role: "/home/circleci/project/" } + vars: + datadog_api_key: "11111111111111111111111111111111" + datadog_agent_major_version: 7 + datadog_apm_instrumentation_enabled: "host" diff --git a/ci_test/install_agent_7_apm_custom_dir.yaml b/ci_test/install_agent_7_apm_custom_dir.yaml new file mode 100644 index 00000000..264205b7 --- /dev/null +++ b/ci_test/install_agent_7_apm_custom_dir.yaml @@ -0,0 +1,12 @@ +--- + +- hosts: all + roles: + - { role: "/home/circleci/project/" } + vars: + datadog_api_key: "11111111111111111111111111111111" + datadog_agent_major_version: 7 + datadog_apm_instrumentation_enabled: "host" + datadog_apm_instrumentation_libraries: ["python", "java"] + # Test custom SSI script directory + datadog_ssi_script_dir: "/opt/datadog-ssi-scripts" \ No newline at end of file diff --git a/ci_test/install_agent_7_apm_python.yaml b/ci_test/install_agent_7_apm_python.yaml new file mode 100644 index 00000000..8d3082c7 --- /dev/null +++ b/ci_test/install_agent_7_apm_python.yaml @@ -0,0 +1,10 @@ +--- + +- hosts: all + roles: + - { role: "/home/circleci/project/" } + vars: + datadog_api_key: "11111111111111111111111111111111" + datadog_agent_major_version: 7 + datadog_apm_instrumentation_enabled: "all" + datadog_apm_instrumentation_libraries: ["python"] diff --git a/ci_test/downgrade_to_5.yaml b/ci_test/install_agent_7_macos.yaml similarity index 59% rename from ci_test/downgrade_to_5.yaml rename to ci_test/install_agent_7_macos.yaml index f401bb26..f770547a 100644 --- a/ci_test/downgrade_to_5.yaml +++ b/ci_test/install_agent_7_macos.yaml @@ -2,12 +2,13 @@ - hosts: all roles: - - { role: '/root/project/'} + - {role: '/Users/distiller/project/'} vars: datadog_api_key: "11111111111111111111111111111111" - datadog_agent_major_version: 5 - datadog_agent_version: 1:5.23.0-1 - datadog_agent_allow_downgrade: yes + datadog_enabled: false + datadog_agent_major_version: 7 + # avoid checking that the agent is stopped for centos + datadog_skip_running_check: true datadog_config: tags: "mytag0, mytag1" log_level: INFO @@ -17,9 +18,11 @@ env: dev trace.concentrator: extra_aggregators: version + runtime_security_config: + enabled: true datadog_checks: process: init_config: instances: - name: agent - search_string: ['agent' ] + search_string: ['agent', 'sshd'] diff --git a/ci_test/install_agent_7_pinned.yaml b/ci_test/install_agent_7_pinned.yaml new file mode 100644 index 00000000..db9e821f --- /dev/null +++ b/ci_test/install_agent_7_pinned.yaml @@ -0,0 +1,13 @@ +--- + +- hosts: all + roles: + - { role: '/root/project/'} + vars: + datadog_api_key: "11111111111111111111111111111111" + datadog_enabled: false + # Target a version above 7.51 which is the last version supported on RHEL6 and similar + # This is to ensure we don't incorrectly detect some configurations as RHEL6 + datadog_agent_version: '7.53.0' + # avoid checking that the agent is stopped for centos + datadog_skip_running_check: true diff --git a/ci_test/install_agent_7_with_integration.yaml b/ci_test/install_agent_7_with_integration.yaml new file mode 100644 index 00000000..066de9ea --- /dev/null +++ b/ci_test/install_agent_7_with_integration.yaml @@ -0,0 +1,25 @@ +--- +- hosts: all + tasks: + - block: + - ansible.builtin.include_role: + name: '/root/project/' + vars: + datadog_agent_major_version: 7 + datadog_api_key: "11111111111111111111111111111111" + datadog_enabled: false + datadog_skip_running_check: true + datadog_integration: + test-integration: + action: install + version: 1.0.0 + rescue: + - name: Integration install failed (expected) + ansible.builtin.debug: + msg: "Integration install failed, but that's okay for this test" + always: + - name: Verify traditional path was detected + ansible.builtin.assert: + that: datadog_agent_binary_path == "/opt/datadog-agent/bin/agent/agent" + fail_msg: "Wrong path: {{ datadog_agent_binary_path }}" + diff --git a/ci_test/install_agent_7_with_integration_fleet.yaml b/ci_test/install_agent_7_with_integration_fleet.yaml new file mode 100644 index 00000000..1eb4d14f --- /dev/null +++ b/ci_test/install_agent_7_with_integration_fleet.yaml @@ -0,0 +1,24 @@ +--- +- hosts: all + tasks: + - block: + - ansible.builtin.include_role: + name: "/home/circleci/project/" + 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 + rescue: + - name: Integration install failed (expected) + ansible.builtin.debug: + msg: "Integration install failed, but that's okay for this test" + 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 }}" diff --git a/ci_test/inventory/ci_macos.ini b/ci_test/inventory/ci_macos.ini new file mode 100644 index 00000000..a0d67335 --- /dev/null +++ b/ci_test/inventory/ci_macos.ini @@ -0,0 +1,2 @@ +[test] +127.0.0.1 ansible_connection=local ansible_user=distiller diff --git a/defaults/main.yml b/defaults/main.yml index d31f9ddb..0e6bdf53 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,17 +1,39 @@ --- -role_version: 4.4.0 +role_version: 5.6.0 -system_probe_config: - enabled: false +# define if the datadog-agent services should be enabled +datadog_enabled: true -datadog_enabled: yes +# Whether the datadog.conf / datadog.yaml, system-probe.yaml, security-agent.yaml and checks config under conf.d are managed by Ansible +datadog_manage_config: true -# default datadog.conf options +# default datadog.conf / datadog.yaml options datadog_config: {} +# default system-probe.yaml options +system_probe_config: {} +network_config: {} +service_monitoring_config: {} +system_probe_other_config: {} + # default checks enabled datadog_checks: {} +# custom Python checks +datadog_custom_checks: {} + +# set this to `true` to delete untracked checks +datadog_disable_untracked_checks: false + +# Add additional checks to keep when `datadog_disable_untracked_checks` is set to `true` +datadog_additional_checks: [] + +# set this to `true` to delete default checks +datadog_disable_default_checks: false + +# set this to `true` to delete example checks +datadog_disable_example_checks: false + # default user/group datadog_user: dd-agent datadog_group: dd-agent @@ -19,8 +41,10 @@ datadog_group: dd-agent # agent integration variables integration_command_user_linux: "dd-agent" integration_command_user_windows: "administrator" +integration_command_user_macos: "dd-agent" datadog_agent_binary_path_linux: /opt/datadog-agent/bin/agent/agent datadog_agent_binary_path_windows: "C:\\Program Files\\Datadog\\Datadog Agent\\bin\\agent.exe" +datadog_agent_binary_path_macos: "/opt/datadog-agent/bin/agent/agent" # list of additional groups for datadog_user datadog_additional_groups: {} @@ -37,40 +61,77 @@ datadog_agent_major_version: "" # compatible (ie. the major version in datadog_agent_version must be datadog_agent_major_version) datadog_agent_version: "" +# Default Package name for APT and RPM installs - can override in playbook for IOT Agent +datadog_agent_flavor: "datadog-agent" + # Default apt repo and keyserver -# By default, the roll uses the official apt Datadog repository for the chosen major version +# By default, the role uses the official apt Datadog repository for the chosen major version # Use the datadog_apt_repo variable to override the repository used. datadog_apt_repo: "" - datadog_apt_cache_valid_time: 3600 datadog_apt_key_retries: 5 -use_apt_backup_keyserver: false -datadog_apt_keyserver: hkp://keyserver.ubuntu.com:80 -datadog_apt_backup_keyserver: hkp://pool.sks-keyservers.net:80 + +# DATADOG_RPM_KEY.public (4172A230) is only useful to install old (< 6.14) Agent packages. +# We no longer add it and we explicitly remove it. +datadog_rpm_remove_keys: [4172A230] # Default yum repo and keys -# By default, the roll uses the official yum Datadog repository for the chosen major version +# By default, the role configures a yum repository for installing the Datadog agent package +# Use the datadog_yum_repo_setup_enabled toggle to disable this configuration +# WARNING: if you use this option, you will have to manually maintain the list of GPG +# signing keys used to sign the packages and update it as necessary by yourself +datadog_yum_repo_config_enabled: true + +# By default, the role uses the official yum Datadog repository for the chosen major version # Use the datadog_yum_repo variable to override the repository used. datadog_yum_repo: "" -datadog_yum_gpgkey: "https://yum.datadoghq.com/DATADOG_RPM_KEY.public" -datadog_yum_gpgkey_e09422b3: "https://yum.datadoghq.com/DATADOG_RPM_KEY_E09422B3.public" -datadog_yum_gpgkey_e09422b3_sha256sum: "694a2ffecff85326cc08e5f1a619937999a5913171e42f166e13ec802c812085" +# Set these variables if the Datadog yum repo should be accessed via proxy +datadog_yum_repo_proxy: "" +datadog_yum_repo_proxy_username: "" +datadog_yum_repo_proxy_password: "" -# Default zypper repo and keys +datadog_yum_repo_gpgcheck: "" +datadog_yum_gpgcheck: true +# NOTE: we don't use URLs starting with https://keys.datadoghq.com/, as Python +# on older CentOS/RHEL/SUSE doesn't support SNI and get_url would fail on them -# By default, the roll uses the official zypper Datadog repository for the chosen major version +# the CURRENT key always contains the key that is used to sign repodata and latest packages +datadog_yum_gpgkey_current: "https://s3.amazonaws.com/public-signing-keys/DATADOG_RPM_KEY_CURRENT.public" +# this key expires in 2022 +datadog_yum_gpgkey_e09422b3: "https://s3.amazonaws.com/public-signing-keys/DATADOG_RPM_KEY_E09422B3.public" +datadog_yum_gpgkey_e09422b3_sha256sum: "694a2ffecff85326cc08e5f1a619937999a5913171e42f166e13ec802c812085" +# this key expires in 2024 +datadog_yum_gpgkey_20200908: "https://s3.amazonaws.com/public-signing-keys/DATADOG_RPM_KEY_FD4BF915.public" +datadog_yum_gpgkey_20200908_sha256sum: "4d16c598d3635086762bd086074140d947370077607db6d6395b8523d5c23a7d" +# this key expires in 2028 +datadog_yum_gpgkey_20280418: "https://s3.amazonaws.com/public-signing-keys/DATADOG_RPM_KEY_B01082D3.public" +datadog_yum_gpgkey_20280418_sha256sum: "d309232f05bcfb5df7fce1a22b0920476254135083058206978aa57910698101" +# this key expires in 2033 +datadog_yum_gpgkey_4f09d16b: "https://s3.amazonaws.com/public-signing-keys/DATADOG_RPM_KEY_4F09D16B.public" +datadog_yum_gpgkey_4f09d16b_sha256sum: "a4dc0e09751cf0e01da7b4095e432f6330c11b1fef41cacd1f2c8981596eaf2b" + +# By default, the role uses the official zypper Datadog repository for the chosen major version # Use the datadog_zypper_repo variable to override the repository used. datadog_zypper_repo: "" -datadog_zypper_gpgkey: "https://yum.datadoghq.com/DATADOG_RPM_KEY.public" -datadog_zypper_gpgkey_sha256sum: "00d6505c33fd95b56e54e7d91ad9bfb22d2af17e5480db25cba8fee500c80c46" -datadog_zypper_gpgkey_e09422b3: "https://yum.datadoghq.com/DATADOG_RPM_KEY_E09422B3.public" -datadog_zypper_gpgkey_e09422b3_sha256sum: "694a2ffecff85326cc08e5f1a619937999a5913171e42f166e13ec802c812085" +# Define if the official zypper Datadog repository services should be installed +datadog_manage_zypper_repofile: true +datadog_zypper_repo_gpgcheck: "" +datadog_zypper_gpgcheck: true +datadog_zypper_gpgkey_current: "https://s3.amazonaws.com/public-signing-keys/DATADOG_RPM_KEY_CURRENT.public" +datadog_zypper_gpgkey_e09422b3: "https://s3.amazonaws.com/public-signing-keys/DATADOG_RPM_KEY_E09422B3.public" +datadog_zypper_gpgkey_e09422b3_sha256sum: "694a2ffecff85326cc08e5f1a619937999a5913171e42f166e13ec802c812085" +datadog_zypper_gpgkey_20200908: "https://s3.amazonaws.com/public-signing-keys/DATADOG_RPM_KEY_FD4BF915.public" +datadog_zypper_gpgkey_20200908_sha256sum: "4d16c598d3635086762bd086074140d947370077607db6d6395b8523d5c23a7d" +datadog_zypper_gpgkey_20280418: "https://s3.amazonaws.com/public-signing-keys/DATADOG_RPM_KEY_B01082D3.public" +datadog_zypper_gpgkey_20280418_sha256sum: "d309232f05bcfb5df7fce1a22b0920476254135083058206978aa57910698101" +datadog_zypper_gpgkey_4f09d16b: "https://s3.amazonaws.com/public-signing-keys/DATADOG_RPM_KEY_4F09D16B.public" +datadog_zypper_gpgkey_4f09d16b_sha256sum: "a4dc0e09751cf0e01da7b4095e432f6330c11b1fef41cacd1f2c8981596eaf2b" # Avoid checking if the agent is running or not. This can be useful if you're # using sysvinit and providing your own init script. datadog_skip_running_check: false @@ -78,7 +139,7 @@ datadog_skip_running_check: false # Set this to `yes` to allow agent downgrades on apt-based platforms. # Internally, this uses `apt-get`'s `--force-yes` option. Use with caution. # On centos this will only work with ansible 2.4 and up -datadog_agent_allow_downgrade: no +datadog_agent_allow_downgrade: false # Default windows latest msi package URL @@ -95,8 +156,18 @@ datadog_windows_agent7_latest_url: "https://s3.amazonaws.com/ddagent-windows-sta # in order to get the full url to the msi package. datadog_windows_versioned_url: "https://s3.amazonaws.com/ddagent-windows-stable/ddagent-cli" -# url of the 6.14 fix script. See http://dtdg.co/win-614-fix for more details. +# url of the 6.14 fix script. See https://dtdg.co/win-614-fix for more details. datadog_windows_614_fix_script_url: "https://s3.amazonaws.com/ddagent-windows-stable/scripts/fix_6_14.ps1" +# whether or not to download and apply the above fix +datadog_apply_windows_614_fix: true + +# Force the role to skip reinstall steps on Windows, even if the Agent +# isn't detected yet. +datadog_windows_skip_install: false + +# Force the role to reinstall the Agent on Windows regardless of the +# automatic feature checks. This can be used to downgrade the Agent on Windows. +datadog_windows_force_reinstall: false # Override to change the name of the windows user to create datadog_windows_ddagentuser_name: "" @@ -116,23 +187,92 @@ datadog_windows_config_root: "{{ ansible_facts.env['ProgramData'] }}\\Datadog" # arguments to supply to the windows installer. win_install_args: " " +# Advanced users - Configure datadog-installer to support advanced scenarios +datadog_installer_registry: "" +datadog_installer_auth: "" +datadog_installer_version: "" +datadog_apm_inject_version: "" + +# Configure APM host injection. Possible values are: "all", "host" or "docker". +# datadog_apm_instrumentation_enabled: "" + +# List of APM libraries with pinned versions to install if host or Docker injection is enabled. +# Example: `["java:1.23.0", "python:2.0.9"]` +# You can see the available values in our official docs: +# https://docs.datadoghq.com/tracing/trace_collection/library_injection_local +datadog_apm_instrumentation_libraries: [] + +# 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" + +# Enable remote updates through datadog-installer +datadog_remote_updates: false + +# Set infrastructure monitoring mode (optional) +# datadog_infrastructure_mode: "" # # Internal variables # The following variables are for internal use only, do not modify them. # +datadog_apt_trusted_d_keyring: "/etc/apt/trusted.gpg.d/datadog-archive-keyring.gpg" +datadog_apt_usr_share_keyring: "/usr/share/keyrings/datadog-archive-keyring.gpg" +datadog_apt_key_current_name: "DATADOG_APT_KEY_CURRENT" +# NOTE: we don't use URLs starting with https://keys.datadoghq.com/, as Python +# on older Debian/Ubuntu doesn't support SNI and get_url would fail on them +datadog_apt_default_keys: + - key: "{{ datadog_apt_key_current_name }}" + value: https://s3.amazonaws.com/public-signing-keys/DATADOG_APT_KEY_CURRENT.public + - key: A2923DFF56EDA6E76E55E492D3A80E30382E94DE + value: https://s3.amazonaws.com/public-signing-keys/DATADOG_APT_KEY_382E94DE.public + - key: D75CEA17048B9ACBF186794B32637D44F14F620E + value: https://s3.amazonaws.com/public-signing-keys/DATADOG_APT_KEY_F14F620E.public + - key: 5F1E256061D813B125E156E8E6266D4AC0962C7D + value: https://s3.amazonaws.com/public-signing-keys/DATADOG_APT_KEY_C0962C7D.public + - key: D18886567EABAD8B2D2526900D826EB906462314 + value: https://s3.amazonaws.com/public-signing-keys/DATADOG_APT_KEY_06462314.public + # The default apt repository for each major Agent version is specified in the following variables. -datadog_agent5_apt_repo: "deb https://apt.datadoghq.com/ stable main" -datadog_agent6_apt_repo: "deb https://apt.datadoghq.com/ stable 6" -datadog_agent7_apt_repo: "deb https://apt.datadoghq.com/ stable 7" +datadog_agent6_apt_repo: "deb [signed-by={{ datadog_apt_usr_share_keyring }}] https://apt.datadoghq.com/ stable 6" +datadog_agent7_apt_repo: "deb [signed-by={{ datadog_apt_usr_share_keyring }}] https://apt.datadoghq.com/ stable 7" # The default yum repository for each major Agent version is specified in the following variables. -datadog_agent5_yum_repo: "https://yum.datadoghq.com/rpm/{{ lookup('vars', 'ansible_userspace_architecture', default=ansible_architecture) }}" -datadog_agent6_yum_repo: "https://yum.datadoghq.com/stable/6/{{ lookup('vars', 'ansible_userspace_architecture', default=ansible_architecture) }}" -datadog_agent7_yum_repo: "https://yum.datadoghq.com/stable/7/{{ lookup('vars', 'ansible_userspace_architecture', default=ansible_architecture) }}" +datadog_agent6_yum_repo: "https://yum.datadoghq.com/stable/6/{{ ansible_facts.architecture }}" +datadog_agent7_yum_repo: "https://yum.datadoghq.com/stable/7/{{ ansible_facts.architecture }}" # The default zypper repository for each major Agent version is specified in the following variables. -datadog_agent5_zypper_repo: "https://yum.datadoghq.com/suse/rpm/{{ lookup('vars', 'ansible_userspace_architecture', default=ansible_architecture) }}" -datadog_agent6_zypper_repo: "https://yum.datadoghq.com/suse/stable/6/{{ lookup('vars', 'ansible_userspace_architecture', default=ansible_architecture) }}" -datadog_agent7_zypper_repo: "https://yum.datadoghq.com/suse/stable/7/{{ lookup('vars', 'ansible_userspace_architecture', default=ansible_architecture) }}" +datadog_agent6_zypper_repo: "https://yum.datadoghq.com/suse/stable/6/{{ ansible_facts.architecture }}" +datadog_agent7_zypper_repo: "https://yum.datadoghq.com/suse/stable/7/{{ ansible_facts.architecture }}" + +# Default macOS latest dmg package URL + +# By default, will use the official latest dmg package for the chosen major version. +# Use the datadog_macos_download_url option to override the dmg package used. +datadog_macos_download_url: "" + +# The default dmg package for each major Agent version is specified in the following variables. +# These variables are for internal use only, do not modify them. +datadog_macos_agent6_latest_url: "https://install.datadoghq.com/datadog-agent-6-latest.dmg" +datadog_macos_agent7_latest_url: "https://install.datadoghq.com/datadog-agent-7-latest.dmg" +datadog_macos_agent7_latest_arch_url: "https://install.datadoghq.com/datadog-agent-7-latest.{{ ansible_facts.architecture }}.dmg" + +# If datadog_agent_version is set, the role will use the following url prefix instead, and append the version number to it +# in order to get the full url to the dmg package. +datadog_macos_versioned_url: "https://install.datadoghq.com/datadog-agent" + +datadog_macos_user: "{{ ansible_user }}" +datadog_macos_service_name: "com.datadoghq.agent" +datadog_macos_user_plist_file_path: "Library/LaunchAgents/{{ datadog_macos_service_name }}.plist" +datadog_macos_system_plist_file_path: "/Library/LaunchDaemons/{{ datadog_macos_service_name }}.plist" +datadog_macos_etc_dir: "/opt/datadog-agent/etc" +datadog_macos_logs_dir: "/opt/datadog-agent/logs" +datadog_macos_run_dir: "/opt/datadog-agent/run" + +datadog_ansible_facts_subset: + - '!all' + - '!any' + - min + - env diff --git a/handlers/main-macos.yml b/handlers/main-macos.yml new file mode 100644 index 00000000..149e0370 --- /dev/null +++ b/handlers/main-macos.yml @@ -0,0 +1,30 @@ +--- +# This file doesn't actually contain "handlers" in the Ansible sense: when running +# our role, Ansible only loads the contents of handlers/main.yml as handlers. +# However, this is here because this is a "handler-like" task that is dynamically +# included by a handler task in handlers/main.yml. + +# NOTE: We don't use bootout/bootstrap here, because bootout can't wait for the operation +# to finish and if it's in progress for a longer time, bootstrap fails. We use the old +# unload/load combo because they actually wait. +- name: Unload datadog-agent service + 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 + +- name: Load datadog-agent service + 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 + +- name: Restart datadog-agent service + 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 diff --git a/handlers/main-win.yml b/handlers/main-win.yml new file mode 100644 index 00000000..3fb6f319 --- /dev/null +++ b/handlers/main-win.yml @@ -0,0 +1,11 @@ +--- +# This file doesn't actually contain "handlers" in the Ansible sense: when running +# our role, Ansible only loads the contents of handlers/main.yml as handlers. +# However, this is here because this is a "handler-like" task that is dynamically +# included by a handler task in handlers/main.yml. +- name: Restart Windows datadogagent service + ansible.windows.win_service: + name: datadogagent + state: restarted + force_dependent_services: true + when: datadog_enabled and not ansible_check_mode and ansible_facts.os_family == "Windows" and not datadog_remote_update_in_progress diff --git a/handlers/main.yml b/handlers/main.yml index 7d55fe5c..e6cd7c26 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -1,14 +1,38 @@ --- +- name: restart datadog-agent-sysprobe # noqa name[casing] + ansible.builtin.service: + name: datadog-agent-sysprobe + state: restarted + use: service + when: datadog_enabled and agent_datadog_sysprobe_enabled and not ansible_check_mode and + not ansible_facts.os_family == "Windows" and not ansible_facts.os_family == "Darwin" + +- name: Gather service facts + ansible.builtin.service_facts: + when: datadog_enabled and not ansible_check_mode and not ansible_facts.os_family == "Windows" and not ansible_facts.os_family == "Darwin" -- name: restart datadog-agent - service: +- name: restart datadog-agent # noqa name[casing] + ansible.builtin.service: name: datadog-agent state: restarted - when: datadog_enabled and not ansible_check_mode and not ansible_os_family == "Windows" + use: service + when: datadog_enabled and not ansible_check_mode and not ansible_facts.os_family == "Windows" and not ansible_facts.os_family == "Darwin" + and (ansible_facts.services['datadog-agent-exp.service'] is not defined or ansible_facts.services['datadog-agent-exp.service'].state != "running") -- name: restart datadog-agent-win - win_service: - name: datadogagent - state: restarted - force_dependent_services: true - when: datadog_enabled and not ansible_check_mode and ansible_os_family == "Windows" +# We can't add the Windows Agent service restart handler directly here because that makes the role require +# the ansible.windows collection on all platforms. We only want it to be needed on Windows. +# Therefore, what we do is the following: when needed, our Windows tasks call this handler to require a +# Windows Agent restart (through notify: restart datadog-agent-win). +# When notified, the below handler is executed at the end of the playbook run. +# The include_tasks loads the handlers/main-win.yml file, which contains the real service restart task +# (which depends on ansible.windows), and runs it, triggering the Windows Agent restart. +- name: restart datadog-agent-win # noqa name[casing] + ansible.builtin.include_tasks: handlers/main-win.yml + +# When needed, our macOS tasks call this handler to require a +# macOS Agent restart (through notify: restart datadog-agent-macos). +# When notified, the below handler is executed at the end of the playbook run. +# The include_tasks loads the handlers/main-macos.yml file, which contains the real service restart task +# and runs it, triggering the macOS Agent restart. +- name: restart datadog-agent-macos # noqa name[casing] + ansible.builtin.include_tasks: handlers/main-macos.yml diff --git a/kitchen.yml b/kitchen.yml deleted file mode 100644 index 124a810d..00000000 --- a/kitchen.yml +++ /dev/null @@ -1,18 +0,0 @@ ---- -driver: - name: vagrant - -provisioner: - # use an ansible playbook to provision our server - name: ansible_playbook - # name of the host - hosts: test-kitchen - # list of ansible galaxy requirements from the roles meta/main.yml - # requirements_path: dependencies.yml - -platforms: - - name: ubuntu-18.10 - -suites: - # suites found at /test/integration/$test-name - - name: default \ No newline at end of file diff --git a/manual_tests/.gitignore b/manual_tests/.gitignore new file mode 100644 index 00000000..8000dd9d --- /dev/null +++ b/manual_tests/.gitignore @@ -0,0 +1 @@ +.vagrant diff --git a/manual_tests/Vagrantfile b/manual_tests/Vagrantfile index b4a4f311..7b8a8f35 100644 --- a/manual_tests/Vagrantfile +++ b/manual_tests/Vagrantfile @@ -1,3 +1,19 @@ Vagrant.configure("2") do |config| - config.vm.box = "ubuntu/trusty64" + config.vm.define "ubuntu", primary: true do |c| + c.vm.box = "ubuntu/trusty64" + end + + config.vm.define "centos", autostart: false do |c| + c.vm.box = "centos/8" + end + + config.vm.define "amazonlinux", autostart: false do |c| + c.vm.box = "bento/amazonlinux-2" + end + + Dir["test_*.yml"].sort.each do |playbook| + config.vm.provision playbook, type: "ansible" do |ansible| + ansible.playbook = playbook + end + end end diff --git a/manual_tests/inventory b/manual_tests/inventory index ce6468b7..bbed3309 100644 --- a/manual_tests/inventory +++ b/manual_tests/inventory @@ -1,2 +1,2 @@ [test_host] -127.0.0.1 ansible_ssh_host=localhost ansible_ssh_user=vagrant ansible_ssh_port=2222 ansible_ssh_private_key_file=./ansible-datadog/manual_tests/.vagrant/machines/default/virtualbox/private_key +127.0.0.1 ansible_ssh_host=localhost ansible_ssh_user=vagrant ansible_ssh_port=2222 ansible_ssh_private_key_file=./ansible-datadog/manual_tests/.vagrant/machines/ubuntu/virtualbox/private_key diff --git a/manual_tests/inventory_win b/manual_tests/inventory_win new file mode 100644 index 00000000..0921413c --- /dev/null +++ b/manual_tests/inventory_win @@ -0,0 +1,9 @@ +[windows] +win ansible_host=127.0.0.1 + +[windows:vars] +ansible_user=Administrator +ansible_become=no +ansible_connection=winrm +ansible_port=5986 +ansible_winrm_server_cert_validation=ignore diff --git a/manual_tests/readme.md b/manual_tests/readme.md index 6f1e37fc..5258de75 100644 --- a/manual_tests/readme.md +++ b/manual_tests/readme.md @@ -1,20 +1,43 @@ -# Test setup +# Linux test setup with Vagrant This is an example setup, based on vagrant + virtualbox, that allows to easily run ansible commands to test the module. -# Requirements +## Requirements - vagrant > 2.0.0 - virtualbox > 5.1.28 -# Setup +## Setup -in `$WORK_DIR/ansible-datadog/manual_tests`: +From `ansible-datadog/manual_tests` directory: -- provision VM: `vagrant up` -- connect to the VM to check the configuration: `vagrant ssh` -- destroy VM when needed: `vagrant destroy -f` +- provision VM: `vagrant up ubuntu --provision --provision-with test_7_full.yml` +- when done, destroy VM if needed: `vagrant destroy -f` -in `$WORK_DIR`: +To test with different agent versions or configurations, replace +`--provision-with` argument `test_7_full.yml` with any of the other +`test_*.yml` files in this directory. -- run ansible-playbook: `ansible-playbook ansible-datadog/manual_tests/test_5_full.yml -i ansible-datadog/manual_tests/inventory` +To test on different operating systems, replace `ubuntu` with `centos` or `amazonlinux`. + +If `vagrant up --provision` is used without any other parameters, all the +playbooks are applied one by one on an Ubuntu machine. + +# Windows test setup from WSL + +## Requirements + +- Install Ansible and `pywinrm` inside WSL: `sudo python3 -m pip install ansible pywinrm` +- From an elevated Powershell terminal (outside WSL), run the following script to setup WinRM so Ansible can connect: +https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1 +- Make sure the Administrator account is enabled and you know the password (or use a different account in the `inventory_win` file). + +## Setup + +- From `ansible-datadog`'s parent directory, run in a WSL console (it will ask for the Administrator password each time): + +```shell +ansible-playbook -k ansible-datadog/manual_tests/test_7_full.yml -i ansible-datadog/manual_tests/inventory_win +``` + +Note: Replace `test_7_full.yml` with any of the other yaml files on this directory. diff --git a/manual_tests/test_5_default.yml b/manual_tests/test_5_default.yml deleted file mode 100644 index 9a1c992c..00000000 --- a/manual_tests/test_5_default.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -- hosts: all - roles: - - { role: ansible-datadog, become: yes } - vars: - datadog_agent_major_version: 5 diff --git a/manual_tests/test_5_full.yml b/manual_tests/test_5_full.yml deleted file mode 100644 index 9bb2ca30..00000000 --- a/manual_tests/test_5_full.yml +++ /dev/null @@ -1,47 +0,0 @@ -- hosts: all - roles: - - { role: ansible-datadog, become: yes } # On Ansible < 1.9, use `sudo: yes` instead of `become: yes` - vars: - datadog_agent_major_version: 5 - datadog_api_key: "123456" - datadog_agent_version: "1:5.18.0-1" # for apt-based platforms, use a `5.12.3-1` format on yum-based platforms - datadog_agent_allow_downgrade: true - datadog_config: - tags: "mytag0, mytag1" - log_level: INFO - apm_enabled: "true" # has to be set as a string - datadog_config_ex: - trace.config: - env: dev - trace.concentrator: - extra_aggregators: version - datadog_checks: - process: - init_config: - instances: - - name: ssh - search_string: ['ssh', 'sshd' ] - - name: syslog - search_string: ['rsyslog' ] - cpu_check_interval: 0.2 - exact_match: true - ignore_denied_access: true - ssh_check: - init_config: - instances: - - host: localhost - port: 22 - username: root - password: changeme - sftp_check: True - private_key_file: - add_missing_keys: True - nginx: - init_config: - instances: - - nginx_status_url: http://example.com/nginx_status/ - tags: - - instance:foo - - nginx_status_url: http://example2.com:1234/nginx_status/ - tags: - - instance:bar diff --git a/manual_tests/test_6_default.yml b/manual_tests/test_6_default.yml index 2df0d96c..baad2e24 100644 --- a/manual_tests/test_6_default.yml +++ b/manual_tests/test_6_default.yml @@ -1,6 +1,6 @@ --- - hosts: all roles: - - { role: ansible-datadog, become: yes } + - { role: ../../ansible-datadog, become: yes } vars: datadog_agent_major_version: 6 diff --git a/manual_tests/test_6_full.yml b/manual_tests/test_6_full.yml index fd58b5a3..e8ded3ab 100644 --- a/manual_tests/test_6_full.yml +++ b/manual_tests/test_6_full.yml @@ -1,18 +1,19 @@ - hosts: all roles: - - { role: ansible-datadog, become: yes } # On Ansible < 1.9, use `sudo: yes` instead of `become: yes` + - { role: ../../ansible-datadog, become: yes } # On Ansible < 1.9, use `sudo: yes` instead of `become: yes` vars: datadog_agent_major_version: 6 datadog_api_key: "123456" datadog_agent_allow_downgrade: true system_probe_config: - enabled: true source_excludes: "*": - 8301 dest_excludes: "*": - 8301 + network_config: + enabled: true datadog_config: tags: "mytag0, mytag1" log_level: INFO @@ -43,9 +44,9 @@ port: 22 username: root password: changeme - sftp_check: True + sftp_check: true private_key_file: - add_missing_keys: True + add_missing_keys: true nginx: init_config: instances: diff --git a/manual_tests/test_7_default.yml b/manual_tests/test_7_default.yml index 1012d56c..bef90e14 100644 --- a/manual_tests/test_7_default.yml +++ b/manual_tests/test_7_default.yml @@ -1,4 +1,4 @@ --- - hosts: all roles: - - { role: ansible-datadog, become: yes } + - { role: ../../ansible-datadog, become: yes } diff --git a/manual_tests/test_7_full.yml b/manual_tests/test_7_full.yml index 32c4899b..27ace922 100644 --- a/manual_tests/test_7_full.yml +++ b/manual_tests/test_7_full.yml @@ -1,18 +1,19 @@ - hosts: all roles: - - { role: ansible-datadog, become: yes } # On Ansible < 1.9, use `sudo: yes` instead of `become: yes` + - { role: ../../ansible-datadog, become: yes } # On Ansible < 1.9, use `sudo: yes` instead of `become: yes` vars: datadog_agent_major_version: 7 datadog_api_key: "123456" datadog_agent_allow_downgrade: true system_probe_config: - enabled: true source_excludes: "*": - 8301 dest_excludes: "*": - 8301 + network_config: + enabled: true datadog_config: tags: "mytag0, mytag1" log_level: INFO @@ -20,6 +21,8 @@ # logs related config logs_enabled: true logset: main + datadog_apm_instrumentation_libraries: ["java:1.23.0", "python:2.0.9", "js:latest", "dotnet", "ruby"] + datadog_apm_instrumentation_enabled: "host" datadog_config_ex: trace.config: env: dev diff --git a/meta/main.yml b/meta/main.yml index c2ed8599..730a6935 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -1,9 +1,12 @@ --- galaxy_info: + role_name: datadog + namespace: datadog author: 'Brian Akins, Dustin Brown & Datadog' description: Install Datadog agent and configure checks license: Apache2 - min_ansible_version: 2.6 + min_ansible_version: '2.10' + github_branch: main platforms: - name: Ubuntu versions: @@ -11,39 +14,53 @@ galaxy_info: - xenial - artful - bionic + - focal - name: Debian versions: - wheezy - jessie - stretch - buster + - bullseye - name: EL versions: - - 8 - - 7 - - 6 + - '8' + - '9' + - name: Amazon Linux + versions: + - '2023' - name: opensuse versions: - - 12.1 - - 12.2 - - 12.3 - - 13.1 - - 13.2 + - '12.1' + - '12.2' + - '12.3' + - '13.1' + - '13.2' + - '42.1' + - '42.2' + - '42.3' + - '15.0' + - '15.1' + - '15.2' + - '15.3' - name: SLES versions: - 11SP3 - 11SP4 - - 12 + - '12' - 12SP1 - - 15 + - '15' - name: Windows versions: - 2008x64 - 2008R2 - - 2012 + - '2012' - 2012R2 - - 2016 - - 2019 + - '2016' + - '2019' + - name: MacOSX + versions: + - all galaxy_tags: - monitoring dependencies: [] diff --git a/requirements-ansible-lint.txt b/requirements-ansible-lint.txt new file mode 100644 index 00000000..92dc172a --- /dev/null +++ b/requirements-ansible-lint.txt @@ -0,0 +1 @@ +ansible-lint==25.1.2 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..cebabed2 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +galaxy-importer==0.4.29 diff --git a/tasks/_agent-linux-macos-shared.yml b/tasks/_agent-linux-macos-shared.yml new file mode 100644 index 00000000..ae80ce5f --- /dev/null +++ b/tasks/_agent-linux-macos-shared.yml @@ -0,0 +1,172 @@ +--- +- name: Create Datadog agent config directory + ansible.builtin.file: + dest: "{{ agent_dd_config_dir }}" + state: directory + mode: "0755" + owner: "{{ agent_dd_user }}" + group: "{{ agent_dd_group }}" + when: datadog_manage_config + +- name: Create main Datadog agent configuration file + ansible.builtin.template: + src: datadog.yaml.j2 + dest: "{{ agent_dd_config_dir }}/datadog.yaml" + mode: "0640" + owner: "{{ agent_dd_user }}" + group: "{{ agent_dd_group }}" + when: datadog_manage_config + notify: "{{ agent_dd_notify_agent }}" + +- name: Register all check configs present in datadog + ansible.builtin.find: + paths: "{{ agent_dd_config_dir }}/conf.d/" + patterns: + - "conf.yaml*" + recurse: true + depth: 2 + file_type: file + register: agent_datadog_conf_paths + when: datadog_manage_config and (datadog_disable_untracked_checks or datadog_disable_default_checks) + +- name: Delete checks not present in agent_datadog_tracked_checks + ansible.builtin.file: + path: "{{ agent_dd_config_dir }}/conf.d/{{ item }}.d/conf.yaml" + state: absent + loop: >- + {{ + agent_datadog_conf_paths.files | map(attribute='path') | select('match', '.*\/conf\.yaml$') | list + | map('dirname') | map('basename') | list | map('regex_replace', '^(.*).d$', '\1') | list + }} + when: datadog_manage_config and datadog_disable_untracked_checks and item not in agent_datadog_tracked_checks + notify: "{{ agent_dd_notify_agent }}" + +- name: Delete all default checks + ansible.builtin.file: + path: "{{ agent_dd_config_dir }}/conf.d/{{ item }}.d/conf.yaml.default" + state: absent + loop: >- + {{ + agent_datadog_conf_paths.files | map(attribute='path') | select('match', '.*\/conf\.yaml\.default$') | list + | map('dirname') | map('basename') | list | map('regex_replace', '^(.*).d$', '\1') | list + }} + when: datadog_manage_config and datadog_disable_default_checks and item not in agent_datadog_tracked_checks + notify: "{{ agent_dd_notify_agent }}" + +- name: Delete all example checks + ansible.builtin.file: + path: "{{ agent_dd_config_dir }}/conf.d/{{ item }}.d/conf.yaml.example" + state: absent + loop: >- + {{ + agent_datadog_conf_paths.files | map(attribute='path') | select('match', '.*\/conf\.yaml\.example$') | list + | map('dirname') | map('basename') | list | map('regex_replace', '^(.*).d$', '\1') | list + }} + when: datadog_manage_config and datadog_disable_example_checks and item not in agent_datadog_tracked_checks + notify: "{{ agent_dd_notify_agent }}" + +- name: Ensure configuration directories are present for each Datadog check + ansible.builtin.file: + dest: "{{ agent_dd_config_dir }}/conf.d/{{ item }}.d" + state: directory + owner: "{{ agent_dd_user }}" + group: "{{ agent_dd_group }}" + mode: "0755" + with_items: "{{ agent_datadog_checks | list }}" + when: datadog_manage_config + +- name: Create a configuration file for each Datadog check + ansible.builtin.template: + src: checks.yaml.j2 + dest: "{{ agent_dd_config_dir }}/conf.d/{{ item }}.d/conf.yaml" + mode: "0640" + owner: "{{ agent_dd_user }}" + group: "{{ agent_dd_group }}" + with_items: "{{ agent_datadog_checks | list }}" + when: datadog_manage_config + notify: "{{ agent_dd_notify_agent }}" + +- name: Remove old configuration file for each Datadog check + ansible.builtin.file: + dest: "{{ agent_dd_config_dir }}/conf.d/{{ item }}.yaml" + state: absent + with_items: "{{ agent_datadog_checks | list }}" + when: datadog_manage_config + notify: "{{ agent_dd_notify_agent }}" + +- name: Create custom check file for each custom check + ansible.builtin.copy: + src: "{{ datadog_custom_checks[item] }}" + dest: "{{ agent_dd_config_dir }}/checks.d/{{ item }}.py" + mode: "0755" + owner: "{{ agent_dd_user }}" + group: "{{ agent_dd_group }}" + with_items: "{{ datadog_custom_checks | list }}" + notify: "{{ agent_dd_notify_agent }}" + +- name: Create installation information file + ansible.builtin.template: + src: install_info.j2 + dest: "{{ agent_dd_config_dir }}/install_info" + owner: "{{ agent_dd_user }}" + group: "{{ agent_dd_group }}" + mode: "0644" + +- name: Check if install.json exists + ansible.builtin.stat: + path: "{{ agent_dd_config_dir }}/install.json" + register: install_file + +- name: Read remote install.json + register: install_json_value + ansible.builtin.slurp: + src: "{{ agent_dd_config_dir }}/install.json" + when: install_file.stat.exists + +- name: Debug print install.json content + ansible.builtin.debug: + msg: "install.json content : {{ install_json_value.content }}" + when: install_file.stat.exists + +- name: Parse install.json file if it exists + ansible.builtin.set_fact: + install_info: "{{ install_json_value.content | b64decode | from_json }}" + when: install_file.stat.exists + +- name: Generate uuid + when: not install_file.stat.exists + check_mode: false + block: + - name: Generate uuid based on /proc/sys/kernel/random/uuid + ansible.builtin.command: cat /proc/sys/kernel/random/uuid + register: uuid_cmd + changed_when: false + + rescue: + - name: Generate uuid using uuidgen + ansible.builtin.command: uuidgen + register: uuid_cmd + changed_when: false + +- name: Set install signature from file if it exists + ansible.builtin.set_fact: + install_signature: + install_id: "{{ install_info.install_id }}" + install_time: "{{ install_info.install_time }}" + when: install_file.stat.exists + +- name: Generate install signature + ansible.builtin.set_fact: + install_signature: + install_id: "{{ uuid_cmd.stdout }}" + install_time: "{{ ansible_date_time.epoch }}" + when: not install_file.stat.exists + +- name: Create installation json file + ansible.builtin.template: + src: install.json.j2 + dest: "{{ agent_dd_config_dir }}/install.json" + owner: "{{ agent_dd_user }}" + group: "{{ agent_dd_group }}" + mode: "0644" + when: datadog_apm_instrumentation_enabled is defined diff --git a/tasks/_apt-key-import.yml b/tasks/_apt-key-import.yml new file mode 100644 index 00000000..eadd0e7e --- /dev/null +++ b/tasks/_apt-key-import.yml @@ -0,0 +1,100 @@ +--- +# We allow users to specify a file from which to import keys, so we expect +# that to be a binary keyring; at the same time, we have ascii armored +# individual keys at keys.datadoghq.com that we import. The below procedure +# can be called for a URL pointing to a keyring or an ascii armored file +# and extract and import a specific key from it (we specialcase the +# DATADOG_APT_KEY_CURRENT value, which we always expect to be ascii +# armored individual key). + +# NOTE: we use 'noqa risky-shell-pipe' throughout this file, because Debian's +# default shell is /bin/sh which doesn't have a pipefail option and the +# presence of a different shell isn't guaranteed. + +# NOTE: in order to display Ansible's `changed: [hostname]` properly throughout +# tasks in this file, we added `changed_when: false` to a lot of them, even if +# they actually run every time (e.g. importing the CURRENT key). The reason is +# that they operate inside a temporary directory and they don't have a +# permanent effect on the host (nothing will actually change on the host +# whether these tasks run or not) except the last one - the actual import of +# the key to `datadog_apt_usr_share_keyring`. + +- name: Set local variables for processed key {{ item.key }} + ansible.builtin.set_fact: + agent_key_fingerprint: "{{ item.key }}" + agent_keyring_url: "{{ item.value }}" + +- name: Find out whether key is already imported, key = {{ agent_key_fingerprint }} + ansible.builtin.shell: + cmd: > + set -o pipefail && + gpg --no-default-keyring --keyring {{ datadog_apt_usr_share_keyring }} + --list-keys --with-fingerprint --with-colons | grep {{ agent_key_fingerprint }} + executable: /bin/bash + register: agent_key_exists_result + failed_when: false # we expect the command to fail when the key is not found; we never want this task to fail + changed_when: agent_key_exists_result.rc != 0 + when: agent_key_fingerprint != datadog_apt_key_current_name # we always want to import the CURRENT key + +- name: Set local helper variable for determining key import (when not {{ datadog_apt_key_current_name }}) + ansible.builtin.set_fact: + agent_key_needs_import: "{{ false if agent_key_exists_result.rc == 0 else true }}" + when: agent_key_fingerprint != datadog_apt_key_current_name + +- name: Set local helper variable for determining key import (when {{ datadog_apt_key_current_name }}) + ansible.builtin.set_fact: + agent_key_needs_import: true + when: agent_key_fingerprint == datadog_apt_key_current_name + +- name: Create temporary directory for key manipulation + ansible.builtin.tempfile: + state: directory + suffix: keys + register: agent_tempdir + when: agent_key_needs_import + changed_when: false + +- name: Download url to import key. url,key = {{ agent_keyring_url, agent_key_fingerprint }} + ansible.builtin.get_url: + url: "{{ agent_keyring_url }}" + dest: "{{ agent_tempdir.path }}/{{ agent_key_fingerprint }}" + force: true + mode: '600' + when: agent_key_needs_import + changed_when: false + +# gpg --dearmor called on a binary keyring does nothing +- name: Ensure downloaded file for key is a binary keyring, key={{ agent_key_fingerprint }} + ansible.builtin.shell: "cat {{ agent_tempdir.path }}/{{ agent_key_fingerprint }} + | gpg --dearmor > {{ agent_tempdir.path }}/binary.gpg" # noqa risky-shell-pipe + when: agent_key_needs_import + changed_when: false + +- name: Extract the required key from the binary keyring (when not {{ datadog_apt_key_current_name }}) + ansible.builtin.shell: "gpg --no-default-keyring --keyring {{ agent_tempdir.path }}/binary.gpg + --export {{ agent_key_fingerprint }} > {{ agent_tempdir.path }}/single.gpg" + when: agent_key_fingerprint != datadog_apt_key_current_name and agent_key_needs_import + changed_when: false + +- name: Extract the required key from the binary keyring (when {{ datadog_apt_key_current_name }}) + ansible.builtin.copy: + src: "{{ agent_tempdir.path }}/binary.gpg" + dest: "{{ agent_tempdir.path }}/single.gpg" + mode: "0600" + remote_src: true + when: agent_key_fingerprint == datadog_apt_key_current_name and agent_key_needs_import + changed_when: false + +- name: Import key to keyring, key,keyring={{ agent_key_fingerprint, datadog_apt_usr_share_keyring }} + ansible.builtin.shell: cat {{ agent_tempdir.path }}/single.gpg | + gpg --no-default-keyring --keyring {{ datadog_apt_usr_share_keyring }} --import --batch # noqa risky-shell-pipe + when: agent_key_needs_import + register: agent_key_import_result + changed_when: '"imported: 1" in agent_key_import_result.stderr' + +- name: Remove temporary directory for key manipulation + ansible.builtin.file: + path: "{{ agent_tempdir.path }}" + state: absent + when: agent_key_needs_import + changed_when: false diff --git a/tasks/_remove_rpm_keys.yml b/tasks/_remove_rpm_keys.yml new file mode 100644 index 00000000..799ec48a --- /dev/null +++ b/tasks/_remove_rpm_keys.yml @@ -0,0 +1,6 @@ +--- +- name: Ensure GPG key is not present in the RPM db, key={{ item }} + ansible.builtin.rpm_key: + state: absent + key: "{{ item }}" + when: not ansible_check_mode diff --git a/tasks/agent-linux.yml b/tasks/agent-linux.yml index 8b9cd24c..3e225c1e 100644 --- a/tasks/agent-linux.yml +++ b/tasks/agent-linux.yml @@ -1,105 +1,178 @@ --- -- name: populate service facts - service_facts: +- name: Populate service facts + ansible.builtin.service_facts: + when: + - ansible_facts.services is undefined -- name: add "{{ datadog_user }}" user to additional groups - user: name="{{ datadog_user }}" groups="{{ datadog_additional_groups }}" append=yes - when: datadog_additional_groups is defined and (datadog_additional_groups | length != 0) - notify: restart datadog-agent +- name: Set before 6/7.40.0 flag + ansible.builtin.set_fact: + agent_datadog_before_7400: "{{ agent_datadog_major is defined and agent_datadog_minor is defined and agent_datadog_major + | int < 8 and agent_datadog_minor | int < 40 }}" -- name: Create Datadog agent config directory - file: - dest: /etc/datadog-agent - state: directory +- 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 + and datadog_major | int < 8 + and (datadog_minor | int < 61) }}" -- name: Create main Datadog agent configuration file - template: - src: datadog.yaml.j2 - dest: /etc/datadog-agent/datadog.yaml - owner: "{{ datadog_user }}" - group: "{{ datadog_group }}" - notify: restart datadog-agent +- name: Set before 6/7.24.1 flag + ansible.builtin.set_fact: + agent_datadog_before_7241: "{{ agent_datadog_major is defined and agent_datadog_minor is defined and agent_datadog_bugfix is defined + and agent_datadog_major | int < 8 and (agent_datadog_minor | int < 24 or (agent_datadog_minor | int == 24 and agent_datadog_bugfix | int < 1)) }}" -- name: Ensure configuration directories are present for each Datadog check - file: - dest: "/etc/datadog-agent/conf.d/{{ item }}.d" - state: directory - owner: "{{ datadog_user }}" - group: "{{ datadog_group }}" - with_items: '{{ datadog_checks|list }}' +- name: Set before 6/7.18.0 flag + ansible.builtin.set_fact: + agent_datadog_before_7180: "{{ agent_datadog_major is defined and agent_datadog_minor is defined and agent_datadog_major + | int < 8 and agent_datadog_minor | int < 18 }}" -- name: Create a configuration file for each Datadog check - template: - src: checks.yaml.j2 - dest: "/etc/datadog-agent/conf.d/{{ item }}.d/conf.yaml" - owner: "{{ datadog_user }}" - group: "{{ datadog_group }}" - with_items: "{{ datadog_checks|list }}" +- name: Add user to additional groups, user="{{ datadog_user }}" + ansible.builtin.user: + name: "{{ datadog_user }}" + groups: "{{ datadog_additional_groups }}" + append: true + when: datadog_additional_groups | default([], true) | length > 0 notify: restart datadog-agent -- name: Remove old configuration file for each Datadog check - file: - dest: "/etc/datadog-agent/conf.d/{{ item }}.yaml" - state: absent - with_items: "{{ datadog_checks|list }}" - notify: restart datadog-agent +- name: Include configuration setup tasks + ansible.builtin.include_tasks: _agent-linux-macos-shared.yml + vars: + agent_dd_config_dir: /etc/datadog-agent + agent_dd_user: "{{ datadog_user }}" + agent_dd_group: "{{ datadog_group }}" + agent_dd_notify_agent: restart datadog-agent + +- name: Set system probe installed + ansible.builtin.set_fact: + agent_datadog_sysprobe_installed: "{{ ansible_facts.services['datadog-agent-sysprobe'] is defined or + ansible_facts.services['datadog-agent-sysprobe.service'] is defined }}" + when: not datadog_skip_running_check + +# Before 6/7.24.1, system_probe_config controls the system-probe service +# agent_datadog_minor is only defined when a specific Agent version is given +# (see tasks/parse-version.yml) +- name: Set system probe enabled (before 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'] and agent_datadog_sysprobe_installed }}" + when: not datadog_skip_running_check and agent_datadog_before_7241 + +# Since 6/7.24.1, setting enabled: true in network_config is enough to start the system-probe service: +# https://docs.datadoghq.com/network_monitoring/performance/setup/?tab=agent#setup +- 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) + +# Since 6/7.40.0, setting enabled: true in service_monitoring_config is enough to start the system-probe service: +# https://docs.datadoghq.com/tracing/universal_service_monitoring/?tab=configurationfiles#enabling-universal-service-monitoring +- 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) + +# Since 6/7.61.0, setting system_probe_other_config is enough to start the system-probe service: +- 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) - name: Create system-probe configuration file - template: + ansible.builtin.template: src: system-probe.yaml.j2 dest: /etc/datadog-agent/system-probe.yaml - mode: 0640 - owner: "root" + mode: "0640" + owner: root group: "{{ datadog_group }}" + when: datadog_manage_config and not datadog_skip_running_check and (system_probe_config is defined or network_config is defined or + service_monitoring_config is defined or runtime_security_config is defined or system_probe_other_config is defined) + notify: "{% if agent_datadog_before_7180 %}restart datadog-agent-sysprobe{% else %}restart datadog-agent{% endif %}" + +# Templates don't support the "state: absent" argument, so if the file was created in a previous run +# and then all system-probe configs were completely removed, this is the only way to ensure +# we remove the leftover config file. +- name: Remove system-probe configuration file if system-probe is no longer configured + ansible.builtin.file: + path: /etc/datadog-agent/system-probe.yaml + state: absent + when: datadog_manage_config and not datadog_skip_running_check and system_probe_config is not defined and network_config is not defined and + service_monitoring_config is not defined and runtime_security_config is not defined and system_probe_other_config is not defined + notify: "{% if agent_datadog_before_7180 %}restart datadog-agent-sysprobe{% else %}restart datadog-agent{% endif %}" - name: Ensure datadog-agent is running - service: + ansible.builtin.service: name: datadog-agent state: started - enabled: yes + enabled: true + use: service when: not datadog_skip_running_check and datadog_enabled and not ansible_check_mode - -- name: set system probe installed - set_fact: - datadog_sysprobe_installed: "{{ ansible_facts.services['datadog-agent-sysprobe'] is defined - or ansible_facts.services['datadog-agent-sysprobe.service'] is defined }}" - when: not datadog_skip_running_check - -- name: set system probe enabled - set_fact: - datadog_sysprobe_enabled: "{{ system_probe_config is defined - and system_probe_config['enabled'] - and datadog_sysprobe_installed }}" - when: not datadog_skip_running_check + and (ansible_facts.services['datadog-agent-exp.service'] is not defined or ansible_facts.services['datadog-agent-exp.service'].state != "running") - name: Ensure datadog-agent-sysprobe is running if enabled and installed - service: + ansible.builtin.service: name: datadog-agent-sysprobe state: started - enabled: yes - when: not datadog_skip_running_check and datadog_enabled and not ansible_check_mode and datadog_sysprobe_enabled - -- name: Ensure datadog-agent-sysprobe is stopped if disabled or not installed - service: - name: datadog-agent-sysprobe - state: stopped - enabled: no - when: not datadog_skip_running_check and (not datadog_enabled or not datadog_sysprobe_enabled) and datadog_sysprobe_installed + enabled: true + use: service + when: not datadog_skip_running_check and datadog_enabled and not ansible_check_mode and agent_datadog_sysprobe_enabled - name: Ensure datadog-agent, datadog-agent-process and datadog-agent-trace are not running - service: + ansible.builtin.service: name: "{{ item }}" state: stopped - enabled: no - when: not datadog_skip_running_check and not datadog_enabled + enabled: false + use: service + when: not datadog_skip_running_check and not datadog_enabled and not ansible_check_mode with_list: - datadog-agent - datadog-agent-process - datadog-agent-trace -- name: Create installation information file - template: - src: install_info.j2 - dest: /etc/datadog-agent/install_info - owner: "{{ datadog_user }}" +# Stop system-probe manually on Agent versions < 6/7.18, as it was not tied +# to the main Agent service: https://github.com/DataDog/datadog-agent/pull/4883 +- name: Ensure datadog-agent-sysprobe is stopped if disabled or not installed (before 6/7.18.0) + ansible.builtin.service: + name: datadog-agent-sysprobe + state: stopped + enabled: false + use: service + when: not datadog_skip_running_check and (not datadog_enabled or not agent_datadog_sysprobe_enabled) + and agent_datadog_before_7180 and agent_datadog_sysprobe_installed + +- name: Ensure datadog-agent-security is not running + ansible.builtin.service: + name: datadog-agent-security + state: stopped + enabled: false + use: service + when: not datadog_skip_running_check and not datadog_enabled + failed_when: false # Since older versions of the Agent don't include the security agent + +- name: Create security-agent configuration file + ansible.builtin.template: + src: security-agent.yaml.j2 + dest: /etc/datadog-agent/security-agent.yaml + mode: "0640" + owner: root group: "{{ datadog_group }}" + when: datadog_manage_config and (runtime_security_config is defined and runtime_security_config | default({}, true) | length > 0) + notify: "{% if agent_datadog_before_7180 %}restart datadog-agent-sysprobe{% else %}restart datadog-agent{% endif %}" + +# Templates don't support the "state: absent" argument, so if the file was created in a previous run +# and then runtime_security_config was completely removed, this is the only way to ensure +# we remove the leftover config file. +- name: Remove security-agent configuration file if security-agent is no longer configured + ansible.builtin.file: + path: /etc/datadog-agent/security-agent.yaml + state: absent + when: datadog_manage_config and (runtime_security_config is not defined or runtime_security_config | default({}, true) | length == 0) + notify: "{% if agent_datadog_before_7180 %}restart datadog-agent-sysprobe{% else %}restart datadog-agent{% endif %}" diff --git a/tasks/agent-macos.yml b/tasks/agent-macos.yml new file mode 100644 index 00000000..143d45fe --- /dev/null +++ b/tasks/agent-macos.yml @@ -0,0 +1,98 @@ +--- +# NOTE: the DMG gets installed as ansible_user, but we then configure it to run +# under datadog_macos_user and remove the user-specific config for ansible_user +- name: Load user data + ansible.builtin.shell: + cmd: "set -o pipefail && dscacheutil -q user -a name {{ datadog_macos_user }} | + awk 'BEGIN { RS=\"\\n\"; ORS=\" \" } /uid:/ { print \"{ \\\"uid\\\": \" $2\",\" } /gid:/ { print + \"\\\"gid\\\": \" $2 \" }\"}'" + executable: /bin/bash + changed_when: false + register: agent_macos_user_output + check_mode: false + +# This task is used to more cleanly format the variable contents.The ABOVE task's shell command returns a JSON +# object as a string but nested in `.stdout`. Ansible has built in behavior that if it receives JSON data as +# a string it will automatically convert it to the corresponding object. This enables us to get multiple values +# out of the ABOVE task preventing us from having to run 2 similar commands. +- name: Extract JSON user data as variable object + ansible.builtin.set_fact: + agent_macos_user_data: "{{ agent_macos_user_output.stdout | from_json }}" + +- name: Load user group data + ansible.builtin.shell: + cmd: "set -o pipefail && dscacheutil -q group -a gid {{ agent_macos_user_data.gid }} | grep '^name: ' | awk '{ print $2 }'" + executable: /bin/bash + register: agent_macos_user_group + changed_when: false + +# If the ansible_user was logged in via GUI during installation, the postinstall package script +# created launchctl service for the user and also a login item + +- name: Find out if user LaunchAgent is running + ansible.builtin.shell: + cmd: "launchctl print gui/$(id -u)/{{ datadog_macos_service_name }}" + register: agent_user_service_created + changed_when: false + failed_when: false + +- name: Unload and stop user LaunchAgent + ansible.builtin.shell: + cmd: "launchctl bootout gui/$(id -u)/{{ datadog_macos_service_name }}" + when: agent_user_service_created.rc == 0 + changed_when: false + +- name: Remove user login item + ansible.builtin.command: |- + osascript -e 'tell application "System Events" to if login item "Datadog Agent" exists then delete login item "Datadog Agent"' + when: agent_user_service_created.rc == 0 + changed_when: false + +- name: Remove user LaunchAgent plist file + ansible.builtin.file: + path: /Users/{{ ansible_user }}/{{ datadog_macos_user_plist_file_path }} + state: absent + +# We could take the plist file from user LaunchAgent location and just add UID/GID, +# but when the version is pinned and agent is already installed, that file had +# already been removed and won't be recreated and so we won't be able to use it. +# +# The disadvantage of using a template obviously is that if we changed the plist +# file in the .dmg, we would also have to update this. Fortunately this seems +# to basically never happen, so I think it's an acceptable downside. +- name: Add system LaunchDaemon plist file + ansible.builtin.template: + src: com.datadoghq.agent.plist.j2 + dest: "{{ datadog_macos_system_plist_file_path }}" + owner: 0 + group: 0 + mode: "0644" + become: true + notify: restart datadog-agent-macos + vars: + # NOTE: https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html + # docs say both UID/GID and UserName/GroupName work, but only UserName/GroupName actually work. + agent_username: "{{ datadog_macos_user }}" + agent_groupname: "{{ agent_macos_user_group.stdout }}" + +- name: Include configuration setup tasks + ansible.builtin.import_tasks: _agent-linux-macos-shared.yml + vars: + agent_dd_config_dir: "{{ datadog_macos_etc_dir }}" + agent_dd_user: "{{ agent_macos_user_data.uid }}" + agent_dd_group: "{{ agent_macos_user_data.gid }}" + agent_dd_notify_agent: "restart datadog-agent-macos" + become: true + +- name: Set permissions for DataDog Directories + ansible.builtin.file: + path: "{{ item }}" + owner: "{{ agent_macos_user_data.uid }}" + group: "{{ agent_macos_user_data.gid }}" + recurse: true + with_items: + - "{{ datadog_macos_etc_dir }}" + - "{{ datadog_macos_logs_dir }}" + - "{{ datadog_macos_run_dir }}" + notify: restart datadog-agent-macos + become: true diff --git a/tasks/agent-win.yml b/tasks/agent-win.yml index c9492bce..bb58cc02 100644 --- a/tasks/agent-win.yml +++ b/tasks/agent-win.yml @@ -1,48 +1,154 @@ --- - name: Create main Datadog agent configuration file - win_template: + ansible.builtin.template: src: datadog.yaml.j2 - dest: "{{ datadog_windows_config_root }}\\datadog.yaml" + dest: "{{ agent_datadog_windows_config_root }}\\datadog.yaml" + mode: '0644' + when: datadog_manage_config + notify: restart datadog-agent-win + +- name: Register all check configs present in datadog + ansible.windows.win_find: + paths: "{{ ansible_facts.env['ProgramData'] }}\\Datadog\\conf.d" + patterns: + - "conf.yaml*" + recurse: true + depth: 2 + file_type: file + register: agent_datadog_conf_paths + when: datadog_manage_config and (datadog_disable_untracked_checks or datadog_disable_default_checks) + +- name: Delete checks not present in agent_datadog_tracked_checks + ansible.windows.win_file: + path: "{{ ansible_facts.env['ProgramData'] }}\\Datadog\\conf.d\\{{ item }}.d\\conf.yaml" + state: absent + loop: >- + {{ + agent_datadog_conf_paths.files | map(attribute='path') | select('match', '.*\\conf\.yaml$') | list + | map('win_dirname') | map('win_basename') | list | map('regex_replace', '^(.*).d$', '\1') | list + }} + when: datadog_manage_config and datadog_disable_untracked_checks and item not in agent_datadog_tracked_checks + notify: restart datadog-agent-win + +- name: Delete default checks + ansible.windows.win_file: + path: "{{ ansible_facts.env['ProgramData'] }}\\Datadog\\conf.d\\{{ item }}.d\\conf.yaml.default" + state: absent + loop: >- + {{ + agent_datadog_conf_paths.files | map(attribute='path') | select('match', '.*\\conf\.yaml\.default$') | list + | map('win_dirname') | map('win_basename') | list | map('regex_replace', '^(.*).d$', '\1') | list + }} + when: datadog_manage_config and datadog_disable_default_checks and item not in agent_datadog_tracked_checks + notify: restart datadog-agent-win + +- name: Delete example checks + ansible.windows.win_file: + path: "{{ ansible_facts.env['ProgramData'] }}\\Datadog\\conf.d\\{{ item }}.d\\conf.yaml.example" + state: absent + loop: >- + {{ + agent_datadog_conf_paths.files | map(attribute='path') | select('match', '.*\\conf\.yaml\.example$') | list + | map('win_dirname') | map('win_basename') | list | map('regex_replace', '^(.*).d$', '\1') | list + }} + when: datadog_manage_config and datadog_disable_example_checks and item not in agent_datadog_tracked_checks notify: restart datadog-agent-win - name: Ensure configuration directories are present for each Datadog check - win_file: - path: "{{ datadog_windows_config_root }}\\conf.d\\{{ item }}.d" + ansible.windows.win_file: + path: "{{ agent_datadog_windows_config_root }}\\conf.d\\{{ item }}.d" state: directory - with_items: '{{ datadog_checks|list }}' + with_items: "{{ agent_datadog_checks | list }}" + when: datadog_manage_config - name: Create a configuration file for each Datadog check - win_template: + ansible.builtin.template: src: checks.yaml.j2 - dest: "{{ datadog_windows_config_root }}\\conf.d\\{{ item }}.d\\conf.yaml" - with_items: "{{ datadog_checks|list }}" + dest: "{{ agent_datadog_windows_config_root }}\\conf.d\\{{ item }}.d\\conf.yaml" + mode: '0644' + with_items: "{{ agent_datadog_checks | list }}" + when: datadog_manage_config notify: restart datadog-agent-win - name: Remove old configuration file for each Datadog check - win_file: - path: "{{ datadog_windows_config_root }}\\conf.d\\{{ item }}.yaml" + ansible.windows.win_file: + path: "{{ agent_datadog_windows_config_root }}\\conf.d\\{{ item }}.yaml" state: absent - with_items: "{{ datadog_checks|list }}" + with_items: "{{ agent_datadog_checks | list }}" + when: datadog_manage_config + notify: restart datadog-agent-win + +- name: Create custom check file for each custom check + ansible.windows.win_copy: + src: "{{ datadog_custom_checks[item] }}" + dest: "{{ agent_datadog_windows_config_root }}\\checks.d\\{{ item }}.py" + with_items: "{{ datadog_custom_checks | list }}" + notify: restart datadog-agent-win + +- name: Ensure datadog-trace-agent and datadog-process-agent are not disabled + ansible.windows.win_service: + name: "{{ item }}" + start_mode: manual + when: not datadog_skip_running_check and datadog_enabled and not ansible_check_mode and not datadog_remote_update_in_progress + with_list: + - datadog-trace-agent + - datadog-process-agent + +- name: Create system-probe configuration file + ansible.builtin.template: + src: system-probe.yaml.j2 + dest: "{{ agent_datadog_windows_config_root }}\\system-probe.yaml" + mode: '0644' + when: datadog_manage_config notify: restart datadog-agent-win +- name: Check if datadog-agent service exists + ansible.windows.win_service: + name: datadogagent + register: datadog_service_info + when: not datadog_skip_running_check and datadog_enabled and not ansible_check_mode and not datadog_remote_update_in_progress + - name: Ensure datadog-agent is running - win_service: + ansible.windows.win_service: name: datadogagent state: started - start_mode: auto - when: not datadog_skip_running_check and datadog_enabled and not ansible_check_mode + start_mode: delayed + when: + - not datadog_skip_running_check + - datadog_enabled + - not ansible_check_mode + - (datadog_service_info.exists | default(false)) + - not datadog_remote_update_in_progress + failed_when: false + register: datadog_start_result -- name: Ensure datadog-agent is not running - win_service: +- name: Wait and retry if service failed to start + ansible.windows.win_service: + name: datadogagent + state: started + when: + - not datadog_skip_running_check + - datadog_enabled + - not ansible_check_mode + - (datadog_service_info.exists | default(false)) + - (datadog_start_result.failed | default(false)) + - not datadog_remote_update_in_progress + delay: 10 + retries: 3 + +- name: Ensure datadog-agent is disabled + ansible.windows.win_service: name: "{{ item }}" state: stopped - when: not datadog_skip_running_check and not datadog_enabled + start_mode: disabled + when: not datadog_skip_running_check and not datadog_enabled and not datadog_remote_update_in_progress with_list: - - datadogagent - - datadog-process-agent - datadog-trace-agent + - datadog-process-agent + - datadogagent - name: Create installation information file - template: + ansible.builtin.template: src: install_info.j2 - dest: "{{ datadog_windows_config_root }}\\install_info" + dest: "{{ agent_datadog_windows_config_root }}\\install_info" + mode: '0644' diff --git a/tasks/agent5-linux.yml b/tasks/agent5-linux.yml deleted file mode 100644 index 507bfd3d..00000000 --- a/tasks/agent5-linux.yml +++ /dev/null @@ -1,43 +0,0 @@ ---- -- name: (agent5) Create Datadog agent config directory - file: - dest: /etc/dd-agent - state: directory - -- name: (agent5) Create main Datadog agent configuration file - template: - src: datadog.conf.j2 - dest: /etc/dd-agent/datadog.conf - owner: "{{ datadog_user }}" - group: "{{ datadog_group }}" - notify: restart datadog-agent - -- name: (agent5) Ensure datadog-agent is running - service: - name: datadog-agent - state: started - enabled: yes - when: not datadog_skip_running_check and datadog_enabled and not ansible_check_mode - -- name: (agent5) Ensure datadog-agent is not running - service: - name: datadog-agent - state: stopped - enabled: no - when: not datadog_skip_running_check and not datadog_enabled - -- name: (agent5) Create a configuration file for each Datadog check - template: - src: checks.yaml.j2 - dest: "/etc/dd-agent/conf.d/{{ item }}.yaml" - owner: "{{ datadog_user }}" - group: "{{ datadog_group }}" - with_items: "{{ datadog_checks|list }}" - notify: restart datadog-agent - -- name: Create installation information file - template: - src: install_info.j2 - dest: /etc/dd-agent/install_info - owner: "{{ datadog_user }}" - group: "{{ datadog_group }}" diff --git a/tasks/apm-single-step-instrumentation.yml b/tasks/apm-single-step-instrumentation.yml new file mode 100644 index 00000000..e69d10d6 --- /dev/null +++ b/tasks/apm-single-step-instrumentation.yml @@ -0,0 +1,59 @@ +--- +# We use this step to not render empty environment variables when not explicitly set +- name: Build Datadog installer environment variables + ansible.builtin.set_fact: + datadog_apm_single_step_instrumentation_environment: > + {{ + { + 'DD_APM_INSTRUMENTATION_ENABLED': datadog_apm_instrumentation_enabled, + 'DD_APM_INSTRUMENTATION_LIBRARIES': datadog_apm_instrumentation_libraries | join(','), + 'DD_INSTALLER_REGISTRY_AUTH_INSTALLER_PACKAGE': datadog_installer_auth, + 'DD_INSTALLER_REGISTRY_URL_INSTALLER_PACKAGE': datadog_installer_registry, + 'DD_INSTALLER_DEFAULT_PKG_VERSION_DATADOG_INSTALLER': datadog_installer_version, + 'DD_INSTALLER_DEFAULT_PKG_VERSION_DATADOG_APM_INJECT': datadog_apm_inject_version, + } + | dict2items + | rejectattr('value', 'equalto', '') + | items2dict + }} + +# Build the installer-domain url if datadog_installer_registry is set, else default to install.datadoghq.com for the domain. +- name: Build installer script url + ansible.builtin.set_fact: + datadog_installer_install_ssi_script_url: >- + {{ + 'https://' + datadog_installer_registry + '/scripts/install-ssi.sh' + if datadog_installer_registry != '' + else 'https://install.datadoghq.com/scripts/install-ssi.sh' + }} + +# Create the directory for the datadog-installer script +- name: Create directory for SSI script + ansible.builtin.file: + path: "{{ datadog_ssi_script_dir }}" + state: directory + mode: "0755" + +# We download the datadog-installer install-ssi.sh script. +- name: Download datadog-installer install-ssi.sh script + ansible.builtin.get_url: + url: "{{ datadog_installer_install_ssi_script_url }}" + dest: "{{ datadog_ssi_script_dir }}/install-ssi.sh" + mode: "0750" + # Always overwrite the file to ensure we have the latest version. + force: true + register: install_ssi_script_result + +- name: Run datadog-installer install-ssi.sh script + ansible.builtin.command: + cmd: "{{ datadog_ssi_script_dir }}/install-ssi.sh" + environment: "{{ datadog_apm_single_step_instrumentation_environment }}" + when: install_ssi_script_result.status_code == 200 + changed_when: true + +# Clean up the script after execution for security +- name: Clean up SSI script after execution + ansible.builtin.file: + path: "{{ datadog_ssi_script_dir }}/install-ssi.sh" + state: absent + when: install_ssi_script_result.status_code == 200 diff --git a/tasks/check-removed-config.yml b/tasks/check-removed-config.yml new file mode 100644 index 00000000..878bf6a0 --- /dev/null +++ b/tasks/check-removed-config.yml @@ -0,0 +1,10 @@ +--- +- 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 + +- 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 diff --git a/tasks/integration.yml b/tasks/integration.yml index e1263d63..634b547b 100644 --- a/tasks/integration.yml +++ b/tasks/integration.yml @@ -1,67 +1,21 @@ --- -- name: set agent binary path (windows) - set_fact: - datadog_agent_binary_path: "{{ datadog_agent_binary_path_windows }}" - when: ansible_os_family == "Windows" - -- name: set agent binary path (unix) - set_fact: - datadog_agent_binary_path: "{{ datadog_agent_binary_path_linux }}" - when: ansible_os_family != "Windows" - -- name: set agent user for integration commmand (windows) - set_fact: - integration_command_user: "{{ integration_command_user_windows }}" - when: ansible_os_family == "Windows" - -- name: set agent agent binary path (unix) - set_fact: - integration_command_user: "{{ integration_command_user_linux }}" - when: ansible_os_family != "Windows" - - name: Validate integrations actions - fail: + ansible.builtin.fail: msg: "Unkown action '{{ item.value.action }}' for integration command ({{ item.key }}). Valid actions are 'install' and 'remove'" when: item.value.action != "install" and item.value.action != "remove" - loop: "{{ datadog_integration|dict2items }}" - -# Remove Integrations - -- name: Removing integrations (Unix) - command: - argv: - - "{{ datadog_agent_binary_path }}" - - integration - - remove - - "{{ item.key }}" - become: yes - become_user: "{{ integration_command_user }}" - loop: "{{ datadog_integration|dict2items }}" - when: item.value.action == "remove" and ansible_os_family != "Windows" - -- name: Removing integrations (Windows) - win_command: "\"{{ datadog_agent_binary_path }}\" integration remove {{ item.key }}" - become: yes - become_user: "{{ integration_command_user }}" - loop: "{{ datadog_integration|dict2items }}" - when: item.value.action == "remove" and ansible_os_family == "Windows" - -# Install integrations - -- name: Install pinned version of integrations (Unix) - command: "{{ datadog_agent_binary_path }} integration install {{ third_party }} {{ item.key }}=={{ item.value.version }}" - become: yes - become_user: "{{ integration_command_user }}" - vars: - third_party: "{% if 'third_party' in item.value and item.value.third_party | bool %}--third-party{% endif %}" - loop: "{{ datadog_integration|dict2items }}" - when: item.value.action == "install" and ansible_os_family != "Windows" - -- name: Install pinned version of integrations (Windows) - win_command: "\"{{ datadog_agent_binary_path }}\" integration install {{ third_party }} {{ item.key }}=={{ item.value.version }}" - become: yes - vars: - third_party: "{% if 'third_party' in item.value and item.value.third_party | bool %}--third-party{% endif %}" - become_user: "{{ integration_command_user }}" - loop: "{{ datadog_integration|dict2items }}" - when: item.value.action == "install" and ansible_os_family == "Windows" + loop: "{{ datadog_integration | dict2items }}" + +# The Windows tasks use win_command, so if users don't have the "ansible.windows" collection +# installed, parsing the task would fail even if the host is not Windows. By hiding the task +# inside a conditionally included file, we can prevent this. +- name: Include Windows Integration Tasks + ansible.builtin.include_tasks: integration/windows.yml + when: ansible_facts.os_family == "Windows" + +- name: Include macOS Integration Tasks + ansible.builtin.include_tasks: integration/macos.yml + when: ansible_facts.os_family == "Darwin" + +- name: Include Linux Integration Tasks + ansible.builtin.include_tasks: integration/linux.yml + when: ansible_facts.os_family != "Darwin" and ansible_facts.os_family != "Windows" diff --git a/tasks/integration/_linux-macos-shared.yml b/tasks/integration/_linux-macos-shared.yml new file mode 100644 index 00000000..caffa4a8 --- /dev/null +++ b/tasks/integration/_linux-macos-shared.yml @@ -0,0 +1,42 @@ +# Check current state of the integration + +- name: Check integration state, integration={{ item.key }} + ansible.builtin.command: + argv: + - "{{ datadog_agent_binary_path }}" + - integration + - show + - -q + - "{{ item.key }}" + register: integration_version + failed_when: false # This task is supposed to fail when the integration is not installed + changed_when: false + +# Remove integration + +- name: Removing integration, integration={{ item.key }} + ansible.builtin.command: + argv: + - "{{ datadog_agent_binary_path }}" + - integration + - remove + - "{{ item.key }}" + become: true + become_user: "{{ integration_command_user }}" + when: + - item.value.action == "remove" + - integration_version.rc == 0 + changed_when: true + +# Install integration + +- 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 }}" + become: true + become_user: "{{ integration_command_user }}" + vars: + third_party: "{% if 'third_party' in item.value and item.value.third_party | bool %}--third-party{% endif %}" + when: + - item.value.action == "install" + - integration_version.stdout | trim != item.value.version + changed_when: true diff --git a/tasks/integration/_windows-integration-update.yml b/tasks/integration/_windows-integration-update.yml new file mode 100644 index 00000000..aeeddf8f --- /dev/null +++ b/tasks/integration/_windows-integration-update.yml @@ -0,0 +1,31 @@ +# Check current state of the integrations + +- name: Check integration state, integration={{ item.key }} + ansible.windows.win_command: "\"{{ datadog_agent_binary_path }}\" integration show -q {{ item.key }}" + register: integration_version + failed_when: false # This task is supposed to fail when the integration is not installed + changed_when: false + +# Remove integration + +- name: Removing integration, integration={{ item.key }} + ansible.windows.win_command: "\"{{ datadog_agent_binary_path }}\" integration remove {{ item.key }}" + become: true + become_user: "{{ integration_command_user }}" + when: + - item.value.action == "remove" + - integration_version.rc == 0 + changed_when: true + +# Install integration + +- name: Installing pinned version of integration, integration={{ item.key }} + ansible.windows.win_command: "\"{{ datadog_agent_binary_path }}\" integration install {{ third_party }} {{ item.key }}=={{ item.value.version }}" + become: true + vars: + third_party: "{% if 'third_party' in item.value and item.value.third_party | bool %}--third-party{% endif %}" + become_user: "{{ integration_command_user }}" + when: + - item.value.action == "install" + - integration_version.stdout | trim != item.value.version + changed_when: true diff --git a/tasks/integration/linux.yml b/tasks/integration/linux.yml new file mode 100644 index 00000000..4cb40bd4 --- /dev/null +++ b/tasks/integration/linux.yml @@ -0,0 +1,19 @@ +--- +- name: Check if /bin/datadog-agent exists + ansible.builtin.stat: + path: /bin/datadog-agent + register: bin_agent + when: datadog_agent_binary_path is not defined + +- name: Set Agent binary path + ansible.builtin.set_fact: + datadog_agent_binary_path: "{{ '/bin/datadog-agent' if bin_agent.stat.exists else datadog_agent_binary_path_linux }}" + when: datadog_agent_binary_path is not defined + +- name: Set Agent user for integration commmand + ansible.builtin.set_fact: + integration_command_user: "{{ integration_command_user_linux }}" + +- name: Include shared integration installation and removal tasks + ansible.builtin.include_tasks: integration/_linux-macos-shared.yml + loop: "{{ datadog_integration | dict2items }}" diff --git a/tasks/integration/macos.yml b/tasks/integration/macos.yml new file mode 100644 index 00000000..c97eb7c4 --- /dev/null +++ b/tasks/integration/macos.yml @@ -0,0 +1,12 @@ +--- +- name: Set Agent binary path + ansible.builtin.set_fact: + datadog_agent_binary_path: "{{ datadog_agent_binary_path_macos }}" + +- name: Set Agent user for integration commmand + ansible.builtin.set_fact: + integration_command_user: "{{ integration_command_user_macos }}" + +- name: Include shared integration installation and removal tasks + ansible.builtin.include_tasks: integration/_linux-macos-shared.yml + loop: "{{ datadog_integration | dict2items }}" diff --git a/tasks/integration/windows.yml b/tasks/integration/windows.yml new file mode 100644 index 00000000..dc154543 --- /dev/null +++ b/tasks/integration/windows.yml @@ -0,0 +1,12 @@ +--- +- name: Set Agent binary path + ansible.builtin.set_fact: + datadog_agent_binary_path: "{{ datadog_agent_binary_path_windows }}" + +- name: Set Agent user for integration commmand + ansible.builtin.set_fact: + integration_command_user: "{{ integration_command_user_windows }}" + +- name: Include integration installation and removal tasks + ansible.builtin.include_tasks: integration/_windows-integration-update.yml + loop: "{{ datadog_integration | dict2items }}" diff --git a/tasks/main.yml b/tasks/main.yml index e5393d26..d22a41be 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,47 +1,128 @@ --- +- name: Gather Ansible Facts + ansible.builtin.setup: + gather_subset: "{{ datadog_ansible_facts_subset }}" + # 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 + +- name: Initialize internal datadog_config variable + ansible.builtin.set_fact: + agent_datadog_config: "{{ datadog_config }}" - name: Check if OS is supported - include_tasks: os-check.yml + ansible.builtin.include_tasks: os-check.yml + +# Check for Windows remote updates before proceeding with installation +- name: Windows remote update check + ansible.builtin.include_tasks: windows_remote_update_check.yml + when: ansible_facts.os_family == "Windows" + +- name: Fail if API key is missing + ansible.builtin.fail: + 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 + ansible.builtin.include_tasks: sanitize-checks.yml + +# Also sets agent_datadog_skip_install - name: Set Facts for Datadog Agent Major Version - include_tasks: set-parse-version.yml + ansible.builtin.include_tasks: set-parse-version.yml + +- name: Remove /opt/datadog-agent/python-scripts/__pycache__ + ansible.builtin.file: + path: /opt/datadog-agent/python-scripts/__pycache__ + state: absent + when: not agent_datadog_skip_install and ansible_facts.os_family != "Windows" and ansible_facts.os_family != "Darwin" + failed_when: false + changed_when: false + +- name: Remove legacy package-based datadog-installer + ansible.builtin.include_tasks: remove-legacy-installer.yml + when: + - ansible_facts.os_family != "Windows" + - ansible_facts.os_family != "Darwin" + - not ansible_check_mode - name: Debian Install Tasks - include_tasks: pkg-debian.yml - when: ansible_os_family == "Debian" + ansible.builtin.include_tasks: pkg-debian.yml + when: ansible_facts.os_family == "Debian" +- name: Include tasks to remove old GPG keys + ansible.builtin.include_tasks: _remove_rpm_keys.yml + when: ansible_facts.os_family in ["RedHat", "Rocky", "AlmaLinux", "Suse"] + loop: "{{ datadog_rpm_remove_keys }}" + +- name: Include tasks to check removed configuration value usage + ansible.builtin.include_tasks: check-removed-config.yml + +# Only Ansible >= 3.0 knows that AlmaLinux belongs to "RedHat" family +# (and latest bugfix releases of some 2.X) +# For Rocky it is some 4.X and >= 5.0 - name: RedHat Install Tasks - include_tasks: pkg-redhat.yml - when: ansible_os_family == "RedHat" + ansible.builtin.include_tasks: pkg-redhat.yml + when: ansible_facts.os_family in ["RedHat", "Rocky", "AlmaLinux"] - name: Suse Install Tasks - include_tasks: pkg-suse.yml - when: ansible_os_family == "Suse" + ansible.builtin.include_tasks: pkg-suse.yml + when: ansible_facts.os_family == "Suse" + +# Windows variable initialization - always needed for configuration +- name: Set windows NPM installed + ansible.builtin.set_fact: + agent_datadog_sysprobe_enabled: "{{ network_config is defined and 'enabled' in (network_config | default({}, true)) and network_config['enabled'] }}" + when: ansible_facts.os_family == "Windows" +- name: Include Windows opts tasks + ansible.builtin.include_tasks: pkg-windows-opts.yml + when: ansible_facts.os_family == "Windows" + +# Note we don't check agent_datadog_skip_install variable value for windows here, +# because some tasks in pkg-windows.yml are carried out regardless of its value. - name: Windows Install Tasks - include_tasks: pkg-windows.yml - when: ansible_os_family == "Windows" + ansible.builtin.include_tasks: pkg-windows.yml + when: ansible_facts.os_family == "Windows" and not datadog_remote_update_in_progress -- name: Linux Configuration Tasks (Agent 5) - include_tasks: agent5-linux.yml - when: datadog_agent_major_version|int == 5 and ansible_os_family != "Windows" +- name: MacOS Install Tasks + ansible.builtin.include_tasks: pkg-macos.yml + when: ansible_facts.os_family == "Darwin" and not agent_datadog_skip_install - name: Linux Configuration Tasks - include_tasks: agent-linux.yml - when: datadog_agent_major_version|int > 5 and ansible_os_family != "Windows" + ansible.builtin.include_tasks: agent-linux.yml + when: ansible_facts.os_family != "Windows" and ansible_facts.os_family != "Darwin" - name: Windows Configuration Tasks - include_tasks: agent-win.yml - when: datadog_agent_major_version|int > 5 and ansible_os_family == "Windows" + ansible.builtin.include_tasks: agent-win.yml + when: ansible_facts.os_family == "Windows" + +- name: MacOS Configuration Tasks + ansible.builtin.include_tasks: agent-macos.yml + when: ansible_facts.os_family == "Darwin" - name: Integrations Tasks - include_tasks: integration.yml + ansible.builtin.include_tasks: integration.yml when: datadog_integration is defined -- name: Post Tasks - include_tasks: post_tasks/*.yml - when: post_tasks is defined +# Determine if APM Single Step Instrumentation should be installed +- name: Determine and validate APM Single Step Instrumentation configuration + ansible.builtin.set_fact: + apm_single_step_instrumentation_should_install: >- + {{ + datadog_apm_instrumentation_enabled is defined + and datadog_apm_instrumentation_enabled in ["host", "docker", "all"] + }} + +- name: Fail explicitly if APM Single Step Instrumentation is desired but misconfigured + ansible.builtin.fail: + msg: "datadog_apm_instrumentation_enabled must be set to 'host', 'docker', or 'all' when enabling APM Single Step Instrumentation" + when: + - datadog_apm_instrumentation_enabled is defined + - datadog_apm_instrumentation_enabled not in ["host", "docker", "all"] -- name: Pre Tasks - include_tasks: pre_tasks/*.yml - when: pre_tasks is defined +- name: APM Single Step Instrumentation Install Tasks + ansible.builtin.include_tasks: apm-single-step-instrumentation.yml + when: + - apm_single_step_instrumentation_should_install + - not ansible_check_mode diff --git a/tasks/os-check.yml b/tasks/os-check.yml index b2bbebc2..b5a56a4d 100644 --- a/tasks/os-check.yml +++ b/tasks/os-check.yml @@ -1,5 +1,5 @@ --- - name: Fail if OS is not supported - fail: + ansible.builtin.fail: msg: "The Datadog Ansible role does not support your OS yet. Please email support@datadoghq.com to open a feature request." - when: ansible_os_family not in ["RedHat", "Debian", "Suse", "Windows"] + when: ansible_facts.os_family not in ["RedHat", "Rocky", "AlmaLinux", "Debian", "Suse", "Windows", "Darwin"] diff --git a/tasks/parse-version-macos.yml b/tasks/parse-version-macos.yml new file mode 100644 index 00000000..9601613a --- /dev/null +++ b/tasks/parse-version-macos.yml @@ -0,0 +1,10 @@ +--- +- 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 + register: agent_datadog_version_check_macos + changed_when: false + failed_when: false + check_mode: false + when: ansible_facts.os_family == "Darwin" diff --git a/tasks/parse-version-windows.yml b/tasks/parse-version-windows.yml new file mode 100644 index 00000000..cf307d3e --- /dev/null +++ b/tasks/parse-version-windows.yml @@ -0,0 +1,38 @@ +--- +# NOTE: This won't work with rc / beta builds. +- name: Get Windows Agent version + ansible.windows.win_shell: | + $product_name = "Datadog Agent" + $version=Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | + Select-Object DisplayName,DisplayVersion,PSChildName -unique | + Where-Object {$_.DisplayName -clike $product_name} | + Select-Object DisplayVersion -ExpandProperty DisplayVersion + + if (!$version) { + Write-Host "" + } else { + $ddmaj, $ddmin, $ddpatch, $ddbuild = $version.split(".") + Write-Host "$($ddmaj).$($ddmin).$($ddpatch)" + } + register: agent_datadog_version_check_win + changed_when: false + failed_when: false + check_mode: false + when: ansible_facts.os_family == "Windows" + +- name: Parse installed Windows Agent version into components + ansible.builtin.set_fact: + agent_datadog_installed_version: "{{ agent_datadog_version_check_win.stdout | trim | + regex_search(installed_agent_regexp, '\\g', '\\g', '\\g') }}" + vars: + installed_agent_regexp: (?P[0-9]+)\.(?P[0-9]+)\.(?P[0-9]+) + when: >- + ansible_facts.os_family == "Windows" and + agent_datadog_version_check_win.stdout | trim | length > 0 + +- name: Set installed version component vars + ansible.builtin.set_fact: + agent_datadog_installed_major: "{{ agent_datadog_installed_version.0 | default('', true) | string }}" + agent_datadog_installed_minor: "{{ agent_datadog_installed_version.1 | default('', true) | string }}" + agent_datadog_installed_bugfix: "{{ agent_datadog_installed_version.2 | default('', true) | string }}" + when: ansible_facts.os_family == "Windows" and agent_datadog_version_check_win.stdout | trim | length > 0 diff --git a/tasks/parse-version.yml b/tasks/parse-version.yml index a9971104..0d7b33ac 100644 --- a/tasks/parse-version.yml +++ b/tasks/parse-version.yml @@ -1,43 +1,104 @@ --- - name: Parse Agent version - set_fact: - agent_version: "{{ datadog_agent_version | regex_search(regexp, '\\g', '\\g', '\\g', '\\g', '\\g', '\\g') }}" + ansible.builtin.set_fact: + agent_version: "{{ datadog_agent_version + | regex_search(agent_regexp, '\\g', '\\g', '\\g', '\\g', '\\g', '\\g') }}" vars: - regexp: '(?:(?P[0-9]+):)?(?P[0-9]+)\.(?P[0-9]+)\.(?P[0-9]+)(?P(?:~|-)[^0-9\s-]+[^-\s]*)?(?:-(?P[0-9]+))?' + agent_regexp: (?:(?P[0-9]+):)?(?P[0-9]+)\.(?P[0-9]+)\.(?P[0-9]+)(?P(?:~|-)[^0-9\s-]+[^-\s]*)?(?:-(?P[0-9]+))? - name: Set version vars - set_fact: - datadog_epoch: "{{ agent_version.0 }}" - datadog_major: "{{ agent_version.1 }}" - datadog_minor: "{{ agent_version.2 }}" - datadog_bugfix: "{{ agent_version.3 }}" - datadog_suffix: "{{ agent_version.4 }}" - datadog_release: "{{ agent_version.5 }}" + ansible.builtin.set_fact: + agent_datadog_epoch: "{{ agent_version.0 | default('', true) | string }}" + agent_datadog_major: "{{ agent_version.1 | default('', true) | string }}" + agent_datadog_minor: "{{ agent_version.2 | default('', true) | string }}" + agent_datadog_bugfix: "{{ agent_version.3 | default('', true) | string }}" + agent_datadog_suffix: "{{ agent_version.4 | default('', true) | string }}" + agent_datadog_release: "{{ agent_version.5 | default('', true) | string }}" - name: Fill empty version epoch with default - set_fact: - datadog_epoch: "1" - when: datadog_epoch | length == 0 + ansible.builtin.set_fact: + agent_datadog_epoch: "1" + when: agent_datadog_epoch | length == 0 - name: Fill empty version release with default - set_fact: - datadog_release: "1" - when: datadog_release | length == 0 + ansible.builtin.set_fact: + agent_datadog_release: "1" + when: agent_datadog_release | length == 0 - name: Stop play if datadog_agent_version and datadog_agent_major_version are not compatible - fail: - msg: "The provided major version {{ datadog_agent_major_version }} is not compatible with the - version {{ datadog_major }} deduced from datadog_agent_version ({{ datadog_agent_version }}). - Aborting play." - when: datadog_agent_major_version | length > 0 and datadog_major != datadog_agent_major_version + ansible.builtin.fail: + msg: "The provided major version {{ agent_datadog_agent_major_version }} is not compatible with the version {{ agent_datadog_major }} + deduced from datadog_agent_version ({{ datadog_agent_version }}). Aborting play." + when: agent_datadog_agent_major_version | length > 0 and agent_datadog_major != agent_datadog_agent_major_version -- name: Set datadog_agent_major_version to deduced value from datadog_agent_version - set_fact: - datadog_agent_major_version: "{{ datadog_major }}" +- name: Set agent_datadog_agent_major_version to deduced value from datadog_agent_version + ansible.builtin.set_fact: + agent_datadog_agent_major_version: "{{ agent_datadog_major }}" + +- name: Set helper variables + ansible.builtin.set_fact: + agent_datadog_agent_linux_version: "{{ agent_datadog_epoch }}:{{ agent_datadog_major }}.{{ agent_datadog_minor }}.{{ agent_datadog_bugfix }}{{ agent_datadog_suffix }}-{{ agent_datadog_release }}" # noqa yaml[line-length] + agent_datadog_rpm_version_finding_cmd: "rpm -q --qf '%{EPOCH}:%{VERSION}-%{RELEASE}' {{ datadog_agent_flavor }}" - name: Set OS-specific versions - set_fact: - datadog_agent_debian_version: "{{ datadog_epoch }}:{{ datadog_major }}.{{ datadog_minor }}.{{ datadog_bugfix }}{{ datadog_suffix }}-{{ datadog_release }}" - datadog_agent_redhat_version: "{{ datadog_major }}.{{ datadog_minor }}.{{ datadog_bugfix }}{{ datadog_suffix }}-{{ datadog_release }}" - datadog_agent_suse_version: "{{ datadog_epoch }}:{{ datadog_major }}.{{ datadog_minor }}.{{ datadog_bugfix }}{{ datadog_suffix }}-{{ datadog_release }}" - datadog_agent_windows_version: "{{ datadog_major }}.{{ datadog_minor }}.{{ datadog_bugfix }}{{ datadog_suffix }}" + # NOTE: if changing these, make sure the format correspond with values in agent_datadog_version_finding_cmds below + ansible.builtin.set_fact: + agent_datadog_agent_debian_version: "{{ agent_datadog_agent_linux_version }}" + agent_datadog_agent_redhat_version: "{{ agent_datadog_agent_linux_version }}" + agent_datadog_agent_suse_version: "{{ agent_datadog_agent_linux_version }}" + agent_datadog_agent_windows_version: "{{ agent_datadog_major }}.{{ agent_datadog_minor }}.{{ agent_datadog_bugfix }}{{ agent_datadog_suffix }}" + agent_datadog_agent_macos_version: "{{ agent_datadog_major }}.{{ agent_datadog_minor }}.{{ agent_datadog_bugfix }}{{ agent_datadog_suffix }}" + +- name: Construct commands to find Agent version + ansible.builtin.set_fact: + agent_datadog_version_finding_cmds: + Debian: "dpkg-query --showformat '${Status} ${Version}\n' --show {{ datadog_agent_flavor }} | grep installed | awk '{print $NF}'" + RedHat: "{{ agent_datadog_rpm_version_finding_cmd }}" + Rocky: "{{ agent_datadog_rpm_version_finding_cmd }}" + AlmaLinux: "{{ agent_datadog_rpm_version_finding_cmd }}" + Suse: "{{ agent_datadog_rpm_version_finding_cmd }}" + +- name: Create OS-specific version dict + ansible.builtin.set_fact: + agent_datadog_agent_os2version: + Debian: "{{ agent_datadog_agent_debian_version }}" + RedHat: "{{ agent_datadog_agent_redhat_version }}" + Rocky: "{{ agent_datadog_agent_redhat_version }}" + AlmaLinux: "{{ agent_datadog_agent_redhat_version }}" + Suse: "{{ agent_datadog_agent_suse_version }}" + Windows: "{{ agent_datadog_agent_windows_version }}" + Darwin: "{{ agent_datadog_agent_macos_version }}" + +- name: Get Linux Agent version + ansible.builtin.shell: "{{ agent_datadog_version_finding_cmds[ansible_facts.os_family] }}" # noqa command-instead-of-shell - We need shell because of pipes + register: agent_datadog_version_check_linux + changed_when: false + failed_when: false + check_mode: false + when: ansible_facts.system is defined and ansible_facts.system == "Linux" + +# The task is win_shell, so if users don't have the "ansible.windows" collection installed, +# parsing the task would fail even if the host is not Windows. By hiding the task inside +# a conditionally included file, we can prevent this. +- name: Include Windows Agent version tasks + ansible.builtin.include_tasks: parse-version-windows.yml + when: ansible_facts.os_family == "Windows" + +- name: Include macOS Agent version tasks + ansible.builtin.include_tasks: parse-version-macos.yml + when: ansible_facts.os_family == "Darwin" + +- name: Set skip install flag if version already installed (Linux) + ansible.builtin.set_fact: + agent_datadog_skip_install: "{{ agent_datadog_version_check_linux.stdout | trim == agent_datadog_agent_os2version[ansible_facts.os_family] }}" + when: ansible_facts.system is defined and ansible_facts.system == "Linux" + +- name: Set skip install flag if version already installed (Windows) + ansible.builtin.set_fact: + agent_datadog_skip_install: "{{ agent_datadog_version_check_win.stdout | trim == agent_datadog_agent_os2version[ansible_facts.os_family] }}" + when: ansible_facts.os_family == "Windows" + +- name: Set skip install flag if version already installed (macOS) + ansible.builtin.set_fact: + agent_datadog_skip_install: "{{ agent_datadog_version_check_macos.stdout | trim == agent_datadog_agent_os2version[ansible_facts.os_family] }}" + when: ansible_facts.os_family == "Darwin" diff --git a/tasks/pkg-debian.yml b/tasks/pkg-debian.yml index c4cf14e7..6c9e37c4 100644 --- a/tasks/pkg-debian.yml +++ b/tasks/pkg-debian.yml @@ -1,90 +1,133 @@ --- - name: Install apt-transport-https - apt: - update_cache: yes + ansible.builtin.apt: + update_cache: true name: apt-transport-https state: present when: not ansible_check_mode -- name: Install ubuntu apt-key server - apt_key: - id: A2923DFF56EDA6E76E55E492D3A80E30382E94DE - keyserver: "{{ datadog_apt_backup_keyserver if use_apt_backup_keyserver else datadog_apt_keyserver }}" +- name: Install gnupg + ansible.builtin.apt: + update_cache: true + name: gnupg state: present - # keyserver.ubuntu.com is a pool of server, we should retry if one of them is down - register: result - until: not result.failed is defined or not result.failed - retries: "{{ datadog_apt_key_retries }}" - when: datadog_apt_key_url_new is not defined - -- name: Install Datadog apt-key - apt_key: - id: A2923DFF56EDA6E76E55E492D3A80E30382E94DE - url: "{{ datadog_apt_key_url_new }}" - state: present - when: datadog_apt_key_url_new is defined + when: not ansible_check_mode + +- name: Check if keyring exists with correct mode, keyring={{ datadog_apt_usr_share_keyring }} + ansible.builtin.stat: + path: "{{ datadog_apt_usr_share_keyring }}" + register: agent_apt_keyring_file -- name: Ensure Datadog non-https repositories are deprecated - apt_repository: +- name: Ensure keyring exists, keyring={{ datadog_apt_usr_share_keyring }} + ansible.builtin.file: + path: "{{ datadog_apt_usr_share_keyring }}" + owner: root + group: root + mode: "0644" + state: touch + when: not ansible_check_mode and (not agent_apt_keyring_file.stat.exists or not agent_apt_keyring_file.stat.mode == "0644") + +- name: Install apt keys from default URLs + ansible.builtin.include_tasks: _apt-key-import.yml + with_items: "{{ datadog_apt_default_keys }}" + when: datadog_apt_key_url_new is not defined and not ansible_check_mode + +- name: Install apt keys from custom URL + ansible.builtin.include_tasks: _apt-key-import.yml + with_items: + - key: A2923DFF56EDA6E76E55E492D3A80E30382E94DE + value: "{{ datadog_apt_key_url_new }}" + - key: D75CEA17048B9ACBF186794B32637D44F14F620E + value: "{{ datadog_apt_key_url_new }}" + - key: 5F1E256061D813B125E156E8E6266D4AC0962C7D + value: "{{ datadog_apt_key_url_new }}" + - key: D18886567EABAD8B2D2526900D826EB906462314 + value: "{{ datadog_apt_key_url_new }}" + when: datadog_apt_key_url_new is defined and not ansible_check_mode + +- 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: + src: "{{ datadog_apt_usr_share_keyring }}" + dest: "{{ datadog_apt_trusted_d_keyring }}" + mode: "0644" + remote_src: true + when: ((ansible_distribution == 'Debian' and ansible_distribution_major_version|int < 9) or + (ansible_distribution == 'Ubuntu' and ansible_distribution_major_version | int < 16)) and not ansible_check_mode + +- name: Ensure Datadog non-https repositories and repositories not using signed-by option are deprecated + ansible.builtin.apt_repository: repo: "{{ item }}" - state: "absent" - update_cache: yes + state: absent + update_cache: true with_items: - - "deb http://apt.datadoghq.com/ stable main" - - "deb http://apt.datadoghq.com/ stable 6" - - "deb http://apt.datadoghq.com/ stable 7" + - deb http://apt.datadoghq.com/ stable main + - deb http://apt.datadoghq.com/ stable 6 + - deb http://apt.datadoghq.com/ stable 7 + - deb https://apt.datadoghq.com/ stable main + - deb https://apt.datadoghq.com/ stable 6 + - deb https://apt.datadoghq.com/ stable 7 when: not ansible_check_mode - name: Ensure Datadog repository is up-to-date - apt_repository: - filename: "ansible_datadog_{{ item.key }}" + ansible.builtin.apt_repository: + filename: ansible_datadog_{{ item.key }} repo: "{{ item.value }}" - state: "{% if item.key == datadog_agent_major_version|int and datadog_apt_repo | length == 0 %}present{% else %}absent{% endif %}" - update_cache: yes + state: "{% if item.key == agent_datadog_agent_major_version | int and datadog_apt_repo | length == 0 %}present{% else %}absent{% endif %}" + update_cache: true when: (not ansible_check_mode) with_dict: - 5: '{{ datadog_agent5_apt_repo }}' - 6: '{{ datadog_agent6_apt_repo }}' - 7: '{{ datadog_agent7_apt_repo }}' + 6: "{{ datadog_agent6_apt_repo }}" + 7: "{{ datadog_agent7_apt_repo }}" - name: Initialize custom repo file deletion flag to False - set_fact: - datadog_remove_custom_repo_file: "False" + ansible.builtin.set_fact: + agent_datadog_remove_custom_repo_file: "False" - name: Check if custom repository file exists - stat: + ansible.builtin.stat: path: /etc/apt/sources.list.d/ansible_datadog_custom.list - register: datadog_custom_repo_file + register: agent_datadog_custom_repo_file - name: Fetch custom repository file - slurp: + ansible.builtin.slurp: src: /etc/apt/sources.list.d/ansible_datadog_custom.list - register: datadog_custom_repo_file_contents - when: datadog_custom_repo_file.stat.exists + register: agent_datadog_custom_repo_file_contents + when: agent_datadog_custom_repo_file.stat.exists - name: Flag custom repository file for deletion if different from current repository config - 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 }}" vars: - datadog_repo_file_contents: "{{ datadog_custom_repo_file_contents['content'] | b64decode | trim }}" - when: datadog_custom_repo_file.stat.exists + agent_datadog_repo_file_contents: "{{ agent_datadog_custom_repo_file_contents['content'] | b64decode | trim }}" + when: agent_datadog_custom_repo_file.stat.exists - name: (Custom) Remove Datadog custom repository file when not set or updated - file: + ansible.builtin.file: path: /etc/apt/sources.list.d/ansible_datadog_custom.list state: absent - when: (datadog_apt_repo | length == 0) or datadog_remove_custom_repo_file and (not ansible_check_mode) + when: (datadog_apt_repo | length == 0) or agent_datadog_remove_custom_repo_file and (not ansible_check_mode) - name: (Custom) Ensure Datadog repository is up-to-date - apt_repository: + ansible.builtin.apt_repository: filename: ansible_datadog_custom repo: "{{ datadog_apt_repo }}" state: present - update_cache: yes + update_cache: true when: (datadog_apt_repo | length > 0) and (not ansible_check_mode) -- include_tasks: pkg-debian/install-pinned.yml - when: datadog_agent_debian_version is defined +- name: Include debian pinned version install task + ansible.builtin.include_tasks: pkg-debian/install-pinned.yml + when: not agent_datadog_skip_install and agent_datadog_agent_debian_version is defined -- include_tasks: pkg-debian/install-latest.yml - when: datadog_agent_debian_version is not defined +- name: Include debian latest version install task + ansible.builtin.include_tasks: pkg-debian/install-latest.yml + when: not agent_datadog_skip_install and agent_datadog_agent_debian_version is not defined + +- name: Install latest datadog-signing-keys package + ansible.builtin.apt: + name: datadog-signing-keys + state: latest # noqa package-latest + # we don't use update_cache: yes, as that was just done by the "Ensure Datadog repository is up-to-date" task above + register: agent_datadog_signing_keys_install + when: not ansible_check_mode diff --git a/tasks/pkg-debian/install-latest.yml b/tasks/pkg-debian/install-latest.yml index 5780cf46..4411595c 100644 --- a/tasks/pkg-debian/install-latest.yml +++ b/tasks/pkg-debian/install-latest.yml @@ -1,9 +1,9 @@ --- - name: Install latest datadog-agent package - apt: - name: datadog-agent - state: latest # noqa 403 - update_cache: yes + ansible.builtin.apt: + name: "{{ datadog_agent_flavor }}" + state: latest # noqa package-latest + update_cache: true cache_valid_time: "{{ datadog_apt_cache_valid_time }}" - register: datadog_agent_install + register: agent_datadog_agent_install when: not ansible_check_mode diff --git a/tasks/pkg-debian/install-pinned.yml b/tasks/pkg-debian/install-pinned.yml index 74cf264f..c0a5e8a1 100644 --- a/tasks/pkg-debian/install-pinned.yml +++ b/tasks/pkg-debian/install-pinned.yml @@ -1,10 +1,10 @@ --- - name: Install pinned datadog-agent package - apt: - name: "datadog-agent={{ datadog_agent_debian_version }}" + ansible.builtin.apt: + name: "{{ datadog_agent_flavor }}={{ agent_datadog_agent_debian_version }}" state: present force: "{{ datadog_agent_allow_downgrade }}" - update_cache: yes + update_cache: true cache_valid_time: "{{ datadog_apt_cache_valid_time }}" - register: datadog_agent_install + register: agent_datadog_agent_install when: not ansible_check_mode diff --git a/tasks/pkg-macos.yml b/tasks/pkg-macos.yml new file mode 100644 index 00000000..06440a45 --- /dev/null +++ b/tasks/pkg-macos.yml @@ -0,0 +1,87 @@ +--- +# NOTE: the DMG gets installed as ansible_user, but we then configure it to run +# under datadog_macos_user and remove the user-specific config for ansible_user +- name: Check if the macOS user for Agent service exists + ansible.builtin.command: id -u "{{ datadog_macos_user }}" + register: agent_mac_user_check + changed_when: false + ignore_errors: true + +- name: Fail if the macOS user for Agent service doesn't exist + ansible.builtin.fail: + msg: "The Datadog ansible role wasn't able to find the user : {{ datadog_macos_user }}" + when: agent_mac_user_check.rc != 0 + +- name: Include macos agent latest version install task + ansible.builtin.include_tasks: pkg-macos/macos_agent_latest.yml + when: (not agent_datadog_skip_install) and (agent_datadog_agent_macos_version is not defined) + +- name: Include macos agent pinned version install task + ansible.builtin.include_tasks: pkg-macos/macos_agent_version.yml + when: (not agent_datadog_skip_install) and (agent_datadog_agent_macos_version is defined) + +- name: Display macOS download URL + ansible.builtin.debug: + var: agent_dd_download_url + when: not agent_datadog_skip_install + +- name: Pre-Delete temporary dmg + ansible.builtin.file: + path: /tmp/datadog-agent.dmg + state: absent + become: true + when: not agent_datadog_skip_install + +- name: Create temporary datadog install user file + ansible.builtin.copy: + dest: /tmp/datadog-install-user + content: "{{ datadog_macos_user }}" + mode: "0554" + when: (not agent_datadog_skip_install) and (not ansible_check_mode) + +- name: Download macOS datadog agent + ansible.builtin.get_url: + url: "{{ agent_dd_download_url }}" + dest: /tmp/datadog-agent.dmg + mode: "0750" + register: agent_download_dmg_result + when: (not agent_datadog_skip_install) and (not ansible_check_mode) + +- name: Detach agent dmg if already mounted + ansible.builtin.shell: hdiutil detach "/Volumes/datadog_agent" >/dev/null 2>&1 || true + when: (not agent_datadog_skip_install) and (not ansible_check_mode) + changed_when: true + +- name: Attach agent dmg + ansible.builtin.command: hdiutil attach /tmp/datadog-agent.dmg -mountpoint "/Volumes/datadog_agent" + when: (not agent_datadog_skip_install) and (not ansible_check_mode) and (agent_download_dmg_result.status_code == 200) + changed_when: true + +- name: Unpack and copy Datadog Agent files + ansible.builtin.shell: + cmd: /usr/sbin/installer -pkg "`find "/Volumes/datadog_agent" -name \*.pkg 2>/dev/null`" -target / + chdir: / + become: true + register: agent_datadog_agent_install + when: (not agent_datadog_skip_install) and (not ansible_check_mode) and (agent_download_dmg_result.status_code == 200) + changed_when: true + notify: restart datadog-agent-macos + +- name: Detach mounted dmg + ansible.builtin.command: hdiutil detach "/Volumes/datadog_agent" + when: (not agent_datadog_skip_install) and (not ansible_check_mode) and (agent_download_dmg_result.status_code == 200) + changed_when: true + +- name: Delete temporary dmg + ansible.builtin.file: + path: "{{ agent_download_dmg_result.dest }}" + state: absent + become: true + when: (not agent_datadog_skip_install) and (not ansible_check_mode) and (agent_download_dmg_result.status_code == 200) + +- name: Delete temporary datadog install user file + ansible.builtin.file: + path: /tmp/datadog-install-user + state: absent + become: true + when: (not agent_datadog_skip_install) and (not ansible_check_mode) diff --git a/tasks/pkg-macos/macos_agent_latest.yml b/tasks/pkg-macos/macos_agent_latest.yml new file mode 100644 index 00000000..ef7c202f --- /dev/null +++ b/tasks/pkg-macos/macos_agent_latest.yml @@ -0,0 +1,30 @@ +--- +- name: Set agent download filename to custom URL + ansible.builtin.set_fact: + agent_dd_download_url: "{{ datadog_macos_download_url }}" + when: datadog_macos_download_url | default('', true) | length > 0 + +- name: Check architecture-specific URL for latest Agent 7 + ansible.builtin.uri: + url: "{{ datadog_macos_agent7_latest_arch_url }}" + method: GET + follow_redirects: all + return_content: false + status_code: 200 + register: datadog_macos_agent7_latest_arch_check + failed_when: false + retries: 2 + when: + - datadog_macos_download_url | default('', true) | length == 0 + - agent_datadog_agent_major_version | int >= 7 + +- name: Set agent download filename to latest + ansible.builtin.set_fact: + agent_dd_download_url: >- + {%- if agent_datadog_agent_major_version | int < 7 -%} + {{ datadog_macos_agent6_latest_url }}{%- else -%} + {%- if datadog_macos_agent7_latest_arch_check is defined and datadog_macos_agent7_latest_arch_check.status == 200 -%} + {{ datadog_macos_agent7_latest_arch_url }}{%- else -%} + {{ datadog_macos_agent7_latest_url }}{%- endif -%} + {%- endif -%} + when: datadog_macos_download_url | default('', true) | length == 0 diff --git a/tasks/pkg-macos/macos_agent_version.yml b/tasks/pkg-macos/macos_agent_version.yml new file mode 100644 index 00000000..49ffc55c --- /dev/null +++ b/tasks/pkg-macos/macos_agent_version.yml @@ -0,0 +1,9 @@ +--- +- name: Set agent download filename to a specific version + ansible.builtin.set_fact: + agent_dd_download_url: "{{ datadog_macos_versioned_url }}-{{ agent_datadog_agent_macos_version }}-1{{ maybe_arch }}.dmg" + vars: + maybe_arch: >- + {{ '.' + ansible_facts.architecture + if agent_datadog_agent_macos_version is version('7.70', '>=') + else '' }} diff --git a/tasks/pkg-redhat.yml b/tasks/pkg-redhat.yml index a5c29f3a..bf31c49e 100644 --- a/tasks/pkg-redhat.yml +++ b/tasks/pkg-redhat.yml @@ -1,44 +1,187 @@ --- -- name: Download new RPM key - get_url: - url: "{{ datadog_yum_gpgkey_e09422b3 }}" - dest: /tmp/DATADOG_RPM_KEY_E09422B3.public - checksum: "sha256:{{ datadog_yum_gpgkey_e09422b3_sha256sum }}" - -- name: Import new RPM key - rpm_key: - key: /tmp/DATADOG_RPM_KEY_E09422B3.public - state: present - when: not ansible_check_mode - -- name: Install Datadog yum repo - yum_repository: - name: "ansible_datadog_{{ item.key }}" - description: Datadog, Inc. - baseurl: "{{ item.value }}" - enabled: yes - gpgcheck: yes - gpgkey: "{% if datadog_agent_major_version|int == 7 %}{{ datadog_yum_gpgkey_e09422b3 }}{% else %}{{ datadog_yum_gpgkey }}{% endif %}" - state: "{% if item.key == datadog_agent_major_version|int and datadog_yum_repo | length == 0 %}present{% else %}absent{% endif %}" - when: (not ansible_check_mode) - with_dict: - 5: '{{ datadog_agent5_yum_repo }}' - 6: '{{ datadog_agent6_yum_repo }}' - 7: '{{ datadog_agent7_yum_repo }}' - -- name: (Custom) Install Datadog yum repo - yum_repository: - name: ansible_datadog_custom - description: Datadog, Inc. - baseurl: "{{ datadog_yum_repo }}" - enabled: yes - gpgcheck: yes - gpgkey: "{{ datadog_yum_gpgkey }}" - state: present - when: (datadog_yum_repo | length > 0) and (not ansible_check_mode) - -- include_tasks: pkg-redhat/install-pinned.yml - when: datadog_agent_redhat_version is defined - -- include_tasks: pkg-redhat/install-latest.yml - when: datadog_agent_redhat_version is not defined +- name: Ensure dnf is used as package manager + ansible.builtin.set_fact: + ansible_pkg_mgr: dnf + +- name: If yum repo configuration is enabled + when: datadog_yum_repo_config_enabled | bool + block: + - name: Find out whether to set repo_gpgcheck or not + # We turn off repo_gpgcheck on custom repos and on RHEL/CentOS 8.1 because + # of https://bugzilla.redhat.com/show_bug.cgi?id=1792506 + ansible.builtin.set_fact: + agent_do_yum_repo_gpgcheck: >- + {{ datadog_yum_repo_gpgcheck if datadog_yum_repo_gpgcheck != '' else ( + 'no' if ( + ansible_facts.distribution_version.startswith('8.1.') or ansible_facts.distribution_version == '8.1' or + datadog_yum_repo != '' + ) else 'yes' + ) }} + + - name: Download current RPM key + ansible.builtin.get_url: + url: "{{ datadog_yum_gpgkey_current }}" + dest: /tmp/DATADOG_RPM_KEY_CURRENT.public + mode: '600' + force: true + + - name: Import current RPM key + ansible.builtin.rpm_key: + key: /tmp/DATADOG_RPM_KEY_CURRENT.public + state: present + when: not ansible_check_mode + + - name: Download old RPM key (Expires in 2022) + ansible.builtin.get_url: + url: "{{ datadog_yum_gpgkey_e09422b3 }}" + dest: /tmp/DATADOG_RPM_KEY_E09422B3.public + mode: '600' + checksum: "sha256:{{ datadog_yum_gpgkey_e09422b3_sha256sum }}" + when: agent_datadog_minor is defined and agent_datadog_minor | int < 36 + + - name: Import old RPM key (Expires in 2022) + ansible.builtin.rpm_key: + key: /tmp/DATADOG_RPM_KEY_E09422B3.public + state: present + when: not ansible_check_mode and agent_datadog_minor is defined and agent_datadog_minor | int < 36 + + - name: Download new RPM key (Expires in 2024) + ansible.builtin.get_url: + url: "{{ datadog_yum_gpgkey_20200908 }}" + dest: /tmp/DATADOG_RPM_KEY_20200908.public + mode: '600' + checksum: "sha256:{{ datadog_yum_gpgkey_20200908_sha256sum }}" + + - name: Import new RPM key (Expires in 2024) + ansible.builtin.rpm_key: + key: /tmp/DATADOG_RPM_KEY_20200908.public + state: present + when: not ansible_check_mode + + - name: Download new RPM key (Expires in 2028) + ansible.builtin.get_url: + url: "{{ datadog_yum_gpgkey_20280418 }}" + dest: /tmp/DATADOG_RPM_KEY_20280418.public + mode: '600' + checksum: "sha256:{{ datadog_yum_gpgkey_20280418_sha256sum }}" + + - name: Import new RPM key (Expires in 2028) + ansible.builtin.rpm_key: + key: /tmp/DATADOG_RPM_KEY_20280418.public + state: present + when: not ansible_check_mode + + - name: Download future RPM key (Expires in 2033) + ansible.builtin.get_url: + url: "{{ datadog_yum_gpgkey_4f09d16b }}" + dest: /tmp/DATADOG_RPM_KEY_4FA09D16B.public + mode: '600' + checksum: "sha256:{{ datadog_yum_gpgkey_4f09d16b_sha256sum }}" + + - name: Import future RPM key (Expires in 2033) + ansible.builtin.rpm_key: + key: /tmp/DATADOG_RPM_KEY_4FA09D16B.public + state: present + when: not ansible_check_mode + + - name: Set versioned includepkgs variable + ansible.builtin.set_fact: + agent_datadog_includepkgs: "{{ datadog_agent_flavor }}-{{ agent_datadog_agent_redhat_version | regex_replace('^\\d+:', '') }}" + when: agent_datadog_agent_redhat_version is defined + + - name: Set plain includepkgs variable + ansible.builtin.set_fact: + agent_datadog_includepkgs: "{{ datadog_agent_flavor }}" + when: agent_datadog_agent_redhat_version is not defined + + - name: Install Datadog Agent 6 yum repo + ansible.builtin.yum_repository: + name: datadog + description: Datadog, Inc. + baseurl: "{{ datadog_agent6_yum_repo }}" + enabled: true + includepkgs: "{{ agent_datadog_includepkgs }}" + repo_gpgcheck: "{{ agent_do_yum_repo_gpgcheck }}" + gpgcheck: "{{ datadog_yum_gpgcheck }}" + gpgkey: [ + "{{ datadog_yum_gpgkey_current }}", + "{{ datadog_yum_gpgkey_20280418 }}", + "{{ datadog_yum_gpgkey_20200908 }}", + "{{ datadog_yum_gpgkey_e09422b3 }}", + ] + proxy: "{{ datadog_yum_repo_proxy if datadog_yum_repo_proxy != '' else omit }}" + proxy_username: "{{ datadog_yum_repo_proxy_username if datadog_yum_repo_proxy_username != '' else omit }}" + proxy_password: "{{ datadog_yum_repo_proxy_password if datadog_yum_repo_proxy_password != '' else omit }}" + register: agent_repofile6 + when: (agent_datadog_agent_major_version | int == 6) and (datadog_yum_repo | length == 0) and (not ansible_check_mode) + + - name: Install Datadog Agent 7 yum repo + ansible.builtin.yum_repository: + name: datadog + description: Datadog, Inc. + baseurl: "{{ datadog_agent7_yum_repo }}" + enabled: true + includepkgs: "{{ agent_datadog_includepkgs }}" + repo_gpgcheck: "{{ agent_do_yum_repo_gpgcheck }}" + gpgcheck: "{{ datadog_yum_gpgcheck }}" + gpgkey: [ + "{{ datadog_yum_gpgkey_current }}", + "{{ datadog_yum_gpgkey_20280418 }}", + "{{ datadog_yum_gpgkey_20200908 }}", + "{{ datadog_yum_gpgkey_e09422b3 }}", + ] + proxy: "{{ datadog_yum_repo_proxy if datadog_yum_repo_proxy != '' else omit }}" + proxy_username: "{{ datadog_yum_repo_proxy_username if datadog_yum_repo_proxy_username != '' else omit }}" + proxy_password: "{{ datadog_yum_repo_proxy_password if datadog_yum_repo_proxy_password != '' else omit }}" + register: agent_repofile7 + when: (agent_datadog_agent_major_version | int == 7) and (datadog_yum_repo | length == 0) and (not ansible_check_mode) + + - name: Install Datadog Custom yum repo + ansible.builtin.yum_repository: + name: datadog + description: Datadog, Inc. + baseurl: "{{ datadog_yum_repo }}" + enabled: true + includepkgs: "{{ agent_datadog_includepkgs }}" + repo_gpgcheck: "{{ agent_do_yum_repo_gpgcheck }}" + gpgcheck: "{{ datadog_yum_gpgcheck }}" + gpgkey: [ + "{{ datadog_yum_gpgkey_current }}", + "{{ datadog_yum_gpgkey_20280418 }}", + "{{ datadog_yum_gpgkey_20200908 }}", + "{{ datadog_yum_gpgkey_e09422b3 }}", + ] + proxy: "{{ datadog_yum_repo_proxy if datadog_yum_repo_proxy != '' else omit }}" + proxy_username: "{{ datadog_yum_repo_proxy_username if datadog_yum_repo_proxy_username != '' else omit }}" + proxy_password: "{{ datadog_yum_repo_proxy_password if datadog_yum_repo_proxy_password != '' else omit }}" + register: agent_repofilecustom + when: (datadog_yum_repo | length > 0) and (not ansible_check_mode) + + - name: Clean repo metadata if repo changed # noqa: command-instead-of-module no-handler + ansible.builtin.command: dnf clean metadata --disablerepo="*" --enablerepo=datadog + failed_when: false # Cleaning the metadata is only needed when downgrading a major version of the Agent, don't fail because of this + when: agent_repofile6.changed or agent_repofile7.changed or agent_repofilecustom.changed + changed_when: true + + # On certain version of dnf, gpg keys aren't imported into the local db with the package install task. + # This rule assures that they are correctly imported into the local db and users won't have to manually accept + # them if running dnf commands on the hosts. + - name: Refresh Datadog repository cache # noqa: command-instead-of-module no-handler + ansible.builtin.command: dnf -y makecache --disablerepo="*" --enablerepo=datadog + failed_when: false + when: agent_repofile6.changed or agent_repofile7.changed or agent_repofilecustom.changed + changed_when: true + + - name: Remove old yum repo files + ansible.builtin.yum_repository: + name: ansible_datadog_{{ item }} + state: absent + with_items: [6, 7, custom] + +- name: Include redhat agent pinned version install task + ansible.builtin.include_tasks: pkg-redhat/install-pinned.yml + when: not agent_datadog_skip_install and agent_datadog_agent_redhat_version is defined + +- name: Include redhat agent latest version install task + ansible.builtin.include_tasks: pkg-redhat/install-latest.yml + when: not agent_datadog_skip_install and agent_datadog_agent_redhat_version is not defined diff --git a/tasks/pkg-redhat/install-latest.yml b/tasks/pkg-redhat/install-latest.yml index b644f6ed..88af048f 100644 --- a/tasks/pkg-redhat/install-latest.yml +++ b/tasks/pkg-redhat/install-latest.yml @@ -1,9 +1,19 @@ --- -- name: Install latest datadog-agent package - yum: - name: datadog-agent - update_cache: yes - state: latest # noqa 403 - register: datadog_agent_install +- name: Set installation target for latest + ansible.builtin.set_fact: + # Apply a version cap if required, otherwise just target the agent package + datadog_agent_target: >- + {{ datadog_agent_flavor }} + {% if datadog_agent_max_minor_version is defined %} + < 1:{{ agent_datadog_agent_major_version }}.{{ datadog_agent_max_minor_version + 1 }}.0-1 + {% endif %} + +- name: Install latest datadog-agent package (dnf) + ansible.builtin.dnf: + name: "{{ datadog_agent_target }}" + update_cache: true + state: latest # noqa package-latest + disablerepo: "appstream" + register: agent_datadog_agent_install when: not ansible_check_mode notify: restart datadog-agent diff --git a/tasks/pkg-redhat/install-pinned.yml b/tasks/pkg-redhat/install-pinned.yml index 73d1ce34..b5c7979a 100644 --- a/tasks/pkg-redhat/install-pinned.yml +++ b/tasks/pkg-redhat/install-pinned.yml @@ -1,9 +1,11 @@ --- -- name: Install pinned datadog-agent package - yum: - name: "datadog-agent-{{ datadog_agent_redhat_version }}" +- name: Install pinned datadog-agent package (dnf) + ansible.builtin.dnf: + name: "{{ datadog_agent_flavor }}-{{ agent_datadog_agent_redhat_version }}" + update_cache: true state: present allow_downgrade: "{{ datadog_agent_allow_downgrade }}" - register: datadog_agent_install + disablerepo: "appstream" + register: agent_datadog_agent_install when: not ansible_check_mode notify: restart datadog-agent diff --git a/tasks/pkg-suse.yml b/tasks/pkg-suse.yml index 50294127..1f8024d1 100644 --- a/tasks/pkg-suse.yml +++ b/tasks/pkg-suse.yml @@ -1,74 +1,145 @@ --- -# Do not import old key if installing Agent 7, as all Agent 7 packages are signed with the new key -- block: # Work around due to SNI check for SLES11 - - name: Stat if RPM key already exists - stat: - path: /tmp/DATADOG_RPM_KEY.public - register: ddkey - - name: Download RPM key (SLES11) - get_url: - url: "{{ datadog_zypper_gpgkey }}" - dest: /tmp/DATADOG_RPM_KEY.public - when: not ddkey.stat.exists - when: datadog_agent_major_version|int < 7 and ansible_distribution_version|int == 11 - -# Do not import old key if installing Agent 7, as all Agent 7 packages are signed with the new key -- name: Download RPM key - get_url: - url: "{{ datadog_zypper_gpgkey }}" - dest: /tmp/DATADOG_RPM_KEY.public - checksum: "sha256:{{ datadog_zypper_gpgkey_sha256sum }}" - when: datadog_agent_major_version|int < 7 and ansible_distribution_version|int >= 12 - -- name: Import RPM key - rpm_key: - key: /tmp/DATADOG_RPM_KEY.public +- name: Find out whether to set repo_gpgcheck or not + ansible.builtin.set_fact: + agent_do_zypper_repo_gpgcheck: >- + {{ datadog_zypper_repo_gpgcheck if datadog_zypper_repo_gpgcheck != '' else ( + 'yes' if datadog_zypper_repo == '' else 'no' + ) }} + +- name: Check and download RPM Key(SLES11) # Work around due to SNI check for SLES11 + when: ansible_distribution_version|int == 11 + block: + - name: Stat if current RPM key already exists + ansible.builtin.stat: + path: /tmp/DATADOG_RPM_KEY_CURRENT.public + register: agent_ddkeycurrent + - name: Download current RPM key (SLES11) + ansible.builtin.get_url: + url: "{{ datadog_zypper_gpgkey_current }}" + dest: /tmp/DATADOG_RPM_KEY_CURRENT.public + mode: '600' + force: true + when: not agent_ddkeycurrent.stat.exists + +- name: Download current RPM key + ansible.builtin.get_url: + url: "{{ datadog_zypper_gpgkey_current }}" + dest: /tmp/DATADOG_RPM_KEY_CURRENT.public + force: true + mode: '600' + when: ansible_distribution_version|int >= 12 + +- name: Import current RPM key + ansible.builtin.rpm_key: + key: /tmp/DATADOG_RPM_KEY_CURRENT.public state: present - when: datadog_agent_major_version|int < 7 and not ansible_check_mode - -- block: # Work around due to SNI check for SLES11 - - name: Stat if new RPM key already exists - stat: - path: /tmp/DATADOG_RPM_KEY_E09422B3.public - register: ddnewkey - - name: Download new RPM key (SLES11) - get_url: - url: "{{ datadog_zypper_gpgkey_e09422b3 }}" - dest: /tmp/DATADOG_RPM_KEY_E09422B3.public - when: not ddnewkey.stat.exists + when: not ansible_check_mode + +- name: Check and download E09422B3 key # Work around due to SNI check for SLES11 when: ansible_distribution_version|int == 11 + block: + - name: Stat if E09422B3 key (Expires 2022) RPM key already exists + ansible.builtin.stat: + path: /tmp/DATADOG_RPM_KEY_E09422B3.public + register: agent_ddnewkey + - name: Download E09422B3 key (Expires 2022) RPM key (SLES11) + ansible.builtin.get_url: + url: "{{ datadog_zypper_gpgkey_e09422b3 }}" + dest: /tmp/DATADOG_RPM_KEY_E09422B3.public + mode: '600' + when: not agent_ddnewkey.stat.exists and agent_datadog_minor is defined and agent_datadog_minor | int < 36 -- name: Download new RPM key - get_url: +- name: Download E09422B3 key (Expires 2022) RPM key + ansible.builtin.get_url: url: "{{ datadog_zypper_gpgkey_e09422b3 }}" dest: /tmp/DATADOG_RPM_KEY_E09422B3.public - checksum: "sha256:{{ datadog_zypper_gpgkey_e09422b3_sha256sum }}" - when: ansible_distribution_version|int >= 12 + 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 -- name: Import new RPM key - rpm_key: +- name: Import E09422B3 key (Expires 2022) RPM key + ansible.builtin.rpm_key: key: /tmp/DATADOG_RPM_KEY_E09422B3.public state: present + when: not ansible_check_mode and agent_datadog_minor is defined and agent_datadog_minor | int < 36 + +- name: Check and download 20200908 key # Work around due to SNI check for SLES11 + when: ansible_distribution_version|int == 11 + block: + - name: Stat if 20200908 key (Expires 2024) RPM key already exists + ansible.builtin.stat: + path: /tmp/DATADOG_RPM_KEY_20200908.public + register: agent_ddnewkey_20200908 + - name: Download 20200908 key (Expires 2024) RPM key (SLES11) + ansible.builtin.get_url: + url: "{{ datadog_zypper_gpgkey_20200908 }}" + dest: /tmp/DATADOG_RPM_KEY_20200908.public + mode: '600' + when: not agent_ddnewkey_20200908.stat.exists + +- 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' + when: ansible_distribution_version|int >= 12 + +- name: Import 20200908 key (Expires 2024) RPM key + ansible.builtin.rpm_key: + key: /tmp/DATADOG_RPM_KEY_20200908.public + state: present + when: not ansible_check_mode + +- name: Check and download 20280418 key # Work around due to SNI check for SLES11 + when: ansible_distribution_version|int == 11 + block: + - name: Stat if 20280418 key (Expires 2028) RPM key already exists + ansible.builtin.stat: + path: /tmp/DATADOG_RPM_KEY_20280418.public + register: agent_ddnewkey_20280418 + - name: Download 20280418 key (Expires 2028) RPM key (SLES11) + ansible.builtin.get_url: + url: "{{ datadog_zypper_gpgkey_20280418 }}" + dest: /tmp/DATADOG_RPM_KEY_20280418.public + mode: '600' + when: not agent_ddnewkey_20280418.stat.exists + +- 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' + when: ansible_distribution_version|int >= 12 + +- name: Import 20280418 key (Expires 2028) RPM key + ansible.builtin.rpm_key: + key: /tmp/DATADOG_RPM_KEY_20280418.public + state: present when: not ansible_check_mode # ansible don't allow repo_gpgcheck to be set, we have to create the repo file manually - name: Install DataDog zypper repo - template: + ansible.builtin.template: src: zypper.repo.j2 dest: /etc/zypp/repos.d/datadog.repo - owner: "root" - group: "root" - register: datadog_zypper_repo + owner: root + group: root + mode: "0644" + register: agent_datadog_zypper_repo_template + when: datadog_manage_zypper_repofile # refresh zypper repos only if the template changed -- name: refresh Datadog zypper_repos # noqa 503 - command: zypper refresh datadog - when: datadog_zypper_repo.changed and not ansible_check_mode - args: - warn: false # silence warning about using zypper directly +- name: Refresh Datadog zypper_repos # noqa: command-instead-of-module + ansible.builtin.command: zypper refresh datadog + when: not agent_datadog_skip_install and agent_datadog_zypper_repo_template.changed and not ansible_check_mode + changed_when: true -- include_tasks: pkg-suse/install-pinned.yml - when: datadog_agent_suse_version is defined +- name: Include Suse agent pinned version install task + ansible.builtin.include_tasks: pkg-suse/install-pinned.yml + when: not agent_datadog_skip_install and agent_datadog_agent_suse_version is defined -- include_tasks: pkg-suse/install-latest.yml - when: datadog_agent_suse_version is not defined +- name: Include Suse agent latest version install task + ansible.builtin.include_tasks: pkg-suse/install-latest.yml + when: not agent_datadog_skip_install and agent_datadog_agent_suse_version is not defined diff --git a/tasks/pkg-suse/install-latest.yml b/tasks/pkg-suse/install-latest.yml index 18b7d0cd..fcac4cbb 100644 --- a/tasks/pkg-suse/install-latest.yml +++ b/tasks/pkg-suse/install-latest.yml @@ -1,8 +1,8 @@ --- - name: Ensure Datadog agent is installed - zypper: + ansible.builtin.package: name: datadog-agent - state: latest # noqa 403 - register: datadog_agent_install + state: latest # noqa package-latest + register: agent_datadog_agent_install when: not ansible_check_mode notify: restart datadog-agent diff --git a/tasks/pkg-suse/install-pinned.yml b/tasks/pkg-suse/install-pinned.yml index 831e505b..77c10330 100644 --- a/tasks/pkg-suse/install-pinned.yml +++ b/tasks/pkg-suse/install-pinned.yml @@ -1,9 +1,9 @@ --- - name: Install pinned datadog-agent package - zypper: - name: "datadog-agent={{ datadog_agent_suse_version }}" + ansible.builtin.package: + name: datadog-agent={{ agent_datadog_agent_suse_version }} state: present oldpackage: "{{ datadog_agent_allow_downgrade }}" - register: datadog_agent_install + register: agent_datadog_agent_install when: not ansible_check_mode notify: restart datadog-agent diff --git a/tasks/pkg-windows-opts.yml b/tasks/pkg-windows-opts.yml index 112340ee..b93f72cd 100644 --- a/tasks/pkg-windows-opts.yml +++ b/tasks/pkg-windows-opts.yml @@ -1,88 +1,165 @@ +--- +- name: Set agent_datadog_windows_config_root default value + ansible.builtin.set_fact: + agent_datadog_windows_config_root: "{{ datadog_windows_config_root }}" + +- name: Initialize force reinstall value + ansible.builtin.set_fact: + agent_datadog_force_reinstall: false + +- name: Initialize internal agent_win_install_args variable + ansible.builtin.set_fact: + agent_win_install_args: "{{ win_install_args }}" + - 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 Password Arg - set_fact: - win_install_args: "{{ win_install_args }} DDAGENTUSER_PASSWORD={{ datadog_windows_ddagentuser_password }}" - when: datadog_windows_ddagentuser_password | length > 0 +- name: Get Windows Agent features + ansible.windows.win_shell: | + $installer = new-object -comobject WindowsInstaller.Installer + $uninstall_key = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*" + $agent_item = (Get-ItemProperty $uninstall_key -EA 0 | Where { $_.DisplayName -like "Datadog Agent*" }).PSChildName + if (!$agent_item) { + return + } + $features = $installer.features($agent_item) + ForEach ($f in $features) { + if (($f -ieq 'MainApplication') -or ($installer.FeatureState($agent_item, $f) -ne 3)) { + continue + } + Write-Host $f + } + register: agent_windows_active_features + changed_when: false -# check the registry. On upgrade, the location of the config file root will -# be set here. +# NOTE: We don't set DD Password Arg here to prevent it from being printed; +# we set it right before using agent_win_install_args + +# check the registry. On upgrade, the location of the config file root will +# be set here. - name: Check existing config file Directory - win_reg_stat: + ansible.windows.win_reg_stat: path: HKLM:\SOFTWARE\Datadog\Datadog Agent name: ConfigRoot - register: config_root_from_registry + register: agent_config_root_from_registry # check the registry. On upgrade, the location of the installation root directory will -# be set here. +# be set here. - name: Check existing installPath Directory - win_reg_stat: + ansible.windows.win_reg_stat: path: HKLM:\SOFTWARE\Datadog\Datadog Agent name: InstallPath - register: install_path_from_registry + register: agent_install_path_from_registry -## validate the config path. Only necessary if it's set in the registry alread (i.e. upgrade) +## validate the config path. Only necessary if it's set in the registry already (i.e. upgrade) ## Will fail the install if the caller has set the config root to a non-standard root, and that ## root is different than what's already present. - name: Validate config path - fail: - msg: "Incompatible configuration option {{ config_root_from_registry.value }} != {{ datadog_windows_config_files_dir }}" - when: ( (config_root_from_registry.exists) and - (datadog_windows_config_files_dir | length > 0 ) and - (config_root_from_registry.value | regex_replace('\\\\$','') | lower != datadog_windows_config_files_dir | lower ) ) + 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 ) ) - name: Validated config path - debug: - msg: "Allowing configuration option {{ config_root_from_registry.value }} == {{ datadog_windows_config_files_dir }}" - when: ( (config_root_from_registry.exists) and - (datadog_windows_config_files_dir | length > 0 ) and - (config_root_from_registry.value | regex_replace('\\\\$','') | lower == datadog_windows_config_files_dir | lower ) ) + ansible.builtin.debug: + msg: "Allowing 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 ) ) ## validate the binary install path. Only necessary if it's set in the registry alread (i.e. upgrade) ## Will fail the install if the caller has set the binary install path to a non-standard root, and that ## root is different than what's already present. - name: Validate install path - fail: - msg: "Incompatible configuration option {{ install_path_from_registry.value }} != {{ datadog_windows_program_files_dir }}" - when: ( (install_path_from_registry.exists) and - (datadog_windows_program_files_dir | length > 0 ) and - (install_path_from_registry.value | regex_replace('\\\\$','') | lower != datadog_windows_program_files_dir | lower ) ) + ansible.builtin.fail: + msg: "Incompatible configuration option {{ agent_install_path_from_registry.value }} != {{ datadog_windows_program_files_dir }}" + when: ( (agent_install_path_from_registry.exists) and (datadog_windows_program_files_dir | length > 0 ) and (agent_install_path_from_registry.value + | regex_replace('\\\\$','') | lower != datadog_windows_program_files_dir | lower ) ) - name: Validated install path - debug: - msg: "Allowing configuration option {{ install_path_from_registry.value }} == {{ datadog_windows_program_files_dir }}" - when: ( (install_path_from_registry.exists) and - (datadog_windows_program_files_dir | length > 0 ) and - (install_path_from_registry.value | regex_replace('\\\\$','') | lower == datadog_windows_program_files_dir | lower ) ) - + ansible.builtin.debug: + msg: "Allowing configuration option {{ agent_install_path_from_registry.value }} == {{ datadog_windows_program_files_dir }}" + when: ( (agent_install_path_from_registry.exists) and (datadog_windows_program_files_dir | length > 0 ) and (agent_install_path_from_registry.value + | regex_replace('\\\\$','') | lower == datadog_windows_program_files_dir | lower ) ) - name: Set Program Files Target Directory - set_fact: - win_install_args: "{{ win_install_args }} PROJECTLOCATION=\"{{ datadog_windows_program_files_dir }}\" " + ansible.builtin.set_fact: + agent_win_install_args: '{{ agent_win_install_args }} PROJECTLOCATION="{{ datadog_windows_program_files_dir }}" ' when: datadog_windows_program_files_dir | length > 0 - name: Set Config Files Target Directory - set_fact: - win_install_args: "{{ win_install_args }} APPLICATIONDATADIRECTORY=\"{{ datadog_windows_config_files_dir }}\" " + ansible.builtin.set_fact: + agent_win_install_args: '{{ agent_win_install_args }} APPLICATIONDATADIRECTORY="{{ datadog_windows_config_files_dir }}" ' when: datadog_windows_config_files_dir | length > 0 # if the current installation was set to a non-standard config root, and that config root is not # presented here, then update accordingly, so that any config file modifications will be made # in the right place - name: Set config root for config Files - set_fact: - datadog_windows_config_root: "{{ datadog_windows_config_files_dir }}" - when: ((datadog_windows_config_files_dir | length > 0) and (not config_root_from_registry.exists)) + ansible.builtin.set_fact: + agent_datadog_windows_config_root: "{{ datadog_windows_config_files_dir }}" + when: ((datadog_windows_config_files_dir | length > 0) and (not agent_config_root_from_registry.exists)) - name: Set config root for config files from current location - set_fact: - datadog_windows_config_root: "{{ config_root_from_registry.value | regex_replace('\\\\$','') }}" - when: config_root_from_registry.exists + ansible.builtin.set_fact: + agent_datadog_windows_config_root: "{{ agent_config_root_from_registry.value | regex_replace('\\\\$', '') }}" + when: agent_config_root_from_registry.exists + +# Add the installation arguments to install Windows NPM. +- name: Set Windows NPM flag + ansible.builtin.set_fact: + agent_win_install_args: "{{ agent_win_install_args }} ADDLOCAL=MainApplication,NPM" + when: agent_datadog_sysprobe_enabled + +# Check for potential config changes that require a reinstall: +- name: Check NPM feature change to force a reinstallation if enabled features have changed + ansible.builtin.set_fact: + agent_datadog_skip_install: false + agent_datadog_force_reinstall: true + # Starting from agent 7.45 the NPM driver is installed by default and gets + # reported as such regardless of the provided parameters. Since we don't + # want to force the install for nothing in those version, we skip the step + # when the agent is 7.45+ + when: >- + (agent_datadog_skip_install and (agent_datadog_major | int <= 7) and (agent_datadog_minor | int < 45)) and + (("NPM" in agent_windows_active_features.stdout_lines) != agent_datadog_sysprobe_enabled) + +# Check if downgrade is requested (installed version is higher than requested version) +- name: Initialize downgrade detection flag + ansible.builtin.set_fact: + agent_datadog_downgrade_detected: false + +- name: Detect if downgrade is requested + ansible.builtin.set_fact: + agent_datadog_downgrade_detected: true + when: >- + agent_datadog_installed_major is defined and + agent_datadog_installed_minor is defined and + agent_datadog_installed_bugfix is defined and + ( + (agent_datadog_installed_major | int > agent_datadog_major | int) or + (agent_datadog_installed_major | int == agent_datadog_major | int and + agent_datadog_installed_minor | int > agent_datadog_minor | int) or + (agent_datadog_installed_major | int == agent_datadog_major | int and + agent_datadog_installed_minor | int == agent_datadog_minor | int and + agent_datadog_installed_bugfix | int > agent_datadog_bugfix | int) + ) + +# Skip downgrade warning if remote update is in progress +- name: Warn about downgrade + ansible.builtin.debug: + msg: >- + datadog_agent_version {{ agent_datadog_major }}.{{ agent_datadog_minor }}.{{ agent_datadog_bugfix }} + is lower than installed version + {{ agent_datadog_installed_major }}.{{ agent_datadog_installed_minor }}.{{ agent_datadog_installed_bugfix }}, + proceeding to downgrade by uninstalling current version first + when: agent_datadog_downgrade_detected and not datadog_remote_update_in_progress -- name: Set Test - set_fact: - win_install_args: "{{ win_install_args }}" \ No newline at end of file +# We do not need to check for remote update in progress here because installation is skipped if remote update is in progress anyway +- name: Force reinstall for downgrade + ansible.builtin.set_fact: + agent_datadog_skip_install: false + agent_datadog_force_reinstall: true + when: agent_datadog_downgrade_detected diff --git a/tasks/pkg-windows.yml b/tasks/pkg-windows.yml index ed88679b..51f0d970 100644 --- a/tasks/pkg-windows.yml +++ b/tasks/pkg-windows.yml @@ -1,83 +1,96 @@ --- -- name: Fail if Agent 5 - fail: - msg: "The Datadog ansible role does not currently support Agent 5" - when: datadog_agent_major_version|int == 5 - -# This is a best-effort solution to avoid redownloading the msi when -# It won't work with rc / beta builds, and won't work if the version to install -# is not pinned (as we don't know what version latest will be before downloading -# the package). -- name: Check currently installed Agent version - win_shell: | - $product_name = "Datadog Agent" - $query = "Select Name,IdentifyingNumber,InstallDate,InstallLocation,ProductID,Version FROM Win32_Product where Name like '$product_name%'" - $installs = Get-WmiObject -query $query - - if (!$installs -or ($installs.Count -eq 0) -or ($installs.Count -gt 1)) { - Write-Host "" - } else { - $ddmaj, $ddmin, $ddpatch, $ddbuild = $installs.Version.split(".") - Write-Host "$($ddmaj).$($ddmin).$($ddpatch)" - } - register: version_check - changed_when: false # By default win_shell returns changed, but we know this script doesn't change anything. +# Note: Windows opts tasks and NPM setup are now included in main.yml to ensure variables are set even during remote updates -- name: Initialize skip install flag to false - set_fact: - datadog_skip_windows_install: "False" +- name: Force skip install when requested + ansible.builtin.set_fact: + agent_datadog_skip_install: true + when: datadog_windows_skip_install | bool -- name: Set skip install flag if version already installed - set_fact: - datadog_skip_windows_install: "{{ version_check.stdout | trim == datadog_agent_windows_version }}" - when: datadog_agent_windows_version is defined +- name: Force Agent reinstall when requested + ansible.builtin.set_fact: + agent_datadog_force_reinstall: true + agent_datadog_skip_install: false + when: datadog_windows_force_reinstall | bool - name: Download windows datadog agent 614 fix script - win_get_url: + ansible.windows.win_get_url: url: "{{ datadog_windows_614_fix_script_url }}" dest: '%TEMP%\fix_6_14.ps1' - when: not datadog_skip_windows_install + proxy_url: "{{ http_proxy | default(omit) }}" + when: not agent_datadog_skip_install and datadog_apply_windows_614_fix - name: Run 6.14.0/1 PowerShell fix - win_shell: | + ansible.windows.win_shell: | Set-ExecutionPolicy Bypass -Scope Process -Force &$env:temp\fix_6_14.ps1 - when: not datadog_skip_windows_install - -- include_tasks: win_agent_latest.yml - when: (not datadog_skip_windows_install) and (datadog_agent_windows_version is not defined) + when: not agent_datadog_skip_install and datadog_apply_windows_614_fix -- include_tasks: win_agent_version.yml - when: (not datadog_skip_windows_install) and (datadog_agent_windows_version is defined) +- name: Include Windows agent latest version install tasks + ansible.builtin.include_tasks: win_agent_latest.yml + when: (not agent_datadog_skip_install) and (agent_datadog_agent_windows_version is not defined) -- name: show URL var - debug: - var: dd_download_url - when: not datadog_skip_windows_install +- name: Include Windows agent pinned version install tasks + ansible.builtin.include_tasks: win_agent_version.yml + when: (not agent_datadog_skip_install) and (agent_datadog_agent_windows_version is defined) -- include_tasks: pkg-windows-opts.yml +- name: Show URL var + ansible.builtin.debug: + var: agent_dd_download_url + when: not agent_datadog_skip_install -- name: pre-Delete temporary msi - win_file: +- name: Pre-Delete temporary msi + ansible.windows.win_file: path: '%TEMP%\ddagent.msi' state: absent - when: not datadog_skip_windows_install + when: not agent_datadog_skip_install - name: Download windows datadog agent - win_get_url: - url: "{{ dd_download_url }}" + ansible.windows.win_get_url: + url: "{{ agent_dd_download_url }}" dest: '%TEMP%\ddagent.msi' - register: download_msi_result - when: not datadog_skip_windows_install + proxy_url: "{{ http_proxy | default(omit) }}" + register: agent_download_msi_result + when: (not agent_datadog_skip_install) and (not ansible_check_mode) + +- name: Look up installed Datadog Agent product ids when forcing reinstall + ansible.windows.win_shell: | + $productName = "Datadog Agent" + $uninstallRoots = @( + "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", + "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall" + ) + $productIds = foreach ($root in $uninstallRoots) { + if (-not (Test-Path $root)) { + continue + } + Get-ItemProperty "$root\*" -ErrorAction SilentlyContinue | + Where-Object { $_.DisplayName -clike $productName } | + Select-Object -ExpandProperty PSChildName + } + $productIds | Sort-Object -Unique + register: agent_datadog_installed_product_ids_result + changed_when: false + check_mode: false + when: + - not agent_datadog_skip_install + - agent_datadog_force_reinstall + +- name: Cache installed product ids when available + ansible.builtin.set_fact: + agent_datadog_windows_installed_product_ids: "{{ agent_datadog_installed_product_ids_result.stdout_lines | select('match', '.+') | list }}" + when: + - not agent_datadog_skip_install + - agent_datadog_force_reinstall + - agent_datadog_installed_product_ids_result.stdout_lines | length > 0 - name: Create Binary directory root (if not default) - win_file: + ansible.windows.win_file: path: "{{ datadog_windows_program_files_dir }}" state: directory when: datadog_windows_program_files_dir | length > 0 - name: Set default permissions on binary directory root (if not default) - win_acl: + ansible.windows.win_acl: path: "{{ datadog_windows_program_files_dir }}" inherit: ContainerInherit,ObjectInherit user: "BUILTIN\\USERS" @@ -87,15 +100,37 @@ propagation: None when: datadog_windows_program_files_dir | length > 0 +- name: Show installation flags + ansible.builtin.debug: + msg: "{{ agent_win_install_args }}{% if datadog_windows_ddagentuser_password | default('', true) | length > 0 %} DDAGENTUSER_PASSWORD={% endif %}" + +# We set DD Password Arg here to prevent it from being printed in any kind of debug logs/messages prior usage +- name: Set DD Password Arg + ansible.builtin.set_fact: + agent_win_install_args: "{{ agent_win_install_args }} DDAGENTUSER_PASSWORD={{ datadog_windows_ddagentuser_password }}" + when: datadog_windows_ddagentuser_password | default('', true) | length > 0 + no_log: true + +- name: Uninstall installed Datadog Agent to update optional features or downgrade or because requested + ansible.windows.win_package: + product_id: "{{ item }}" + state: absent + loop: "{{ agent_datadog_windows_installed_product_ids }}" + when: + - not agent_datadog_skip_install + - agent_datadog_force_reinstall + - agent_datadog_windows_installed_product_ids is defined + - agent_datadog_windows_installed_product_ids | length > 0 + - name: Install downloaded agent - win_package: - path: "{{ download_msi_result.dest }}" - arguments: "{{ win_install_args }}" - register: datadog_agent_install - when: (not datadog_skip_windows_install) and (not ansible_check_mode) + ansible.windows.win_package: + path: "{{ agent_download_msi_result.dest }}" + arguments: "{{ agent_win_install_args }}" + register: agent_datadog_agent_install + when: (not agent_datadog_skip_install) and (not ansible_check_mode) - name: Delete temporary msi - win_file: - path: "{{ download_msi_result.dest }}" + ansible.windows.win_file: + path: "{{ agent_download_msi_result.dest }}" state: absent - when: (not datadog_skip_windows_install) and (download_msi_result.status_code == 200) + when: (not agent_datadog_skip_install) and (not ansible_check_mode) and (agent_download_msi_result.status_code == 200) diff --git a/tasks/remove-legacy-installer.yml b/tasks/remove-legacy-installer.yml new file mode 100644 index 00000000..221b314b --- /dev/null +++ b/tasks/remove-legacy-installer.yml @@ -0,0 +1,36 @@ +--- +# This task removes the legacy installer package and systemd services +- name: Remove legacy installer package + ansible.builtin.package: + name: datadog-installer + state: absent + # Best effort removal - ignore failures to remove the package (e.g. on AL2023 when not being able to use the correct package manager with Python 3) + failed_when: false + +- name: Stop legacy systemd services + ansible.builtin.systemd: + name: "{{ item }}" + state: stopped + enabled: false + failed_when: false + loop: + - datadog-installer-exp.service + - datadog-installer.service + +- name: Remove legacy systemd services + ansible.builtin.file: + name: "{{ item }}" + state: absent + failed_when: false + loop: + - /etc/systemd/system/datadog-installer-exp.service + - /etc/systemd/system/datadog-installer.service + - /lib/systemd/system/datadog-installer-exp.service + - /lib/systemd/system/datadog-installer.service + - /usr/lib/systemd/system/datadog-installer-exp.service + - /usr/lib/systemd/system/datadog-installer.service + +- name: Reload systemd units + ansible.builtin.systemd: + daemon_reload: true + failed_when: false diff --git a/tasks/sanitize-checks.yml b/tasks/sanitize-checks.yml new file mode 100644 index 00000000..70feae2e --- /dev/null +++ b/tasks/sanitize-checks.yml @@ -0,0 +1,13 @@ +--- +- name: Defend against defined but null datadog_checks variable + ansible.builtin.set_fact: + agent_datadog_checks: "{{ datadog_checks | default({}, true) }}" + +- name: Resolve agent_datadog_tracked_checks + ansible.builtin.set_fact: + agent_datadog_tracked_checks: "{{ agent_datadog_checks | list + datadog_additional_checks | default([], true) }}" + +- name: Check that agent_datadog_checks is a mapping + ansible.builtin.assert: + that: + - agent_datadog_checks is mapping diff --git a/tasks/set-parse-version.yml b/tasks/set-parse-version.yml index 8cf8d93d..714fc8d5 100644 --- a/tasks/set-parse-version.yml +++ b/tasks/set-parse-version.yml @@ -1,12 +1,17 @@ --- - name: Convert datadog_agent_major_version to string - set_fact: - datadog_agent_major_version: "{{ datadog_agent_major_version | string }}" + ansible.builtin.set_fact: + agent_datadog_agent_major_version: "{{ datadog_agent_major_version | default('', true) | string }}" -- include_tasks: parse-version.yml - when: datadog_agent_version | length > 0 +- name: Initialize skip install flag to false + ansible.builtin.set_fact: + agent_datadog_skip_install: false + +- name: Include parse version tasks + ansible.builtin.include_tasks: parse-version.yml + when: datadog_agent_version | default('', true) | length > 0 - name: Set Agent default major version - set_fact: - datadog_agent_major_version: "7" - when: datadog_agent_major_version | length == 0 + ansible.builtin.set_fact: + agent_datadog_agent_major_version: "7" + when: agent_datadog_agent_major_version | length == 0 diff --git a/tasks/win_agent_latest.yml b/tasks/win_agent_latest.yml index 0a1299d2..b8ac34b7 100644 --- a/tasks/win_agent_latest.yml +++ b/tasks/win_agent_latest.yml @@ -1,12 +1,11 @@ --- - - name: (Custom) Set agent download filename to latest - set_fact: - dd_download_url: "{{ datadog_windows_download_url }}" - when: datadog_windows_download_url | length > 0 + ansible.builtin.set_fact: + agent_dd_download_url: "{{ datadog_windows_download_url }}" + when: datadog_windows_download_url | default('', true) | length > 0 - name: Set agent download filename to latest - set_fact: - dd_download_url: "{% if datadog_agent_major_version|int == 7 %}{{ datadog_windows_agent7_latest_url }} - {% else %}{{ datadog_windows_agent6_latest_url }}{% endif %}" - when: datadog_windows_download_url | 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 diff --git a/tasks/win_agent_version.yml b/tasks/win_agent_version.yml index 96a0d93e..90f0cc9e 100644 --- a/tasks/win_agent_version.yml +++ b/tasks/win_agent_version.yml @@ -1,10 +1,9 @@ --- - - name: Check agent pinned version on Windows - fail: - msg: "The Agent versions you pinned (6.14.0 or 6.14.1) have been blacklisted, please use 6.14.2 instead. See http://dtdg.co/win-614-fix." + ansible.builtin.fail: + msg: "The Agent versions you pinned (6.14.0 or 6.14.1) have been blacklisted, please use 6.14.2 instead. See https://dtdg.co/win-614-fix." when: datadog_agent_version == "6.14.0" or datadog_agent_version == "6.14.1" -- name: set agent download filename to a specific version - set_fact: - dd_download_url: "{{ datadog_windows_versioned_url }}-{{ datadog_agent_windows_version }}.msi" +- name: Set agent download filename to a specific version + ansible.builtin.set_fact: + agent_dd_download_url: "{{ datadog_windows_versioned_url }}-{{ agent_datadog_agent_windows_version }}.msi" diff --git a/tasks/windows_remote_update_check.yml b/tasks/windows_remote_update_check.yml new file mode 100644 index 00000000..9f256010 --- /dev/null +++ b/tasks/windows_remote_update_check.yml @@ -0,0 +1,27 @@ +--- +- name: Initialize remote update flag + ansible.builtin.set_fact: + datadog_remote_update_in_progress: false + +- name: Check if remote update is in progress + ansible.windows.win_shell: | + Get-CimInstance Win32_Process | Where-Object { + $_.Name -eq "datadog-installer.exe" -and + $_.CommandLine -match "postStartExperimentBackground" + } + register: remote_update_check + +- name: Update remote update flag if installer is running + ansible.builtin.set_fact: + datadog_remote_update_in_progress: true + when: + - remote_update_check.stdout is defined + - remote_update_check.stdout | trim | length > 0 + +- name: Inform about remote update in progress + ansible.builtin.debug: + msg: >- + Remote update is in progress. Skipping installation and restart of the Agent. + Any changes to the configuration will only take effect at the next Agent restart, + either manually or through a future role execution. + when: datadog_remote_update_in_progress diff --git a/templates/checks.yaml.j2 b/templates/checks.yaml.j2 index 39274f28..783a5b36 100644 --- a/templates/checks.yaml.j2 +++ b/templates/checks.yaml.j2 @@ -1 +1,3 @@ -{{ datadog_checks[item] | to_nice_yaml }} +# {{ ansible_managed }} + +{{ agent_datadog_checks[item] | to_nice_yaml(indent=2, width=160, sort_keys=False) }} diff --git a/templates/com.datadoghq.agent.plist.j2 b/templates/com.datadoghq.agent.plist.j2 new file mode 100644 index 00000000..5f48f3db --- /dev/null +++ b/templates/com.datadoghq.agent.plist.j2 @@ -0,0 +1,33 @@ + + + + + KeepAlive + + SuccessfulExit + + + Label + com.datadoghq.agent + EnvironmentVariables + + DD_LOG_TO_CONSOLE + false + + ProgramArguments + + /opt/datadog-agent/bin/agent/agent + run + + StandardOutPath + /opt/datadog-agent/logs/launchd.log + StandardErrorPath + /opt/datadog-agent/logs/launchd.log + ExitTimeOut + 10 + UserName + {{ agent_username }} + GroupName + {{ agent_groupname }} + + diff --git a/templates/datadog.conf.j2 b/templates/datadog.conf.j2 index 1aec885b..08a93904 100644 --- a/templates/datadog.conf.j2 +++ b/templates/datadog.conf.j2 @@ -1,22 +1,22 @@ -# Managed by Ansible +# {{ ansible_managed }} [Main] -{% if datadog_config["dd_url"] is not defined -%} +{% if agent_datadog_config is not defined or agent_datadog_config["dd_url"] is not defined -%} dd_url: {{ datadog_url | default('https://app.datadoghq.com') }} {% endif %} -{% if datadog_config["api_key"] is not defined -%} - api_key: {{ datadog_api_key | default('youshouldsetthis') }} +{% if agent_datadog_config is not defined or agent_datadog_config["api_key"] is not defined -%} + api_key: {{ datadog_api_key }} {% endif %} -{% if datadog_config["use_mount"] is not defined -%} +{% if agent_datadog_config is not defined or agent_datadog_config["use_mount"] is not defined -%} use_mount: {{ datadog_use_mount | default('no') }} {% endif %} {# These variables are free-style, passed through a hash -#} -{% if datadog_config -%} -{% for key, value in datadog_config | dictsort -%} +{% if agent_datadog_config is defined and agent_datadog_config -%} +{% for key, value in agent_datadog_config | dictsort -%} {{ key }}: {{ value }} {% endfor -%} {% endif %} diff --git a/templates/datadog.yaml.j2 b/templates/datadog.yaml.j2 index 3b705e9c..40663fc6 100644 --- a/templates/datadog.yaml.j2 +++ b/templates/datadog.yaml.j2 @@ -1,19 +1,28 @@ -# Managed by Ansible +# {{ ansible_managed }} {% if datadog_site is defined - and datadog_config["site"] is not defined -%} + and (agent_datadog_config is not defined or agent_datadog_config["site"] is not defined) -%} site: {{ datadog_site }} {% endif %} -{% if datadog_config["dd_url"] is not defined +{% if (agent_datadog_config is not defined or agent_datadog_config["dd_url"] is not defined) and datadog_url is defined -%} dd_url: {{ datadog_url }} {% endif %} -{% if datadog_config["api_key"] is not defined -%} -api_key: {{ datadog_api_key | default('youshouldsetthis') }} +{% if agent_datadog_config is not defined or agent_datadog_config["api_key"] is not defined -%} +api_key: {{ datadog_api_key }} {% endif %} -{% if datadog_config is defined and datadog_config|length > 0 -%} -{{ datadog_config | to_nice_yaml }} +{% if (agent_datadog_config is not defined or agent_datadog_config["infrastructure_mode"] is not defined) + and datadog_infrastructure_mode is defined -%} +infrastructure_mode: {{ datadog_infrastructure_mode }} +{% endif %} + +{% if datadog_remote_updates is defined -%} +remote_updates: {{ datadog_remote_updates }} +{% endif -%} + +{% if agent_datadog_config | default({}, true) | length > 0 -%} +{{ agent_datadog_config | to_nice_yaml }} {% endif %} diff --git a/templates/install.json.j2 b/templates/install.json.j2 new file mode 100644 index 00000000..fdd93121 --- /dev/null +++ b/templates/install.json.j2 @@ -0,0 +1 @@ +{"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 }}} diff --git a/templates/security-agent.yaml.j2 b/templates/security-agent.yaml.j2 new file mode 100644 index 00000000..b8ab0c0a --- /dev/null +++ b/templates/security-agent.yaml.j2 @@ -0,0 +1,23 @@ +# {{ ansible_managed }} + +{% if runtime_security_config is defined and runtime_security_config | default({}, true) | length > 0 -%} +runtime_security_config: +{# The "first" option in indent() is only supported by jinja 2.10+ + while the old equivalent option "indentfirst" is removed in jinja 3. + Using non-keyword argument in indent() to be backward compatible. +#} +{% filter indent(2, True) %} +{{ runtime_security_config | to_nice_yaml }} +{% endfilter %} +{% endif %} + +{% if compliance_config is defined and compliance_config | default({}, true) | length > 0 -%} +compliance_config: +{# The "first" option in indent() is only supported by jinja 2.10+ + while the old equivalent option "indentfirst" is removed in jinja 3. + Using non-keyword argument in indent() to be backward compatible. +#} +{% filter indent(2, True) %} +{{ compliance_config | to_nice_yaml }} +{% endfilter %} +{% endif %} diff --git a/templates/system-probe.yaml.j2 b/templates/system-probe.yaml.j2 index 50138b2b..2ec9d4ae 100644 --- a/templates/system-probe.yaml.j2 +++ b/templates/system-probe.yaml.j2 @@ -1,15 +1,49 @@ -# Managed by Ansible +# {{ ansible_managed }} -{% if system_probe_config is defined and system_probe_config|length > 0 -%} +{% if system_probe_config is defined and system_probe_config | default({}, true) | length > 0 -%} system_probe_config: -{# The "first" option is only supported by jinja 2.10+ - which is not present on older systems (CentOS 7, Debian 8, etc.) - Using the equivalent option "indentfirst" will work with - all currently existing jinja 2 versions (as of this comment, up to 2.10). - TODO: when future versions of Jinja are released, check that - indentfirst is still supported. - #} -{% filter indent(width=2, indentfirst=True) %} +{# The "first" option in indent() is only supported by jinja 2.10+ + while the old equivalent option "indentfirst" is removed in jinja 3. + Using non-keyword argument in indent() to be backward compatible. +#} +{% filter indent(2, True) %} {{ system_probe_config | to_nice_yaml }} {% endfilter %} {% endif %} + +{% if network_config is defined and network_config | default({}, true) | length > 0 -%} +network_config: +{# The "first" option in indent() is only supported by jinja 2.10+ + while the old equivalent option "indentfirst" is removed in jinja 3. + Using non-keyword argument in indent() to be backward compatible. +#} +{% filter indent(2, True) %} +{{ network_config | to_nice_yaml }} +{% endfilter %} +{% endif %} + +{% if service_monitoring_config is defined and service_monitoring_config | default({}, true) | length > 0 -%} +service_monitoring_config: +{# The "first" option in indent() is only supported by jinja 2.10+ + while the old equivalent option "indentfirst" is removed in jinja 3. + Using non-keyword argument in indent() to be backward compatible. +#} +{% filter indent(2, True) %} +{{ service_monitoring_config | to_nice_yaml }} +{% endfilter %} +{% endif %} + +{% if runtime_security_config is defined and runtime_security_config | default({}, true) | length > 0 -%} +runtime_security_config: +{# The "first" option in indent() is only supported by jinja 2.10+ + while the old equivalent option "indentfirst" is removed in jinja 3. + Using non-keyword argument in indent() to be backward compatible. +#} +{% filter indent(2, True) %} +{{ runtime_security_config | to_nice_yaml }} +{% endfilter %} +{% endif %} + +{% if system_probe_other_config is defined and system_probe_other_config | default({}, true) | length > 0 -%} +{{ system_probe_other_config | to_nice_yaml }} +{% endif %} diff --git a/templates/zypper.repo.j2 b/templates/zypper.repo.j2 index 580693d0..6781c26f 100644 --- a/templates/zypper.repo.j2 +++ b/templates/zypper.repo.j2 @@ -1,10 +1,8 @@ {% if datadog_zypper_repo | length > 0 %} {% set baseurl = datadog_zypper_repo %} -{% elif datadog_agent_major_version|int == 5 %} - {% set baseurl = datadog_agent5_zypper_repo %} -{% elif datadog_agent_major_version|int == 6 %} +{% elif agent_datadog_agent_major_version|int == 6 %} {% set baseurl = datadog_agent6_zypper_repo %} -{% elif datadog_agent_major_version|int == 7 %} +{% elif agent_datadog_agent_major_version|int == 7 %} {% set baseurl = datadog_agent7_zypper_repo %} {% endif %} @@ -15,5 +13,14 @@ autorefresh=1 baseurl={{ baseurl }} type=rpm-md -gpgcheck=1 -repo_gpgcheck=0 +gpgcheck={{ datadog_zypper_gpgcheck|int }} +repo_gpgcheck={{ agent_do_zypper_repo_gpgcheck|int }} +{# zypper in SUSE < 15 will not parse (SUSE 11) or respect (SUSE 12 - 14) mutliple entries in gpgkey #} +{% if ansible_distribution_version|int < 15 %} +gpgkey={{ datadog_zypper_gpgkey_current }} +{% else %} +gpgkey={{ datadog_zypper_gpgkey_current }} + {{ datadog_zypper_gpgkey_20280418 }} + {{ datadog_zypper_gpgkey_20200908 }} + {{ datadog_zypper_gpgkey_e09422b3 }} +{% endif %} diff --git a/test/integration/default/default.yml b/test/integration/default/default.yml deleted file mode 100644 index 71e9eea9..00000000 --- a/test/integration/default/default.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -- hosts: all - roles: - - { role: ansible-datadog, become: yes } \ No newline at end of file diff --git a/test/integration/default/serverspec/localhost/default_spec.rb b/test/integration/default/serverspec/localhost/default_spec.rb deleted file mode 100644 index 4d0a5dcc..00000000 --- a/test/integration/default/serverspec/localhost/default_spec.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'spec_helper' - -describe 'ansible-datadog::default' do - describe file('/etc/datadog-agent') do - it { should be_directory } - end - - describe service('datadog-agent') do - it { should be_enabled } - it { should be_running } - end -end diff --git a/test/integration/default/serverspec/spec_helper.rb b/test/integration/default/serverspec/spec_helper.rb deleted file mode 100644 index d884c121..00000000 --- a/test/integration/default/serverspec/spec_helper.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'serverspec' - -# :backend can be either :exec or :ssh -# since we are running local we use :exec -set :backend, :exec \ No newline at end of file