├── .ansible-lint ├── .gitignore ├── molecule └── default │ ├── requirements.yml │ ├── molecule.yml │ └── converge.yml ├── .github ├── FUNDING.yml └── workflows │ ├── release.yml │ ├── ci.yml │ └── stale.yml ├── .yamllint ├── tasks ├── setup-RedHat.yml ├── setup-Debian.yml └── main.yml ├── meta └── main.yml ├── LICENSE ├── defaults └── main.yml └── README.md /.ansible-lint: -------------------------------------------------------------------------------- 1 | skip_list: 2 | - 'yaml' 3 | - 'role-name' 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.retry 2 | */__pycache__ 3 | *.pyc 4 | .cache 5 | 6 | -------------------------------------------------------------------------------- /molecule/default/requirements.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - src: geerlingguy.repo-epel 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | --- 3 | github: geerlingguy 4 | patreon: geerlingguy 5 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | --- 2 | extends: default 3 | 4 | rules: 5 | line-length: 6 | max: 120 7 | level: warning 8 | 9 | ignore: | 10 | .github/workflows/stale.yml 11 | -------------------------------------------------------------------------------- /tasks/setup-RedHat.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure pip is installed. 3 | yum: 4 | name: '{{ elasticsearch_curator_pip_package }}' 5 | state: present 6 | enablerepo: epel 7 | -------------------------------------------------------------------------------- /tasks/setup-Debian.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure wheel is installed (Ubuntu 20.04). 3 | apt: 4 | name: python3-wheel 5 | state: present 6 | when: 7 | - ansible_facts.distribution == 'Ubuntu' 8 | - ansible_facts.distribution_major_version == '20' 9 | 10 | - name: Ensure pip is installed. 11 | apt: 12 | name: '{{ elasticsearch_curator_pip_package }}' 13 | state: present 14 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: [] 3 | 4 | galaxy_info: 5 | role_name: elasticsearch-curator 6 | author: geerlingguy 7 | description: Elasticsearch curator for Linux. 8 | company: "Midwestern Mac, LLC" 9 | license: "license (BSD, MIT)" 10 | min_ansible_version: 2.10 11 | platforms: 12 | - name: Debian 13 | versions: 14 | - all 15 | - name: Ubuntu 16 | versions: 17 | - all 18 | galaxy_tags: 19 | - web 20 | - system 21 | - monitoring 22 | - elasticsearch 23 | - curator 24 | - efk 25 | - elk 26 | -------------------------------------------------------------------------------- /molecule/default/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | role_name_check: 1 3 | dependency: 4 | name: galaxy 5 | options: 6 | ignore-errors: true 7 | driver: 8 | name: docker 9 | platforms: 10 | - name: instance 11 | image: "geerlingguy/docker-${MOLECULE_DISTRO:-rockylinux9}-ansible:latest" 12 | command: ${MOLECULE_DOCKER_COMMAND:-""} 13 | volumes: 14 | - /sys/fs/cgroup:/sys/fs/cgroup:rw 15 | cgroupns_mode: host 16 | privileged: true 17 | pre_build_image: true 18 | provisioner: 19 | name: ansible 20 | playbooks: 21 | converge: ${MOLECULE_PLAYBOOK:-converge.yml} 22 | -------------------------------------------------------------------------------- /molecule/default/converge.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: all 4 | #become: true 5 | 6 | vars: 7 | elasticsearch_curator_pip_extra_args: '--ignore-installed PyYAML' 8 | 9 | pre_tasks: 10 | - name: Update apt cache. 11 | apt: update_cache=yes cache_valid_time=600 12 | when: ansible_facts.os_family == 'Debian' 13 | 14 | - name: Install cron (RedHat). 15 | yum: name=cronie state=present 16 | when: ansible_facts.os_family == 'RedHat' 17 | 18 | - name: Install cron (Debian). 19 | apt: name=cron state=present 20 | when: ansible_facts.os_family == 'Debian' 21 | 22 | roles: 23 | - role: geerlingguy.repo-epel 24 | when: ansible_facts.os_family == 'RedHat' 25 | - role: geerlingguy.elasticsearch-curator 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Jeff Geerling 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # This workflow requires a GALAXY_API_KEY secret present in the GitHub 3 | # repository or organization. 4 | # 5 | # See: https://github.com/marketplace/actions/publish-ansible-role-to-galaxy 6 | # See: https://github.com/ansible/galaxy/issues/46 7 | 8 | name: Release 9 | 'on': 10 | push: 11 | tags: 12 | - '*' 13 | 14 | defaults: 15 | run: 16 | working-directory: 'geerlingguy.elasticsearch-curator' 17 | 18 | jobs: 19 | 20 | release: 21 | name: Release 22 | runs-on: ubuntu-latest 23 | steps: 24 | - name: Check out the codebase. 25 | uses: actions/checkout@v4 26 | with: 27 | path: 'geerlingguy.elasticsearch-curator' 28 | 29 | - name: Set up Python 3. 30 | uses: actions/setup-python@v5 31 | with: 32 | python-version: '3.13' # Can't go to 3.14+ until Ansible 13.x 33 | 34 | - name: Install Ansible. 35 | run: pip3 install ansible-core 36 | 37 | - name: Trigger a new import on Galaxy. 38 | run: >- 39 | ansible-galaxy role import --api-key ${{ secrets.GALAXY_API_KEY }} 40 | $(echo ${{ github.repository }} | cut -d/ -f1) $(echo ${{ github.repository }} | cut -d/ -f2) 41 | -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | elasticsearch_curator_version: '' 3 | 4 | elasticsearch_curator_cron_jobs: 5 | - name: "Run elasticsearch curator actions." 6 | job: "/usr/local/bin/curator ~/.curator/action.yml" 7 | minute: 0 8 | hour: 1 9 | 10 | elasticsearch_curator_config_directory: ~/.curator 11 | 12 | elasticsearch_curator_hosts: 13 | - 'localhost:9200' 14 | elasticsearch_curator_http_auth: '' 15 | elasticsearch_curator_yaml: | 16 | --- 17 | client: 18 | hosts: {{ elasticsearch_curator_hosts | to_yaml }} 19 | url_prefix: 20 | use_ssl: False 21 | certificate: 22 | client_cert: 23 | client_key: 24 | ssl_no_validate: False 25 | http_auth: {{ elasticsearch_curator_http_auth }} 26 | timeout: 30 27 | master_only: False 28 | logging: 29 | loglevel: INFO 30 | logfile: 31 | logformat: default 32 | blacklist: ['elasticsearch', 'urllib3'] 33 | 34 | elasticsearch_curator_action_yaml: | 35 | --- 36 | actions: 37 | 1: 38 | action: delete_indices 39 | options: 40 | ignore_empty_list: True 41 | disable_action: False 42 | filters: 43 | - filtertype: pattern 44 | kind: prefix 45 | value: logstash- 46 | exclude: 47 | - filtertype: age 48 | source: name 49 | direction: older 50 | timestring: '%Y.%m.%d' 51 | unit: days 52 | unit_count: 45 53 | exclude: 54 | 55 | elasticsearch_curator_pip_package: 'python3-pip' 56 | elasticsearch_curator_pip_executable: "{{ 'pip3' if elasticsearch_curator_pip_package.startswith('python3') else 'pip' }}" 57 | -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include_tasks: setup-RedHat.yml 3 | when: ansible_facts.os_family == 'RedHat' 4 | 5 | - include_tasks: setup-Debian.yml 6 | when: ansible_facts.os_family == 'Debian' 7 | 8 | - name: Install Elasticsearch Curator via pip. 9 | pip: 10 | name: elasticsearch-curator 11 | version: "{{ elasticsearch_curator_version | default(omit) }}" 12 | executable: "{{ elasticsearch_curator_pip_executable }}" 13 | extra_args: "{{ elasticsearch_curator_pip_extra_args | default(omit) }}" 14 | 15 | - name: Install required dependency. 16 | pip: 17 | name: argparse 18 | executable: "{{ elasticsearch_curator_pip_executable }}" 19 | 20 | - name: Ensure configuration directory exists. 21 | file: 22 | path: '{{ elasticsearch_curator_config_directory }}' 23 | state: directory 24 | mode: 0755 25 | 26 | - name: Write curator.yml and action.yml to configuration directory. 27 | copy: 28 | dest: '{{ elasticsearch_curator_config_directory }}/{{ item.file }}' 29 | content: '{{ item.content }}' 30 | mode: 0644 31 | with_items: 32 | - file: curator.yml 33 | content: '{{ elasticsearch_curator_yaml }}' 34 | - file: action.yml 35 | content: '{{ elasticsearch_curator_action_yaml }}' 36 | 37 | - name: Configure cron jobs for Elasticsearch Curator. 38 | cron: 39 | name: "{{ item.name }}" 40 | job: "{{ item.job }}" 41 | state: "{{ item.state | default('present') }}" 42 | minute: "{{ item.minute | default('*') }}" 43 | hour: "{{ item.hour | default('*') }}" 44 | day: "{{ item.day | default('*') }}" 45 | weekday: "{{ item.weekday | default('*') }}" 46 | month: "{{ item.month | default('*') }}" 47 | with_items: "{{ elasticsearch_curator_cron_jobs }}" 48 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: CI 3 | 'on': 4 | pull_request: 5 | push: 6 | branches: 7 | - master 8 | schedule: 9 | - cron: "0 3 * * 1" 10 | 11 | defaults: 12 | run: 13 | working-directory: 'geerlingguy.elasticsearch-curator' 14 | 15 | jobs: 16 | 17 | lint: 18 | name: Lint 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: Check out the codebase. 22 | uses: actions/checkout@v4 23 | with: 24 | path: 'geerlingguy.elasticsearch-curator' 25 | 26 | - name: Set up Python 3. 27 | uses: actions/setup-python@v5 28 | with: 29 | python-version: '3.13' # Can't go to 3.14+ until Ansible 13.x 30 | 31 | - name: Install test dependencies. 32 | run: pip3 install yamllint 33 | 34 | - name: Lint code. 35 | run: | 36 | yamllint . 37 | 38 | molecule: 39 | name: Molecule 40 | runs-on: ubuntu-latest 41 | strategy: 42 | matrix: 43 | distro: 44 | - rockylinux9 45 | - ubuntu2404 46 | - debian12 47 | 48 | steps: 49 | - name: Check out the codebase. 50 | uses: actions/checkout@v4 51 | with: 52 | path: 'geerlingguy.elasticsearch-curator' 53 | 54 | - name: Set up Python 3. 55 | uses: actions/setup-python@v5 56 | with: 57 | python-version: '3.13' # Can't go to 3.14+ until Ansible 13.x 58 | 59 | - name: Install test dependencies. 60 | run: pip3 install ansible molecule molecule-plugins[docker] docker 61 | 62 | - name: Run Molecule tests. 63 | run: molecule test 64 | env: 65 | PY_COLORS: '1' 66 | ANSIBLE_FORCE_COLOR: '1' 67 | MOLECULE_DISTRO: ${{ matrix.distro }} 68 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Close inactive issues 3 | 'on': 4 | schedule: 5 | - cron: "55 22 * * 0" # semi-random time 6 | 7 | jobs: 8 | close-issues: 9 | runs-on: ubuntu-latest 10 | permissions: 11 | issues: write 12 | pull-requests: write 13 | steps: 14 | - uses: actions/stale@v8 15 | with: 16 | days-before-stale: 120 17 | days-before-close: 60 18 | exempt-issue-labels: bug,pinned,security,planned 19 | exempt-pr-labels: bug,pinned,security,planned 20 | stale-issue-label: "stale" 21 | stale-pr-label: "stale" 22 | stale-issue-message: | 23 | This issue has been marked 'stale' due to lack of recent activity. If there is no further activity, the issue will be closed in another 30 days. Thank you for your contribution! 24 | 25 | Please read [this blog post](https://www.jeffgeerling.com/blog/2020/enabling-stale-issue-bot-on-my-github-repositories) to see the reasons why I mark issues as stale. 26 | close-issue-message: | 27 | This issue has been closed due to inactivity. If you feel this is in error, please reopen the issue or file a new issue with the relevant details. 28 | stale-pr-message: | 29 | This pr has been marked 'stale' due to lack of recent activity. If there is no further activity, the issue will be closed in another 30 days. Thank you for your contribution! 30 | 31 | Please read [this blog post](https://www.jeffgeerling.com/blog/2020/enabling-stale-issue-bot-on-my-github-repositories) to see the reasons why I mark issues as stale. 32 | close-pr-message: | 33 | This pr has been closed due to inactivity. If you feel this is in error, please reopen the issue or file a new issue with the relevant details. 34 | repo-token: ${{ secrets.GITHUB_TOKEN }} 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ansible Role: Elasticsearch Curator 2 | 3 | [![CI](https://github.com/geerlingguy/ansible-role-elasticsearch-curator/actions/workflows/ci.yml/badge.svg)](https://github.com/geerlingguy/ansible-role-elasticsearch-curator/actions/workflows/ci.yml) 4 | 5 | An Ansible Role that installs [Elasticsearch Curator](https://github.com/elasticsearch/curator) on RedHat/CentOS or Debian/Ubuntu. 6 | 7 | ## Requirements 8 | 9 | None, but it's a lot more helpful if you have Elasticsearch running somewhere! 10 | 11 | On RedHat/CentOS, make sure you have the EPEL repository configured, so the `python-pip` package can be installed. You can install the EPEL repo by simply adding `geerlingguy.repo-epel` to your playbook's roles. 12 | 13 | ## Role Variables 14 | 15 | Available variables are listed below, along with default values (see `defaults/main.yml`): 16 | 17 | elasticsearch_curator_version: '' 18 | 19 | The version of `elasticsearch-curator` to install. Available versions are listed on the [Python Package Index](https://pypi.org/project/elasticsearch-curator/). By default, no version is specified, so the latest version will be installed. 20 | 21 | elasticsearch_curator_cron_jobs: 22 | - name: "Run elasticsearch curator actions." 23 | job: "/usr/local/bin/curator ~/.curator/action.yml" 24 | minute: 0 25 | hour: 1 26 | 27 | A list of cron jobs. Typically you would run one cron job using the actions defined in `action.yml`, but you can split up cron jobs or use the `curator_cli` to run actions individually instead of via an action file. You can add any of `minute`, `hour`, `day`, `weekday`, and `month` to the cron jobs—values that are not explicitly set will default to `*`. You can also use `state` to define whether the job should be `present` or `absent`. 28 | 29 | elasticsearch_curator_config_directory: ~/.curator 30 | 31 | The directory inside which Curator's configuration (and action file) will be stored. 32 | 33 | elasticsearch_curator_hosts: 34 | - 'localhost:9200' 35 | elasticsearch_curator_http_auth: '' 36 | 37 | These variables control parameters used in the default `elasticsearch_curator_yaml`. If you define your own custom `elasticsearch_curator_yaml`, you may not need to define or override these variables. `_hosts` is a list of hosts with ports, and `_http_auth` is a basic `http_auth` `user:pass` string, if your Elasticsearch instance requires basic HTTP authorization. 38 | 39 | elasticsearch_curator_yaml: | 40 | --- 41 | client: 42 | hosts: {{ elasticsearch_curator_hosts | to_yaml }} 43 | url_prefix: 44 | use_ssl: False 45 | certificate: 46 | client_cert: 47 | client_key: 48 | ssl_no_validate: False 49 | http_auth: {{ elasticsearch_curator_http_auth }} 50 | timeout: 30 51 | master_only: False 52 | logging: 53 | loglevel: INFO 54 | logfile: 55 | logformat: default 56 | blacklist: ['elasticsearch', 'urllib3'] 57 | 58 | This YAML goes into the file `~/.curator/curator.yml` and stores the connection details Elasticsearch Curator uses to when connecting to Elasticsearch, as well as Curator logging configuration. 59 | 60 | elasticsearch_curator_action_yaml: | 61 | --- 62 | actions: 63 | 1: 64 | action: delete_indices 65 | options: 66 | ignore_empty_list: True 67 | disable_action: False 68 | filters: 69 | - filtertype: pattern 70 | kind: prefix 71 | value: logstash- 72 | exclude: 73 | - filtertype: age 74 | source: name 75 | direction: older 76 | timestring: '%Y.%m.%d' 77 | unit: days 78 | unit_count: 45 79 | exclude: 80 | 81 | This YAML goes into the file `~/.curator/action.yml` and defines the actions Curator performs when the default cron job is run. See documentation: [Curator actions file](https://www.elastic.co/guide/en/elasticsearch/client/curator/current/actionfile.html). 82 | 83 | elasticsearch_curator_pip_package: 'python3-pip' 84 | elasticsearch_curator_pip_executable: "{{ 'pip3' if elasticsearch_curator_pip_package.startswith('python3') else 'pip' }}" 85 | 86 | System pip package which needs to be installed, and the `pip` executable to run. For older OSes or when using Python 2, you may need to override this and change these to `python-pip`, and `pip`, respectively. 87 | 88 | ## Dependencies 89 | 90 | - geerlingguy.repo-epel (RedHat/CentOS only) 91 | 92 | ## Example Playbook 93 | 94 | - hosts: search 95 | roles: 96 | - { role: geerlingguy.elasticsearch-curator } 97 | 98 | ## License 99 | 100 | MIT / BSD 101 | 102 | ## Author Information 103 | 104 | This role was created in 2014 by [Jeff Geerling](https://www.jeffgeerling.com/), author of [Ansible for DevOps](https://www.ansiblefordevops.com/). 105 | --------------------------------------------------------------------------------