add curl_scheduled role
This commit is contained in:
16
roles/curl_scheduled/.ansible-lint
Normal file
16
roles/curl_scheduled/.ansible-lint
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
profile: production
|
||||||
|
strict: true
|
||||||
|
|
||||||
|
# Enable checking of loop variable prefixes in roles
|
||||||
|
loop_var_prefix: "^(__|{role}_)"
|
||||||
|
|
||||||
|
skip_list:
|
||||||
|
- var-naming[no-role-prefix]
|
||||||
|
|
||||||
|
warn_list:
|
||||||
|
- role-name[path]
|
||||||
|
- var-naming[no-role-prefix]
|
||||||
|
|
||||||
|
exclude_paths:
|
||||||
|
- .github/
|
||||||
2
roles/curl_scheduled/.gitignore
vendored
Normal file
2
roles/curl_scheduled/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
.vscode
|
||||||
|
.idea
|
||||||
8
roles/curl_scheduled/.yamllint
Normal file
8
roles/curl_scheduled/.yamllint
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
rules:
|
||||||
|
brackets:
|
||||||
|
forbid: false
|
||||||
|
min-spaces-inside: 0
|
||||||
|
max-spaces-inside: 2
|
||||||
|
min-spaces-inside-empty: -1
|
||||||
|
max-spaces-inside-empty: 2
|
||||||
41
roles/curl_scheduled/README.md
Normal file
41
roles/curl_scheduled/README.md
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
curl-scheduled
|
||||||
|
=========
|
||||||
|
|
||||||
|
Configure curl to run on schedule by deploying a systemd service + timer. Useful for sending heartbeats.
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
------------
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
Role Variables
|
||||||
|
--------------
|
||||||
|
|
||||||
|
- `args`: arguments to the curl command
|
||||||
|
|
||||||
|
- `url`: address to be accessed by curl
|
||||||
|
|
||||||
|
- `schedule`: string compatible with systemd timer `OnSchedule` option (default: `minutely`)
|
||||||
|
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
------------
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
Example Playbook
|
||||||
|
----------------
|
||||||
|
|
||||||
|
See `molecule/default/converge.yml`.
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
BSD
|
||||||
|
|
||||||
|
Author Information
|
||||||
|
------------------
|
||||||
|
|
||||||
|
msayganova@genlab.llc
|
||||||
|
|
||||||
|
corvus-migratorius@proton.me
|
||||||
11
roles/curl_scheduled/conda.dev.yml
Normal file
11
roles/curl_scheduled/conda.dev.yml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
name: ansible-curl-scheduled
|
||||||
|
channels:
|
||||||
|
- conda-forge
|
||||||
|
dependencies:
|
||||||
|
- python~=3.12.0
|
||||||
|
- pip>=24.2
|
||||||
|
- actionlint
|
||||||
|
- pip:
|
||||||
|
- -r requirements.txt
|
||||||
|
- -r requirements.ci.txt
|
||||||
9
roles/curl_scheduled/conda.prod.yml
Normal file
9
roles/curl_scheduled/conda.prod.yml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
name: ansible-curl-scheduled
|
||||||
|
channels:
|
||||||
|
- conda-forge
|
||||||
|
dependencies:
|
||||||
|
- python~=3.12.0
|
||||||
|
- pip>=24.2
|
||||||
|
- pip:
|
||||||
|
- -r requirements.txt
|
||||||
4
roles/curl_scheduled/defaults/main.yml
Normal file
4
roles/curl_scheduled/defaults/main.yml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
default_curl_cmd: "/usr/bin/curl"
|
||||||
|
default_curl_args: "-fsS -m 10"
|
||||||
|
default_schedule: "minutely"
|
||||||
1
roles/curl_scheduled/handlers/main.yml
Normal file
1
roles/curl_scheduled/handlers/main.yml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
---
|
||||||
17
roles/curl_scheduled/meta/main.yml
Normal file
17
roles/curl_scheduled/meta/main.yml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
galaxy_info:
|
||||||
|
role_name: curl_scheduled
|
||||||
|
namespace: genlab
|
||||||
|
author: "Alexander Gorelyshev"
|
||||||
|
company: "Genlab, LLC"
|
||||||
|
description: ""
|
||||||
|
license: "MIT"
|
||||||
|
min_ansible_version: "2.1"
|
||||||
|
|
||||||
|
platforms:
|
||||||
|
- name: "Ubuntu"
|
||||||
|
versions: [ "focal", "jammy", "noble" ]
|
||||||
|
|
||||||
|
galaxy_tags: [ ]
|
||||||
|
|
||||||
|
dependencies: []
|
||||||
45
roles/curl_scheduled/molecule/default/converge.yml
Normal file
45
roles/curl_scheduled/molecule/default/converge.yml
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
---
|
||||||
|
- name: Converge
|
||||||
|
hosts: all
|
||||||
|
|
||||||
|
pre_tasks:
|
||||||
|
- name: "Create test directory"
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/test"
|
||||||
|
state: directory
|
||||||
|
mode: "0664"
|
||||||
|
|
||||||
|
- name: "Create a test file"
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: "/test/index.html"
|
||||||
|
create: true
|
||||||
|
mode: "0664"
|
||||||
|
line: "OK"
|
||||||
|
|
||||||
|
- name: "Simulate remote HTTP server(s) directly on localhost"
|
||||||
|
changed_when: false
|
||||||
|
async: 1
|
||||||
|
poll: 0
|
||||||
|
args:
|
||||||
|
chdir: "/test"
|
||||||
|
loop:
|
||||||
|
- 8080
|
||||||
|
- 8081
|
||||||
|
- 8082
|
||||||
|
ansible.builtin.shell:
|
||||||
|
cmd: nohup python3 -m http.server {{ item }} </dev/null >/dev/null 2>&1 &
|
||||||
|
executable: /bin/bash
|
||||||
|
|
||||||
|
roles:
|
||||||
|
- role: genlab.curl_scheduled
|
||||||
|
services:
|
||||||
|
- label: "localhost-test-zero"
|
||||||
|
url: "http://127.0.0.1:8080"
|
||||||
|
schedule: minutely
|
||||||
|
- label: "localhost-test-one"
|
||||||
|
url: "http://127.0.0.1:8081"
|
||||||
|
schedule: hourly
|
||||||
|
- label: "localhost-test-chained-curl"
|
||||||
|
curl_cmd: '/usr/bin/curl "http://127.0.0.1:8081" && /usr/bin/curl'
|
||||||
|
url: "http://127.0.0.1:8082"
|
||||||
|
schedule: minutely
|
||||||
27
roles/curl_scheduled/molecule/default/molecule.yml
Normal file
27
roles/curl_scheduled/molecule/default/molecule.yml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
dependency:
|
||||||
|
name: galaxy
|
||||||
|
|
||||||
|
driver:
|
||||||
|
name: docker
|
||||||
|
|
||||||
|
platforms:
|
||||||
|
- name: ubuntu
|
||||||
|
image: geerlingguy/docker-${MOLECULE_DISTRO:-ubuntu2404}-ansible:latest
|
||||||
|
pre_build_image: true
|
||||||
|
command: ${MOLECULE_DOCKER_COMMAND:-""}
|
||||||
|
volumes:
|
||||||
|
- /sys/fs/cgroup:/sys/fs/cgroup:rw
|
||||||
|
cgroupns_mode: host
|
||||||
|
privileged: true
|
||||||
|
|
||||||
|
provisioner:
|
||||||
|
name: ansible
|
||||||
|
|
||||||
|
verifier:
|
||||||
|
name: ansible
|
||||||
|
|
||||||
|
lint: |
|
||||||
|
set -e
|
||||||
|
yamllint .
|
||||||
|
ansible-lint .
|
||||||
81
roles/curl_scheduled/molecule/default/verify.yml
Normal file
81
roles/curl_scheduled/molecule/default/verify.yml
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
---
|
||||||
|
- name: Verify
|
||||||
|
hosts: all
|
||||||
|
gather_facts: false
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
# Verify the systemd timers
|
||||||
|
|
||||||
|
- name: "Check the timer status - localhost-test-zero"
|
||||||
|
register: timer_zero
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "curl-localhost-test-zero.timer"
|
||||||
|
|
||||||
|
- name: "Assert that the localhost-test-zero timer is running"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- timer_zero.status.ActiveState == "active"
|
||||||
|
success_msg: "Timer is running"
|
||||||
|
fail_msg: "Unexpected timer state: '{{ timer_zero.status.ActiveState }}'"
|
||||||
|
|
||||||
|
- name: "Check the timer status - localhost-test-one"
|
||||||
|
register: timer_one
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "curl-localhost-test-one.timer"
|
||||||
|
|
||||||
|
- name: "Assert that the localhost-test-one timer is running"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- timer_one.status.ActiveState == "active"
|
||||||
|
success_msg: "Timer is running"
|
||||||
|
fail_msg: "Unexpected timer state: '{{ timer_one.status.ActiveState }}'"
|
||||||
|
|
||||||
|
- name: "Check the timer status - localhost-test-chained-curl"
|
||||||
|
register: timer_chained_curl
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "curl-localhost-test-chained-curl.timer"
|
||||||
|
|
||||||
|
- name: "Assert that the localhost-test-chained-curl timer is running"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- timer_chained_curl.status.ActiveState == "active"
|
||||||
|
success_msg: "Timer is running"
|
||||||
|
fail_msg: "Unexpected timer state: '{{ timer_chained_curl.status.ActiveState }}'"
|
||||||
|
|
||||||
|
## Verify the systemd services
|
||||||
|
|
||||||
|
- name: "Check the service status - zero"
|
||||||
|
register: service_zero
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "curl-localhost-test-zero.service"
|
||||||
|
|
||||||
|
- name: "Assert that the localhost-test-zero service exited with a 0/SUCCESS status"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- 'service_zero.status.ExecMainStatus == "0"'
|
||||||
|
success_msg: "Service has exited with a 0/SUCCESS status"
|
||||||
|
fail_msg: "Unexpected service status code: '{{ service_zero.status.ExecMainStatus }}'"
|
||||||
|
|
||||||
|
- name: "Check the service status - one"
|
||||||
|
register: service_one
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "curl-localhost-test-one.service"
|
||||||
|
|
||||||
|
- name: "Assert that the localhost-test-one service exited with a 0/SUCCESS status"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- 'service_one.status.ExecMainStatus == "0"'
|
||||||
|
success_msg: "Service has exited with a 0/SUCCESS status"
|
||||||
|
fail_msg: "Unexpected service status code: '{{ service_one.status.ExecMainStatus }}'"
|
||||||
|
|
||||||
|
- name: "Check the service status - localhost-test-chained-curl"
|
||||||
|
register: service_chained_curl
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "curl-localhost-test-chained-curl.service"
|
||||||
|
|
||||||
|
- name: "Assert that the localhost-test-chained-curl service exited with a 0/SUCCESS status"
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- 'service_chained_curl.status.ExecMainStatus == "0"'
|
||||||
|
success_msg: "Service has exited with a 0/SUCCESS status"
|
||||||
|
fail_msg: "Unexpected service status code: '{{ service_chained_curl.status.ExecMainStatus }}'"
|
||||||
6
roles/curl_scheduled/renovate.json
Normal file
6
roles/curl_scheduled/renovate.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||||
|
"extends": [
|
||||||
|
"config:recommended"
|
||||||
|
]
|
||||||
|
}
|
||||||
6
roles/curl_scheduled/requirements.ci.txt
Normal file
6
roles/curl_scheduled/requirements.ci.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
ansible-lint
|
||||||
|
molecule==24.12.0
|
||||||
|
molecule-plugins[docker]
|
||||||
|
docker~=7.1.0
|
||||||
|
requests==2.31.0 # pinned to the latest version not breaking Docker SDK
|
||||||
|
yamllint
|
||||||
1
roles/curl_scheduled/requirements.txt
Normal file
1
roles/curl_scheduled/requirements.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ansible~=11.1.0
|
||||||
3
roles/curl_scheduled/requirements.yml
Normal file
3
roles/curl_scheduled/requirements.yml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# requirements file
|
||||||
|
---
|
||||||
|
collections: []
|
||||||
33
roles/curl_scheduled/tasks/deploy-service.yml
Normal file
33
roles/curl_scheduled/tasks/deploy-service.yml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
- name: "Deploy-Service | Create systemd service file: '{{ job.label }}'"
|
||||||
|
vars:
|
||||||
|
label: "{{ job.label }}"
|
||||||
|
url: "{{ job.url }}"
|
||||||
|
curl_cmd: "{{ job.curl_cmd | default(default_curl_cmd) }}"
|
||||||
|
curl_args: "{{ job.curl_args | default(default_curl_args) }}"
|
||||||
|
register: service
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "placeholder.service"
|
||||||
|
dest: "/etc/systemd/system/curl-{{ job.label }}.service"
|
||||||
|
mode: "0660"
|
||||||
|
validate: systemd-analyze verify %s
|
||||||
|
|
||||||
|
- name: "Deploy-Service | Create systemd timer file: '{{ job.label }}'"
|
||||||
|
vars:
|
||||||
|
label: "{{ job.label }}"
|
||||||
|
schedule: "{{ job.schedule | default(default_schedule) }}"
|
||||||
|
register: timer
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: "placeholder.timer"
|
||||||
|
dest: "/etc/systemd/system/curl-{{ job.label }}.timer"
|
||||||
|
mode: "0660"
|
||||||
|
validate: systemd-analyze verify %s
|
||||||
|
|
||||||
|
- name: "Deploy-Service | Enable and start the timer: '{{ job.label }}'" # noqa: no-handler
|
||||||
|
become: true
|
||||||
|
when: service.changed or timer.changed
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "curl-{{ job.label }}.timer"
|
||||||
|
state: started
|
||||||
|
enabled: true
|
||||||
|
daemon_reload: true
|
||||||
19
roles/curl_scheduled/tasks/main.yml
Normal file
19
roles/curl_scheduled/tasks/main.yml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
- name: "Install curl (Debian derivatives)"
|
||||||
|
when: ansible_os_family == "Debian"
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: curl
|
||||||
|
state: present
|
||||||
|
update_cache: true
|
||||||
|
|
||||||
|
- name: "Install curl (RHEL derivatives)"
|
||||||
|
when: ansible_os_family == "RedHat"
|
||||||
|
ansible.builtin.dnf:
|
||||||
|
name: curl
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: "Configure and deploy systemd service"
|
||||||
|
loop: "{{ services }}"
|
||||||
|
loop_control:
|
||||||
|
loop_var: "job"
|
||||||
|
ansible.builtin.include_tasks: "deploy-service.yml"
|
||||||
21
roles/curl_scheduled/templates/placeholder.service
Normal file
21
roles/curl_scheduled/templates/placeholder.service
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Run an HTTP request via curl designated '{{ label }}'
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart={{ curl_cmd }} {{ curl_args }} "{{ url }}"
|
||||||
|
Restart=no
|
||||||
|
|
||||||
|
# Security hardening
|
||||||
|
ProtectSystem=strict
|
||||||
|
NoNewPrivileges=true
|
||||||
|
PrivateTmp=true
|
||||||
|
ProtectKernelModules=true
|
||||||
|
ProtectControlGroups=true
|
||||||
|
ProtectKernelTunables=true
|
||||||
|
ProtectClock=yes
|
||||||
|
RestrictSUIDSGID=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.targer
|
||||||
12
roles/curl_scheduled/templates/placeholder.timer
Normal file
12
roles/curl_scheduled/templates/placeholder.timer
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Trigger a curl command designated '{{ label }}'
|
||||||
|
Requires=curl-{{ label }}.service
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
Unit=curl-{{ label }}.service
|
||||||
|
OnCalendar={{ schedule }}
|
||||||
|
AccuracySec=1m
|
||||||
|
Persistent=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
||||||
2
roles/curl_scheduled/vars/main.yml
Normal file
2
roles/curl_scheduled/vars/main.yml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
---
|
||||||
|
kuma_port: "3001"
|
||||||
Reference in New Issue
Block a user