commit 8d10bfb76a79199ac8cfd2816a81cf095fca0735 Author: Robert Kaussow Date: Thu Jan 25 10:04:31 2024 +0100 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f64e8e3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +# ---> Ansible +*.retry +plugins +library + +# ---> Python +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# ---> Docs +/_docs diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..6b1d0bf --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3812eb4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Robert Kaussow + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..60019e6 --- /dev/null +++ b/README.md @@ -0,0 +1,12 @@ +# xoxys.dockerengine + +[![Build Status](https://img.shields.io/drone/build/ansible/xoxys.dockerengine?logo=drone&server=https%3A%2F%2Fdrone.rknet.org)](https://drone.rknet.org/ansible/xoxys.dockerengine) +[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) + +Setup docker engine. + +You can find the full documentation at [https://galaxy.geekdocs.de](https://galaxy.geekdocs.de/roles/system/dockerengine/). + +## License + +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..294186a --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,69 @@ +--- +dockerengine_packages: + - docker-ce + - docker-ce-cli + - containerd.io + +dockerengine_service: docker + +# @var dockerengine_service_override_unit:description: > +# Multiline string of options to add to the `systemd` service override unit section. +# @end +# @var dockerengine_service_override_unit: $ "_unset_" +# @var dockerengine_service_override_unit:example: > +# dockerengine_service_override_unit: | +# After=time-sync.target +# Requires=time-sync.target +# @end + +dockerengine_docker_group_enabled: False + +# @var dockerengine_registries:description: List of docker registries to auto login +# @var dockerengine_registries:example: > +# dockerengine_registries: +# - registry: myregistry.example.com (optional) +# username: docker +# password: secure +# reauthorize: False +# state: present +# @end +dockerengine_registries: [] + +# @var dockerengine_http_proxy: $ "_unset_" +# @var dockerengine_https_proxy: $ "_unset" +# @var dockerengine_no_proxy: $ "_unset_" + +dockerengine_usernamespace_enabled: False +dockerengine_nsremap_user: dockremap +dockerengine_nsremap_range_start: 231072 +dockerengine_nsremap_range_length: 65536 + +dockerengine_daemon_config: + selinux-enabled: False + log-driver: journald + log-level: info + live-restore: True + +# @var dockerengine_daemon_config_extra:example: > +# dockerengine_daemon_config_extra: +# userns-remap: "{{ dockerengine_nsremap_user +':' + dockerengine_nsremap_user }}" +# @end +dockerengine_daemon_config_extra: {} + +# @var dockerengine_networks:description: List of additional docker networks to create. +# @var dockerengine_networks:example: > +# dockerengine_networks: +# - name: my_network +# driver: bridge +# enable_ipv6: True +# ipam_config: +# - subnet: fdd1:ac8c:0557:7ce1::/64 +# force: False +# state: present +# @end +dockerengine_networks: [] + +# @var dockerengine_networks:description: > +# List of extra docker networks to create. For configuration detials see `docker_networks`. +# @end +dockerengine_networks_extra: [] diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..d3cfcd4 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,10 @@ +--- +- name: Restart docker engine + service: + state: restarted + name: "{{ dockerengine_service }}" + daemon_reload: yes + enabled: yes + listen: __docker_restart + become: True + become_user: root diff --git a/meta/main.yml b/meta/main.yml new file mode 100644 index 0000000..df893e1 --- /dev/null +++ b/meta/main.yml @@ -0,0 +1,24 @@ +--- +galaxy_info: + # @meta author:value: [Robert Kaussow](https://gitea.rknet.org/xoxys) + author: Robert Kaussow + namespace: xoxys + role_name: dockerengine + # @meta description: > + # [![Build Status](https://ci.rknet.org/api/badges/ansible/xoxys.dockerengine/status.svg)](https://ci.rknet.org/repos/ansible/xoxys.dockerengine) + # [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://gitea.rknet.org/ansible/xoxys.dockerengine/src/branch/main/LICENSE) + # + # Setup docker engine. + # @end + description: Setup docker engine + license: MIT + min_ansible_version: "2.10" + platforms: + - name: EL + versions: + - "9" + galaxy_tags: + - docker + - dockerengine +dependencies: [] +collections: [] diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml new file mode 100644 index 0000000..13d8041 --- /dev/null +++ b/molecule/default/converge.yml @@ -0,0 +1,5 @@ +--- +- name: Converge + hosts: all + roles: + - role: xoxys.dockerengine diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml new file mode 100644 index 0000000..8c50d8c --- /dev/null +++ b/molecule/default/molecule.yml @@ -0,0 +1,17 @@ +--- +driver: + name: molecule_hetznercloud +dependency: + name: galaxy + options: + role-file: molecule/requirements.yml + requirements-file: molecule/requirements.yml +platforms: + - name: "ubuntu-22.04-alertmanager" + server_type: "cx11" + image: "ubuntu-22.04" +provisioner: + name: ansible + log: False +verifier: + name: testinfra diff --git a/molecule/default/prepare.yml b/molecule/default/prepare.yml new file mode 100644 index 0000000..3f1ce5e --- /dev/null +++ b/molecule/default/prepare.yml @@ -0,0 +1,20 @@ +--- +- name: Prepare + hosts: all + gather_facts: False + tasks: + - name: Bootstrap python for Ansible + 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 + + - name: Wait for apt lock + shell: while fuser /var/lib/apt/lists/lock >/dev/null 2>&1; do echo 'Waiting for apt list lock.' && sleep 10; done + changed_when: False + + - name: Update package cache + apt: + update_cache: True diff --git a/molecule/default/tests/test_default.py b/molecule/default/tests/test_default.py new file mode 100644 index 0000000..2188ec0 --- /dev/null +++ b/molecule/default/tests/test_default.py @@ -0,0 +1,18 @@ +import os + +import testinfra.utils.ansible_runner + +testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( + os.environ["MOLECULE_INVENTORY_FILE"] +).get_hosts("all") + + +def test_alertmanager_running_and_enabled(host): + alertmanager = host.service("alertmanager") + assert alertmanager.is_running + assert alertmanager.is_enabled + + +def test_alertmanager_socket(host): + # Verify the socket is listening for HTTP traffic + assert host.socket("tcp://127.0.0.1:9093").is_listening diff --git a/molecule/requirements.yml b/molecule/requirements.yml new file mode 100644 index 0000000..8152505 --- /dev/null +++ b/molecule/requirements.yml @@ -0,0 +1,7 @@ +--- +collections: [] + +roles: + - src: https://gitea.rknet.org/ansible/xoxys.dockerengine + scm: git + version: main diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..d0f36cd --- /dev/null +++ b/pyproject.toml @@ -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", +] diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..ead8470 --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,127 @@ +--- +- block: + - name: Add Docker CE repository + yum_repository: + name: "docker-ce" + file: "Docker-CE" + description: "Docker CE Stable" + baseurl: "https://download.docker.com/linux/centos/{{ ansible_distribution_major_version }}/{{ ansible_architecture }}/stable" + gpgcheck: yes + enabled: yes + gpgkey: "https://download.docker.com/linux/rhel/gpg" + + - name: Ensure to remove old docker packages + package: + name: + - docker + - docker-common + - docker-engine + state: absent + + - name: Install packages + package: + name: "{{ item }}" + state: present + loop: "{{ dockerengine_packages }}" + + - name: Add namespace group + group: + name: "{{ dockerengine_nsremap_user }}" + state: present + when: dockerengine_usernamespace_enabled | bool + + - name: Setup namespace user + user: + name: "{{ dockerengine_nsremap_user }}" + group: "{{ dockerengine_nsremap_user }}" + shell: /sbin/nologin + state: "{{ 'present' if dockerengine_usernamespace_enabled | bool else 'absent' }}" + + - name: Remove namespace group + group: + name: "{{ dockerengine_nsremap_user }}" + state: absent + when: not dockerengine_usernamespace_enabled | bool + + - name: Configure namespace id range + lineinfile: + dest: "{{ item }}" + regexp: "^{{ dockerengine_nsremap_user }}:" + line: "{{ dockerengine_nsremap_user }}:{{ dockerengine_nsremap_range_start }}:{{ dockerengine_nsremap_range_length }}" + state: "{{ 'present' if dockerengine_usernamespace_enabled | bool else 'absent' }}" + loop: + - /etc/subuid + - /etc/subgid + + - name: Create required directories + loop: + - name: /etc/systemd/system/docker.service.d + mode: "0755" + - name: /etc/docker + mode: "0755" + loop_control: + label: "{{ item.name }}" + file: + path: "{{ item.name }}" + state: directory + mode: "{{ item.mode }}" + + - name: Write environment file + template: + src: etc/sysconfig/docker.j2 + dest: /etc/sysconfig/docker + mode: "0600" + notify: __docker_restart + + - name: Write service override.conf + template: + src: etc/systemd/system/docker.service.d/override.conf.j2 + dest: /etc/systemd/system/docker.service.d/override.conf + mode: 0644 + notify: __docker_restart + + - name: Write daemon config + copy: + content: "{{ (dockerengine_daemon_config | combine(dockerengine_daemon_config_extra)) | to_nice_json }}" + dest: /etc/docker/daemon.json + mode: "0600" + notify: __docker_restart + + - name: Deploy daemon config + copy: + content: "{{ (dockerengine_daemon_config | combine(dockerengine_daemon_config_extra)) | to_nice_json }}" + dest: /etc/docker/daemon.json + mode: "0600" + notify: __docker_restart + + - name: Ensure docker engine is up and running + service: + name: "{{ dockerengine_service }}" + enabled: True + state: started + + - name: Handle registry logins + docker_login: + registry: "{{ item.url | default(omit) }}" + username: "{{ item.username }}" + password: "{{ item.password }}" + reauthorize: "{{ item.reauthorize | default(False) }}" + state: '{{ item.state | default("present") }}' + loop: "{{ dockerengine_registries }}" + loop_control: + label: "{{ item.url | default('DockerHub') }}" + + - name: Create docker networks + docker_network: + name: "{{ item.name }}" + driver: "{{ item.driver | default('bridge') }}" + enable_ipv6: "{{ item.enable_ipv6 | default(False) }}" + ipam_config: "{{ item.ipam_config | default(omit) }}" + force: "{{ item.force | default(omit) }}" + state: "{{ item.state | default('present') }}" + loop: "{{ dockerengine_networks + dockerengine_networks_extra }}" + loop_control: + label: "{{ item.name }}" + notify: __docker_restart + become: True + become_user: root diff --git a/templates/bin/docker-compose.j2 b/templates/bin/docker-compose.j2 new file mode 100644 index 0000000..3e439e0 --- /dev/null +++ b/templates/bin/docker-compose.j2 @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +set -eo pipefail + +exec /opt/python2/ansible-deps/bin/docker-compose "$@" diff --git a/templates/etc/sysconfig/docker.j2 b/templates/etc/sysconfig/docker.j2 new file mode 100644 index 0000000..2c4d193 --- /dev/null +++ b/templates/etc/sysconfig/docker.j2 @@ -0,0 +1,14 @@ +#jinja2: lstrip_blocks: True +{{ ansible_managed | comment }} +OPTIONS='{{'--userns-remap=' + dockerengine_nsremap_user + ':' + dockerengine_nsremap_user if dockerengine_usernamespace_enabled | bool else '' }}' + +# Proxy settings +{% if dockerengine_http_proxy is defined %} +HTTP_PROXY={{ dockerengine_http_proxy }} +{% endif %} +{% if dockerengine_https_proxy is defined %} +HTTPS_PROXY={{ dockerengine_https_proxy }} +{% endif %} +{% if dockerengine_no_proxy is defined %} +NO_PROXY={{ dockerengine_no_proxy|join(',') }}" +{% endif %} diff --git a/templates/etc/systemd/system/docker.service.d/override.conf.j2 b/templates/etc/systemd/system/docker.service.d/override.conf.j2 new file mode 100644 index 0000000..7d51f7c --- /dev/null +++ b/templates/etc/systemd/system/docker.service.d/override.conf.j2 @@ -0,0 +1,12 @@ +#jinja2: lstrip_blocks: True +{{ ansible_managed | comment }} +{% if dockerengine_service_override_unit is defined %} +[Unit] +{{ dockerengine_service_override_unit }} +{% endif %} +[Service] +EnvironmentFile=-/etc/sysconfig/docker +ExecStart= +ExecStart=/usr/bin/dockerd -H fd:// \ + --containerd=/run/containerd/containerd.sock \ + $OPTIONS