bookstack working

authelia
chatton 2 years ago
parent b7754cad54
commit c320aadd0b

@ -60,7 +60,7 @@
"name": "plugins/modules/portainer_stack.py", "name": "plugins/modules/portainer_stack.py",
"ftype": "file", "ftype": "file",
"chksum_type": "sha256", "chksum_type": "sha256",
"chksum_sha256": "e75fa1655aed9c13955315a80aa9a3f0b54ac1bc386697756bb308e0cfe4ecbb", "chksum_sha256": "8f8c5a3fcefa02becec7dad10442e92db1b40dccdd43e297baa273a03f260105",
"format": 1 "format": 1
}, },
{ {

@ -23,7 +23,7 @@
"name": "FILES.json", "name": "FILES.json",
"ftype": "file", "ftype": "file",
"chksum_type": "sha256", "chksum_type": "sha256",
"chksum_sha256": "a3d632538c4fb62677f3dceb2b32648f6688932bfa4354ad1ad21ecd1e031a7d", "chksum_sha256": "df6db8314d203f2365d1ff4253d6d793197067dced93c835a6b88074c18d4921",
"format": 1 "format": 1
}, },
"format": 1 "format": 1

@ -16,6 +16,8 @@ except ImportError:
_query_params_to_string, _query_params_to_string,
) )
import yaml
DOCUMENTATION = r""" DOCUMENTATION = r"""
--- ---
module: portainer_stack module: portainer_stack
@ -117,17 +119,15 @@ def _create_stack(client, module, file_contents):
def _update_stack(client, module, stack_id): def _update_stack(client, module, stack_id):
target_stack_name = module.params["stack_name"] target_stack_name = module.params["stack_name"]
with open(module.params["docker_compose_file_path"]) as f: contents = _get_stack_contents(module.params)
file_contents = f.read()
return client.put( return client.put(
f"stacks/{stack_id}?&endpointId={client.endpoint}", f"stacks/{stack_id}?&endpointId={client.endpoint}",
body={ body={
"name": target_stack_name, "name": target_stack_name,
"stackFileContent": file_contents, "stackFileContent": contents,
}, },
) )
def handle_state_present(client, module): def handle_state_present(client, module):
result = dict(changed=False, stack_name=module.params["stack_name"]) result = dict(changed=False, stack_name=module.params["stack_name"])
@ -135,8 +135,7 @@ def handle_state_present(client, module):
stacks = client.get("stacks") stacks = client.get("stacks")
result["stacks"] = stacks result["stacks"] = stacks
with open(module.params["docker_compose_file_path"]) as f: contents = _get_stack_contents(module.params)
file_contents = f.read()
target_stack_name = module.params["stack_name"] target_stack_name = module.params["stack_name"]
for stack in stacks: for stack in stacks:
@ -146,7 +145,7 @@ def handle_state_present(client, module):
break break
if not already_exists: if not already_exists:
stack = _create_stack(client, module, file_contents) stack = _create_stack(client, module, contents)
result["changed"] = True result["changed"] = True
result["stack_id"] = stack["Id"] result["stack_id"] = stack["Id"]
module.exit_json(**result) module.exit_json(**result)
@ -158,7 +157,7 @@ def handle_state_present(client, module):
) )
result["are_equal"] = ( result["are_equal"] = (
current_file_contents_resp["StackFileContent"] == file_contents current_file_contents_resp["StackFileContent"] == contents
) )
if result["are_equal"]: if result["are_equal"]:
module.exit_json(**result) module.exit_json(**result)
@ -191,13 +190,22 @@ def handle_state_absent(client, module):
) )
result["changed"] = True result["changed"] = True
module.exit_json(**result) module.exit_json(**result)
def _get_stack_contents(params):
if params.get("docker_compose_file_path"):
with open(params["docker_compose_file_path"]) as f:
return f.read()
if params.get("definition"):
return yaml.dump(params["definition"], indent=4)
raise ValueError("No docker_compose_file_path or definition provided.")
def run_module(): def run_module():
# define available arguments/parameters a user can pass to the module # define available arguments/parameters a user can pass to the module
module_args = dict( module_args = dict(
stack_name=dict(type="str", required=True), stack_name=dict(type="str", required=True),
docker_compose_file_path=dict(type="str"), docker_compose_file_path=dict(type="str"),
definition=dict(type=dict),
username=dict(type="str", default="admin"), username=dict(type="str", default="admin"),
password=dict(type="str", required=True, no_log=True), password=dict(type="str", required=True, no_log=True),
endpoint_id=dict(type="int", required=True), endpoint_id=dict(type="int", required=True),
@ -205,11 +213,6 @@ def run_module():
state=dict(type="str", default="present", choices=["present", "absent"]), state=dict(type="str", default="present", choices=["present", "absent"]),
) )
required_if = [
# docker compose file is only required if we are ensuring the stack is present.
["state", "present", ("docker_compose_file_path",)],
]
state_fns = {"present": handle_state_present, "absent": handle_state_absent} state_fns = {"present": handle_state_present, "absent": handle_state_absent}
# the AnsibleModule object will be our abstraction working with Ansible # the AnsibleModule object will be our abstraction working with Ansible
@ -218,7 +221,16 @@ def run_module():
# supports check mode # supports check mode
module = AnsibleModule( module = AnsibleModule(
argument_spec=module_args, argument_spec=module_args,
required_if=required_if, # required_if = [
# docker compose file is only required if we are ensuring the stack is present.
# ["state", "present", ("docker_compose_file_path",)],
# ],
mutually_exclusive=[
('docker_compose_file_path', 'definition'),
],
required_one_of=[
('docker_compose_file_path', 'definition'),
],
# TODO: support check mode # TODO: support check mode
supports_check_mode=False, supports_check_mode=False,
) )

@ -55,13 +55,26 @@
- role: setup_compose_services - role: setup_compose_services
tags: [compose] tags: [compose]
- name: Setup and deploy portainer services.
hosts: servers - name: Setup and deploy portainer services (snunmu).
hosts: snunmu
become: true become: true
pre_tasks: pre_tasks:
- name: Include vault variables. - name: Include vault variables.
ansible.builtin.include_vars: '../{{ vault_file }}' ansible.builtin.include_vars: '../{{ vault_file }}'
tags: [always] tags: [always]
roles: roles:
- role: setup_hosted_services - role: portainer_bookstack
tags: [services] tags: [services]
#- name: Setup and deploy portainer services.
# hosts: servers
# become: true
# pre_tasks:
# - name: Include vault variables.
# ansible.builtin.include_vars: '../{{ vault_file }}'
# tags: [always]
# roles:
# - role: setup_hosted_services
# tags: [services]

@ -8,7 +8,7 @@ roles:
collections: collections:
- name: https://github.com/chatton/ansible-portainer.git - name: https://github.com/chatton/ansible-portainer.git
type: git type: git
version: master version: support_definition
- name: https://github.com/chatton/ansible-docker-backup.git - name: https://github.com/chatton/ansible-docker-backup.git
type: git type: git
version: master version: master

@ -0,0 +1,18 @@
---
bookstack_image: linuxserver/bookstack
bookstack_tag: 23.06.1
bookstack_backup_enabled: true
bookstack_backup_schedule: "nightly"
bookstack_puid: 1000
bookstack_pgid: 1000
bookstack_db_host: qnap
bookstack_database: bookstackapp
bookstack_db_user: bookstack
bookstack_app_url: https://bookstack.cianhatton.ie
bookstack_expose_port: 6875
bookstack_restart_policy: unless-stopped
bookstack_container_name: bookstack
bookstack_portainer_stack_name: bookstack
bookstack_docker_backup_restore_force: false
bookstack_docker_backup_restore_latest_s3_key: true
bookstack_docker_backup_fail_on_no_s3_backups: false

@ -0,0 +1,43 @@
---
- name: "Bookstack | Restore any missing volumes from S3"
ansible.builtin.include_role:
name: chatton.docker_backup.docker_s3_volume_restore
vars:
docker_backup_restore_force: "{{ bookstack_docker_backup_restore_force }}"
docker_backup_restore_latest_s3_key: "{{ bookstack_docker_backup_restore_latest_s3_key }}"
docker_backup_fail_on_no_s3_backups: "{{ bookstack_docker_backup_fail_on_no_s3_backups }}"
docker_backup_s3_volume:
name: "{{ bookstack_portainer_stack_name }}_config"
- name: "Bookstack | Update Portainer."
chatton.portainer.portainer_stack:
username: admin
password: '{{ portainer.password }}'
base_url: '{{ portainer_base_url }}'
stack_name: '{{ bookstack_portainer_stack_name }}'
endpoint_id: '{{ portainer_endpoint }}'
state: present
definition:
version: "3.1"
services:
bookstack:
labels:
ie.cianhatton.backup.enabled: "{{ bookstack_backup_enabled }}"
ie.cianhatton.backup.schedule: "{{ bookstack_backup_schedule }}"
image: "{{ bookstack_image }}:{{ bookstack_tag }}"
container_name: "{{ bookstack_container_name }}"
environment:
- PUID={{ bookstack_puid }}
- PGID={{ bookstack_pgid }}
- DB_HOST={{ bookstack_db_host }}
- DB_USER={{ bookstack_db_user }}
- DB_PASS={{ bookstack_password }}
- DB_DATABASE={{ bookstack_database }}
- APP_URL={{ bookstack_app_url }}
volumes:
- config:/config"
ports:
- "{{ bookstack_expose_port }}:80"
restart: "{{ bookstack_restart_policy }}"
volumes:
config: {}
Loading…
Cancel
Save