initial commit
Some checks failed
ci/woodpecker/push/test Pipeline failed
ci/woodpecker/push/docs unknown status
ci/woodpecker/push/notify Pipeline was successful
ci/woodpecker/push/lint Pipeline was successful

This commit is contained in:
Robert Kaussow 2024-02-15 11:17:18 +01:00
commit 4a498eaa1b
Signed by: xoxys
GPG Key ID: 4E692A2EAECC03C0
23 changed files with 470 additions and 0 deletions

11
.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
# ---> Ansible
*.retry
plugins
library
# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

15
.later.yml Normal file
View File

@ -0,0 +1,15 @@
---
ansible:
custom_modules:
- iptables_raw
- openssl_pkcs12
- proxmox_kvm
- ucr
- corenetworks_dns
- corenetworks_token
rules:
exclude_files:
- "LICENSE*"
- "**/*.md"
- "**/*.ini"

7
.markdownlint.yml Normal file
View File

@ -0,0 +1,7 @@
---
default: True
MD013: False
MD041: False
MD024: False
MD004:
style: dash

1
.prettierignore Normal file
View File

@ -0,0 +1 @@
LICENSE

47
.woodpecker/docs.yaml Normal file
View File

@ -0,0 +1,47 @@
---
when:
- event: [pull_request]
- event: [push, manual]
branch:
- ${CI_REPO_DEFAULT_BRANCH}
steps:
- name: generate
image: quay.io/thegeeklab/ansible-doctor
environment:
ANSIBLE_DOCTOR_EXCLUDE_FILES: molecule/
ANSIBLE_DOCTOR_FORCE_OVERWRITE: "true"
ANSIBLE_DOCTOR_LOG_LEVEL: INFO
ANSIBLE_DOCTOR_ROLE_NAME: ${CI_REPO_NAME}
ANSIBLE_DOCTOR_TEMPLATE: readme
- name: format
image: quay.io/thegeeklab/alpine-tools
commands:
- prettier -w README.md
- name: diff
image: quay.io/thegeeklab/alpine-tools
commands:
- git diff --color=always README.md
- name: publish
image: quay.io/thegeeklab/wp-git-action
settings:
action:
- commit
- push
author_email: ci-bot@rknet.org
author_name: ci-bot
branch: main
message: "[skip ci] automated docs update"
netrc_machine: gitea.rknet.org
netrc_password:
from_secret: gitea_token
when:
- event: [push, manual]
branch:
- ${CI_REPO_DEFAULT_BRANCH}
depends_on:
- test

30
.woodpecker/lint.yaml Normal file
View File

@ -0,0 +1,30 @@
---
when:
- event: [pull_request, tag]
- event: [push, manual]
branch:
- ${CI_REPO_DEFAULT_BRANCH}
steps:
- name: ansible-later
image: quay.io/thegeeklab/ansible-later:4
commands:
- ansible-later
environment:
FORCE_COLOR: "1"
- name: python-format
image: docker.io/python:3.12
commands:
- pip install -qq ruff
- ruff format --check --diff .
environment:
PY_COLORS: "1"
- name: python-lint
image: docker.io/python:3.12
commands:
- pip install -qq ruff
- ruff .
environment:
PY_COLORS: "1"

26
.woodpecker/notify.yml Normal file
View File

@ -0,0 +1,26 @@
---
when:
- event: [tag]
- event: [push, manual]
branch:
- ${CI_REPO_DEFAULT_BRANCH}
runs_on: [success, failure]
steps:
- name: matrix
image: quay.io/thegeeklab/wp-matrix
settings:
homeserver:
from_secret: matrix_homeserver
password:
from_secret: matrix_password
roomid:
from_secret: matrix_roomid
username:
from_secret: matrix_username
when:
- status: [success, failure]
depends_on:
- docs

25
.woodpecker/test.yaml Normal file
View File

@ -0,0 +1,25 @@
---
when:
- event: [pull_request, tag]
- event: [push, manual]
branch:
- ${CI_REPO_DEFAULT_BRANCH}
variables:
- &molecule_base
image: quay.io/thegeeklab/molecule:6
group: molecule
secrets:
- source: molecule_hcloud_token
target: HCLOUD_TOKEN
environment:
PY_COLORS: "1"
steps:
- name: molecule-default
<<: *molecule_base
commands:
- molecule test -s default
depends_on:
- lint

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Robert Kaussow <mail@thegeeklab.de>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

1
README.md Normal file
View File

@ -0,0 +1 @@
# xoxys.woodpecker_agent

52
defaults/main.yml Normal file
View File

@ -0,0 +1,52 @@
---
woodpecker_agent_image: "docker.io/woodpeckerci/woodpecker-agent:latest"
woodpecker_agent_service_started: True
woodpecker_agent_name: agent-1
# @var woodpecker_agent_volumes:description: Define required docker volumes.
woodpecker_agent_volumes:
- name: /var/run/docker.sock
dest: /var/run/docker.sock
type: bind
# @var woodpecker_agent_network:description: Use a custom docker network for grafana.
# @var woodpecker_agent_network:value: $ "_unset_"
# @var woodpecker_agent_exposed_ports:description: Ports you want to publish outside of docker.
woodpecker_agent_exposed_ports: []
woodpecker_agent_cap_add: []
woodpecker_agent_cap_drop: []
woodpecker_agent_docker_args:
- --privileged
- --pids-limit=-1
woodpecker_agent_woodpecker_server: localhost:9000
woodpecker_agent_max_workflows: 1
woodpecker_agent_log_level: info
# @var woodpecker_agent_filter_labels:description: Configures labels to filter pipelines that can be handled by this agent.
# @var woodpecker_agent_filter_labels:example: >
# woodpecker_agent_filter_labels:
# - key=value
# - second-key=*
# @end
woodpecker_agent_filter_labels: []
# @var woodpecker_agent_env:description: Custom environment variables to set for the agent container.
# @var woodpecker_agent_env:example: >
# woodpecker_agent_env:
# - name: WOODPECKER_GRPC_SECURE
# value: True
# @end
woodpecker_agent_env: []
# @var woodpecker_agent_instances:description: List of multiple agents to deploy.
# @var woodpecker_agent_instances:example: >
# woodpecker_agent_instances:
# - name: agent-1
# filter_labels: []
# @end
woodpecker_agent_instances: []

7
handlers/main.yml Normal file
View File

@ -0,0 +1,7 @@
---
- name: Restart agent
service:
name: "woodpecker-agent-{{ __woodpecker_agent_name }}"
state: "{{ woodpecker_agent_service_started | ternary('restarted', 'stopped', 'restarted') }}"
daemon_reload: True
listen: __woodpecker_agent_restart

25
meta/main.yml Normal file
View File

@ -0,0 +1,25 @@
---
galaxy_info:
# @meta author:value: [Robert Kaussow](https://gitea.rknet.org/xoxys)
author: "Robert Kaussow <mail@thegeeklab.de>"
namespace: xoxys
role_name: woodpecker_agent
# @meta description: >
# [![Build Status](https://ci.rknet.org/api/badges/ansible/xoxys.woodpecker_agent/status.svg)](https://ci.rknet.org/repos/ansible/xoxys.woodpecker_agent)
# [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg?label=license)](https://gitea.rknet.org/ansible/xoxys.woodpecker_agent/src/branch/main/LICENSE)
#
# Setup Woodpecker CI docker agent
# @end
description: Setup Woodpecker CI docker agent
license: MIT
min_ansible_version: "2.10"
platforms:
- name: EL
versions:
- "9"
galaxy_tags: []
dependencies: []
collections:
- xoxys.general
- community.general
- community.docker

View File

@ -0,0 +1,8 @@
---
- name: Converge
hosts: all
vars:
woodpecker_agent_service_started: False
roles:
- role: xoxys.dockerengine
- role: xoxys.woodpecker_agent

View File

@ -0,0 +1,17 @@
---
driver:
name: molecule_hetznercloud
dependency:
name: galaxy
options:
role-file: molecule/requirements.yml
requirements-file: molecule/requirements.yml
platforms:
- name: "rocky9-woodpecker-agent"
server_type: "cx11"
image: "rocky-9"
provisioner:
name: ansible
log: False
verifier:
name: testinfra

View File

@ -0,0 +1,11 @@
---
- name: Prepare
hosts: all
gather_facts: False
tasks:
- name: Bootstrap Python for Ansible
ansible.builtin.raw: |
command -v python3 python ||
((test -e /usr/bin/apt && (apt -y update && apt install -y python-minimal)) ||
echo "Warning: Python not boostrapped due to unknown platform.")
changed_when: False

View File

@ -0,0 +1,12 @@
import os
import testinfra.utils.ansible_runner
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ["MOLECULE_INVENTORY_FILE"]
).get_hosts("all")
def test_service_file(host):
f = host.file("/etc/systemd/system/woodpecker-agent-agent-1.service")
assert f.exists

View File

@ -0,0 +1,9 @@
---
collections:
- name: community.docker
roles:
- src: https://gitea.rknet.org/ansible/xoxys.dockerengine.git
name: xoxys.dockerengine
scm: git
version: main

19
pyproject.toml Normal file
View File

@ -0,0 +1,19 @@
[tool.ruff]
exclude = [".git","__pycache__"]
line-length = 99
indent-width = 4
ignore = ["W191", "E111", "E114", "E117", "S101", "S105"]
select = ["F", "E", "I", "W", "S"]
[tool.ruff.format]
quote-style = "double"
indent-style = "space"
line-ending = "lf"
[tool.pytest.ini_options]
filterwarnings = [
"ignore::FutureWarning",
"ignore::DeprecationWarning",
]

49
tasks/instance.yml Normal file
View File

@ -0,0 +1,49 @@
---
- name: Register agent metadata
set_fact:
__woodpecker_agent_name: "{{ inst.name | default(woodpecker_agent_name) | regex_replace('[^a-z0-9]+', '-', ignorecase=True) }}"
__woodpecker_agent_volumes: "{{ inst.volumes | default(woodpecker_agent_volumes) }}"
__woodpecker_agent_cap_add: "{{ inst.cap_add | default(woodpecker_agent_cap_add) }}"
__woodpecker_agent_cap_drop: "{{ inst.cap_drop | default(woodpecker_agent_cap_drop) }}"
__woodpecker_agent_env: "{{ inst.env | default (woodpecker_agent_env) }}"
__woodpecker_agent_filter_labels: "{{ inst.filter_labels | default(woodpecker_agent_filter_labels) }}"
- name: Create container volumes
community.docker.docker_volume:
name: "{{ item.name }}"
driver_options: "{{ item.options | default(omit) }}"
state: "{{ item.state | default('present') }}"
loop: "{{ __woodpecker_agent_volumes }}"
loop_control:
label: "{{ item.name }}"
when: item.type | default("volume") | lower == "volume"
register: __woodpecker_agent_volumes_raw
- name: Register container volumes map
ansible.builtin.set_fact:
__woodpecker_agent_volumes_map: "{{ __woodpecker_agent_volumes_raw.results | json_query('[].volume') | items2dict(key_name='Name', value_name='Mountpoint') }}"
- name: Deploy env file
ansible.builtin.template:
src: etc/sysconfig/woodpecker_agent.j2
dest: "/etc/sysconfig/woodpecker-agent-{{ __woodpecker_agent_name }}"
owner: root
group: root
mode: "0600"
notify: __woodpecker_agent_restart
- name: Create container specs
ansible.builtin.template:
src: etc/systemd/system/woodpecker_agent.service.j2
dest: "/etc/systemd/system/woodpecker-agent-{{ __woodpecker_agent_name }}.service"
owner: root
group: root
mode: "0640"
notify: __woodpecker_agent_restart
- name: Ensure service state
ansible.builtin.service:
name: "woodpecker-agent-{{ __woodpecker_agent_name }}.service"
state: "{{ woodpecker_agent_service_started | ternary('started', 'stopped', 'started') }}"
daemon_reload: True
enabled: True

7
tasks/main.yml Normal file
View File

@ -0,0 +1,7 @@
---
- include_tasks:
file: instance.yml
loop: "{{ woodpecker_agent_instances }}"
loop_control:
loop_var: inst
no_log: True

View File

@ -0,0 +1,21 @@
#jinja2: lstrip_blocks: True
{{ ansible_managed | comment }}
WOODPECKER_SERVER={{ inst.woodpecker_server | default(woodpecker_agent_woodpecker_server) }}
WOODPECKER_LOG_LEVEL={{ inst.log_level | default(woodpecker_agent_log_level) }}
WOODPECKER_MAX_WORKFLOWS={{ inst.max_workflows | default(woodpecker_agent_max_workflows) }}
{% if __woodpecker_agent_filter_labels | length > 0 %}
WOODPECKER_FILTER_LABELS={{ __woodpecker_agent_filter_labels | join(",") }}
{% endif %}
{% if __woodpecker_agent_env | length > 0 %}
{% for item in __woodpecker_agent_env %}
{{ item.name | upper }}={{ item.value }}
{% endfor %}
{% for item in inst.env_extra %}
{{ item.name | upper }}={{ item.value }}
{% endfor %}
{% endif %}
WOODPECKER_BACKEND=docker
DOCKER_HOST=unix:///var/run/docker.sock

View File

@ -0,0 +1,49 @@
#jinja2: lstrip_blocks: True
{{ ansible_managed | comment }}
[Unit]
Description=Woodpecker Agent ({{ __woodpecker_agent_name }})
Wants=docker.service
After=docker.service
[Service]
Restart=on-failure
RestartSec=5s
EnvironmentFile=/etc/environment
ExecStop=/usr/bin/docker pull {{ woodpecker_agent_image }}
ExecStop=/bin/sh -c '/usr/bin/docker ps | /bin/grep %p 1> /dev/null && /usr/bin/docker stop %p || true'
ExecStartPre=/bin/sh -c '/usr/bin/docker ps | /bin/grep %p 1> /dev/null && /usr/bin/docker kill %p || true'
ExecStartPre=/bin/sh -c '/usr/bin/docker ps -a | /bin/grep %p 1> /dev/null && /usr/bin/docker rm %p || true'
ExecStartPre=/usr/bin/docker pull {{ woodpecker_agent_image }}
ExecStart=/usr/bin/docker run --rm \
--name %p \
--hostname %p \
--env-file /etc/sysconfig/woodpecker-agent-{{ __woodpecker_agent_name }} \
{% if woodpecker_agent_network is defined and woodpecker_agent_network %}
--network {{ woodpecker_agent_network }} \
{% endif %}
{% if woodpecker_agent_cap_add | length > 0 %}
--cap-add {{ woodpecker_agent_cap_add | join (" ") }}
{% endif %}
{% if woodpecker_agent_cap_drop | length > 0 %}
--cap-drop {{ woodpecker_agent_cap_drop | join (" ") }}
{% endif %}
{% for volume in woodpecker_agent_volumes %}
--mount '{{ "type=bind," if (volume.type | default(False) | lower == "bind") else "" }}src={{ volume.name }},target={{ volume.dest }}' \
{% endfor %}
{% for port in woodpecker_agent_exposed_ports %}
--publish {{ port }} \
{% endfor %}
{% for item in inst.docker_args | default(woodpecker_agent_docker_args) %}
{{ item }} \
{% endfor %}
--health-interval 5s \
--health-retries 5 \
--health-timeout 10s \
{{ woodpecker_agent_image }}
[Install]
WantedBy=multi-user.target