diff --git a/.drone.jsonnet b/.drone.jsonnet
new file mode 100644
index 0000000..bd10eb2
--- /dev/null
+++ b/.drone.jsonnet
@@ -0,0 +1,148 @@
+local PipelineLinting = {
+ kind: "pipeline",
+ name: "linting",
+ platform: {
+ os: "linux",
+ arch: "amd64",
+ },
+ steps: [
+ {
+ name: "ansible-later",
+ image: "xoxys/ansible-later:latest",
+ environment: {
+ PY_COLORS: 1
+ },
+ commands: [
+ "git clone https://gitea.rknet.org/ansible/ansible-later-policy.git ~/policy",
+ "ansible-later -c ~/policy/config.yml"
+ ],
+ },
+ ],
+ trigger: {
+ ref: ["refs/heads/master", "refs/tags/**", "refs/pull/**"],
+ },
+};
+
+local PipelineDeployment = {
+ kind: "pipeline",
+ name: "deployment",
+ platform: {
+ os: "linux",
+ arch: "amd64",
+ },
+ concurrency: {
+ limit: 1
+ },
+ workspace: {
+ base: "/drone/src",
+ path: "xoxys.selinux"
+ },
+ steps: [
+ {
+ name: "ansible-molecule",
+ image: "xoxys/molecule:do-linux-amd64",
+ environment: {
+ DO_API_KEY: { "from_secret": "do_api_key" },
+ USER: "root",
+ MOLECULE_CUSTOM_MODULES_REPO: "https://gitea.rknet.org/ansible/custom_modules",
+ MOLECULE_CUSTOM_FILTERS_REPO: "https://gitea.rknet.org/ansible/custom_filters",
+ PY_COLORS: 1
+ },
+ commands: [
+ "/bin/bash /docker-entrypoint.sh",
+ "molecule test -s default",
+ ],
+ },
+ ],
+ depends_on: [
+ "linting",
+ ],
+ trigger: {
+ ref: ["refs/heads/master", "refs/tags/**"],
+ },
+};
+
+local PipelineDocumentation = {
+ kind: "pipeline",
+ name: "documentation",
+ platform: {
+ os: "linux",
+ arch: "amd64",
+ },
+ steps: [
+ {
+ name: "ansible-doctor",
+ image: "xoxys/ansible-doctor:latest",
+ environment: {
+ ANSIBLE_DOCTOR_LOG_LEVEL: "INFO",
+ ANSIBLE_DOCTOR_FORCE_OVERWRITE: true,
+ ANSIBLE_DOCTOR_EXCLUDE_FILES: "molecule/",
+ ANSIBLE_DOCTOR_CUSTOM_HEADER: "HEADER.md",
+ PY_COLORS: 1
+ },
+ },
+ {
+ name: "push-to-repo",
+ image: "plugins/git-action:latest",
+ settings: {
+ actions: ["commit", "push"],
+ author_email: "shipper@rknet.org",
+ author_name: "DroneShipper",
+ branch: "master",
+ message: "[SKIP CI] update readme",
+ remote: "https://gitea.rknet.org/ansible/xoxys.selinux",
+ netrc_machine: "gitea.rknet.org",
+ netrc_username: {"from_secret": "gitea_username"},
+ netrc_password: {"from_secret": "gitea_token"},
+ },
+ when: {
+ ref: ["refs/heads/master"],
+ },
+ },
+ ],
+ depends_on: [
+ "deployment",
+ ],
+ trigger: {
+ ref: ["refs/heads/master", "refs/tags/**", "refs/pull/**"],
+ },
+};
+
+local PipelineNotification= {
+ kind: "pipeline",
+ name: "notification",
+ platform: {
+ os: "linux",
+ arch: "amd64",
+ },
+ clone: {
+ disable: true,
+ },
+ steps: [
+ {
+ name: "matrix",
+ image: "plugins/matrix",
+ settings: {
+ homeserver: { "from_secret": "matrix_homeserver" },
+ roomid: { "from_secret": "matrix_roomid" },
+ template: "Status: **{{ build.status }}**
Build: [{{ repo.Owner }}/{{ repo.Name }}]({{ build.link }}) ({{ build.branch }}) by {{ build.author }}
Message: {{ build.message }}",
+ username: { "from_secret": "matrix_username" },
+ password: { "from_secret": "matrix_password" },
+ },
+ },
+ ],
+ depends_on: [
+ "documentation",
+ ],
+ trigger: {
+ status: [ "success", "failure" ],
+ ref: ["refs/heads/master", "refs/tags/**"],
+ },
+};
+
+[
+ PipelineLinting,
+ PipelineDeployment,
+ PipelineDocumentation,
+ PipelineNotification,
+]
diff --git a/.drone.yml b/.drone.yml
index 289d224..20b2f1d 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -1,22 +1,148 @@
---
kind: pipeline
-name: default
+name: linting
+
+platform:
+ os: linux
+ arch: amd64
steps:
- - name: ansible-latest
- image: python:2.7
- pull: always
- commands:
- - pip install ansible ansible-later -q
- - git clone https://gitea.rknet.org/ansible/ansible-later-policy.git ~/policy
- - git ls-files *[^LICENSE,.md] | xargs ansible-later -c ~/policy/config.ini
- depends_on: [ clone ]
+- name: ansible-later
+ image: xoxys/ansible-later:latest
+ commands:
+ - git clone https://gitea.rknet.org/ansible/ansible-later-policy.git ~/policy
+ - ansible-later -c ~/policy/config.yml
+ environment:
+ PY_COLORS: 1
- - name: ansible-master
- image: python:2.7
- pull: always
- commands:
- - pip install ansible ansible-later -q
- - git clone https://gitea.rknet.org/ansible/ansible-later-policy.git ~/policy
- - git ls-files *[^LICENSE,.md] | xargs ansible-later -c ~/policy/config.ini
- depends_on: [ clone ]
+trigger:
+ ref:
+ - refs/heads/master
+ - "refs/tags/**"
+ - "refs/pull/**"
+
+---
+kind: pipeline
+name: deployment
+
+platform:
+ os: linux
+ arch: amd64
+
+concurrency:
+ limit: 1
+
+workspace:
+ base: /drone/src
+ path: xoxys.selinux
+
+steps:
+- name: ansible-molecule
+ image: xoxys/molecule:do-linux-amd64
+ commands:
+ - /bin/bash /docker-entrypoint.sh
+ - molecule test -s default
+ environment:
+ DO_API_KEY:
+ from_secret: do_api_key
+ MOLECULE_CUSTOM_FILTERS_REPO: https://gitea.rknet.org/ansible/custom_filters
+ MOLECULE_CUSTOM_MODULES_REPO: https://gitea.rknet.org/ansible/custom_modules
+ PY_COLORS: 1
+ USER: root
+
+trigger:
+ ref:
+ - refs/heads/master
+ - "refs/tags/**"
+
+depends_on:
+- linting
+
+---
+kind: pipeline
+name: documentation
+
+platform:
+ os: linux
+ arch: amd64
+
+steps:
+- name: ansible-doctor
+ image: xoxys/ansible-doctor:latest
+ environment:
+ ANSIBLE_DOCTOR_CUSTOM_HEADER: HEADER.md
+ ANSIBLE_DOCTOR_EXCLUDE_FILES: molecule/
+ ANSIBLE_DOCTOR_FORCE_OVERWRITE: true
+ ANSIBLE_DOCTOR_LOG_LEVEL: INFO
+ PY_COLORS: 1
+
+- name: push-to-repo
+ image: plugins/git-action:latest
+ settings:
+ actions:
+ - commit
+ - push
+ author_email: "shipper@rknet.org"
+ author_name: DroneShipper
+ branch: master
+ message: "[SKIP CI] update readme"
+ netrc_machine: gitea.rknet.org
+ netrc_password:
+ from_secret: gitea_token
+ netrc_username:
+ from_secret: gitea_username
+ remote: https://gitea.rknet.org/ansible/xoxys.selinux
+ when:
+ ref:
+ - refs/heads/master
+
+trigger:
+ ref:
+ - refs/heads/master
+ - "refs/tags/**"
+ - "refs/pull/**"
+
+depends_on:
+- deployment
+
+---
+kind: pipeline
+name: notification
+
+platform:
+ os: linux
+ arch: amd64
+
+clone:
+ disable: true
+
+steps:
+- name: matrix
+ image: plugins/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 }}) ({{ build.branch }}) by {{ build.author }}
Message: {{ build.message }}"
+ username:
+ from_secret: matrix_username
+
+trigger:
+ ref:
+ - refs/heads/master
+ - "refs/tags/**"
+ status:
+ - success
+ - failure
+
+depends_on:
+- documentation
+
+---
+kind: signature
+hmac: 69ad928f610ab8de63aaa3f7837c7c1775a16ba374a8cee6f543128f62f805b1
+
+...
diff --git a/.gitignore b/.gitignore
index 5c199eb..5becda8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,11 @@
# ---> Ansible
*.retry
+filter/plugins/
+library
+
+# ---> Python
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
diff --git a/HEADER.md b/HEADER.md
new file mode 100644
index 0000000..5c68da7
--- /dev/null
+++ b/HEADER.md
@@ -0,0 +1,4 @@
+# xoxys.selinux
+
+[![Build Status](https://drone.rknet.org/api/badges/ansible/xoxys.selinux/status.svg)](https://drone.rknet.org/ansible/xoxys.selinux)
+
diff --git a/molecule/default/create.yml b/molecule/default/create.yml
new file mode 100644
index 0000000..41f112d
--- /dev/null
+++ b/molecule/default/create.yml
@@ -0,0 +1,87 @@
+---
+- name: Create
+ hosts: localhost
+ connection: local
+ gather_facts: false
+ no_log: "{{ molecule_no_log }}"
+ vars:
+ ssh_user: root
+ ssh_port: 22
+
+ keypair_name: molecule_key
+ keypair_path: "{{ lookup('env', 'MOLECULE_EPHEMERAL_DIRECTORY') }}/ssh_key"
+ tasks:
+ - name: Create local keypair
+ user:
+ name: "{{ lookup('env', 'USER') }}"
+ generate_ssh_key: true
+ ssh_key_file: "{{ keypair_path }}"
+ register: local_keypair
+
+ - name: Create remote keypair
+ digital_ocean_sshkey:
+ name: "{{ keypair_name }}"
+ ssh_pub_key: "{{ local_keypair.ssh_public_key }}"
+ state: present
+ register: remote_keypair
+
+ - name: Create molecule instance(s)
+ digital_ocean_droplet:
+ name: "{{ item.name }}"
+ unique_name: true
+ region: "{{ item.region_id }}"
+ image: "{{ item.image_id }}"
+ size: "{{ item.size_id }}"
+ ssh_keys: "{{ remote_keypair.data.ssh_key.id }}"
+ wait: true
+ wait_timeout: 300
+ 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: digitalocean_jobs
+ until: digitalocean_jobs.finished
+ retries: 300
+ loop: "{{ server.results }}"
+
+ # Mandatory configuration for Molecule to function.
+
+ - name: Populate instance config dict
+ set_fact:
+ instance_conf_dict: {
+ 'instance': "{{ item.data.droplet.name }}",
+ 'address': "{{ item.data.ip_address }}",
+ 'user': "{{ ssh_user }}",
+ 'port': "{{ ssh_port }}",
+ 'identity_file': "{{ keypair_path }}",
+ 'droplet_id': "{{ item.data.droplet.id }}",
+ 'ssh_key_id': "{{ remote_keypair.data.ssh_key.id }}",
+ }
+ loop: "{{ digitalocean_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: "{{ instance_conf | to_json | from_json | molecule_to_yaml | molecule_header }}"
+ 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
+ timeout: 320
+ loop: "{{ lookup('file', molecule_instance_config) | molecule_from_yaml }}"
diff --git a/molecule/default/destroy.yml b/molecule/default/destroy.yml
new file mode 100644
index 0000000..19c8c93
--- /dev/null
+++ b/molecule/default/destroy.yml
@@ -0,0 +1,54 @@
+---
+- name: Destroy
+ hosts: localhost
+ connection: local
+ gather_facts: false
+ no_log: "{{ molecule_no_log }}"
+ tasks:
+ - block:
+ - name: Populate instance config
+ set_fact:
+ instance_conf: "{{ lookup('file', molecule_instance_config) | molecule_from_yaml }}"
+ skip_instances: false
+ rescue:
+ - name: Populate instance config when file missing
+ set_fact:
+ instance_conf: {}
+ skip_instances: true
+
+ - name: Destroy molecule instance(s)
+ digital_ocean_droplet:
+ name: "{{ item.instance }}"
+ id: "{{ item.droplet_id }}"
+ state: absent
+ register: server
+ loop: "{{ instance_conf | flatten(levels=1) }}"
+ when: not skip_instances
+ async: 7200
+ poll: 0
+
+ - name: Wait for instance(s) deletion to complete
+ async_status:
+ jid: "{{ item.ansible_job_id }}"
+ register: digitalocean_jobs
+ until: digitalocean_jobs.finished
+ retries: 300
+ loop: "{{ server.results }}"
+
+ - name: Delete remote keypair
+ digital_ocean_sshkey:
+ fingerprint: "{{ item.ssh_key_id }}"
+ state: absent
+ loop: "{{ instance_conf | flatten(levels=1) }}"
+
+ # Mandatory configuration for Molecule to function.
+
+ - name: Populate instance config
+ set_fact:
+ instance_conf: {}
+
+ - name: Dump instance config
+ copy:
+ content: "{{ instance_conf | molecule_to_yaml | molecule_header }}"
+ dest: "{{ molecule_instance_config }}"
+ when: server.changed | bool
diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml
new file mode 100644
index 0000000..6f30baf
--- /dev/null
+++ b/molecule/default/molecule.yml
@@ -0,0 +1,22 @@
+---
+dependency:
+ name: galaxy
+driver:
+ name: digitalocean
+platforms:
+ - name: centos7-selinux
+ region_id: fra1
+ image_id: centos-7-x64
+ size_id: s-1vcpu-1gb
+lint:
+ name: yamllint
+ enabled: False
+provisioner:
+ name: ansible
+ lint:
+ name: ansible-lint
+ enabled: False
+verifier:
+ name: testinfra
+ lint:
+ name: flake8
diff --git a/molecule/default/playbook.yml b/molecule/default/playbook.yml
new file mode 100644
index 0000000..27a5ee7
--- /dev/null
+++ b/molecule/default/playbook.yml
@@ -0,0 +1,5 @@
+---
+- name: Converge
+ hosts: all
+ roles:
+ - role: xoxys.selinux
diff --git a/molecule/default/prepare.yml b/molecule/default/prepare.yml
new file mode 100644
index 0000000..4b18d48
--- /dev/null
+++ b/molecule/default/prepare.yml
@@ -0,0 +1,9 @@
+---
+- name: Prepare
+ hosts: all
+ gather_facts: false
+ tasks:
+ - name: Install python for Ansible
+ raw: test -e /usr/bin/python || (apt -y update && apt install -y python-minimal)
+ become: true
+ changed_when: false
diff --git a/molecule/default/tests/test_default.py b/molecule/default/tests/test_default.py
new file mode 100644
index 0000000..ea15d88
--- /dev/null
+++ b/molecule/default/tests/test_default.py
@@ -0,0 +1,14 @@
+import os
+
+import testinfra.utils.ansible_runner
+
+import warnings
+warnings.filterwarnings("ignore", category=DeprecationWarning)
+
+testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
+ os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')
+
+
+def test_selinux_setup(host):
+ assert host.command.check_output('/usr/sbin/getenforce') == 'Enforcing'
+ assert host.package('policycoreutils-python').is_installed
diff --git a/molecule/pytest.ini b/molecule/pytest.ini
new file mode 100644
index 0000000..c24fe5b
--- /dev/null
+++ b/molecule/pytest.ini
@@ -0,0 +1,3 @@
+[pytest]
+filterwarnings =
+ ignore::DeprecationWarning