diff --git a/.drone.jsonnet b/.drone.jsonnet
deleted file mode 100644
index bf6e5ab..0000000
--- a/.drone.jsonnet
+++ /dev/null
@@ -1,159 +0,0 @@
-local PipelineLinting = {
- kind: 'pipeline',
- name: 'linting',
- platform: {
- os: 'linux',
- arch: 'amd64',
- },
- steps: [
- {
- name: 'ansible-later',
- image: 'thegeeklab/ansible-later',
- commands: [
- 'ansible-later',
- ],
- },
- {
- name: 'python-format',
- image: 'python:3.11',
- environment: {
- PY_COLORS: 1,
- },
- commands: [
- 'pip install -qq yapf',
- '[ -z "$(find . -type f -name *.py)" ] || (yapf -rd ./)',
- ],
- },
- {
- name: 'python-flake8',
- image: 'python:3.11',
- environment: {
- PY_COLORS: 1,
- },
- commands: [
- 'pip install -qq flake8',
- 'flake8',
- ],
- },
- ],
- trigger: {
- ref: ['refs/heads/main', 'refs/tags/**', 'refs/pull/**'],
- },
-};
-
-local PipelineDeployment(scenario='centos7') = {
- kind: 'pipeline',
- name: 'testing-' + scenario,
- platform: {
- os: 'linux',
- arch: 'amd64',
- },
- concurrency: {
- limit: 1,
- },
- workspace: {
- base: '/drone/src',
- path: '${DRONE_REPO_NAME}',
- },
- steps: [
- {
- name: 'ansible-molecule',
- image: 'thegeeklab/molecule:4',
- environment: {
- HCLOUD_TOKEN: { from_secret: 'hcloud_token' },
- },
- commands: [
- 'molecule test -s ' + scenario,
- ],
- },
- ],
- depends_on: [
- 'linting',
- ],
- trigger: {
- ref: ['refs/heads/main', 'refs/tags/**'],
- },
-};
-
-local PipelineDocumentation = {
- kind: 'pipeline',
- name: 'documentation',
- platform: {
- os: 'linux',
- arch: 'amd64',
- },
- steps: [
- {
- name: 'generate',
- image: 'thegeeklab/ansible-doctor',
- environment: {
- ANSIBLE_DOCTOR_LOG_LEVEL: 'INFO',
- ANSIBLE_DOCTOR_FORCE_OVERWRITE: true,
- ANSIBLE_DOCTOR_EXCLUDE_FILES: 'molecule/',
- ANSIBLE_DOCTOR_TEMPLATE: 'hugo-book',
- ANSIBLE_DOCTOR_ROLE_NAME: '${DRONE_REPO_NAME#*.}',
- ANSIBLE_DOCTOR_OUTPUT_DIR: '_docs/',
- },
- },
- {
- name: 'publish',
- image: 'plugins/gh-pages',
- settings: {
- remote_url: 'https://gitea.rknet.org/ansible/${DRONE_REPO_NAME}',
- netrc_machine: 'gitea.rknet.org',
- username: { from_secret: 'gitea_username' },
- password: { from_secret: 'gitea_token' },
- pages_directory: '_docs/',
- target_branch: 'docs',
- },
- when: {
- ref: ['refs/heads/main'],
- },
- },
- ],
- trigger: {
- ref: ['refs/heads/main', 'refs/tags/**', 'refs/pull/**'],
- },
- depends_on: [
- 'testing-centos7',
- ],
-};
-
-local PipelineNotification = {
- kind: 'pipeline',
- name: 'notification',
- platform: {
- os: 'linux',
- arch: 'amd64',
- },
- clone: {
- disable: true,
- },
- steps: [
- {
- name: 'matrix',
- image: 'thegeeklab/drone-matrix',
- settings: {
- homeserver: { from_secret: 'matrix_homeserver' },
- roomid: { from_secret: 'matrix_roomid' },
- template: 'Status: **{{ .Build.Status }}**
Build: [{{ .Repo.Owner }}/{{ .Repo.Name }}]({{ .Build.Link }}){{ if .Build.Branch }} ({{ .Build.Branch }}){{ end }} by {{ .Commit.Author }}
Message: {{ .Commit.Message.Title }}',
- username: { from_secret: 'matrix_username' },
- password: { from_secret: 'matrix_password' },
- },
- },
- ],
- depends_on: [
- 'documentation',
- ],
- trigger: {
- status: ['success', 'failure'],
- ref: ['refs/heads/main', 'refs/tags/**'],
- },
-};
-
-[
- PipelineLinting,
- PipelineDeployment(scenario='centos7'),
- PipelineDocumentation,
- PipelineNotification,
-]
diff --git a/.drone.yml b/.drone.yml
deleted file mode 100644
index 3c168db..0000000
--- a/.drone.yml
+++ /dev/null
@@ -1,152 +0,0 @@
----
-kind: pipeline
-name: linting
-
-platform:
- os: linux
- arch: amd64
-
-steps:
- - name: ansible-later
- image: thegeeklab/ansible-later
- commands:
- - ansible-later
-
- - name: python-format
- image: python:3.11
- commands:
- - pip install -qq yapf
- - "[ -z \"$(find . -type f -name *.py)\" ] || (yapf -rd ./)"
- environment:
- PY_COLORS: 1
-
- - name: python-flake8
- image: python:3.11
- commands:
- - pip install -qq flake8
- - flake8
- environment:
- PY_COLORS: 1
-
-trigger:
- ref:
- - refs/heads/main
- - refs/tags/**
- - refs/pull/**
-
----
-kind: pipeline
-name: testing-centos7
-
-platform:
- os: linux
- arch: amd64
-
-concurrency:
- limit: 1
-
-workspace:
- base: /drone/src
- path: ${DRONE_REPO_NAME}
-
-steps:
- - name: ansible-molecule
- image: thegeeklab/molecule:4
- commands:
- - molecule test -s centos7
- environment:
- HCLOUD_TOKEN:
- from_secret: hcloud_token
-
-trigger:
- ref:
- - refs/heads/main
- - refs/tags/**
-
-depends_on:
- - linting
-
----
-kind: pipeline
-name: documentation
-
-platform:
- os: linux
- arch: amd64
-
-steps:
- - name: generate
- image: thegeeklab/ansible-doctor
- environment:
- ANSIBLE_DOCTOR_EXCLUDE_FILES: molecule/
- ANSIBLE_DOCTOR_FORCE_OVERWRITE: true
- ANSIBLE_DOCTOR_LOG_LEVEL: INFO
- ANSIBLE_DOCTOR_OUTPUT_DIR: _docs/
- ANSIBLE_DOCTOR_ROLE_NAME: ${DRONE_REPO_NAME#*.}
- ANSIBLE_DOCTOR_TEMPLATE: hugo-book
-
- - name: publish
- image: plugins/gh-pages
- settings:
- netrc_machine: gitea.rknet.org
- pages_directory: _docs/
- password:
- from_secret: gitea_token
- remote_url: https://gitea.rknet.org/ansible/${DRONE_REPO_NAME}
- target_branch: docs
- username:
- from_secret: gitea_username
- when:
- ref:
- - refs/heads/main
-
-trigger:
- ref:
- - refs/heads/main
- - refs/tags/**
- - refs/pull/**
-
-depends_on:
- - testing-centos7
-
----
-kind: pipeline
-name: notification
-
-platform:
- os: linux
- arch: amd64
-
-clone:
- disable: true
-
-steps:
- - name: matrix
- image: thegeeklab/drone-matrix
- settings:
- homeserver:
- from_secret: matrix_homeserver
- password:
- from_secret: matrix_password
- roomid:
- from_secret: matrix_roomid
- template: "Status: **{{ .Build.Status }}**
Build: [{{ .Repo.Owner }}/{{ .Repo.Name }}]({{ .Build.Link }}){{ if .Build.Branch }} ({{ .Build.Branch }}){{ end }} by {{ .Commit.Author }}
Message: {{ .Commit.Message.Title }}"
- username:
- from_secret: matrix_username
-
-trigger:
- ref:
- - refs/heads/main
- - refs/tags/**
- status:
- - success
- - failure
-
-depends_on:
- - documentation
-
----
-kind: signature
-hmac: 8deae8ced5d7f9c3945e28632266d5573cf0ce26d1a21b1e494e34128c05e2a1
-
-...
diff --git a/.gitignore b/.gitignore
index 9d13a2b..d97b7cd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,6 @@
# ---> Ansible
*.retry
-filter/plugins/
+plugins
library
# ---> Python
@@ -9,5 +9,3 @@ __pycache__/
*.py[cod]
*$py.class
-# ---> Docs
-/_docs
diff --git a/.later.yml b/.later.yml
deleted file mode 100644
index 0efe5d5..0000000
--- a/.later.yml
+++ /dev/null
@@ -1,19 +0,0 @@
----
-ansible:
- custom_modules:
- - iptables_raw
- - openssl_pkcs12
- - proxmox_kvm
- - ucr
- - corenetworks_dns
- - corenetworks_token
-
-rules:
- exclude_files:
- - molecule/
- - "LICENSE*"
- - "**/*.md"
- - "**/*.ini"
-
- exclude_filter:
- - LINT0009
diff --git a/.markdownlint.yml b/.markdownlint.yml
new file mode 100644
index 0000000..da116c7
--- /dev/null
+++ b/.markdownlint.yml
@@ -0,0 +1,7 @@
+---
+default: True
+MD013: False
+MD041: False
+MD024: False
+MD004:
+ style: dash
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..6b1d0bf
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1 @@
+LICENSE
diff --git a/.woodpecker/docs.yaml b/.woodpecker/docs.yaml
new file mode 100644
index 0000000..857444b
--- /dev/null
+++ b/.woodpecker/docs.yaml
@@ -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_RENDERER__FORCE_OVERWRITE: "true"
+ ANSIBLE_DOCTOR_LOGGING__LEVEL: info
+ ANSIBLE_DOCTOR_ROLE__NAME: ${CI_REPO_NAME}
+ ANSIBLE_DOCTOR_TEMPLATE__NAME: 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
diff --git a/.woodpecker/lint.yaml b/.woodpecker/lint.yaml
new file mode 100644
index 0000000..c48a8e4
--- /dev/null
+++ b/.woodpecker/lint.yaml
@@ -0,0 +1,30 @@
+---
+when:
+ - event: [pull_request, tag]
+ - event: [push, manual]
+ branch:
+ - ${CI_REPO_DEFAULT_BRANCH}
+
+steps:
+ - name: ansible-lint
+ image: quay.io/thegeeklab/ansible-dev-tools:1
+ commands:
+ - ansible-lint
+ 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 check .
+ environment:
+ PY_COLORS: "1"
diff --git a/.woodpecker/notify.yml b/.woodpecker/notify.yml
new file mode 100644
index 0000000..45bc21e
--- /dev/null
+++ b/.woodpecker/notify.yml
@@ -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
+ room_id:
+ from_secret: matrix_room_id
+ user_id:
+ from_secret: matrix_user_id
+ access_token:
+ from_secret: matrix_access_token
+ when:
+ - status: [failure]
+
+depends_on:
+ - docs
diff --git a/.woodpecker/test.yaml b/.woodpecker/test.yaml
new file mode 100644
index 0000000..661dc8b
--- /dev/null
+++ b/.woodpecker/test.yaml
@@ -0,0 +1,24 @@
+---
+when:
+ - event: [pull_request, tag]
+ - event: [push, manual]
+ branch:
+ - ${CI_REPO_DEFAULT_BRANCH}
+
+variables:
+ - &molecule_base
+ image: quay.io/thegeeklab/ansible-dev-tools:1
+ group: molecule
+ environment:
+ PY_COLORS: "1"
+ HCLOUD_TOKEN:
+ from_secret: molecule_hcloud_token
+
+steps:
+ - name: molecule-default
+ <<: *molecule_base
+ commands:
+ - molecule test -s default
+
+depends_on:
+ - lint
diff --git a/.yamllint b/.yamllint
new file mode 100644
index 0000000..df1d39e
--- /dev/null
+++ b/.yamllint
@@ -0,0 +1,20 @@
+---
+extends: default
+
+rules:
+ truthy:
+ allowed-values: ["True", "False"]
+ comments:
+ min-spaces-from-content: 1
+ comments-indentation: False
+ line-length: disable
+ braces:
+ min-spaces-inside: 0
+ max-spaces-inside: 1
+ brackets:
+ min-spaces-inside: 0
+ max-spaces-inside: 0
+ indentation: enable
+ octal-values:
+ forbid-implicit-octal: True
+ forbid-explicit-octal: True
diff --git a/README.md b/README.md
index fd358dc..cab5e35 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1 @@
# xoxys.zigbee2mqtt
-
-[![Build Status](https://img.shields.io/drone/build/ansible/xoxys.zigbee2mqtt?logo=drone&server=https%3A%2F%2Fdrone.rknet.org)](https://drone.rknet.org/ansible/xoxys.zigbee2mqtt)
-[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
-
-Setup [zigbee2mqtt](https://github.com/Koenkk/zigbee2mqtt). Zigbee2mqtt allows you to use your Zigbee devices without the vendors bridge or gateway. It bridges events and allows you to control your Zigbee devices via MQTT.
-
-You can find the full documentation at [https://galaxy.geekdocs.de](https://galaxy.geekdocs.de/roles/IoT/zigbee2mqtt/).
-
-## 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
index a6c7e24..e2753c2 100644
--- a/defaults/main.yml
+++ b/defaults/main.yml
@@ -1,44 +1,27 @@
---
-zigbee2mqtt_version: latest
-zigbee2mqtt_image: "koenkk/zigbee2mqtt:{{ zigbee2mqtt_version }}"
+zigbee2mqtt_image: "docker.io/koenkk/zigbee2mqtt:latest"
-zigbee2mqtt_service_directory: /var/lib/docker/services/zigbee2mqtt
-zigbee2mqtt_container_name: zigbee2mqtt
-zigbee2mqtt_restart_policy: always
-zigbee2mqtt_service_stopped: False
-# @var zigbee2mqtt_networks:example: >
-# zigbee2mqtt_networks:
-# - name: default
-# # optional network driver, defaults to 'bride'
-# driver: host
-# external: false
-# @end
-zigbee2mqtt_networks:
- - name: default
+zigbee2mqtt_service_started: True
-zigbee2mqtt_networks_applied:
- - default
+zigbee2mqtt_data_volume: zigbee2mqtt-data
# @var zigbee2mqtt_volumes:description: Define required docker volumes.
-# @var zigbee2mqtt_volumes:example: >
-# zigbee2mqtt_volumes:
-# # Instead of the name you could specify a path on the container host system,
-# # but you also have to enable bind mount for this volume
-# - name: data
-# # target location inside the container
-# dest: /var/www/app/data
-# # enable bind mount, if false volume will be configured as named volume
-# # keep in mind you MUST set bind in any case
-# bind: True
-# # Options for bind mounts
-# bind_opt: "ro,z"
-# @end
zigbee2mqtt_volumes:
- name: "{{ zigbee2mqtt_data_volume }}"
dest: /app/data
- bind: True
-zigbee2mqtt_data_volume: "/opt/zigbee2mqtt/data"
+# @var zigbee2mqtt_network:description: Use a custom docker network for grafana.
+# @var zigbee2mqtt_network:value: $ "_unset_"
+
+# @var zigbee2mqtt_exposed_ports:description: Ports you want to publish outside of docker.
+zigbee2mqtt_exposed_ports: []
+
+zigbee2mqtt_cap_add: []
+zigbee2mqtt_cap_drop: []
+zigbee2mqtt_security_opts: []
+
+zigbee2mqtt_docker_args:
+ - --pids-limit=-1
# @var zigbee2mqtt_devices:description: Define required devices e.g. `/dev/ttyACM0`.
# @var zigbee2mqtt_devices:example: >
@@ -47,21 +30,7 @@ zigbee2mqtt_data_volume: "/opt/zigbee2mqtt/data"
# dest: "{{ zigbee2mqtt_serial_port }}"
# opt: z
# @end
-
-zigbee2mqtt_exposed_ports: []
-zigbee2mqtt_extra_hosts: []
-
-# @var zigbee2mqtt_memory_limit: $ "_unset_"
-# @var zigbee2mqtt_memory_limit:example: $ "512m"
-# @var zigbee2mqtt_memory_reservation: $ "_unset_"
-# @var zigbee2mqtt_memory_reservation:example: $ "256m"
-# @var zigbee2mqtt_cpu_shares: $ "_unset_"
-# @var zigbee2mqtt_cpu_shares:example: $ "1024"
-
-zigbee2mqtt_cap_add: []
-zigbee2mqtt_cap_drop: []
-zigbee2mqtt_security_opt: []
-# @var zigbee2mqtt_pids_limit: $ "_unset_"
+zigbee2mqtt_devices: []
zigbee2mqtt_log_level: info
diff --git a/handlers/main.yml b/handlers/main.yml
index 5e5c5ad..582e116 100644
--- a/handlers/main.yml
+++ b/handlers/main.yml
@@ -1,11 +1,7 @@
---
-- name: Restart zigbee2mqtt service
- docker_compose:
- project_src: "{{ zigbee2mqtt_service_directory }}"
- pull: yes
- remove_orphans: yes
- stopped: "{{ zigbee2mqtt_service_stopped }}"
- restarted: "{{ not zigbee2mqtt_service_stopped }}"
+- name: Restart zigbee2mqtt
+ ansible.builtin.service:
+ name: "zigbee2mqtt.service"
+ state: "{{ zigbee2mqtt_service_started | ternary('restarted', 'stopped', 'restarted') }}"
+ daemon_reload: True
listen: __zigbee2mqtt_restart
- become: True
- become_user: root
diff --git a/meta/main.yml b/meta/main.yml
index 8f363b1..10dc60d 100644
--- a/meta/main.yml
+++ b/meta/main.yml
@@ -4,7 +4,7 @@ galaxy_info:
# @meta author:value: [Robert Kaussow](https://gitea.rknet.org/xoxys)
author: Robert Kaussow
namespace: xoxys
- role_name: zigbee2mqtt_docker
+ role_name: zigbee2mqtt
# @meta description: >
# [![Source Code](https://img.shields.io/badge/gitea-source%20code-blue?logo=gitea&logoColor=white)](https://gitea.rknet.org/ansible/xoxys.zigbee2mqtt)
# [![Build Status](https://img.shields.io/drone/build/ansible/xoxys.zigbee2mqtt?logo=drone&server=https%3A%2F%2Fdrone.rknet.org)](https://drone.rknet.org/ansible/xoxys.zigbee2mqtt)
@@ -16,15 +16,12 @@ galaxy_info:
# @end
description: Setup zigbee2mqtt
license: MIT
- min_ansible_version: 2.10
+ min_ansible_version: "2.10"
platforms:
- name: EL
versions:
- - 7
+ - "9"
galaxy_tags:
- zigbee
- zigbee2mqtt
dependencies: []
-collections:
- - xoxys.general
- - community.general
diff --git a/molecule/centos7/converge.yml b/molecule/centos7/converge.yml
deleted file mode 100644
index b12556c..0000000
--- a/molecule/centos7/converge.yml
+++ /dev/null
@@ -1,23 +0,0 @@
----
-- name: Converge (Stage 1)
- hosts: all
- vars:
- dockerengine_packages_extra:
- - epel-release
- - python-pip
- - python-virtualenv
-
- roles:
- - role: xoxys.docker_engine
-
-- name: Converge (Stage 2)
- hosts: all
- environment:
- PYTHONPATH: /opt/python2/ansible-deps/lib/python2.7/site-packages
- vars:
- mosquitto_bind_address: "127.0.0.1"
- zigbee2mqtt_service_stopped: True
-
- roles:
- - role: xoxys.mosquitto
- - role: xoxys.zigbee2mqtt_docker
diff --git a/molecule/centos7/create.yml b/molecule/centos7/create.yml
deleted file mode 100644
index 8b945cd..0000000
--- a/molecule/centos7/create.yml
+++ /dev/null
@@ -1,120 +0,0 @@
----
-- name: Create
- hosts: localhost
- connection: local
- gather_facts: false
- no_log: "{{ molecule_no_log }}"
- vars:
- ssh_port: 22
- ssh_user: root
- ssh_path: "{{ lookup('env', 'MOLECULE_EPHEMERAL_DIRECTORY') }}/ssh_key"
- tasks:
- - name: Create SSH key
- user:
- name: "{{ lookup('env', 'USER') }}"
- generate_ssh_key: true
- ssh_key_file: "{{ ssh_path }}"
- force: true
- register: generated_ssh_key
-
- - name: Register the SSH key name
- set_fact:
- ssh_key_name: "molecule-generated-{{ 12345 | random | to_uuid }}"
-
- - name: Register SSH key for test instance(s)
- hcloud_ssh_key:
- name: "{{ ssh_key_name }}"
- public_key: "{{ generated_ssh_key.ssh_public_key }}"
- state: present
-
- - name: Create molecule instance(s)
- hcloud_server:
- name: "{{ item.name }}"
- server_type: "{{ item.server_type }}"
- ssh_keys:
- - "{{ ssh_key_name }}"
- image: "{{ item.image }}"
- location: "{{ item.location | default(omit) }}"
- datacenter: "{{ item.datacenter | default(omit) }}"
- user_data: "{{ item.user_data | default(omit) }}"
- api_token: "{{ lookup('env', 'HCLOUD_TOKEN') }}"
- state: present
- register: server
- loop: "{{ molecule_yml.platforms }}"
- async: 7200
- poll: 0
-
- - name: Wait for instance(s) creation to complete
- async_status:
- jid: "{{ item.ansible_job_id }}"
- register: hetzner_jobs
- until: hetzner_jobs.finished
- retries: 300
- loop: "{{ server.results }}"
-
- - name: Create volume(s)
- hcloud_volume:
- name: "{{ item.name }}"
- server: "{{ item.name }}"
- location: "{{ item.location | default(omit) }}"
- size: "{{ item.volume_size | default(10) }}"
- api_token: "{{ lookup('env', 'HCLOUD_TOKEN') }}"
- state: "present"
- loop: "{{ molecule_yml.platforms }}"
- when: item.volume | default(False) | bool
- register: volumes
- async: 7200
- poll: 0
-
- - name: Wait for volume(s) creation to complete
- async_status:
- jid: "{{ item.ansible_job_id }}"
- register: hetzner_volumes
- until: hetzner_volumes.finished
- retries: 300
- when: volumes.changed
- loop: "{{ volumes.results }}"
-
- # Mandatory configuration for Molecule to function.
-
- - name: Populate instance config dict
- set_fact:
- instance_conf_dict:
- {
- "instance": "{{ item.hcloud_server.name }}",
- "ssh_key_name": "{{ ssh_key_name }}",
- "address": "{{ item.hcloud_server.ipv4_address }}",
- "user": "{{ ssh_user }}",
- "port": "{{ ssh_port }}",
- "identity_file": "{{ ssh_path }}",
- "volume": "{{ item.item.item.volume | default(False) | bool }}",
- }
- loop: "{{ hetzner_jobs.results }}"
- register: instance_config_dict
- when: server.changed | bool
-
- - name: Convert instance config dict to a list
- set_fact:
- instance_conf: "{{ instance_config_dict.results | map(attribute='ansible_facts.instance_conf_dict') | list }}"
- when: server.changed | bool
-
- - name: Dump instance config
- copy:
- content: |
- # Molecule managed
-
- {{ instance_conf | to_nice_yaml(indent=2) }}
- dest: "{{ molecule_instance_config }}"
- when: server.changed | bool
-
- - name: Wait for SSH
- wait_for:
- port: "{{ ssh_port }}"
- host: "{{ item.address }}"
- search_regex: SSH
- delay: 10
- loop: "{{ lookup('file', molecule_instance_config) | from_yaml }}"
-
- - name: Wait for VM to settle down
- pause:
- seconds: 30
diff --git a/molecule/centos7/destroy.yml b/molecule/centos7/destroy.yml
deleted file mode 100644
index 6454c71..0000000
--- a/molecule/centos7/destroy.yml
+++ /dev/null
@@ -1,78 +0,0 @@
----
-- name: Destroy
- hosts: localhost
- connection: local
- gather_facts: false
- no_log: "{{ molecule_no_log }}"
- tasks:
- - name: Check existing instance config file
- stat:
- path: "{{ molecule_instance_config }}"
- register: cfg
-
- - name: Populate the instance config
- set_fact:
- instance_conf: "{{ (lookup('file', molecule_instance_config) | from_yaml) if cfg.stat.exists else [] }}"
-
- - name: Destroy molecule instance(s)
- hcloud_server:
- name: "{{ item.instance }}"
- api_token: "{{ lookup('env', 'HCLOUD_TOKEN') }}"
- state: absent
- register: server
- loop: "{{ instance_conf }}"
- async: 7200
- poll: 0
-
- - name: Wait for instance(s) deletion to complete
- async_status:
- jid: "{{ item.ansible_job_id }}"
- register: hetzner_jobs
- until: hetzner_jobs.finished
- retries: 300
- loop: "{{ server.results }}"
-
- - pause:
- seconds: 5
-
- - name: Destroy volume(s)
- hcloud_volume:
- name: "{{ item.instance }}"
- server: "{{ item.instance }}"
- api_token: "{{ lookup('env', 'HCLOUD_TOKEN') }}"
- state: "absent"
- register: volumes
- loop: "{{ instance_conf }}"
- when: item.volume | default(False) | bool
- async: 7200
- poll: 0
-
- - name: Wait for volume(s) deletion to complete
- async_status:
- jid: "{{ item.ansible_job_id }}"
- register: hetzner_volumes
- until: hetzner_volumes.finished
- retries: 300
- when: volumes.changed
- loop: "{{ volumes.results }}"
-
- - name: Remove registered SSH key
- hcloud_ssh_key:
- name: "{{ instance_conf[0].ssh_key_name }}"
- state: absent
- when: (instance_conf | default([])) | length > 0
-
- # Mandatory configuration for Molecule to function.
-
- - name: Populate instance config
- set_fact:
- instance_conf: {}
-
- - name: Dump instance config
- copy:
- content: |
- # Molecule managed
-
- {{ instance_conf | to_nice_yaml(indent=2) }}
- dest: "{{ molecule_instance_config }}"
- when: server.changed | bool
diff --git a/molecule/centos7/molecule.yml b/molecule/centos7/molecule.yml
deleted file mode 100644
index 4ba9390..0000000
--- a/molecule/centos7/molecule.yml
+++ /dev/null
@@ -1,24 +0,0 @@
----
-dependency:
- name: galaxy
- options:
- role-file: molecule/requirements.yml
- requirements-file: molecule/requirements.yml
- env:
- ANSIBLE_GALAXY_DISPLAY_PROGRESS: "false"
-driver:
- name: delegated
-platforms:
- - name: centos7-zigbee2mqtt
- image: centos-7
- server_type: cx11
-lint: |
- /usr/local/bin/flake8
-provisioner:
- name: ansible
- env:
- ANSIBLE_FILTER_PLUGINS: ${ANSIBLE_FILTER_PLUGINS:-./plugins/filter}
- ANSIBLE_LIBRARY: ${ANSIBLE_LIBRARY:-./library}
- log: False
-verifier:
- name: testinfra
diff --git a/molecule/centos7/prepare.yml b/molecule/centos7/prepare.yml
deleted file mode 100644
index 183f4d3..0000000
--- a/molecule/centos7/prepare.yml
+++ /dev/null
@@ -1,15 +0,0 @@
----
-- name: Prepare
- hosts: all
- gather_facts: false
- tasks:
- - name: Bootstrap python for Ansible
- raw: |
- command -v python3 python || (
- (test -e /usr/bin/dnf && sudo dnf install -y python3) ||
- (test -e /usr/bin/apt && (apt -y update && apt install -y python-minimal)) ||
- (test -e /usr/bin/yum && sudo yum -y -qq install python3) ||
- echo "Warning: Python not boostrapped due to unknown platform."
- )
- become: true
- changed_when: false
diff --git a/molecule/centos7/tests/test_default.py b/molecule/centos7/tests/test_default.py
deleted file mode 100644
index 00c8dca..0000000
--- a/molecule/centos7/tests/test_default.py
+++ /dev/null
@@ -1,15 +0,0 @@
-import os
-
-import testinfra.utils.ansible_runner
-
-testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
- os.environ["MOLECULE_INVENTORY_FILE"]
-).get_hosts("all")
-
-
-# TODO: add some tests if zigbee2mqtt can work with a
-# dummy interface
-def test_hosts_file(host):
- f = host.file('/etc/hosts')
-
- assert f.exists
diff --git a/molecule/default b/molecule/default
deleted file mode 120000
index 2fdf3e8..0000000
--- a/molecule/default
+++ /dev/null
@@ -1 +0,0 @@
-centos7
\ No newline at end of file
diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml
new file mode 100644
index 0000000..40c619f
--- /dev/null
+++ b/molecule/default/converge.yml
@@ -0,0 +1,8 @@
+---
+- name: Converge
+ hosts: all
+ vars:
+ zigbee2mqtt_service_started: False
+ roles:
+ - role: xoxys.dockerengine
+ - role: xoxys.zigbee2mqtt
diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml
new file mode 100644
index 0000000..83b7369
--- /dev/null
+++ b/molecule/default/molecule.yml
@@ -0,0 +1,17 @@
+---
+driver:
+ name: molecule_hetznercloud
+dependency:
+ name: galaxy
+ options:
+ role-file: requirements.yml
+ requirements-file: requirements.yml
+platforms:
+ - name: "rocky9-zigbee2mqtt"
+ server_type: "cx22"
+ image: "rocky-9"
+provisioner:
+ name: ansible
+ log: True
+verifier:
+ name: testinfra
diff --git a/molecule/default/prepare.yml b/molecule/default/prepare.yml
new file mode 100644
index 0000000..0df1d77
--- /dev/null
+++ b/molecule/default/prepare.yml
@@ -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
diff --git a/molecule/pytest.ini b/molecule/pytest.ini
deleted file mode 100644
index c24fe5b..0000000
--- a/molecule/pytest.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[pytest]
-filterwarnings =
- ignore::DeprecationWarning
diff --git a/molecule/requirements.yml b/molecule/requirements.yml
deleted file mode 100644
index 35dde5b..0000000
--- a/molecule/requirements.yml
+++ /dev/null
@@ -1,15 +0,0 @@
----
-collections:
- - name: https://gitea.rknet.org/ansible/xoxys.general/releases/download/v2.1.1/xoxys-general-2.1.1.tar.gz
- - name: community.general
-
-roles:
- - src: https://gitea.rknet.org/ansible/xoxys.docker_engine.git
- name: xoxys.docker_engine
- scm: git
- version: main
-
- - src: https://gitea.rknet.org/ansible/xoxys.mosquitto.git
- name: xoxys.mosquitto
- scm: git
- version: main
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..7193140
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,17 @@
+[tool.ruff]
+exclude = [".git", "__pycache__"]
+
+line-length = 99
+indent-width = 4
+
+[tool.ruff.lint]
+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/requirements.yml b/requirements.yml
new file mode 100644
index 0000000..5300ab9
--- /dev/null
+++ b/requirements.yml
@@ -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
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 2bb8674..0000000
--- a/setup.cfg
+++ /dev/null
@@ -1,12 +0,0 @@
-[flake8]
-ignore = D100, D101, D102, D103, D105, D107, E402, W503
-max-line-length = 99
-inline-quotes = double
-exclude = .git,.tox,__pycache__,build,dist,tests,*.pyc,*.egg-info,.cache,.eggs,env*
-
-[yapf]
-based_on_style = google
-column_limit = 99
-dedent_closing_brackets = true
-coalesce_brackets = true
-split_before_logical_operator = true
diff --git a/tasks/main.yml b/tasks/main.yml
index 1f69f7a..fedbac6 100644
--- a/tasks/main.yml
+++ b/tasks/main.yml
@@ -1,2 +1,58 @@
---
-- include_tasks: setup.yml
+- name: Create container volumes
+ community.docker.docker_volume:
+ name: "{{ item.name }}"
+ driver_options: "{{ item.options | default(omit) }}"
+ state: "{{ item.state | default('present') }}"
+ loop: "{{ zigbee2mqtt_volumes }}"
+ loop_control:
+ label: "{{ item.name }}"
+ when: item.type | default("volume") | lower == "volume"
+ register: __zigbee2mqtt_volumes_raw
+
+- name: Register container volumes map
+ ansible.builtin.set_fact:
+ __zigbee2mqtt_volumes_map: "{{ __zigbee2mqtt_volumes_raw.results | json_query('[].volume') | items2dict(key_name='Name', value_name='Mountpoint') }}"
+
+- name: Deploy env file
+ ansible.builtin.template:
+ src: etc/sysconfig/zigbee2mqtt.j2
+ dest: "/etc/sysconfig/zigbee2mqtt"
+ owner: root
+ group: root
+ mode: "0600"
+ notify: __zigbee2mqtt_restart
+
+- name: Create container specs
+ ansible.builtin.template:
+ src: etc/systemd/system/zigbee2mqtt.service.j2
+ dest: "/etc/systemd/system/zigbee2mqtt.service"
+ owner: root
+ group: root
+ mode: "0640"
+ notify: __zigbee2mqtt_restart
+
+- name: Deploy configuration file
+ template:
+ src: "zigbee2mqtt/configuration.yaml.j2"
+ dest: "{{ __zigbee2mqtt_volumes_map[zigbee2mqtt_data_volume] }}/configuration.yaml"
+ mode: 0600
+ notify: __zigbee2mqtt_restart
+
+- name: Ensure device files exists
+ file:
+ path: "{{ item }}"
+ mode: 0640
+ state: touch
+ access_time: preserve
+ modification_time: preserve
+ loop:
+ - "{{ __zigbee2mqtt_volumes_map[zigbee2mqtt_data_volume] }}/devices.yaml"
+ - "{{ __zigbee2mqtt_volumes_map[zigbee2mqtt_data_volume] }}/groups.yaml"
+
+- name: Ensure service state
+ ansible.builtin.service:
+ name: "zigbee2mqtt.service"
+ state: "{{ zigbee2mqtt_service_started | ternary('started', 'stopped', 'started') }}"
+ daemon_reload: True
+ enabled: True
diff --git a/tasks/setup.yml b/tasks/setup.yml
deleted file mode 100644
index 805ce75..0000000
--- a/tasks/setup.yml
+++ /dev/null
@@ -1,54 +0,0 @@
----
-- block:
- - name: Ensure service directory exists
- file:
- path: "{{ zigbee2mqtt_service_directory }}"
- mode: 0750
- state: directory
-
- - name: Create bind mount source directory
- file:
- path: "{{ item.name }}"
- mode: 0750
- state: directory
- loop: "{{ zigbee2mqtt_volumes }}"
- loop_control:
- label: "{{ item.name }}"
- when: item.bind | bool
-
- - name: Deploy compose file to '{{ zigbee2mqtt_service_directory }}'
- template:
- src: "services/zigbee2mqtt_compose.yml.j2"
- dest: "{{ zigbee2mqtt_service_directory }}/docker-compose.yml"
- owner: root
- group: root
- mode: 0640
- validate: "docker-compose -f %s config -q"
-
- - name: Deploy configuration file
- template:
- src: "zigbee2mqtt/data/configuration.yaml.j2"
- dest: "{{ zigbee2mqtt_data_volume }}/configuration.yaml"
- mode: 0600
- notify: __zigbee2mqtt_restart
-
- - name: Ensure device files exists
- file:
- path: "{{ item }}"
- mode: 0640
- state: touch
- access_time: preserve
- modification_time: preserve
- loop:
- - "{{ zigbee2mqtt_data_volume }}/devices.yaml"
- - "{{ zigbee2mqtt_data_volume }}/groups.yaml"
-
- - name: Ensure service is up and running
- docker_compose:
- project_src: "{{ zigbee2mqtt_service_directory }}"
- pull: yes
- remove_orphans: yes
- stopped: "{{ zigbee2mqtt_service_stopped }}"
- state: present
- become: True
- become_user: root
diff --git a/templates/etc/sysconfig/zigbee2mqtt.j2 b/templates/etc/sysconfig/zigbee2mqtt.j2
new file mode 100644
index 0000000..b715059
--- /dev/null
+++ b/templates/etc/sysconfig/zigbee2mqtt.j2
@@ -0,0 +1,3 @@
+#jinja2: lstrip_blocks: True
+{{ ansible_managed | comment }}
+TZ={{ zigbee2mqtt_timezone }}
diff --git a/templates/etc/systemd/system/zigbee2mqtt.service.j2 b/templates/etc/systemd/system/zigbee2mqtt.service.j2
new file mode 100644
index 0000000..be85beb
--- /dev/null
+++ b/templates/etc/systemd/system/zigbee2mqtt.service.j2
@@ -0,0 +1,55 @@
+#jinja2: lstrip_blocks: True
+{{ ansible_managed | comment }}
+[Unit]
+Description=Zigbee2mqtt
+
+Wants=docker.service
+After=docker.service
+
+[Service]
+Restart=on-failure
+RestartSec=5s
+EnvironmentFile=/etc/environment
+
+ExecStop=/usr/bin/docker pull {{ zigbee2mqtt_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 {{ zigbee2mqtt_image }}
+
+ExecStart=/usr/bin/docker run --rm \
+ --name %p \
+ --hostname %p \
+ --env-file /etc/sysconfig/zigbee2mqtt \
+ {% if zigbee2mqtt_network is defined and zigbee2mqtt_network %}
+ --network {{ zigbee2mqtt_network }} \
+ {% endif %}
+ {% for cap in zigbee2mqtt_cap_add %}
+ --cap-add {{ cap }} \
+ {% endfor %}
+ {% for cap in zigbee2mqtt_cap_drop %}
+ --cap-drop {{ cap }} \
+ {% endfor %}
+ {% for opt in zigbee2mqtt_security_opts %}
+ --security-opt "{{ opt }}" \
+ {% endfor %}
+ {% for volume in zigbee2mqtt_volumes %}
+ --mount '{{ "type=bind," if (volume.type | default(False) | lower == "bind") else "" }}src={{ volume.name }},target={{ volume.dest }}' \
+ {% endfor %}
+ {% for device in zigbee2mqtt_devices %}
+ --device "{{ device.src }}:{{ device.dest }}{% if device.opt is defined %}:{{ device.opt }}{% endif %}" \
+ {% endfor %}
+ {% for port in zigbee2mqtt_exposed_ports %}
+ --publish {{ port }} \
+ {% endfor %}
+ {% for item in inst.docker_args | default(zigbee2mqtt_docker_args) %}
+ {{ item }} \
+ {% endfor %}
+ --health-interval 5s \
+ --health-retries 5 \
+ --health-timeout 10s \
+ {{ zigbee2mqtt_image }}
+
+[Install]
+WantedBy=multi-user.target
diff --git a/templates/services/zigbee2mqtt_compose.yml.j2 b/templates/services/zigbee2mqtt_compose.yml.j2
deleted file mode 100644
index 55b50dc..0000000
--- a/templates/services/zigbee2mqtt_compose.yml.j2
+++ /dev/null
@@ -1,90 +0,0 @@
-#jinja2:lstrip_blocks: True
-{{ ansible_managed | comment }}
-version: "2.4"
-
-services:
- zigbee2mqtt:
- container_name: {{ zigbee2mqtt_container_name }}
- image: {{ zigbee2mqtt_image }}
- restart: {{ zigbee2mqtt_restart_policy }}
- {% if zigbee2mqtt_exposed_ports | default([]) %}
- ports:
- {% for port in zigbee2mqtt_exposed_ports %}
- - {{ port | quote }}
- {% endfor %}
- {% endif %}
- {% if zigbee2mqtt_volumes | default([]) %}
- volumes:
- {% for volume in zigbee2mqtt_volumes %}
- - "{{ volume.name }}:{{ volume.dest }}{% if volume.bind_opt is defined %}:{{ volume.bind_opt }}{% endif %}"
- {% endfor %}
- {% endif %}
- {% if zigbee2mqtt_devices | default([]) %}
- devices:
- {% for device in zigbee2mqtt_devices %}
- - "{{ device.src }}:{{ device.dest }}{% if device.opt is defined %}:{{ device.opt }}{% endif %}"
- {% endfor %}
- {% endif %}
- {% if zigbee2mqtt_networks_applied | default([]) %}
- networks:
- {% for network in zigbee2mqtt_networks_applied %}
- - {{ network }}
- {% endfor %}
- {% endif %}
- {% if zigbee2mqtt_extra_hosts | default([]) %}
- extra_hosts:
- {% for host in zigbee2mqtt_extra_hosts %}
- - {{ host | quote }}
- {% endfor %}
- {% endif %}
- environment:
- - TZ={{ zigbee2mqtt_timezone }}
- {% if zigbee2mqtt_memory_limit is defined %}
- mem_limit: {{ zigbee2mqtt_memory_limit }}
- {% endif %}
- {% if zigbee2mqtt_memory_reservation is defined %}
- mem_reservation: {{ zigbee2mqtt_memory_reservation }}
- {% endif %}
- {% if zigbee2mqtt_cpu_shares is defined %}
- cpu_shares: {{ zigbee2mqtt_cpu_shares }}
- {% endif %}
- {% if not zigbee2mqtt_cap_add | length == 0 %}
- cap_add:
- {% for item in zigbee2mqtt_cap_add %}
- - {{ item }}
- {% endfor %}
- {% endif %}
- {% if not zigbee2mqtt_cap_drop | length == 0 %}
- cap_drop:
- {% for item in zigbee2mqtt_cap_drop %}
- - {{ item }}
- {% endfor %}
- {% endif %}
- {% if not zigbee2mqtt_security_opt | length == 0 %}
- security_opt:
- {% for item in zigbee2mqtt_security_opt %}
- - {{ item }}
- {% endfor %}
- {% endif %}
- {% if zigbee2mqtt_pids_limit is defined %}
- pids_limit: {{ zigbee2mqtt_pids_limit }}
- {% endif %}
-{% if zigbee2mqtt_volumes | default([]) | rejectattr("bind") | list | length > 0 %}
-
-volumes:
- {% for volume in zigbee2mqtt_volumes | rejectattr("bind") %}
- {{ volume.name }}:
- {% endfor %}
-{% endif %}
-{% if zigbee2mqtt_networks | default([]) | length > 0 %}
-
-networks:
- {% for network in zigbee2mqtt_networks %}
- {{ network.name }}:
- {% if network.external | default(False) | bool %}
- external: true
- {% else %}
- driver: {{ network.backend | default("bridge") }}
- {% endif %}
- {% endfor %}
-{% endif %}
diff --git a/templates/zigbee2mqtt/data/configuration.yaml.j2 b/templates/zigbee2mqtt/configuration.yaml.j2
similarity index 98%
rename from templates/zigbee2mqtt/data/configuration.yaml.j2
rename to templates/zigbee2mqtt/configuration.yaml.j2
index 216c3e4..744c8c4 100644
--- a/templates/zigbee2mqtt/data/configuration.yaml.j2
+++ b/templates/zigbee2mqtt/configuration.yaml.j2
@@ -53,6 +53,8 @@ advanced:
channel: {{ zigbee2mqtt_channel }}
cache_state: {{ zigbee2mqtt_cache_state }}
log_level: "{{ zigbee2mqtt_log_level }}"
+ log_output:
+ - console
last_seen: "{{ zigbee2mqtt_last_seen }}"
elapsed: {{ zigbee2mqtt_elapsed }}
diff --git a/vars/main.yml b/vars/main.yml
deleted file mode 100644
index cb7b30b..0000000
--- a/vars/main.yml
+++ /dev/null
@@ -1,12 +0,0 @@
----
-__zigbee2mqtt_npm_executable: /usr/local/bin/npm
-__zigbee2mqtt_release_exclude:
- - data/
- - docker/
- - docs/
- - images/
- - LICENSE
- - README.md
- - scripts/
- - test/
- - update.sh