Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

* **role:wordpress**: Entries in `wordpress__plugins` accept `enabled: false`, which keeps a plugin installed but deactivated.
* **role:system_update**: The role's inventory variables are type-checked when it starts, so a mistyped value fails the run right away instead of surfacing further in as a confusing error.
* **role:wordpress**: Several WordPress instances can share a host as pseudo hosts in the inventory, under different host names as well as under different paths of one host name, such as `https://example.com/blog`.
* **role:fail2ban**: The `wordpress-login` filter and `z10-wordpress-login` jail ban IPs with too many failed WordPress logins, on the host whose Apache logs the visitor's address.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@ wordpress__admin_user:
wordpress__database_user:
username: 'wordpress'
password: 'linuxfabrik'
# One plugin to install and one that is absent and was never installed, so the install, the
# uninstall and their change detection all run, together with a theme.
# One plugin to install, one that is absent and was never installed, and one installed but
# deactivated, so the install, the uninstall, the deactivation and their change detection all
# run, together with a theme.
wordpress__plugins:
- name: 'hello-dolly'
state: 'present'
- name: 'akismet'
state: 'absent'
- name: 'classic-editor'
enabled: false
state: 'present'
wordpress__site_title: 'Molecule'
wordpress__theme: 'twentytwentyfive'
# 127.0.0.1 stands in for the reverse proxy: verify.yml sends requests with X-Forwarded-* headers
Expand Down
12 changes: 11 additions & 1 deletion extensions/molecule/setup_wordpress/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@
register: '__molecule__wordpress_plugins_result'
changed_when: false

- name: 'wp plugin list --status=inactive --field=name'
ansible.builtin.command: '/usr/local/bin/wp plugin list --status=inactive --field=name --path={{ __molecule__wordpress_dir }}'
args:
chdir: '{{ __molecule__wordpress_dir }}'
become_user: 'apache'
register: '__molecule__wordpress_inactive_plugins_result'
changed_when: false

- name: 'wp theme list --status=active --field=name'
ansible.builtin.command: '/usr/local/bin/wp theme list --status=active --field=name --path={{ __molecule__wordpress_dir }}'
args:
Expand All @@ -59,8 +67,10 @@
- '"disable-json-api" not in __molecule__wordpress_plugins_result["stdout_lines"]'
- '"hello-dolly" in __molecule__wordpress_plugins_result["stdout_lines"]'
- '"akismet" not in __molecule__wordpress_plugins_result["stdout_lines"]'
- '"akismet" not in __molecule__wordpress_inactive_plugins_result["stdout_lines"]'
- '"classic-editor" in __molecule__wordpress_inactive_plugins_result["stdout_lines"]'
- '__molecule__wordpress_theme_result["stdout_lines"] == [wordpress__theme]'
fail_msg: 'active plugins: {{ __molecule__wordpress_plugins_result["stdout_lines"] }}, active theme: {{ __molecule__wordpress_theme_result["stdout_lines"] }}'
fail_msg: 'active plugins: {{ __molecule__wordpress_plugins_result["stdout_lines"] }}, inactive plugins: {{ __molecule__wordpress_inactive_plugins_result["stdout_lines"] }}, active theme: {{ __molecule__wordpress_theme_result["stdout_lines"] }}'

# --url sets HTTPS for WP-CLI, which application passwords require before any filter applies
- name: 'wp eval wp_is_application_passwords_available()'
Expand Down
10 changes: 9 additions & 1 deletion roles/wordpress/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ wordpress__url: 'https://wordpress.example.com'

`wordpress__plugins`

* List of WordPress plugin slugs. To get a list of already installed plugins, use the WordPress CLI `sudo -u apache /usr/local/bin/wp plugin list --status=active`.
* List of WordPress plugin slugs. To get a list of already installed plugins and whether they are active, use the WordPress CLI `sudo -u apache /usr/local/bin/wp plugin list`.
* Type: List of dictionaries.
* Default: `[]`
* Subkeys:
Expand All @@ -211,6 +211,12 @@ wordpress__url: 'https://wordpress.example.com'
* Mandatory. Plugin slug, path to a local zip file, or URL to a remote zip file.
* Type: String.

* `enabled`:

* Optional. Activates the plugin (`true`) or keeps it installed but deactivated (`false`). With `false`, `name` has to be the plugin slug, since WP-CLI cannot deactivate a plugin by the path or URL of its zip file.
* Type: Bool.
* Default: `true`

* `state`:

* Optional. Either `'present'` or `'absent'`.
Expand Down Expand Up @@ -262,6 +268,8 @@ wordpress__plugins:
state: 'present'
- name: 'Akismet'
state: 'absent'
- name: 'classic-editor'
enabled: false
wordpress__theme: 'twentysixteen'
wordpress__timer_core_minor_update_enabled: true
wordpress__trusted_proxies:
Expand Down
2 changes: 1 addition & 1 deletion roles/wordpress/meta/argument_specs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ argument_specs:
elements: 'dict'
required: false
default: []
description: 'WordPress plugins to install or remove.'
description: 'WordPress plugins to install, remove, activate or deactivate.'

wordpress__site_title:
type: 'str'
Expand Down
24 changes: 22 additions & 2 deletions roles/wordpress/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,11 @@
changed_when: '__wordpress__plugin_uninstall_result["rc"] == 0'
when: 'item["state"] | d("present") == "absent"'
loop: '{{ wordpress__plugins }}'
loop_control:
label: '{{ item["name"] }}'

- name: 'wp plugin install --url={{ wordpress__url | quote }} {{ item["name"] | lower | quote }} --activate'
ansible.builtin.command: '/usr/local/bin/wp plugin install --url={{ wordpress__url | quote }} {{ item["name"] | lower | quote }} --activate'
- name: 'wp plugin install --url={{ wordpress__url | quote }} {{ item["name"] | lower | quote }}{{ (item["enabled"] | d(true) | bool) | ternary(" --activate", "") }}'
ansible.builtin.command: '/usr/local/bin/wp plugin install --url={{ wordpress__url | quote }} {{ item["name"] | lower | quote }}{{ (item["enabled"] | d(true) | bool) | ternary(" --activate", "") }}'
args:
chdir: '{{ wordpress__install_dir }}'
become: true
Expand All @@ -151,6 +153,24 @@
or "activated." in __wordpress__plugin_install_result["stdout"]'
when: 'item["state"] | d("present") != "absent"'
loop: '{{ wordpress__plugins }}'
loop_control:
label: '{{ item["name"] }}'

- name: 'wp plugin deactivate --url={{ wordpress__url | quote }} {{ item["name"] | lower | quote }}'
ansible.builtin.command: '/usr/local/bin/wp plugin deactivate --url={{ wordpress__url | quote }} {{ item["name"] | lower | quote }}'
args:
chdir: '{{ wordpress__install_dir }}'
become: true
become_user: 'apache'
register: '__wordpress__plugin_deactivate_result'
# WP-CLI prints "Plugin already deactivated." for a plugin that is not active
changed_when: '"Plugin already deactivated." not in __wordpress__plugin_deactivate_result["stdout"]'
when:
- 'item["state"] | d("present") != "absent"'
- 'not item["enabled"] | d(true) | bool'
loop: '{{ wordpress__plugins }}'
loop_control:
label: '{{ item["name"] }}'

- name: 'wp theme install --url={{ wordpress__url | quote }} {{ wordpress__theme | quote }} --activate'
ansible.builtin.command: '/usr/local/bin/wp theme install --url={{ wordpress__url | quote }} {{ wordpress__theme | quote }} --activate'
Expand Down
Loading