├── .circleci └── config.yml ├── .github ├── CODEOWNERS └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── datadog ├── config.sls ├── files │ ├── conf.yaml.jinja │ ├── datadog.conf.jinja │ ├── datadog.yaml.jinja │ └── install_info.jinja ├── init.sls ├── install.sls ├── map.jinja ├── service.sls └── uninstall.sls ├── pillar.example └── test ├── base ├── top.sls ├── top_install.sls └── top_uninstall.sls ├── dist ├── debian_Dockerfile └── redhat_Dockerfile ├── docker-compose.yaml ├── minion.d └── masterless.conf ├── pillar ├── datadog.sls ├── datadog5.sls ├── datadog6.sls ├── datadog7.sls └── top.sls ├── start.sh └── utils ├── check_apt_install.py ├── check_rpm_install.py ├── check_yum_install.py ├── helpers.py └── systemctl.py /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | commands: 4 | setup_common: 5 | steps: 6 | - run: curl -L https://bootstrap.saltstack.com | sh -s -- -d -X stable; exit 0 7 | - run: mkdir -p /etc/salt/minion.d && cp test/minion.d/masterless.conf /etc/salt/minion.d/ 8 | - run: mkdir -p /srv/pillar && cp -r test/pillar /srv/ 9 | - run: mkdir -p /srv/salt && cp -r test/base /srv/salt/ 10 | - run: mkdir -p /srv/salt/base && cp -r datadog /srv/salt/base/ 11 | 12 | setup_installed_version: 13 | parameters: 14 | version: 15 | type: string 16 | default: "7" 17 | steps: 18 | - run: cp test/pillar/datadog{<>,}.sls 19 | 20 | setup_ubuntu: 21 | steps: 22 | - run: apt-get update && apt-get install -y curl sudo python3 23 | - run: cp test/utils/systemctl.py /bin/systemctl 24 | - run: cp test/utils/systemctl.py /bin/systemd 25 | - setup_common 26 | - run: update-alternatives --install /usr/bin/python python /usr/bin/python3 1 27 | 28 | setup_centos: 29 | steps: 30 | - run: yum -y update && yum install -y curl sudo python3 31 | - run: cp test/utils/systemctl.py /usr/bin/systemctl 32 | - run: cp test/utils/systemctl.py /usr/bin/systemd 33 | - setup_common 34 | 35 | setup_suse: 36 | steps: 37 | - run: zypper refresh && zypper -n install curl sudo python3 38 | - setup_common 39 | - run: cp test/utils/systemctl.py /usr/bin/systemctl 40 | - run: cp test/utils/systemctl.py /usr/bin/systemd 41 | 42 | install: 43 | steps: 44 | - run: cp /srv/salt/base/top{_install,}.sls 45 | - run: salt-call --local state.highstate -l debug 46 | 47 | check_installed_version: 48 | parameters: 49 | version: 50 | type: string 51 | default: "7" 52 | repo_type: 53 | type: string 54 | default: "apt" 55 | steps: 56 | - run: python test/utils/check_<>_install.py --major-version <> 57 | 58 | uninstall: 59 | steps: 60 | - run: cp /srv/salt/base/top{_uninstall,}.sls 61 | - run: salt-call --local state.highstate -l debug 62 | 63 | check_uninstalled: 64 | parameters: 65 | repo_type: 66 | type: string 67 | default: "apt" 68 | steps: 69 | - run: python test/utils/check_<>_install.py --not-installed 70 | 71 | jobs: 72 | agent7_ubuntu: 73 | docker: 74 | - image: ubuntu:bionic-20191202 75 | steps: 76 | - checkout 77 | - setup_installed_version: 78 | version: "7" 79 | - setup_ubuntu 80 | - install 81 | - check_installed_version: 82 | version: "7" 83 | repo_type: "apt" 84 | - uninstall 85 | - check_uninstalled: 86 | repo_type: "apt" 87 | 88 | agent7_centos: 89 | docker: 90 | - image: centos:7 91 | steps: 92 | - checkout 93 | - setup_installed_version: 94 | version: "7" 95 | - setup_centos 96 | - install 97 | - check_installed_version: 98 | version: "7" 99 | repo_type: "yum" 100 | - uninstall 101 | - check_uninstalled: 102 | repo_type: "yum" 103 | 104 | agent6_ubuntu: 105 | docker: 106 | - image: ubuntu:bionic-20191202 107 | steps: 108 | - checkout 109 | - setup_installed_version: 110 | version: "6" 111 | - setup_ubuntu 112 | - install 113 | - check_installed_version: 114 | version: "6" 115 | repo_type: "apt" 116 | - uninstall 117 | - check_uninstalled: 118 | repo_type: "apt" 119 | 120 | agent6_centos: 121 | docker: 122 | - image: centos:7 123 | steps: 124 | - checkout 125 | - setup_installed_version: 126 | version: "6" 127 | - setup_centos 128 | - install 129 | - check_installed_version: 130 | version: "6" 131 | repo_type: "yum" 132 | - uninstall 133 | - check_uninstalled: 134 | repo_type: "yum" 135 | 136 | agent5_ubuntu: 137 | docker: 138 | - image: ubuntu:bionic-20191202 139 | steps: 140 | - checkout 141 | - setup_installed_version: 142 | version: "5" 143 | - setup_ubuntu 144 | - install 145 | - check_installed_version: 146 | version: "5" 147 | repo_type: "apt" 148 | - uninstall 149 | - check_uninstalled: 150 | repo_type: "apt" 151 | 152 | agent5_centos: 153 | docker: 154 | - image: centos:7 155 | steps: 156 | - checkout 157 | - setup_installed_version: 158 | version: "5" 159 | - setup_centos 160 | - install 161 | - check_installed_version: 162 | version: "5" 163 | repo_type: "yum" 164 | - uninstall 165 | - check_uninstalled: 166 | repo_type: "yum" 167 | 168 | agent7_suse: 169 | docker: 170 | - image: opensuse/leap:15 171 | steps: 172 | - checkout 173 | - setup_installed_version: 174 | version: "7" 175 | - setup_suse 176 | - install 177 | - check_installed_version: 178 | version: "7" 179 | repo_type: "rpm" 180 | - uninstall 181 | - check_uninstalled: 182 | repo_type: "rpm" 183 | 184 | workflows: 185 | version: 2.1 186 | test_datadog_formula: 187 | jobs: 188 | - agent7_ubuntu 189 | - agent7_centos 190 | - agent6_ubuntu 191 | - agent6_centos 192 | - agent5_ubuntu 193 | - agent5_centos 194 | - agent7_suse 195 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @DataDog/container-ecosystems @DataDog/agent-delivery 2 | 3 | # Docs 4 | *README.md @DataDog/container-ecosystems @DataDog/agent-delivery @DataDog/documentation 5 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### What does this PR do? 2 | 3 | 4 | 5 | ### Motivation 6 | 7 | 8 | 9 | ### Additional Notes 10 | 11 | 12 | 13 | ### Describe your test plan 14 | 15 | 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/* 2 | lib/* 3 | include/* 4 | etc/* 5 | share/* 6 | .vagrant/* 7 | .Python 8 | *.pyc 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changes 2 | 3 | ## 3.7 / 2023-10-31 4 | 5 | * [FEATURE] Add support for SUSE [#89][] 6 | 7 | ## 3.6 / 2023-07-10 8 | 9 | * [FEATURE] Update signing keys [#83][] 10 | 11 | ## 3.5 / 2023-01-12 12 | 13 | * [DEPRECATION] Remove the old RPM GPG key 4172A230 from hosts that still trust it, and stop trusting it. 14 | 15 | ## 3.4 / 2021-08-12 16 | 17 | * [FEATURE] Install datadog-signing-keys on Debian-based platforms [#69][] 18 | * [FEATURE] Implement improvements to APT keys management [#68][] 19 | * [FEATURE] Enable repo_gpgcheck for Agent > 5 yum repos [#67][] 20 | * [FEATURE] Add 'CURRENT' public key entry, get keys from keys.datadoghq.com [#65][] 21 | 22 | ## 3.3 / 2020-11-16 23 | 24 | * [FEATURE] Trust new Datadog GPG keys [#63][] 25 | 26 | ## 3.2 / 2020-08-31 27 | 28 | * [FEATURE] Allow installing third-party integrations [#57][] & [#58][] 29 | * [BUGFIX] Restart the datadog-agent service after an integration install [#59][] 30 | 31 | ## 3.1 / 2020-07-21 32 | 33 | * [FEATURE] Create install info file [#52][] 34 | * [BUGFIX] Remove old check config file if check is installed with Agent 6/7 [#47][] 35 | 36 | ## 3.0 / 2019-12-18 37 | 38 | **This formula will install Agent v7 by default.** Datadog Agent v7 runs checks with Python 3, so if you were running any custom checks written in Python, they must be compatible with Python 3. If you were not running any custom checks or if your custom checks are already compatible with Python 3, then it is safe to upgrade to Agent v7. 39 | 40 | This release contains breaking changes to the pillar file structure. Please read the `README` file, in particular the `Pillar configuration`, as well as the [pillar example file](pillar.example) for details on how to write your pillar file. 41 | 42 | * [FEATURE] Add Agent v7 support [#40][] 43 | * [FEATURE] Allow all `datadog.yaml` config options for Agent v6 and v7 [#35][] 44 | * [FEATURE] Add ability to choose check versions [#37][] 45 | * [BUGFIX] Put check config files in the `.d/` directory on Agent v6 and v7 [#39][] 46 | * [BUGFIX] Fix Agent v6 and v7 install from beta repositories [#42][] 47 | * [BUGFIX] Fix checks config directory permissions [#45][] 48 | * [OTHER] Testing docs & scripts improvements [#44][] 49 | * [OTHER] Do not import the old rpm GPG key if installing Agent v7 [#43][] 50 | * [OTHER] Unused variable cleanup [#36][] 51 | 52 | ## 2.1 / 2019-08-27 53 | 54 | * [FEATURE] Add python_version option [#33][] 55 | * [FEATURE] Add site option [#32][] 56 | * [BUGFIX] Retry on failure when pulling the gpg key from keyserver.ubuntu.com [#28][] 57 | * [OTHER] Trust the new rpm gpg key on RHEL [#31][] 58 | * [OTHER] Use the long apt key fingerprint [#30][] 59 | 60 | ## 2.0 / 2018-07-05 61 | 62 | * Add support for Agent 6. 63 | * Add option to specify which version of the Agent to install (installs the latest version of Agent 6 by default). 64 | * Add CentOS testing environment, with the ability to specify which testing environment you want to spin up. 65 | 66 | ## 1.2 / 2018-06-05 67 | 68 | * Make datadog.checks optional, see [#22][]. 69 | 70 | ## 1.1 / 2018-03-05 71 | 72 | * Trust the new GPG key in the APT repository, see [#20][]. 73 | 74 | ## 1.0 / 2018-02-20 75 | 76 | * Refactor the formula using a map. 77 | * Added a Docker compose file to ease development. 78 | * Added uninstall state. 79 | * Watch config file for changes, see [#17][]. 80 | * Configure checks, see [#18][]. 81 | 82 | 83 | [#17]: https://github.com/DataDog/datadog-formula/issues/17 84 | [#18]: https://github.com/DataDog/datadog-formula/issues/18 85 | [#20]: https://github.com/DataDog/datadog-formula/issues/20 86 | [#22]: https://github.com/DataDog/datadog-formula/issues/22 87 | [#28]: https://github.com/DataDog/datadog-formula/issues/28 88 | [#30]: https://github.com/DataDog/datadog-formula/issues/30 89 | [#31]: https://github.com/DataDog/datadog-formula/issues/31 90 | [#32]: https://github.com/DataDog/datadog-formula/issues/32 91 | [#33]: https://github.com/DataDog/datadog-formula/issues/33 92 | [#35]: https://github.com/DataDog/datadog-formula/issues/35 93 | [#36]: https://github.com/DataDog/datadog-formula/issues/36 94 | [#37]: https://github.com/DataDog/datadog-formula/issues/37 95 | [#39]: https://github.com/DataDog/datadog-formula/issues/39 96 | [#40]: https://github.com/DataDog/datadog-formula/issues/40 97 | [#42]: https://github.com/DataDog/datadog-formula/issues/42 98 | [#43]: https://github.com/DataDog/datadog-formula/issues/43 99 | [#44]: https://github.com/DataDog/datadog-formula/issues/44 100 | [#45]: https://github.com/DataDog/datadog-formula/issues/45 101 | [#47]: https://github.com/DataDog/datadog-formula/issues/47 102 | [#52]: https://github.com/DataDog/datadog-formula/issues/52 103 | [#57]: https://github.com/DataDog/datadog-formula/issues/57 104 | [#58]: https://github.com/DataDog/datadog-formula/issues/58 105 | [#59]: https://github.com/DataDog/datadog-formula/issues/59 106 | [#63]: https://github.com/DataDog/datadog-formula/issues/63 107 | [#65]: https://github.com/DataDog/datadog-formula/issues/65 108 | [#67]: https://github.com/DataDog/datadog-formula/issues/67 109 | [#68]: https://github.com/DataDog/datadog-formula/issues/68 110 | [#69]: https://github.com/DataDog/datadog-formula/issues/69 111 | [#83]: https://github.com/DataDog/datadog-formula/issues/83 112 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | First of all, thanks for contributing! 4 | 5 | This document provides guidelines and instructions for contributing to this repository. To propose improvements, feel free to submit a PR. 6 | 7 | ## Submitting issues 8 | 9 | * If you think you've found an issue, search the issue list to see if there's an existing issue. 10 | * Then, if you find nothing, open a Github issue. 11 | 12 | ## Pull Requests 13 | 14 | Have you fixed a bug or written a new feature and want to share it? Many thanks! 15 | 16 | When submitting your PR, here are some items you can check or improve to facilitate the review process: 17 | 18 | * Have a proper commit history (we advise you to rebase if needed). 19 | * Write tests for the code you wrote. 20 | * Preferably, make sure that all unit tests pass locally and some relevant kitchen tests. 21 | * Summarize your PR with an explanatory title and a message describing your changes, cross-referencing any related bugs/PRs. 22 | * Open your PR against the `main` branch. 23 | 24 | Your pull request must pass all CI tests before we merge it. If you see an error and don't think it's your fault, it may not be! [Join us on Slack][slack] or send us an email, and together we'll get it sorted out. 25 | 26 | ### Keep it small, focused 27 | 28 | Avoid changing too many things at once. For instance if you're fixing a recipe and at the same time adding some code refactor, it makes reviewing harder and the _time-to-release_ longer. 29 | 30 | ### Commit messages 31 | 32 | Please don't be this person: `git commit -m "Fixed stuff"`. Take a moment to write meaningful commit messages. 33 | 34 | The commit message should describe the reason for the change and give extra details that allows someone later on to understand in 5 seconds the thing you've been working on for a day. 35 | 36 | ### Squash your commits 37 | 38 | Rebase your changes on `main` and squash your commits whenever possible. This keeps history cleaner and easier to revert things. It also makes developers happier! 39 | 40 | ## Development 41 | 42 | To ease the development of this formula, use Docker and Docker Compose with the compose file in `test/docker-compose.yaml`. 43 | 44 | First, build and run a Docker container to create a masterless SaltStack minion. You have the option of choosing either 45 | a Debian or Red Hat-based minion. Then, get a shell running in the container. 46 | 47 | ```shell 48 | $ cd test/ 49 | $ TEST_DIST=debian docker-compose run masterless /bin/bash 50 | ``` 51 | 52 | Once you've built the container and have a shell up and running, apply the SaltStack state on your minion: 53 | 54 | ```shell 55 | $ # On your SaltStack minion 56 | $ salt-call --local state.highstate -l debug 57 | ``` 58 | 59 | ### Testing 60 | 61 | A proper integration test suite is still a work in progress. In the meantime, use the Docker Compose file provided in the `test` directory to check out the formula in action. 62 | 63 | #### Requirements 64 | 65 | * Docker 66 | * Docker Compose 67 | 68 | #### Run the formula 69 | 70 | ```shell 71 | $ cd test/ 72 | $ TEST_DIST=debian docker-compose up --build 73 | ``` 74 | 75 | Check the logs to see if all the states completed successfully. 76 | 77 | 78 | [slack]: http://datadoghq.slack.com 79 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Simplified BSD License 2 | 3 | Copyright (c) 2010-2016, Datadog 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | * Neither the name of the copyright holder nor the names of its contributors 15 | may be used to endorse or promote products derived from this software 16 | without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Datadog Formula 2 | 3 | The Datadog SaltStack formula is used to install the Datadog Agent and the Agent-based integrations (checks). For more details on SaltStack formulas, see the [Salt formulas installation and usage instructions][1]. 4 | 5 | ## Setup 6 | 7 | ### Requirements 8 | 9 | The Datadog SaltStack formula only supports installs on Debian-based and RedHat-based systems. 10 | 11 | ### Installation 12 | 13 | The following instructions add the Datadog formula to the `base` Salt environment. To add it to another Salt environment, change the `base` references to the name of your Salt environment. 14 | 15 | #### Option 1 16 | 17 | Install the [Datadog formula][6] in the base environment of your Salt master node, using the `gitfs_remotes` option in your Salt master configuration file (defaults to `/etc/salt/master`): 18 | 19 | ```text 20 | fileserver_backend: 21 | - roots # Active by default, necessary to be able to use the local salt files we define in the next steps 22 | - gitfs # Adds gitfs as a fileserver backend to be able to use gitfs_remotes 23 | 24 | gitfs_remotes: 25 | - https://github.com/DataDog/datadog-formula.git: 26 | - saltenv: 27 | - base: 28 | - ref: 3.0 # Pin the version of the formula you want to use 29 | ``` 30 | 31 | Then restart your Salt Master service to apply the configuration changes: 32 | 33 | ```shell 34 | systemctl restart salt-master 35 | # OR 36 | service salt-master restart 37 | ``` 38 | 39 | #### Option 2 40 | 41 | Alternatively, clone the Datadog formula on your Salt master node: 42 | 43 | ```shell 44 | mkdir -p /srv/formulas && cd /srv/formulas 45 | git clone https://github.com/DataDog/datadog-formula.git 46 | ``` 47 | 48 | Then, add it to the base environment under `file_roots` of your Salt master configuration file (defaults to `/etc/salt/master`): 49 | 50 | ```text 51 | file_roots: 52 | base: 53 | - /srv/salt/ 54 | - /srv/formulas/datadog-formula/ 55 | ``` 56 | 57 | ### Deployment 58 | 59 | To deploy the Datadog Agent on your hosts: 60 | 61 | 1. Add the Datadog formula to your top file (defaults to `/srv/salt/top.sls`): 62 | 63 | ```text 64 | base: 65 | '*': 66 | - datadog 67 | ``` 68 | 69 | 2. Create `datadog.sls` in your pillar directory (defaults to `/srv/pillar/`). Add the following and update your [Datadog API key][2]: 70 | 71 | ``` 72 | datadog: 73 | config: 74 | api_key: 75 | install_settings: 76 | agent_version: 77 | ``` 78 | 79 | 3. Add `datadog.sls` to the top pillar file (defaults to `/srv/pillar/top.sls`): 80 | 81 | ```text 82 | base: 83 | '*': 84 | - datadog 85 | ``` 86 | 87 | ### Configuration 88 | 89 | The formula configuration must be written in the `datadog` key of the pillar file. It contains three parts: `config`, `install_settings`, and `checks`. 90 | 91 | #### Config 92 | 93 | Under `config`, add the configuration options to write to the minions' Agent configuration file (`datadog.yaml` for Agent v6 & v7, `datadog.conf` for Agent v5). 94 | 95 | Depending on the Agent version installed, different options can be set: 96 | 97 | - Agent v6 & v7: all options supported by the Agent's configuration file are supported. 98 | - Agent v5: only the `api_key` option is supported. 99 | 100 | The example below sets your Datadog API key and the Datadog site to `datadoghq.eu` (available for Agent v6 & v7). 101 | 102 | ```text 103 | datadog: 104 | config: 105 | api_key: 106 | site: datadoghq.eu 107 | ``` 108 | 109 | #### Install settings 110 | 111 | Under `install_settings`, configure the Agent installation option: 112 | 113 | - `agent_version`: The version of the Agent to install (defaults to the latest Agent v7). 114 | 115 | The example below installs Agent v6.14.1: 116 | 117 | ```text 118 | datadog: 119 | install_settings: 120 | agent_version: 6.14.1 121 | ``` 122 | 123 | #### Checks 124 | 125 | To add an Agent integration to your host, use the `checks` variable with the check's name as the key. Each check has two options: 126 | 127 | | Option | Description | 128 | |-----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 129 | | `config` | Add the configuration options to write to the check's configuration file:
Agent v6 & v7: `/.d/conf.yaml`
Agent v5: `/.yaml` | 130 | | `version` | For Agent v6 & v7, the version of the check to install (defaults to the version bundled with the Agent). | 131 | | `third_party` | For Agent v6 & v7 (versions v6.21.0/v7.21.0 and higher only), boolean to indicate that the integration to install is a third-party integration. Must be paired with the `version` option. | 132 | 133 | Below is an example to use v1.4.0 of the [Directory][3] integration monitoring the `/srv/pillar` directory: 134 | 135 | ```text 136 | datadog: 137 | config: 138 | api_key: 139 | install_settings: 140 | agent_version: 141 | checks: 142 | directory: 143 | config: 144 | instances: 145 | - directory: "/srv/pillar" 146 | name: "pillars" 147 | version: 1.4.0 148 | ``` 149 | 150 | Below is an example to use v1.0.0 of a sample third-party integration named "third-party-integration": 151 | 152 | ``` 153 | datadog: 154 | config: 155 | api_key: 156 | install_settings: 157 | agent_version: 158 | checks: 159 | third-party-integration: 160 | config: 161 | instances: 162 | - some_config: "some value" 163 | version: 1.0.0 164 | third_party: true 165 | ``` 166 | 167 | ##### Logs 168 | 169 | To enable log collection, set `logs_enabled` to `true` in the main configuration: 170 | ```text 171 | datadog: 172 | config: 173 | logs_enabled: true 174 | ``` 175 | 176 | To send logs to Datadog, use the `logs` key in a check (either an existing check to setup logs for an integration, or a custom check to setup custom log collection). The following example uses a custom check named `system_logs`. 177 | 178 | The contents of the `config:` key of this check is written to the `/etc/datadog-agent/conf.d/.d/conf.yaml` file (in this example: `/etc/datadog-agent/conf.d/system_logs.d/conf.yaml`). 179 | 180 | To list the logs you want to collect, fill the `config` section the same way you'd fill the `conf.yaml` file of a custom log collection configuration file (see the section on [custom log collection](https://docs.datadoghq.com/agent/logs/?tab=tailfiles#custom-log-collection) in the official docs). 181 | 182 | For instance, to collect logs from `/var/log/syslog` and `/var/log/auth.log`, the configuration would be: 183 | 184 | ```text 185 | datadog: 186 | [...] 187 | checks: 188 | system_logs: 189 | config: 190 | logs: 191 | - type: file 192 | path: "/var/log/syslog" 193 | service: "system" 194 | - type: file 195 | path: "/var/log/auth.log" 196 | service: "system" 197 | ``` 198 | 199 | 200 | ## States 201 | 202 | Salt formulas are pre-written Salt states. The following states are available in the Datadog formula: 203 | 204 | | State | Description | 205 | |---------------------|---------------------------------------------------------------------------------------------------------| 206 | | `datadog` | Installs, configures, and starts the Datadog Agent service. | 207 | | `datadog.install` | Configures the correct repo and installs the Datadog Agent. | 208 | | `datadog.config` | Configures the Datadog Agent and integrations using pillar data (see [pillar.example][4]). | 209 | | `datadog.service` | Runs the Datadog Agent service, which watches for changes to the config files for the Agent and checks. | 210 | | `datadog.uninstall` | Stops the service and uninstalls the Datadog Agent. | 211 | 212 | **NOTE**: When using `datadog.config` to configure different check instances on different machines, [pillar_merge_lists][5] must be set to `True` in the Salt master config or the Salt minion config if running masterless. 213 | 214 | [1]: http://docs.saltstack.com/en/latest/topics/development/conventions/formulas.html 215 | [2]: https://app.datadoghq.com/organization-settings/api-keys 216 | [3]: https://docs.datadoghq.com/integrations/directory/ 217 | [4]: https://github.com/DataDog/datadog-formula/blob/master/pillar.example 218 | [5]: https://docs.saltstack.com/en/latest/ref/configuration/master.html#pillar-merge-lists 219 | [6]: https://github.com/DataDog/datadog-formula 220 | -------------------------------------------------------------------------------- /datadog/config.sls: -------------------------------------------------------------------------------- 1 | {% from "datadog/map.jinja" import datadog_config, datadog_install_settings, datadog_checks, latest_agent_version, parsed_version with context %} 2 | {% set config_file_path = '%s/%s'|format(datadog_install_settings.config_folder, datadog_install_settings.config_file) -%} 3 | 4 | {%- if not latest_agent_version and parsed_version[1] == '5' %} 5 | datadog_conf_installed: 6 | file.managed: 7 | - name: {{ config_file_path }} 8 | - source: salt://datadog/files/datadog.conf.jinja 9 | - user: dd-agent 10 | - group: dd-agent 11 | - mode: 600 12 | - template: jinja 13 | - require: 14 | - pkg: datadog-pkg 15 | {%- else %} 16 | datadog_yaml_installed: 17 | file.managed: 18 | - name: {{ config_file_path }} 19 | - source: salt://datadog/files/datadog.yaml.jinja 20 | - user: dd-agent 21 | - group: dd-agent 22 | - mode: 600 23 | - template: jinja 24 | - require: 25 | - pkg: datadog-pkg 26 | {%- endif %} 27 | 28 | {% if datadog_checks is defined %} 29 | {% for check_name in datadog_checks %} 30 | 31 | {%- if latest_agent_version or parsed_version[1] != '5' %} 32 | # Make sure the check directory is present 33 | datadog_{{ check_name }}_folder_installed: 34 | file.directory: 35 | - name: {{ datadog_install_settings.confd_path }}/{{ check_name }}.d 36 | - user: dd-agent 37 | - group: root 38 | - mode: 700 39 | 40 | # Remove the old config file (if it exists) 41 | datadog_{{ check_name }}_old_yaml_removed: 42 | file.absent: 43 | - name: {{ datadog_install_settings.confd_path }}/{{ check_name }}.yaml 44 | {%- endif %} 45 | 46 | datadog_{{ check_name }}_yaml_installed: 47 | file.managed: 48 | {%- if latest_agent_version or parsed_version[1] != '5' %} 49 | - name: {{ datadog_install_settings.confd_path }}/{{ check_name }}.d/conf.yaml 50 | {%- else %} 51 | - name: {{ datadog_install_settings.confd_path }}/{{ check_name }}.yaml 52 | {%- endif %} 53 | - source: salt://datadog/files/conf.yaml.jinja 54 | - user: dd-agent 55 | - group: root 56 | - mode: 600 57 | - template: jinja 58 | - context: 59 | check_name: {{ check_name }} 60 | 61 | {%- if latest_agent_version or parsed_version[1] != '5' %} 62 | {%- if datadog_checks[check_name].version is defined %} 63 | 64 | {%- if datadog_checks[check_name].third_party is defined and datadog_checks[check_name].third_party | to_bool %} 65 | {% set install_command = "install --third-party" %} 66 | {%- else %} 67 | {% set install_command = "install" %} 68 | {%- endif %} 69 | 70 | datadog_check_{{ check_name }}_version_{{ datadog_checks[check_name].version }}_installed: 71 | cmd.run: 72 | - name: sudo -u dd-agent datadog-agent integration {{ install_command }} datadog-{{ check_name }}=={{ datadog_checks[check_name].version }} 73 | - unless: sudo -u dd-agent datadog-agent integration freeze | grep datadog-{{ check_name }}=={{ datadog_checks[check_name].version }} 74 | {%- endif %} 75 | {%- endif %} 76 | 77 | {% endfor %} 78 | {% endif %} 79 | 80 | {% set install_info_path = '%s/install_info'|format(datadog_install_settings.config_folder) -%} 81 | install_info_installed: 82 | file.managed: 83 | - name: {{ install_info_path }} 84 | - source: salt://datadog/files/install_info.jinja 85 | - user: dd-agent 86 | - group: dd-agent 87 | - mode: 600 88 | - template: jinja 89 | - require: 90 | - pkg: datadog-pkg 91 | -------------------------------------------------------------------------------- /datadog/files/conf.yaml.jinja: -------------------------------------------------------------------------------- 1 | {% from "datadog/map.jinja" import datadog_checks with context -%} 2 | 3 | {% if datadog_checks[check_name].config is defined -%} 4 | 5 | {% if datadog_checks[check_name].config.init_config is not defined -%} 6 | init_config: 7 | {% endif -%} 8 | 9 | {{ datadog_checks[check_name].config | yaml(False) }} 10 | 11 | {% endif -%} 12 | -------------------------------------------------------------------------------- /datadog/files/datadog.conf.jinja: -------------------------------------------------------------------------------- 1 | {% from "datadog/map.jinja" import datadog_config with context -%} 2 | 3 | [Main] 4 | dd_url: https://app.datadoghq.com 5 | 6 | {% if datadog_config.api_key is not defined -%} 7 | api_key: 8 | {% else -%} 9 | api_key: {{ datadog_config.api_key }} 10 | {% endif -%} 11 | -------------------------------------------------------------------------------- /datadog/files/datadog.yaml.jinja: -------------------------------------------------------------------------------- 1 | {% from "datadog/map.jinja" import datadog_config with context -%} 2 | 3 | {% if datadog_config.api_key is not defined -%} 4 | api_key: 5 | {% endif -%} 6 | 7 | {% if datadog_config | length -%} 8 | {{ datadog_config | yaml(False) }} 9 | {% endif -%} 10 | -------------------------------------------------------------------------------- /datadog/files/install_info.jinja: -------------------------------------------------------------------------------- 1 | {% from "datadog/map.jinja" import formula_version -%} 2 | --- 3 | install_method: 4 | tool: saltstack 5 | tool_version: saltstack-{{ salt['test.version']() if 'test.version' in salt else 'unknown' }} 6 | installer_version: datadog_formula-{{ formula_version }} 7 | -------------------------------------------------------------------------------- /datadog/init.sls: -------------------------------------------------------------------------------- 1 | include: 2 | - datadog.install 3 | - datadog.config 4 | - datadog.service 5 | -------------------------------------------------------------------------------- /datadog/install.sls: -------------------------------------------------------------------------------- 1 | {% from "datadog/map.jinja" import 2 | datadog_apt_default_keys, 3 | datadog_apt_trusted_d_keyring, 4 | datadog_apt_usr_share_keyring, 5 | datadog_install_settings, 6 | latest_agent_version, 7 | parsed_version 8 | with context %} 9 | 10 | {% macro import_apt_key(key_fingerprint, key_url) %} 11 | {# Since we always have to download at least the CURRENT key, but can't tell Saltstack to not 12 | count it as "changed state", we do this workaround with fetching a URL and setting it 13 | to a variable, which doesn't show up in state at all. #} 14 | {% set key_response = salt['http.query'](key_url) %} 15 | 16 | key-file-{{ key_fingerprint }}-import: 17 | cmd.run: 18 | {# we put key inside an env variable here to prevent the whole long key from appearing in the state output #} 19 | - name: | 20 | echo "${KEY_FROM_URL}" | gpg --import --batch --no-default-keyring --keyring {{ datadog_apt_usr_share_keyring }} 21 | - env: 22 | KEY_FROM_URL: | 23 | {{ key_response.body | indent(10) }} 24 | {# the first part extracts the fingerprint of the key from output like "fpr::::A2923DFF56EDA6E76E55E492D3A80E30382E94DE:" #} 25 | - unless: | 26 | fingerprint=$(echo "${KEY_FROM_URL}" | gpg --with-colons --with-fingerprint 2>/dev/null | grep "fpr:" | sed 's|^fpr||' | tr -d ":") && \ 27 | gpg --no-default-keyring --keyring {{ datadog_apt_usr_share_keyring }} --list-keys --with-fingerprint --with-colons | grep ${fingerprint} 28 | {% endmacro %} 29 | 30 | {%- if grains['os_family'].lower() == 'debian' %} 31 | datadog-apt-https: 32 | pkg.installed: 33 | - name: apt-transport-https 34 | 35 | datadog-gnupg: 36 | pkg.installed: 37 | - name: gnupg 38 | 39 | {# Create the keyring unless it exists #} 40 | {{ datadog_apt_usr_share_keyring }}: 41 | file.managed: 42 | - contents: '' 43 | - contents_newline: False 44 | - mode: 0644 45 | - unless: ls {{ datadog_apt_usr_share_keyring }} 46 | 47 | {% set apt_keys_tmpdir = salt['temp.dir']() %} 48 | 49 | {%- for key_fingerprint, key_url in datadog_apt_default_keys.items() %} 50 | {{ import_apt_key(key_fingerprint, key_url) }} 51 | {%- endfor %} 52 | 53 | {%- if (grains['os'].lower() == 'ubuntu' and grains['osrelease'].split('.')[0]|int < 16) or 54 | (grains['os'].lower() == 'debian' and grains['osrelease'].split('.')[0]|int < 9) %} 55 | {{ datadog_apt_trusted_d_keyring }}: 56 | file.managed: 57 | - mode: 0644 58 | - source: {{ datadog_apt_usr_share_keyring }} 59 | {%- endif %} 60 | 61 | {%- endif %} 62 | 63 | {# Some versions of Salt still in use have issue with providing repo options for 64 | APT sources: https://github.com/saltstack/salt/issues/22412; therefore we use 65 | file.managed instead of pkgrepo.managed for debian platforms #} 66 | 67 | {%- if grains['os_family'].lower() == 'debian' -%} 68 | datadog-repo: 69 | file.managed: 70 | {# Determine beta or stable distribution from version #} 71 | {%- if not latest_agent_version and (parsed_version[2] == 'beta' or parsed_version[2] == 'rc') %} 72 | {% set distribution = 'beta' %} 73 | {%- else %} 74 | {% set distribution = 'stable' %} 75 | {%- endif %} 76 | {# Determine which channel we should look in #} 77 | {%- if latest_agent_version or parsed_version[1] == '7' %} 78 | {% set packages = '7' %} 79 | {%- elif parsed_version[1] == '6' %} 80 | {% set packages = '6' %} 81 | {%- else %} 82 | {% set packages = 'main' %} 83 | {%- endif %} 84 | - contents: deb [signed-by={{ datadog_apt_usr_share_keyring }}] https://apt.datadoghq.com/ {{ distribution }} {{ packages }} 85 | - mode: 0644 86 | - name: /etc/apt/sources.list.d/datadog.list 87 | - require: 88 | - pkg: datadog-apt-https 89 | 90 | {%- elif grains['os_family'].lower() in ['redhat', 'suse'] %} 91 | 92 | datadog-repo: 93 | pkgrepo.managed: 94 | - humanname: "Datadog, Inc." 95 | {#- Determine the location of the package we want #} 96 | {%- if not latest_agent_version and (parsed_version[2] == 'beta' or parsed_version[2] == 'rc') %} 97 | {%- if parsed_version[1] == '7' %} 98 | {% set path = 'beta/7' %} 99 | {%- elif parsed_version[1] == '6' %} 100 | {% set path = 'beta/6' %} 101 | {%- else %} 102 | {% set path = 'beta' %} 103 | {%- endif %} 104 | {%- elif latest_agent_version or parsed_version[1] == '7' %} 105 | {% set path = 'stable/7' %} 106 | {%- elif parsed_version[1] == '6' %} 107 | {% set path = 'stable/6' %} 108 | {%- else %} 109 | {% set path = 'rpm' %} 110 | {%- endif %} 111 | {%- if grains['os_family'].lower() == 'suse' %} 112 | {% set path = 'suse/' + path %} 113 | {%- endif %} 114 | {%- if latest_agent_version or parsed_version[1] != '5' %} 115 | - repo_gpgcheck: '1' 116 | {%- else %} 117 | - repo_gpgcheck: '0' 118 | {%- endif %} 119 | - name: datadog 120 | - baseurl: https://yum.datadoghq.com/{{ path }}/{{ grains['cpuarch'] }} 121 | - gpgcheck: '1' 122 | - gpgkey: https://keys.datadoghq.com/DATADOG_RPM_KEY_CURRENT.public https://keys.datadoghq.com/DATADOG_RPM_KEY_4F09D16B.public https://keys.datadoghq.com/DATADOG_RPM_KEY_B01082D3.public https://keys.datadoghq.com/DATADOG_RPM_KEY_FD4BF915.public https://keys.datadoghq.com/DATADOG_RPM_KEY_E09422B3.public 123 | - gpgautoimport: True 124 | - sslverify: '1' 125 | {%- endif %} 126 | 127 | key-4172a230-removal: 128 | cmd.run: 129 | - name: rpm --erase gpg-pubkey-4172a230-55dd14f6 130 | - onlyif: rpm -q gpg-pubkey-4172a230-55dd14f6 131 | 132 | datadog-pkg: 133 | pkg.installed: 134 | - name: datadog-agent 135 | {%- if latest_agent_version %} 136 | - version: 'latest' 137 | {%- elif grains['os_family'].lower() == 'debian' %} 138 | - version: 1:{{ datadog_install_settings.agent_version }}-1 139 | {%- elif grains['os_family'].lower() == 'redhat' %} 140 | - version: {{ datadog_install_settings.agent_version }}-1 141 | {%- elif grains['os_family'].lower() == 'suse' %} 142 | - version: 1:{{ datadog_install_settings.agent_version }}-1 143 | {%- endif %} 144 | - ignore_epoch: True 145 | - refresh: True 146 | {%- if grains['os_family'].lower() == 'debian' %} 147 | - require: 148 | - file: datadog-repo 149 | {%- elif grains['os_family'].lower() in ['redhat', 'suse'] %} 150 | - require: 151 | - pkgrepo: datadog-repo 152 | {%- endif %} 153 | 154 | {%- if grains['os_family'].lower() == 'debian' %} 155 | datadog-signing-keys-pkg: 156 | pkg.installed: 157 | - name: datadog-signing-keys 158 | - version: 'latest' 159 | - require: 160 | - file: datadog-repo 161 | {%- endif -%} 162 | -------------------------------------------------------------------------------- /datadog/map.jinja: -------------------------------------------------------------------------------- 1 | {% set formula_version = '3.7' %} 2 | 3 | {% set os_family_map = salt['grains.filter_by']({ 4 | 'Debian': {}, 5 | 'RedHat': {}, 6 | 'Suse': {}, 7 | }, 8 | grain="os_family") 9 | %} 10 | 11 | {% set default_settings = { 12 | 'datadog': { 13 | 'config': {}, 14 | 'checks': {}, 15 | 'install_settings': { 16 | 'agent_version': 'latest', 17 | }, 18 | } 19 | }%} 20 | 21 | {# Merge os_family_map into the default settings #} 22 | {% do default_settings.datadog.update(os_family_map) %} 23 | 24 | {# Merge in datadog pillar #} 25 | {% set datadog = salt['pillar.get']('datadog', default=default_settings.datadog, merge=True) %} 26 | {% set datadog_config = datadog['config'] %} 27 | {% set datadog_checks = datadog['checks'] %} 28 | {% set datadog_install_settings = datadog['install_settings'] %} 29 | 30 | {# Set constants for APT key management #} 31 | {% set datadog_apt_trusted_d_keyring = "/etc/apt/trusted.gpg.d/datadog-archive-keyring.gpg" %} 32 | {% set datadog_apt_usr_share_keyring = "/usr/share/keyrings/datadog-archive-keyring.gpg" %} 33 | {% set datadog_apt_key_current_name = "DATADOG_APT_KEY_CURRENT.public" %} 34 | # NOTE: we don't use URLs starting with https://keys.datadoghq.com/, as Python 35 | # on older Debian/Ubuntu doesn't support SNI and get_url would fail on them 36 | {% set datadog_apt_default_keys = { 37 | datadog_apt_key_current_name: "https://s3.amazonaws.com/public-signing-keys/DATADOG_APT_KEY_CURRENT.public", 38 | "D18886567EABAD8B2D2526900D826EB906462314": "https://s3.amazonaws.com/public-signing-keys/DATADOG_APT_KEY_06462314.public", 39 | "5F1E256061D813B125E156E8E6266D4AC0962C7D": "https://s3.amazonaws.com/public-signing-keys/DATADOG_APT_KEY_C0962C7D.public", 40 | "D75CEA17048B9ACBF186794B32637D44F14F620E": "https://s3.amazonaws.com/public-signing-keys/DATADOG_APT_KEY_F14F620E.public", 41 | "A2923DFF56EDA6E76E55E492D3A80E30382E94DE": "https://s3.amazonaws.com/public-signing-keys/DATADOG_APT_KEY_382E94DE.public", 42 | } 43 | %} 44 | 45 | {# Determine if we're looking for the latest package or a specific version #} 46 | {%- if datadog_install_settings.agent_version == 'latest' %} 47 | {%- set latest_agent_version = true %} 48 | {%- else %} 49 | {%- set latest_agent_version = false %} 50 | {%- set parsed_version = datadog_install_settings.agent_version | regex_match('(([0-9]+)\.[0-9]+\.[0-9]+)(?:~(rc|beta)(\.([0-9]+))?)?') %} 51 | {%- endif %} 52 | 53 | {# Determine defaults depending on specified version #} 54 | {%- if latest_agent_version or parsed_version[1] != '5' %} 55 | {% do datadog_install_settings.update({'config_folder': '/etc/datadog-agent'}) %} 56 | {%- else %} 57 | {% do datadog_install_settings.update({'config_folder': '/etc/dd-agent'}) %} 58 | {%- endif %} 59 | 60 | {%- if latest_agent_version or parsed_version[1] != '5' %} 61 | {% do datadog_install_settings.update({'config_file': 'datadog.yaml'}) %} 62 | {%- else %} 63 | {% do datadog_install_settings.update({'config_file': 'datadog.conf'}) %} 64 | {%- endif %} 65 | 66 | {%- if 'confd_path' in datadog_config %} 67 | {% do datadog_install_settings.update({'confd_path': datadog_config.confd_path }) %} 68 | {%- else %} 69 | {%- if latest_agent_version or parsed_version[1] != '5' %} 70 | {% do datadog_install_settings.update({'confd_path': '/etc/datadog-agent/conf.d'}) %} 71 | {%- else %} 72 | {% do datadog_install_settings.update({'confd_path': '/etc/dd-agent/conf.d'}) %} 73 | {%- endif %} 74 | {%- endif %} 75 | -------------------------------------------------------------------------------- /datadog/service.sls: -------------------------------------------------------------------------------- 1 | {% from "datadog/map.jinja" import datadog_install_settings, datadog_checks, latest_agent_version, parsed_version with context %} 2 | {% set config_file_path = '%s/%s'|format(datadog_install_settings.config_folder, datadog_install_settings.config_file) -%} 3 | 4 | datadog-agent-service: 5 | service.running: 6 | - name: datadog-agent 7 | - enable: True 8 | - watch: 9 | - pkg: datadog-agent 10 | - file: {{ config_file_path }} 11 | {%- if datadog_checks | length %} 12 | - file: {{ datadog_install_settings.confd_path }}/* 13 | {% endif %} 14 | {%- if latest_agent_version or parsed_version[1] != '5' %} 15 | {%- if datadog_checks is defined %} 16 | {%- for check_name in datadog_checks %} 17 | {%- if datadog_checks[check_name].version is defined %} 18 | - cmd: datadog_check_{{ check_name }}_version_{{ datadog_checks[check_name].version }}_installed 19 | {% endif %} 20 | {% endfor %} 21 | {% endif %} 22 | {% endif %} 23 | -------------------------------------------------------------------------------- /datadog/uninstall.sls: -------------------------------------------------------------------------------- 1 | {% from "datadog/map.jinja" import datadog_install_settings with context %} 2 | 3 | datadog-uninstall: 4 | service.dead: 5 | - name: datadog-agent 6 | - enable: False 7 | pkg.removed: 8 | - pkgs: 9 | - datadog-agent 10 | - datadog-signing-keys 11 | - require: 12 | - service: datadog-uninstall 13 | -------------------------------------------------------------------------------- /pillar.example: -------------------------------------------------------------------------------- 1 | datadog: 2 | config: 3 | api_key: aaaaaaaabbbbbbbbccccccccdddddddd 4 | site: datadoghq.com 5 | python_version: 2 6 | 7 | checks: 8 | process: 9 | config: 10 | init_config: 11 | procfs_path: /proc 12 | instances: 13 | - name: ssh 14 | search_string: ['sshd'] 15 | tcp_check: 16 | config: 17 | instances: 18 | - host: 127.0.0.1 19 | name: sshd 20 | port: 22 21 | 22 | install_settings: 23 | agent_version: latest 24 | -------------------------------------------------------------------------------- /test/base/top.sls: -------------------------------------------------------------------------------- 1 | base: 2 | '*': 3 | - datadog 4 | - datadog.uninstall 5 | -------------------------------------------------------------------------------- /test/base/top_install.sls: -------------------------------------------------------------------------------- 1 | base: 2 | '*': 3 | - datadog -------------------------------------------------------------------------------- /test/base/top_uninstall.sls: -------------------------------------------------------------------------------- 1 | base: 2 | '*': 3 | - datadog.uninstall -------------------------------------------------------------------------------- /test/dist/debian_Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 2 | LABEL maintainer="package@datadoghq.com" 3 | 4 | # preparation for saltstack 5 | RUN apt-get update &&\ 6 | apt-get install -y curl 7 | 8 | # enable systemd, thanks to @gdraheim (https://github.com/gdraheim/) 9 | ADD utils/systemctl.py /bin/systemctl 10 | ADD utils/systemctl.py /bin/systemd 11 | 12 | # install salt 13 | RUN curl -L https://bootstrap.saltstack.com | sh -s -- -d -X stable 14 | 15 | # add the start test script 16 | ADD start.sh /start.sh 17 | CMD ["bash", "start.sh"] 18 | -------------------------------------------------------------------------------- /test/dist/redhat_Dockerfile: -------------------------------------------------------------------------------- 1 | FROM centos:7 2 | LABEL maintainer="package@datadoghq.com" 3 | 4 | # preparation for saltstack 5 | RUN yum -y update && yum -y install curl python3 6 | 7 | # enable systemd, thanks to @gdraheim (https://github.com/gdraheim/) 8 | ADD utils/systemctl.py /usr/bin/systemctl 9 | ADD utils/systemctl.py /usr/bin/systemd 10 | 11 | # install salt 12 | RUN curl -L https://bootstrap.saltstack.com | sh -s -- -d -X stable 13 | 14 | # add the start test script 15 | ADD start.sh /start.sh 16 | CMD ["bash", "start.sh"] 17 | -------------------------------------------------------------------------------- /test/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | masterless: 3 | platform: linux/amd64 4 | build: 5 | context: . 6 | dockerfile: ./dist/${TEST_DIST}_Dockerfile 7 | volumes: 8 | - ./minion.d:/etc/salt/minion.d 9 | - ./pillar:/srv/pillar 10 | - ./base:/srv/salt/base 11 | - ../datadog:/srv/salt/base/datadog 12 | -------------------------------------------------------------------------------- /test/minion.d/masterless.conf: -------------------------------------------------------------------------------- 1 | file_client: local 2 | file_roots: 3 | base: 4 | - /srv/salt/base 5 | pillar_roots: 6 | base: 7 | - /srv/pillar 8 | providers: 9 | service: systemd_service 10 | -------------------------------------------------------------------------------- /test/pillar/datadog.sls: -------------------------------------------------------------------------------- 1 | datadog: 2 | config: 3 | api_key: aaaaaaaabbbbbbbbccccccccdddddddd 4 | site: datadoghq.com 5 | python_version: 2 6 | hostname: test 7 | 8 | checks: 9 | directory: 10 | config: 11 | instances: 12 | - directory: "/srv/pillar" 13 | name: "pillars" 14 | 15 | install_settings: 16 | agent_version: latest 17 | -------------------------------------------------------------------------------- /test/pillar/datadog5.sls: -------------------------------------------------------------------------------- 1 | datadog: 2 | config: 3 | api_key: aaaaaaaabbbbbbbbccccccccdddddddd 4 | site: datadoghq.com 5 | hostname: test-5 6 | 7 | checks: 8 | directory: 9 | config: 10 | instances: 11 | - directory: "/srv/pillar" 12 | name: "pillars" 13 | 14 | install_settings: 15 | {% if grains['os_family'].lower() == 'redhat' %} 16 | agent_version: 5.32.9 17 | {% else %} 18 | agent_version: 5.32.8 19 | {% endif %} 20 | -------------------------------------------------------------------------------- /test/pillar/datadog6.sls: -------------------------------------------------------------------------------- 1 | datadog: 2 | config: 3 | api_key: aaaaaaaabbbbbbbbccccccccdddddddd 4 | site: datadoghq.com 5 | python_version: 2 6 | hostname: test-6 7 | 8 | checks: 9 | directory: 10 | config: 11 | instances: 12 | - directory: "/srv/pillar" 13 | name: "pillars" 14 | # Test installing a third-party integration 15 | bind9: 16 | config: 17 | instances: 18 | - {} 19 | version: 1.0.0 20 | third_party: true 21 | 22 | install_settings: 23 | agent_version: 6.41.1 24 | -------------------------------------------------------------------------------- /test/pillar/datadog7.sls: -------------------------------------------------------------------------------- 1 | datadog: 2 | config: 3 | api_key: aaaaaaaabbbbbbbbccccccccdddddddd 4 | site: datadoghq.com 5 | hostname: test-7 6 | 7 | checks: 8 | directory: 9 | config: 10 | instances: 11 | - directory: "/srv/pillar" 12 | name: "pillars" 13 | # Test installing a third-party integration 14 | bind9: 15 | config: 16 | instances: 17 | - {} 18 | version: 1.0.0 19 | third_party: true 20 | 21 | install_settings: 22 | agent_version: latest 23 | -------------------------------------------------------------------------------- /test/pillar/top.sls: -------------------------------------------------------------------------------- 1 | base: 2 | '*': 3 | - datadog 4 | -------------------------------------------------------------------------------- /test/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Install & uninstall datadog-agent 4 | salt-call --local state.highstate -l debug 5 | 6 | echo "==== Done ====" 7 | sleep infinity 8 | -------------------------------------------------------------------------------- /test/utils/check_apt_install.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import apt 4 | import re 5 | import sys 6 | from helpers import get_options, check_major_version, check_install_info 7 | 8 | 9 | def get_apt_package_version(package_name): 10 | cache = apt.cache.Cache() 11 | cache.update() 12 | cache.open() 13 | 14 | installed_version = None 15 | try: 16 | pkg = cache["datadog-agent"] 17 | if pkg.is_installed: 18 | # pkg.installed has the form datadog-agent=1:x.y.z-1, we only want x.y.z 19 | installed_version = re.match("datadog-agent=[0-9]+:(.*)-[0-9]+", str(pkg.installed)).groups()[0] 20 | except KeyError: 21 | # datadog-agent is not installed 22 | pass 23 | 24 | return installed_version 25 | 26 | 27 | def main(argv): 28 | expected_major_version = get_options(argv[1:]) 29 | print("Expected major version: {}".format(expected_major_version)) 30 | 31 | installed_version = get_apt_package_version("datadog-agent") 32 | print("Installed Agent version: {}".format(installed_version)) 33 | 34 | assert check_major_version(installed_version, expected_major_version) 35 | print("Agent version check successful!") 36 | 37 | # expected_major_version 38 | if expected_major_version: 39 | assert check_install_info(expected_major_version) 40 | print("install_info check successful!") 41 | else: 42 | print("Skipping install_info check.") 43 | 44 | sys.exit() 45 | 46 | 47 | if __name__ == "__main__": 48 | main(sys.argv) 49 | -------------------------------------------------------------------------------- /test/utils/check_rpm_install.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import subprocess 4 | import sys 5 | from helpers import get_options, check_major_version, check_install_info 6 | 7 | 8 | def is_rpm_package_installed(package_name): 9 | try: 10 | subprocess.check_output(["rpm", "-q", package_name]) 11 | return True 12 | except subprocess.CalledProcessError: 13 | return False 14 | 15 | 16 | def get_rpm_package_version(package_name): 17 | try: 18 | if not is_rpm_package_installed(package_name): 19 | return None 20 | return subprocess.check_output('rpm -qi {} | grep -E "Version[[:space:]]+:" | cut -d: -f2 | xargs'.format(package_name), 21 | shell=True) 22 | except subprocess.CalledProcessError: 23 | return None 24 | 25 | 26 | 27 | def main(argv): 28 | expected_major_version = get_options(argv[1:]) 29 | print("Expected major version: {}".format(expected_major_version)) 30 | 31 | installed_version = get_rpm_package_version("datadog-agent") 32 | print("Installed Agent version: {}".format(installed_version)) 33 | 34 | result = check_major_version(installed_version, expected_major_version) 35 | assert result 36 | print("Agent version check successful!") 37 | 38 | # expected_major_version 39 | if expected_major_version: 40 | assert check_install_info(expected_major_version) 41 | print("install_info check successful!") 42 | else: 43 | print("Skipping install_info check.") 44 | 45 | assert not is_rpm_package_installed("gpg-pubkey-4172a230-55dd14f6") 46 | print("GPG key 4172a230 is not installed.") 47 | 48 | sys.exit() 49 | 50 | 51 | if __name__ == "__main__": 52 | main(sys.argv) 53 | -------------------------------------------------------------------------------- /test/utils/check_yum_install.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import subprocess 4 | import yum 5 | import sys 6 | from helpers import get_options, check_major_version, check_install_info 7 | 8 | 9 | def get_yum_package_version(package_name): 10 | yb = yum.YumBase() 11 | try: 12 | # Use next to stop at the first match 13 | pkg = next(p for p in yb.rpmdb.returnPackages() if p.name == package_name) 14 | installed_version = pkg.version 15 | except StopIteration: 16 | # datadog-agent is not in the list of installed packages 17 | installed_version = None 18 | 19 | return installed_version 20 | 21 | 22 | def is_rpm_package_installed(package_name): 23 | try: 24 | subprocess.check_output(["rpm", "-q", package_name]) 25 | return True 26 | except subprocess.CalledProcessError: 27 | return False 28 | 29 | 30 | def main(argv): 31 | expected_major_version = get_options(argv[1:]) 32 | print("Expected major version: {}".format(expected_major_version)) 33 | 34 | installed_version = get_yum_package_version("datadog-agent") 35 | print("Installed Agent version: {}".format(installed_version)) 36 | 37 | assert check_major_version(installed_version, expected_major_version) 38 | print("Agent version check successful!") 39 | 40 | # expected_major_version 41 | if expected_major_version: 42 | assert check_install_info(expected_major_version) 43 | print("install_info check successful!") 44 | else: 45 | print("Skipping install_info check.") 46 | 47 | assert not is_rpm_package_installed("gpg-pubkey-4172a230-55dd14f6") 48 | print("GPG key 4172a230 is not installed.") 49 | 50 | sys.exit() 51 | 52 | 53 | if __name__ == "__main__": 54 | main(sys.argv) 55 | -------------------------------------------------------------------------------- /test/utils/helpers.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import getopt 4 | import re 5 | import os.path 6 | import os 7 | 8 | def get_options(args): 9 | expected_major_version = None 10 | try: 11 | opts, _ = getopt.getopt(args, "hnm:", ["not-installed", "major-version="]) 12 | except getopt.GetoptError: 13 | print('check_install.py [-n] [-m ]') 14 | sys.exit(2) 15 | for opt, arg in opts: 16 | if opt == '-h': 17 | print('check_apt_install.py [-n] [-m ]') 18 | sys.exit() 19 | elif opt in ("-n", "--not-installed"): 20 | expected_major_version = None 21 | elif opt in ("-m", "--major-version"): 22 | expected_major_version = arg 23 | 24 | return expected_major_version 25 | 26 | def check_major_version(installed_version, expected_major_version): 27 | installed_major_version = None 28 | 29 | if installed_version is not None: 30 | installed_major_version = re.match("([0-9]+).*", installed_version).groups()[0] 31 | 32 | print("Installed Agent major version: {}".format(installed_major_version)) 33 | return installed_major_version == expected_major_version 34 | 35 | def get_config_dir(agent_version): 36 | """Get the agent configuration directory on *nix systems.""" 37 | if int(agent_version) == 5: 38 | return "/etc/dd-agent" 39 | else: 40 | return "/etc/datadog-agent" 41 | 42 | 43 | def check_install_info(agent_version): 44 | """Check install_info file.""" 45 | config_dir = get_config_dir(agent_version) 46 | info_path = os.path.join(config_dir, "install_info") 47 | 48 | if not os.path.isfile(info_path): 49 | print("install_info file not found at {}".format(info_path)) 50 | return False 51 | 52 | with open(info_path, 'r') as install_info: 53 | contents = install_info.read() 54 | for pat in [ 55 | r'^ tool:\s*saltstack$', 56 | r'^ tool_version:\s*saltstack-([0-9.]+|unknown)$', 57 | r'^ installer_version:\s*datadog_formula-[0-9](\.[0-9]+)*$' 58 | ]: 59 | if not re.search(pat, contents, flags=re.MULTILINE): 60 | print("Expected match for '{}' in '{}'".format(pat, contents)) 61 | return False 62 | 63 | return True 64 | --------------------------------------------------------------------------------