Skip to content

Commit

Permalink
Merge pull request #3 from zstyblik/dev
Browse files Browse the repository at this point in the history
Fixes, adjustments and deployment of conf files
  • Loading branch information
zstyblik authored Aug 5, 2024
2 parents 54f28e5 + 6af5d40 commit 157ee2b
Show file tree
Hide file tree
Showing 10 changed files with 234 additions and 112 deletions.
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,26 @@ I might add support for some other OS, if and when I'm bored.
* allow to enable/disable config files
* allow to enable/disable modules

#### Known limitations

##### Ports

* if there are no virtual hosts, httpd should listen at port 80 and 443 as is
by default in Debian.
* ports are generated **ONLY** from managed(defined) virtual hosts. There is
currently no way around this.

##### Virtual Hosts

Virtual host filename is assembled from priority, protocol and servername. If
any of these change, new filename will be created and the old one will be left
behind since unmanaged stuff is left alone. This is kind of suboptimal.

One way around this is either duplicate the whole virtual host configuration or
create a minimal stub with identical combination of port, servername and
ssl/no-ssl and `state: absent`. Then the former virtual host should get
disabled and new one deployed.

## Requirements

None.
Expand Down Expand Up @@ -83,10 +103,16 @@ There are no extra dependencies as far as Ansible goes.
apache_mods:
- name: rewrite
state: present
- name: ssl
conf_content: |
SSLProtocol all -SSLv2 -SSLv3 -TLSv1
apache_confs:
- name: serve-cgi-bin
state: absent
- name: my_config
conf_content: |
TraceEnable On
roles:
- role: zstyblik.apache
```
Expand Down
9 changes: 6 additions & 3 deletions action_plugins/apache_ports_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ def run(self, tmp=None, task_vars=None):

vhosts = self._task.args.get("vhosts", [])
if not vhosts:
vhosts = [{"listen_ip": "", "port": 80, "ssl": False}]
vhosts = [
{"listen_ip": "", "port": 80, "ssl": {}},
{"listen_ip": "", "port": 443, "ssl": {}},
]

# Ref. https://httpd.apache.org/docs/2.4/bind.html
# Structure:
Expand Down Expand Up @@ -84,10 +87,10 @@ def run(self, tmp=None, task_vars=None):
if port not in bindings:
bindings[port] = {}

ssl = vhost.get("ssl", False)
ssl = vhost.get("ssl", {})
# According to documentation, https is default proto for port 443.
# Therefore there is no need to specify it.
if ssl is True and port != 443:
if ssl and port != 443:
ssl = "https"
else:
ssl = ""
Expand Down
11 changes: 10 additions & 1 deletion defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,24 @@ apache_vhosts:
# Only used on Debian/Ubuntu.
# Example:
# apache_mods:
# - name: rewrite
# - name: ssl
# state: present
# # Create or overwrite .conf file with the following content.
# # This can be used to override/neuter default mod configuration.
# conf_content: |
# SSLProtocol all -SSLv2 -SSLv3 -TLSv1
apache_mods: []

# Only used on Debian/Ubuntu.
# Example:
# apache_confs:
# - name: trace
# state: absent
# - name: my_config
# state: present
# # Create or overwrite .conf file with the following content.
# conf_content: |
# TraceEnable On
apache_confs: []

# httpd.conf
Expand Down
4 changes: 2 additions & 2 deletions filter_plugins/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@ def parse_a2query(stdout):
def to_vhost_filename(vhost):
"""Turn apache_vhost item(dict) into a filename."""
try:
priority = int(vhost.get("priority", 25))
priority = int(vhost.get("priority", 200))
if "ssl" in vhost and vhost["ssl"]:
proto = "https"
else:
proto = "http"

servername = vhost["servername"]
result = "{:d}-{:s}_{:s}".format(priority, proto, servername)
result = "{:03d}-{:s}_{:s}".format(priority, proto, servername)
except Exception as exception:
raise AnsibleFilterError(
"to_vhost_filename - {:s}".format(to_native(exception)),
Expand Down
20 changes: 20 additions & 0 deletions specs/apache_conf_argument_specs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
%YAML 1.2
---
argument_specs:
apache_conf_item:
short_description: Specification of Apache httpd conf/module item.
description: Specification of Apache httpd conf/module item.
options:
name:
description: Name of Apache's httpd configuration file(fragment).
required: true
type: str
state:
description: State of configuration file - present, absent etc.
required: false
type: str
choices: ['present', 'absent', 'purged']
conf_content:
description: Content of configuration file itself.
required: false
type: str
85 changes: 14 additions & 71 deletions tasks/configure-Debian.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,81 +104,22 @@
ansible.builtin.set_fact:
_apache_a2q_confs: "{{ _apache_cmd_a2q_confs.stdout_lines | parse_a2query }}"

# NOTE(zstyblik): run a2en* regardless
# re-add check "is in a2q STDOUT", if necessary to save cycles.
- name: Enable desired Apache confs.
ansible.builtin.command:
argv:
- /usr/sbin/a2enconf
- -q
- "{{ item.name }}"
register: _apache_cmd_a2enconf
changed_when: "'To activate the new configuration' in _apache_cmd_a2enconf.stdout_lines"
failed_when: _apache_cmd_a2enconf.rc != 0
loop: "{{ apache_confs }}"
loop_control:
label: "{{ item.name }}"
when:
- item.state | default('present') == 'present'
notify: restart apache
become: true

- name: Disable desired Apache confs.
ansible.builtin.command:
argv:
- /usr/sbin/a2disconf
- -q
- "{{ item.name }}"
register: _apache_cmd_a2disconf
changed_when: "'To activate the new configuration' in _apache_cmd_a2disconf.stdout_lines"
failed_when: _apache_cmd_a2disconf.rc != 0
- name: Configure Apache configuration files(fragment).
ansible.builtin.include_tasks:
file: configure-conf-file.yml
loop: "{{ apache_confs }}"
loop_control:
label: "{{ item.name }}"
when:
- item.state | default('present') != 'present'
- item.name in _apache_a2q_confs
notify: restart apache
become: true
label: "{{ _apache_conf_item.name | default('unknown') }}"
loop_var: _apache_conf_item

# Apache mods
# NOTE(zstyblik): run a2en* regardless
# re-add check "is in a2q STDOUT", if necessary to save cycles.
- name: Enable desired Apache mods.
ansible.builtin.command:
argv:
- /usr/sbin/a2enmod
- -q
- "{{ item.name }}"
register: _apache_cmd_a2enmod
changed_when: "'To activate the new configuration' in _apache_cmd_a2enmod.stdout_lines"
failed_when: _apache_cmd_a2enmod.rc != 0
loop: "{{ apache_mods }}"
loop_control:
label: "{{ item.name }}"
when:
- item.state | default('present') == 'present'
notify: restart apache
become: true

- name: Disable desired Apache mods.
ansible.builtin.command:
argv:
- /usr/sbin/a2dismod
- -q
- "{{ item.name }}"
register: _apache_cmd_a2dismod
changed_when: "'To activate the new configuration' in _apache_cmd_a2dismod.stdout_lines"
failed_when: _apache_cmd_a2dismod.rc != 0
- name: Configure Apache modules.
ansible.builtin.include_tasks:
file: configure-mod-file.yml
loop: "{{ apache_mods }}"
loop_control:
label: "{{ item.name }}"
when:
- item.state | default('present') != 'present'
- item.name in _apache_a2q_mods
- item.name != _apache_mpm_module
notify: restart apache
become: true
label: "{{ _apache_mod_item.name | default('unknown') }}"
loop_var: _apache_mod_item

# Apache vhosts
- name: Get list of enabled Apache sites.
Expand All @@ -190,7 +131,7 @@
changed_when: false
failed_when:
- _apache_cmd_a2q_sites.rc != 0
- _apache_cmd_a2q_sites.rc != 32
- "'No site matches' not in _apache_cmd_a2q_sites.stderr"
become: true

- name: Parse enabled sites from a2query's output.
Expand Down Expand Up @@ -274,7 +215,9 @@
- "{{ apache_default_vhost_filename }}"
register: _apache_cmd_a2dissite_default
changed_when: "'To activate the new configuration' in _apache_cmd_a2dissite_default.stdout_lines"
failed_when: _apache_cmd_a2dissite_default.rc != 0
failed_when:
- _apache_cmd_a2dissite_default.rc != 0
- "_apache_cmd_a2dissite_default.stderr is not search('ERROR: Site .+ does not exist!')"
when:
- apache_remove_default_vhost is true
- apache_default_vhost_filename is defined
Expand Down
56 changes: 56 additions & 0 deletions tasks/configure-conf-file.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
- name: Check conf configuration against spec file
ansible.builtin.validate_argument_spec:
argument_spec: |
{{
(
lookup(
'ansible.builtin.file',
'specs/apache_conf_argument_specs.yml'
) | from_yaml
)['argument_specs']['apache_conf_item']['options']
}}
provided_arguments: "{{ _apache_conf_item }}"

- name: Create Apache config file.
ansible.builtin.copy:
content: "{{ _apache_conf_item.conf_content }}"
dest: "{{ apache_httpd_conf_load_dir }}/{{ _apache_conf_item.name }}.conf"
owner: root
group: root
mode: '0644'
when:
- _apache_conf_item.state | default('present') == 'present'
- _apache_conf_item.conf_content is defined
become: true

# NOTE(zstyblik): run a2en* regardless
# re-add check "is in a2q STDOUT", if necessary to save cycles.
- name: Enable Apache config file.
ansible.builtin.command:
argv:
- /usr/sbin/a2enconf
- -q
- "{{ _apache_conf_item.name }}"
register: _apache_cmd_a2enconf
changed_when: "'To activate the new configuration' in _apache_cmd_a2enconf.stdout_lines"
failed_when: _apache_cmd_a2enconf.rc != 0
when:
- _apache_conf_item.state | default('present') == 'present'
notify: restart apache
become: true

- name: Disable Apache config file.
ansible.builtin.command:
argv:
- /usr/sbin/a2disconf
- -q
- "{{ _apache_conf_item.name }}"
register: _apache_cmd_a2disconf
changed_when: "'To activate the new configuration' in _apache_cmd_a2disconf.stdout_lines"
failed_when: _apache_cmd_a2disconf.rc != 0
when:
- _apache_conf_item.state | default('present') != 'present'
- _apache_conf_item.name in _apache_a2q_confs
notify: restart apache
become: true
57 changes: 57 additions & 0 deletions tasks/configure-mod-file.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
- name: Check mod configuration against spec file
ansible.builtin.validate_argument_spec:
argument_spec: |
{{
(
lookup(
'ansible.builtin.file',
'specs/apache_conf_argument_specs.yml'
) | from_yaml
)['argument_specs']['apache_conf_item']['options']
}}
provided_arguments: "{{ _apache_mod_item }}"

- name: Create config file for Apache module.
ansible.builtin.copy:
content: "{{ _apache_mod_item.conf_content }}"
dest: "{{ apache_httpd_mod_load_dir }}/{{ _apache_mod_item.name }}.conf"
owner: root
group: root
mode: '0644'
when:
- _apache_mod_item.state | default('present') == 'present'
- _apache_mod_item.conf_content is defined
become: true

# NOTE(zstyblik): run a2en* regardless
# re-add check "is in a2q STDOUT", if necessary to save cycles.
- name: Enable Apache module.
ansible.builtin.command:
argv:
- /usr/sbin/a2enmod
- -q
- "{{ _apache_mod_item.name }}"
register: _apache_cmd_a2enmod
changed_when: "'To activate the new configuration' in _apache_cmd_a2enmod.stdout_lines"
failed_when: _apache_cmd_a2enmod.rc != 0
when:
- _apache_mod_item.state | default('present') == 'present'
notify: restart apache
become: true

- name: Disable Apache module.
ansible.builtin.command:
argv:
- /usr/sbin/a2dismod
- -q
- "{{ _apache_mod_item.name }}"
register: _apache_cmd_a2dismod
changed_when: "'To activate the new configuration' in _apache_cmd_a2dismod.stdout_lines"
failed_when: _apache_cmd_a2dismod.rc != 0
when:
- _apache_mod_item.state | default('present') != 'present'
- _apache_mod_item.name in _apache_a2q_mods
- _apache_mod_item.name != _apache_mpm_module
notify: restart apache
become: true
Loading

0 comments on commit 157ee2b

Please sign in to comment.