Compare commits
	
		
			11 Commits
		
	
	
		
			0.1.0
			...
			e7af228f06
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| e7af228f06 | |||
| bff5cce7e9 | |||
| 2edb0eae52 | |||
| 7c2f8277a7 | |||
| 96de942f51 | |||
| 6625557bfa | |||
| 9b3af2f6d4 | |||
| f2aa516b13 | |||
| 39fed04d33 | |||
| 383a89aef7 | |||
| ccc4f52d56 | 
							
								
								
									
										11
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								README.md
									
									
									
									
									
								
							| @@ -4,5 +4,16 @@ | ||||
|  | ||||
| - [`elasticsearch`](roles/elasticsearch/README.md): deploy | ||||
|   elasticsearch (OSS) in a docker container | ||||
|  | ||||
| - [`redis`](roles/redis/README.md): deploy and configure redis, | ||||
|   a fast cache, vector search and NoSQL database. | ||||
|  | ||||
| - [`mariadb`](roles/mariadb/README.md): deploy mariadb | ||||
|   in a docker container | ||||
|  | ||||
| - [`postgresql`](roles/postgresql/README.md): deploy postgresql, | ||||
|   the worlds most advances open-source relational database | ||||
|  | ||||
| - [`valkey`](roles/valkey/README.md): deploy and configure valkey, | ||||
|   an open source in-memory data store under BSD license, forked | ||||
|   from redis. | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| namespace: finallycoffee | ||||
| name: databases | ||||
| version: 0.1.0 | ||||
| version: 0.1.1 | ||||
| readme: README.md | ||||
| authors: | ||||
| - transcaffeine <transcaffeine@finally.coffee> | ||||
| @@ -14,5 +14,9 @@ repository: https://git.finally.coffee/finallycoffee/databases | ||||
| issues: https://codeberg.org/finallycoffee/ansible-collection-databases/issues | ||||
| tags: | ||||
|   - elasticsearch | ||||
|   - redis | ||||
|   - mariadb | ||||
|   - postgresql | ||||
|   - postgres | ||||
|   - valkey | ||||
|   - docker | ||||
|   | ||||
							
								
								
									
										6
									
								
								playbooks/postgresql.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								playbooks/postgresql.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| --- | ||||
| - name: Deploy and configure PostgreSQL | ||||
|   hosts: "{{ postgresql_hosts | default('postgresql', true) }}" | ||||
|   become: "{{ postgresql_become | default(true, true) }}" | ||||
|   roles: | ||||
|     - role: finallycoffee.databases.postgresql | ||||
							
								
								
									
										6
									
								
								playbooks/valkey.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								playbooks/valkey.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| --- | ||||
| - name: Deploy and configure valkey | ||||
|   hosts: "{{ valkey_hosts | default('valkey', true) }}" | ||||
|   become: "{{ valkey_become | default(true, true) }}" | ||||
|   roles: | ||||
|     - finallycoffee.databases.valkey | ||||
| @@ -1,5 +1,5 @@ | ||||
| --- | ||||
| elasticsearch_version: 8.15.3 | ||||
| elasticsearch_version: "8.17.0" | ||||
| elasticsearch_state: present | ||||
|  | ||||
| elasticsearch_base_path: /opt/elasticsearch | ||||
|   | ||||
| @@ -34,6 +34,5 @@ | ||||
|     volumes: "{{ elasticsearch_container_volumes }}" | ||||
|     ulimits: "{{ elasticsearch_container_ulimits }}" | ||||
|     networks: "{{ elasticsearch_container_networks | default(omit, True) }}" | ||||
|     purge_networks: "{{ elasticsearch_container_purge_networks | default(omit, True) }}" | ||||
|     restart_policy: "{{ elasticsearch_container_restart_policy }}" | ||||
|     state: "{{ elasticsearch_container_state }}" | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| --- | ||||
| mariadb_version: "10.11.9" | ||||
| mariadb_version: "10.11.10" | ||||
| mariadb_base_path: /var/lib/mariadb | ||||
| mariadb_data_path: >-2 | ||||
|   {{ mariadb_base_path }}/{{ mariadb_version | split('.') | first }} | ||||
|   | ||||
| @@ -16,6 +16,5 @@ | ||||
|     volumes: "{{ mariadb_container_volumes }}" | ||||
|     networks: "{{ mariadb_container_networks | default(omit, true) }}" | ||||
|     etc_hosts: "{{ mariadb_container_etc_hosts | default(omit, true) }}" | ||||
|     purge_networks: "{{ mariadb_container_purge_networks | default(omit, true) }}" | ||||
|     restart_policy: "{{ mariadb_container_restart_policy }}" | ||||
|     state: "{{ mariadb_container_state }}" | ||||
|   | ||||
							
								
								
									
										4
									
								
								roles/postgresql/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								roles/postgresql/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| # `finallycoffee.databases.postgresql` ansible role | ||||
|  | ||||
| PostgreSQL is the self proclaimed "world's most advanced" open source relational | ||||
| database. This ansible role can deploy and configure postgresql. | ||||
							
								
								
									
										39
									
								
								roles/postgresql/defaults/main/container.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								roles/postgresql/defaults/main/container.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| --- | ||||
| postgresql_container_image_registry: docker.io | ||||
| postgresql_container_image_namespace: ~ | ||||
| postgresql_container_image_name: postgres | ||||
| postgresql_container_image_tag: ~ | ||||
| postgresql_container_image_source: pull | ||||
| postgresql_container_image_force_source: >-2 | ||||
|   {{ postgresql_container_image_tag | default(false, true) | bool }} | ||||
| postgresql_container_image: >-2 | ||||
|   {{ | ||||
|     ([ | ||||
|       postgresql_container_image_registry | default([], true), | ||||
|       postgresql_container_image_namespace | default([], true), | ||||
|       postgresql_container_image_name | ||||
|     ] | flatten | join('/')) | ||||
|     + ':' + postgresql_container_image_tag | default( | ||||
|       postgresql_version + ( | ||||
|         ((postgresql_container_image_flavour is string) | ||||
|           and (postgresql_container_image_flavour | length > 0)) | ||||
|         | ternary( | ||||
|           '_' + postgresql_container_image_flavour | default('', true), | ||||
|           '', | ||||
|         ) | ||||
|       ), | ||||
|       true | ||||
|     ) | ||||
|   }} | ||||
|  | ||||
| postgresql_container_name: "postgresql-{{ postgresql_major_version }}" | ||||
| postgresql_container_env: ~ | ||||
| postgresql_container_user: >-2 | ||||
|   {{ postgresql_user_id }}:{{ postgresql_user_group_id }} | ||||
| postgresql_container_ports: ~ | ||||
| postgresql_container_labels: ~ | ||||
| postgresql_container_networks: ~ | ||||
| postgresql_container_recreate: ~ | ||||
| postgresql_container_restart_policy: "on-failure" | ||||
| postgresql_container_state: >-2 | ||||
|   {{ (postgresql_state == 'present') | ternary('started', 'absent') }} | ||||
							
								
								
									
										18
									
								
								roles/postgresql/defaults/main/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								roles/postgresql/defaults/main/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| --- | ||||
| postgresql_user: postgresql | ||||
| postgresql_version: >-2 | ||||
|   {{ postgresql_version[postgres_major_version | string] }} | ||||
| postgresql_major_version: 16 | ||||
| postgresql_versions: | ||||
|   "17": "17.2" | ||||
|   "16": "16.6" | ||||
|   "15": "15.10" | ||||
|   "14": "14.15" | ||||
|  | ||||
| postgresql_config_path: >-2 | ||||
|   /etc/postgresql/{{ postgresql_major_version }} | ||||
| postgresql_data_path: >-2 | ||||
|   /var/lib/postgresql/{{ postgresql_major_version }} | ||||
|  | ||||
| postgresql_state: present | ||||
| postgresql_deployment_method: docker | ||||
							
								
								
									
										10
									
								
								roles/postgresql/defaults/main/user.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								roles/postgresql/defaults/main/user.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| --- | ||||
| postgresql_user_system: true | ||||
| postgresql_user_create_home: false | ||||
| postgresql_user_groups: ~ | ||||
| postgresql_user_append: ~ | ||||
|  | ||||
| postgresql_user_id: >-2 | ||||
|   {{ postgresql_user_info.uid | default(postgresql_user, true) }} | ||||
| postgresql_user_group_id: >-2 | ||||
|   {{ postgresql_user_info.group | default(postgresql_user, true) }} | ||||
							
								
								
									
										12
									
								
								roles/postgresql/meta/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								roles/postgresql/meta/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| --- | ||||
| allow_duplicates: true | ||||
| dependencies: [] | ||||
| galaxy_info: | ||||
|   role_name: postgresql | ||||
|   description: >-2 | ||||
|     PostgreSQL is the self-proclaimed 'worlds most advanced' open source relational database | ||||
|   galaxy_tags: | ||||
|     - postgresql | ||||
|     - postgres | ||||
|     - database | ||||
|     - docker | ||||
							
								
								
									
										23
									
								
								roles/postgresql/tasks/deploy-docker.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								roles/postgresql/tasks/deploy-docker.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| --- | ||||
| - name: Ensure postgresql container image '{{ postgresql_container_image }}' is {{ postgresql_state }} | ||||
|   community.docker.docker_image: | ||||
|     name: "{{ postgresql_container_image }}" | ||||
|     state: "{{ postgresql_state }}" | ||||
|     source: "{{ postgresql_container_image_source }}" | ||||
|     force_source: "{{ postgresql_container_image_force_source }}" | ||||
|   register: postgresql_container_image_info | ||||
|   until: postgresql_container_image_info is success | ||||
|   retries: 5 | ||||
|   delay: 4 | ||||
|  | ||||
| - name: Ensure postgresql container '{{ postgresql_container_name }}' is {{ postgresql_container_state }} | ||||
|   community.docker.docker_container: | ||||
|     name: "{{ postgresql_container_name }}" | ||||
|     image: "{{ postgresql_container_image }}" | ||||
|     env: "{{ postgresql_container_env | default(omit, true) }}" | ||||
|     user: "{{ postgresql_container_user | default(omit, true) }}" | ||||
|     ports: "{{ postgresql_container_ports | default(omit, true) }}" | ||||
|     labels: "{{ postgresql_container_labels | default(omit, true) }}" | ||||
|     networks: "{{ postgresql_container_networks | default(omit, true) }}" | ||||
|     restart_policy: "{{ postgresql_container_restart_policy | default(omit, true) }}" | ||||
|     state: "{{ postgresql_container_state }}" | ||||
							
								
								
									
										63
									
								
								roles/postgresql/tasks/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								roles/postgresql/tasks/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| --- | ||||
| - name: Ensure state is valid | ||||
|   ansible.builtin.fail: | ||||
|     msg: >-2 | ||||
|       Invalid state '{{ postgresql_state }}'! Supported | ||||
|       states are {{ postgresql_states | join(', ') }}. | ||||
|   when: postgresql_state not in postgresql_states | ||||
|  | ||||
| - name: Ensure deployment method is valid | ||||
|   ansible.builtin.fail: | ||||
|     msg: >-2 | ||||
|       Unsupported deployment method '{{ postgresql_deployment_method }}! | ||||
|       Supported deployment methods are {{ postgresql_deployment_methods | join(', ') }}. | ||||
|   when: postgresql_deployment_method not in postgresql_deployment_methods | ||||
|  | ||||
| - name: Ensure postgresql user '{{ postgresql_user }}' is {{ postgresql_state }} | ||||
|   ansible.builtin.user: | ||||
|     name: "{{ postgresql_user }}" | ||||
|     state: "{{ postgresql_state }}" | ||||
|     system: "{{ postgresql_user_system | default(omit, true) }}" | ||||
|     create_home: "{{ postgresql_user_create_home | default(omit, true) }}" | ||||
|     groups: "{{ postgresql_user_groups | default(omit, true) }}" | ||||
|     append: "{{ postgresql_user_append | default(omit, true) }}" | ||||
|   register: postgresql_user_info | ||||
|  | ||||
| - name: Ensure directories are {{ postgresql_state }} | ||||
|   ansible.builtin.file: | ||||
|     path: "{{ path.name }}" | ||||
|     state: "{{ (postgresql_state == 'present') | ternary('directory', 'absent') }}" | ||||
|     owner: "{{ path.owner | default(postgresql_user_id, true) }}" | ||||
|     group: "{{ path.group | default(postgresql_user_group_id, true) }}" | ||||
|     mode: "{{ path.mode | default('0755', true) }}" | ||||
|   loop: | ||||
|     - name: "{{ postgresql_config_path }}" | ||||
|     - name: "{{ postgresql_data_path }}" | ||||
|   loop_control: | ||||
|     loop_var: path | ||||
|     label: "{{ path.name }}" | ||||
|  | ||||
| - name: Check for existing PG_VERSION file | ||||
|   ansible.builtin.stat: | ||||
|     path: "{{ postgresql_data_path }}/PG_VERSION" | ||||
|   register: postgresql_data_dir_version_info | ||||
|  | ||||
| - name: Read existing PG_VERSION file | ||||
|   ansible.builtin.slurp: | ||||
|     path: "{{ postgresql_data_path }}/PG_VERSION" | ||||
|   register: postgresql_data_dir_version_content | ||||
|   when: | ||||
|     - postgresql_data_dir_version_info.stat.exists | ||||
|  | ||||
| - name: Prevent major version changes | ||||
|   ansible.builtin.fail: | ||||
|     msg: >-2 | ||||
|       Mismatched postgresql version for the data directory! | ||||
|       Aborting... | ||||
|   when: | ||||
|     - postgresql_data_dir_version_info.stat.exists | ||||
|     - "(postgresql_data_dir_version_content | b64decode | int) != (postgresql_major_version | int)" | ||||
|  | ||||
| - name: Deploy postgresql using {{ postgresql_deployment_method }} | ||||
|   ansible.builtin.include_tasks: | ||||
|     file: "deploy-{{ postgresql_deployment_method }}.yml" | ||||
							
								
								
									
										6
									
								
								roles/postgresql/vars/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								roles/postgresql/vars/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| --- | ||||
| postgresql_states: | ||||
|   - present | ||||
|   - absent | ||||
| postgresql_deployment_methods: | ||||
|   - docker | ||||
							
								
								
									
										47
									
								
								roles/redis/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								roles/redis/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| # `finallycoffee.databases.redis` ansible role | ||||
|  | ||||
| Redis is the self-proclaimed world's fastest data platform for caching, | ||||
| vector search and NoSQL databases. Since version 7.2.4, it is no longer | ||||
| considered "Free and open source software" (FOSS), with redis switching | ||||
| their license to the "Serverside public license" (SSPL). | ||||
|  | ||||
| Setting the `redis_version` to higher than `7.2.4` means you will deploy | ||||
| the SSPL-licensed version to redis. | ||||
|  | ||||
| ## Configuration | ||||
|  | ||||
| All container-related options to the `docker_container` ansible module | ||||
| are available under the `redis_container_*` namespace, for example use | ||||
| `redis_container_ports: [ '127.0.0.1:6379:6370/tcp' ]` to map the | ||||
| containers port 6379 to the docker host. | ||||
|  | ||||
| Redis-related config options are either available in the `redis_config_*` | ||||
| namespace or can be specified by setting them as a dictionary in | ||||
| `redis_config` | ||||
|  | ||||
| ### Authentication and authorization | ||||
|  | ||||
| Redis ACL can be specified as an array in the `redis_config_user` variable | ||||
|  - see [the redis documentation](https://github.com/redis/redis/blob/unstable/redis.conf#L869) | ||||
| for the format. Per default, the `default` user is able to connect without | ||||
| any password. To require a password and use a different user, override | ||||
| the variable, for example `redis_config_user: [ 'username on +@all -DEBUG ~* >secret' ]`. | ||||
|  | ||||
| ## Redis on a unix socket | ||||
|  | ||||
| To make redis available on a unix socket, a directory must be supplied in which the | ||||
| socket lives: | ||||
| ```yaml | ||||
| redis_container_socket: /var/run/redis.sock | ||||
| redis_container_volumes: | ||||
|   - "/path/to/socket/on/host/redis.sock:{{ redis_container_socket }}:z" | ||||
| redis_config_unixsocket: "{{ redis_container_socket }}" | ||||
| ``` | ||||
|  | ||||
| ## Container specific information | ||||
|  | ||||
| Redis publishes their official container image in both a debian-based and an | ||||
| alpine-based variant. Which image should be used can be configured in | ||||
| `redis_container_image_flavour`, which defaults to `alpine`, which is smaller | ||||
| in size but also includes less related / debugging tools. To use the debian- | ||||
| based image, unset the flavour using `redis_container_image_flavour: ~`. | ||||
							
								
								
									
										41
									
								
								roles/redis/defaults/main/config.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								roles/redis/defaults/main/config.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| --- | ||||
| redis_config_bind: | ||||
|   - "127.0.0.1" | ||||
|   - "-::1" | ||||
| redis_config_protected_mode: true | ||||
| redis_config_port: 6379 | ||||
| redis_config_unixsocket: ~ | ||||
| redis_config_unixsocketperm: '700' | ||||
| redis_config_user: | ||||
|   - "default on +@all -DEBUG ~* nopass" | ||||
| redis_config_databases: 16 | ||||
| redis_config_supervised: false | ||||
| redis_config_daemonize: false | ||||
| redis_config_dbfilename: dump.rdb | ||||
| redis_config_dir: "{{ redis_data_path }}" | ||||
| redis_config_save: "3600 1 300 100 60 10000" | ||||
| redis_config_appendfsync: everysec | ||||
|  | ||||
| redis_base_config: | ||||
|   bind: "{{ redis_config_bind | join(' ') }}" | ||||
|   "protected-mode": "{{ redis_config_protected_mode | bool | ternary('yes', 'no') }}" | ||||
|   port: "{{ redis_config_port }}" | ||||
|   user: "{{ redis_config_user }}" | ||||
|   databases: "{{ redis_config_databases }}" | ||||
|   daemonize: "{{ redis_config_daemonize | bool | ternary('yes', 'no') }}" | ||||
|   supervised: "{{ redis_config_supervised | bool | ternary('yes', 'no') }}" | ||||
|   save: "{{ redis_config_save }}" | ||||
|   dbfilename: "{{ redis_config_dbfilename }}" | ||||
|   dir: "{{ redis_config_dir }}" | ||||
|   appendfsync: "{{ redis_config_appendfsync }}" | ||||
|  | ||||
| redis_config: ~ | ||||
| redis_merged_config: >-2 | ||||
|   {{ redis_base_config | ||||
|   | combine(({ | ||||
|       'unixsocket': redis_config_unixsocket, | ||||
|       'unixsocketperm': redis_config_unixsocketperm, | ||||
|     }) | ||||
|     if (redis_config_unixsocket | default(false, true)) else {}, | ||||
|     recursive=True) | ||||
|   | combine(redis_config | default({}, true), recursive=True) }} | ||||
							
								
								
									
										49
									
								
								roles/redis/defaults/main/container.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								roles/redis/defaults/main/container.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| --- | ||||
| redis_container_image_registry: docker.io | ||||
| redis_container_image_namespace: ~ | ||||
| redis_container_image_name: redis | ||||
| redis_container_image_tag: ~ | ||||
| redis_container_image_flavour: alpine | ||||
| redis_container_image_source: pull | ||||
| redis_container_image_force_source: >-2 | ||||
|   {{ redis_container_image_tag | default(false, true) | bool }} | ||||
| redis_container_image: >-2 | ||||
|   {{ | ||||
|     ([ | ||||
|       redis_container_image_registry | default([], true), | ||||
|       redis_container_image_namespace | default([], true), | ||||
|       redis_container_image_name, | ||||
|     ] | flatten | join('/')) | ||||
|     + ':' + | ||||
|     (redis_container_image_tag | default( | ||||
|       redis_version + ( | ||||
|         ((redis_container_image_flavour is string) | ||||
|             and (redis_container_image_flavour | length > 0)) | ||||
|         | ternary('-' + (redis_container_image_flavour | default('')), '') | ||||
|       ), | ||||
|       true, | ||||
|     )) | ||||
|   }} | ||||
|  | ||||
| redis_container_name: "redis{{ redis_instance_suffix }}" | ||||
| redis_container_env: ~ | ||||
| redis_container_user: >-2 | ||||
|   {{ redis_run_user_id }}:{{ redis_run_group_id }} | ||||
| redis_container_ports: ~ | ||||
| redis_container_labels: ~ | ||||
| redis_container_volumes: ~ | ||||
| redis_container_merged_volumes: >-2 | ||||
|   {{ redis_container_base_volumes | ||||
|   + redis_container_volumes | default([], true) }} | ||||
| redis_container_command: | ||||
|   - "redis-server" | ||||
|   - "{{ redis_config_file }}" | ||||
| redis_container_networks: ~ | ||||
| redis_container_etc_hosts: ~ | ||||
| redis_container_dns_servers: ~ | ||||
| redis_container_restart_policy: "unless-stopped" | ||||
| redis_container_state: >-2 | ||||
|   {{ (redis_state == 'present') | ternary('started', 'absent') }} | ||||
| redis_container_base_volumes: | ||||
|   - "{{ redis_config_file }}:{{ redis_config_file }}:ro" | ||||
|   - "{{ redis_data_path }}:{{ redis_data_path }}:rw" | ||||
							
								
								
									
										15
									
								
								roles/redis/defaults/main/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								roles/redis/defaults/main/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| --- | ||||
| redis_version: "7.2.4" | ||||
| redis_state: "present" | ||||
| redis_instance: ~ | ||||
| redis_instance_suffix: >-2 | ||||
|   {{ ((redis_instance is string) and (redis_instance | length > 0)) | ||||
|     | ternary('-' + (redis_instance | default('', true)), '') }} | ||||
| redis_user: >-2 | ||||
|   redis{{ redis_instance_suffix }} | ||||
|  | ||||
| redis_config_path: "/etc/redis" | ||||
| redis_config_file: >-2 | ||||
|   {{ redis_config_path }}/redis{{ redis_instance_suffix }}.conf | ||||
| redis_data_path: "/var/lib/redis{{ redis_instance_suffix }}" | ||||
| redis_deployment_method: docker | ||||
							
								
								
									
										10
									
								
								roles/redis/defaults/main/user.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								roles/redis/defaults/main/user.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| --- | ||||
| redis_run_user_id: >-2 | ||||
|   {{ redis_user_info.uid | default(redis_user, true) }} | ||||
| redis_run_group_id: >-2 | ||||
|   {{ redis_user_info.group | default(redis_user, true) }} | ||||
| redis_user_system: true | ||||
| redis_user_create_home: false | ||||
| redis_user_groups: ~ | ||||
| redis_user_append_groups: >-2 | ||||
|   {{ redis_user_groups | default(true, false) | bool }} | ||||
							
								
								
									
										11
									
								
								roles/redis/handlers/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								roles/redis/handlers/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| --- | ||||
| - name: Ensure redis container '{{ redis_container_name }}' is restarted | ||||
|   community.docker.docker_container: | ||||
|     name: "{{ redis_container_name }}" | ||||
|     state: "{{ redis_container_state }}" | ||||
|     restart: true | ||||
|   listen: redis-restart | ||||
|   when: | ||||
|     - redis_deployment_method == 'docker' | ||||
|     - redis_state == 'present' | ||||
|   ignore_errors: "{{ ansible_check_mode }}" | ||||
							
								
								
									
										10
									
								
								roles/redis/meta/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								roles/redis/meta/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| --- | ||||
| allow_duplicates: true | ||||
| dependencies: [] | ||||
| galaxy_info: | ||||
|   role_name: redis | ||||
|   description: >-2 | ||||
|     Deploy and configure redis, a fast caching, vector-search and NoSQL database. | ||||
|   galaxy_tags: | ||||
|     - redis | ||||
|     - docker | ||||
							
								
								
									
										27
									
								
								roles/redis/tasks/deploy-docker.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								roles/redis/tasks/deploy-docker.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| --- | ||||
| - name: Ensure container image '{{ redis_container_image }}' is {{ redis_state }} | ||||
|   community.docker.docker_image: | ||||
|     name: "{{ redis_container_image }}" | ||||
|     state: "{{ redis_state }}" | ||||
|     source: "{{ redis_container_image_source }}" | ||||
|     force_source: "{{ redis_container_image_force_source }}" | ||||
|   register: redis_container_image_info | ||||
|   until: redis_container_image_info is success | ||||
|   retries: 5 | ||||
|   delay: 3 | ||||
|  | ||||
| - name: Ensure container '{{ redis_container_name }}' is {{ redis_container_state }} | ||||
|   community.docker.docker_container: | ||||
|     name: "{{ redis_container_name }}" | ||||
|     image: "{{ redis_container_image }}" | ||||
|     env: "{{ redis_container_env | default(omit, true) }}" | ||||
|     user: "{{ redis_container_user }}" | ||||
|     ports: "{{ redis_container_ports | default(omit, true) }}" | ||||
|     labels: "{{ redis_container_labels | default(omit, true) }}" | ||||
|     command: "{{ redis_container_command }}" | ||||
|     volumes: "{{ redis_container_merged_volumes }}" | ||||
|     networks: "{{ redis_container_networks | default(omit, true) }}" | ||||
|     etc_hosts: "{{ redis_container_etc_hosts | default(omit, true) }}" | ||||
|     dns_servers: "{{ redis_container_dns_servers | default(omit, true) }}" | ||||
|     restart_policy: "{{ redis_container_restart_policy | default(omit, true) }}" | ||||
|     state: "{{ redis_container_state }}" | ||||
							
								
								
									
										68
									
								
								roles/redis/tasks/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								roles/redis/tasks/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| --- | ||||
| - name: Ensure state is valid | ||||
|   ansible.builtin.fail: | ||||
|     msg: >-2 | ||||
|       Unsupported state '{{ redis_state }}'. | ||||
|       Supported states are {{ redis_states | join(', ') }} | ||||
|   when: redis_state not in redis_states | ||||
|  | ||||
| - name: Ensure deployment method is valid | ||||
|   ansible.builtin.fail: | ||||
|     msg: >-2 | ||||
|       Unsupported deployment method '{{ redis_deployment_method }}'! | ||||
|       Supported methods are {{ redis_deployment_method | join(', ') }} | ||||
|   when: redis_deployment_method not in redis_deployment_methods | ||||
|  | ||||
| - name: Ensure redis user '{{ redis_user }}' is {{ redis_state }} | ||||
|   ansible.builtin.user: | ||||
|     name: "{{ redis_user }}" | ||||
|     state: "{{ redis_state }}" | ||||
|     system: "{{ redis_user_system }}" | ||||
|     create_home: "{{ redis_user_create_home }}" | ||||
|     groups: "{{ redis_user_groups | default(omit, true) }}" | ||||
|     append: "{{ redis_user_append_groups | default(omit, true) }}" | ||||
|   register: redis_user_info | ||||
|  | ||||
| - name: Ensure redis config file '{{ redis_config_file }}' is {{ redis_state }} | ||||
|   ansible.builtin.file: | ||||
|     path: "{{ redis_config_file }}" | ||||
|     state: "{{ redis_state }}" | ||||
|   when: redis_state == 'absent' | ||||
|  | ||||
| - name: Ensure redis host directories are {{ redis_state }} | ||||
|   ansible.builtin.file: | ||||
|     path: "{{ path.name }}" | ||||
|     state: >-2 | ||||
|       {{ (redis_state == 'present') | ternary('directory', 'absent') }} | ||||
|     owner: "{{ path.owner | default(redis_run_user_id) }}" | ||||
|     group: "{{ path.group | default(redis_run_group_id) }}" | ||||
|     mode: "{{ path.mode | default('0755') }}" | ||||
|   loop: | ||||
|     - name: "{{ redis_config_path }}" | ||||
|     - name: "{{ redis_data_path }}" | ||||
|   loop_control: | ||||
|     loop_var: "path" | ||||
|     label: "{{ path.name }}" | ||||
|  | ||||
| - name: Ensure redis config file '{{ redis_config_file }}' is {{ redis_state }} | ||||
|   ansible.builtin.copy: | ||||
|     content: |+2 | ||||
|       {% for tuple in (redis_merged_config | dict2items) %} | ||||
|       {% if tuple.value is string  or tuple.value is number %} | ||||
|       {{ tuple.key }} {{ tuple.value }} | ||||
|       {% else %} | ||||
|       {% for value in tuple.value %} | ||||
|       {{ tuple.key }} {{ value }} | ||||
|       {% endfor %} | ||||
|       {% endif %} | ||||
|       {% endfor %} | ||||
|     dest: "{{ redis_config_file }}" | ||||
|     owner: "{{ redis_run_user_id }}" | ||||
|     group: "{{ redis_run_group_id }}" | ||||
|     mode: "0640" | ||||
|   when: redis_state == 'present' | ||||
|   notify: redis-restart | ||||
|  | ||||
| - name: Deploy redis using {{ redis_deployment_method }} | ||||
|   ansible.builtin.include_tasks: | ||||
|     file: "deploy-{{ redis_deployment_method }}.yml" | ||||
							
								
								
									
										6
									
								
								roles/redis/vars/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								roles/redis/vars/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| --- | ||||
| redis_states: | ||||
|   - present | ||||
|   - absent | ||||
| redis_deployment_methods: | ||||
|   - docker | ||||
							
								
								
									
										13
									
								
								roles/valkey/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								roles/valkey/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| # `finallycoffee.databases.valkey` ansible role | ||||
|  | ||||
| Valkey is an open source (BSD 3 licensed), high-performance in-memory key/value | ||||
| data store, ideal for workloads like caching or message queues. It has been | ||||
| forked from redis 7.2.4 before redis license was changed to SSPL. | ||||
|  | ||||
| Valkey offers compatibility to redis and can be used as a drop-in replacement | ||||
| for redis. | ||||
|  | ||||
| ## Configuration | ||||
|  | ||||
| For the configuration, see the [`redis` role configuration](../redis/README.md#configuration), | ||||
| and swap the `redis_` prefix of all variables for the `valkey_` prefix. | ||||
							
								
								
									
										41
									
								
								roles/valkey/defaults/main/config.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								roles/valkey/defaults/main/config.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| --- | ||||
| valkey_config_bind: | ||||
|   - "127.0.0.1" | ||||
|   - "-::1" | ||||
| valkey_config_protected_mode: true | ||||
| valkey_config_port: 6379 | ||||
| valkey_config_unixsocket: ~ | ||||
| valkey_config_unixsocketperm: '700' | ||||
| valkey_config_user: | ||||
|   - "default on +@all -DEBUG ~* nopass" | ||||
| valkey_config_databases: 16 | ||||
| valkey_config_supervised: false | ||||
| valkey_config_daemonize: false | ||||
| valkey_config_dbfilename: dump.rdb | ||||
| valkey_config_dir: "{{ valkey_data_path }}" | ||||
| valkey_config_save: "3600 1 300 100 60 10000" | ||||
| valkey_config_appendfsync: everysec | ||||
|  | ||||
| valkey_base_config: | ||||
|   bind: "{{ valkey_config_bind | join(' ') }}" | ||||
|   "protected-mode": "{{ valkey_config_protected_mode | bool | ternary('yes', 'no') }}" | ||||
|   port: "{{ valkey_config_port }}" | ||||
|   user: "{{ valkey_config_user }}" | ||||
|   databases: "{{ valkey_config_databases }}" | ||||
|   daemonize: "{{ valkey_config_daemonize | bool | ternary('yes', 'no') }}" | ||||
|   supervised: "{{ valkey_config_supervised | bool | ternary('yes', 'no') }}" | ||||
|   save: "{{ valkey_config_save }}" | ||||
|   dbfilename: "{{ valkey_config_dbfilename }}" | ||||
|   dir: "{{ valkey_config_dir }}" | ||||
|   appendfsync: "{{ valkey_config_appendfsync }}" | ||||
|  | ||||
| valkey_config: ~ | ||||
| valkey_merged_config: >-2 | ||||
|   {{ valkey_base_config | ||||
|   | combine(({ | ||||
|       'unixsocket': valkey_config_unixsocket, | ||||
|       'unixsocketperm': valkey_config_unixsocketperm, | ||||
|     }) | ||||
|     if (valkey_config_unixsocket | default(false, true)) else {}, | ||||
|     recursive=True) | ||||
|   | combine(valkey_config | default({}, true), recursive=True) }} | ||||
							
								
								
									
										49
									
								
								roles/valkey/defaults/main/container.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								roles/valkey/defaults/main/container.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| --- | ||||
| valkey_container_image_registry: docker.io | ||||
| valkey_container_image_namespace: valkey | ||||
| valkey_container_image_name: valkey | ||||
| valkey_container_image_tag: ~ | ||||
| valkey_container_image_flavour: alpine | ||||
| valkey_container_image_source: pull | ||||
| valkey_container_image_force_source: >-2 | ||||
|   {{ valkey_container_image_tag | default(false, true) | bool }} | ||||
| valkey_container_image: >-2 | ||||
|   {{ | ||||
|     ([ | ||||
|       valkey_container_image_registry | default([], true), | ||||
|       valkey_container_image_namespace | default([], true), | ||||
|       valkey_container_image_name, | ||||
|     ] | flatten | join('/')) | ||||
|     + ':' + | ||||
|     (valkey_container_image_tag | default( | ||||
|       valkey_version + ( | ||||
|         ((valkey_container_image_flavour is string) | ||||
|             and (valkey_container_image_flavour | length > 0)) | ||||
|         | ternary('-' + (valkey_container_image_flavour | default('')), '') | ||||
|       ), | ||||
|       true, | ||||
|     )) | ||||
|   }} | ||||
|  | ||||
| valkey_container_name: "valkey{{ valkey_instance_suffix }}" | ||||
| valkey_container_env: ~ | ||||
| valkey_container_user: >-2 | ||||
|   {{ valkey_run_user_id }}:{{ valkey_run_group_id }} | ||||
| valkey_container_ports: ~ | ||||
| valkey_container_labels: ~ | ||||
| valkey_container_volumes: ~ | ||||
| valkey_container_merged_volumes: >-2 | ||||
|   {{ valkey_container_base_volumes | ||||
|   + valkey_container_volumes | default([], true) }} | ||||
| valkey_container_command: | ||||
|   - "valkey-server" | ||||
|   - "{{ valkey_config_file }}" | ||||
| valkey_container_networks: ~ | ||||
| valkey_container_etc_hosts: ~ | ||||
| valkey_container_dns_servers: ~ | ||||
| valkey_container_restart_policy: "unless-stopped" | ||||
| valkey_container_state: >-2 | ||||
|   {{ (valkey_state == 'present') | ternary('started', 'absent') }} | ||||
| valkey_container_base_volumes: | ||||
|   - "{{ valkey_config_file }}:{{ valkey_config_file }}:ro" | ||||
|   - "{{ valkey_data_path }}:{{ valkey_data_path }}:rw" | ||||
							
								
								
									
										15
									
								
								roles/valkey/defaults/main/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								roles/valkey/defaults/main/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| --- | ||||
| valkey_version: "8.0.1" | ||||
| valkey_state: "present" | ||||
| valkey_instance: ~ | ||||
| valkey_instance_suffix: >-2 | ||||
|   {{ ((valkey_instance is string) and (valkey_instance | length > 0)) | ||||
|     | ternary('-' + (valkey_instance | default('', true)), '') }} | ||||
| valkey_user: >-2 | ||||
|   valkey{{ valkey_instance_suffix }} | ||||
|  | ||||
| valkey_config_path: "/etc/valkey" | ||||
| valkey_config_file: >-2 | ||||
|   {{ valkey_config_path }}/valkey{{ valkey_instance_suffix }}.conf | ||||
| valkey_data_path: "/var/lib/valkey{{ valkey_instance_suffix }}" | ||||
| valkey_deployment_method: docker | ||||
							
								
								
									
										10
									
								
								roles/valkey/defaults/main/user.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								roles/valkey/defaults/main/user.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| --- | ||||
| valkey_run_user_id: >-2 | ||||
|   {{ valkey_user_info.uid | default(valkey_user, true) }} | ||||
| valkey_run_group_id: >-2 | ||||
|   {{ valkey_user_info.group | default(valkey_user, true) }} | ||||
| valkey_user_system: true | ||||
| valkey_user_create_home: false | ||||
| valkey_user_groups: ~ | ||||
| valkey_user_append_groups: >-2 | ||||
|   {{ valkey_user_groups | default(true, false) | bool }} | ||||
							
								
								
									
										11
									
								
								roles/valkey/handlers/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								roles/valkey/handlers/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| --- | ||||
| - name: Ensure valkey container '{{ valkey_container_name }}' is restarted | ||||
|   community.docker.docker_container: | ||||
|     name: "{{ valkey_container_name }}" | ||||
|     state: "{{ valkey_container_state }}" | ||||
|     restart: true | ||||
|   listen: valkey-restart | ||||
|   when: | ||||
|     - valkey_deployment_method == 'docker' | ||||
|     - valkey_state == 'present' | ||||
|   ignore_errors: "{{ ansible_check_mode }}" | ||||
							
								
								
									
										11
									
								
								roles/valkey/meta/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								roles/valkey/meta/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| --- | ||||
| allow_duplicates: true | ||||
| dependencies: [] | ||||
| galaxy_info: | ||||
|   role_name: valkey | ||||
|   description: >-2 | ||||
|     An open source, in-memory datastore under BSD 3 license | ||||
|   galaxy_tags: | ||||
|     - valkey | ||||
|     - redis | ||||
|     - docker | ||||
							
								
								
									
										27
									
								
								roles/valkey/tasks/deploy-docker.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								roles/valkey/tasks/deploy-docker.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| --- | ||||
| - name: Ensure container image '{{ valkey_container_image }}' is {{ valkey_state }} | ||||
|   community.docker.docker_image: | ||||
|     name: "{{ valkey_container_image }}" | ||||
|     state: "{{ valkey_state }}" | ||||
|     source: "{{ valkey_container_image_source }}" | ||||
|     force_source: "{{ valkey_container_image_force_source }}" | ||||
|   register: valkey_container_image_info | ||||
|   until: valkey_container_image_info is success | ||||
|   retries: 5 | ||||
|   delay: 3 | ||||
|  | ||||
| - name: Ensure container '{{ valkey_container_name }}' is {{ valkey_container_state }} | ||||
|   community.docker.docker_container: | ||||
|     name: "{{ valkey_container_name }}" | ||||
|     image: "{{ valkey_container_image }}" | ||||
|     env: "{{ valkey_container_env | default(omit, true) }}" | ||||
|     user: "{{ valkey_container_user }}" | ||||
|     ports: "{{ valkey_container_ports | default(omit, true) }}" | ||||
|     labels: "{{ valkey_container_labels | default(omit, true) }}" | ||||
|     command: "{{ valkey_container_command }}" | ||||
|     volumes: "{{ valkey_container_merged_volumes }}" | ||||
|     networks: "{{ valkey_container_networks | default(omit, true) }}" | ||||
|     etc_hosts: "{{ valkey_container_etc_hosts | default(omit, true) }}" | ||||
|     dns_servers: "{{ valkey_container_dns_servers | default(omit, true) }}" | ||||
|     restart_policy: "{{ valkey_container_restart_policy | default(omit, true) }}" | ||||
|     state: "{{ valkey_container_state }}" | ||||
							
								
								
									
										68
									
								
								roles/valkey/tasks/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								roles/valkey/tasks/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| --- | ||||
| - name: Ensure state is valid | ||||
|   ansible.builtin.fail: | ||||
|     msg: >-2 | ||||
|       Unsupported state '{{ valkey_state }}'. | ||||
|       Supported states are {{ valkey_states | join(', ') }} | ||||
|   when: valkey_state not in valkey_states | ||||
|  | ||||
| - name: Ensure deployment method is valid | ||||
|   ansible.builtin.fail: | ||||
|     msg: >-2 | ||||
|       Unsupported deployment method '{{ valkey_deployment_method }}'! | ||||
|       Supported methods are {{ valkey_deployment_method | join(', ') }} | ||||
|   when: valkey_deployment_method not in valkey_deployment_methods | ||||
|  | ||||
| - name: Ensure valkey user '{{ valkey_user }}' is {{ valkey_state }} | ||||
|   ansible.builtin.user: | ||||
|     name: "{{ valkey_user }}" | ||||
|     state: "{{ valkey_state }}" | ||||
|     system: "{{ valkey_user_system }}" | ||||
|     create_home: "{{ valkey_user_create_home }}" | ||||
|     groups: "{{ valkey_user_groups | default(omit, true) }}" | ||||
|     append: "{{ valkey_user_append_groups | default(omit, true) }}" | ||||
|   register: valkey_user_info | ||||
|  | ||||
| - name: Ensure valkey config file '{{ valkey_config_file }}' is {{ valkey_state }} | ||||
|   ansible.builtin.file: | ||||
|     path: "{{ valkey_config_file }}" | ||||
|     state: "{{ valkey_state }}" | ||||
|   when: valkey_state == 'absent' | ||||
|  | ||||
| - name: Ensure valkey host directories are {{ valkey_state }} | ||||
|   ansible.builtin.file: | ||||
|     path: "{{ path.name }}" | ||||
|     state: >-2 | ||||
|       {{ (valkey_state == 'present') | ternary('directory', 'absent') }} | ||||
|     owner: "{{ path.owner | default(valkey_run_user_id) }}" | ||||
|     group: "{{ path.group | default(valkey_run_group_id) }}" | ||||
|     mode: "{{ path.mode | default('0755') }}" | ||||
|   loop: | ||||
|     - name: "{{ valkey_config_path }}" | ||||
|     - name: "{{ valkey_data_path }}" | ||||
|   loop_control: | ||||
|     loop_var: "path" | ||||
|     label: "{{ path.name }}" | ||||
|  | ||||
| - name: Ensure valkey config file '{{ valkey_config_file }}' is {{ valkey_state }} | ||||
|   ansible.builtin.copy: | ||||
|     content: |+2 | ||||
|       {% for tuple in (valkey_merged_config | dict2items) %} | ||||
|       {% if tuple.value is string  or tuple.value is number %} | ||||
|       {{ tuple.key }} {{ tuple.value }} | ||||
|       {% else %} | ||||
|       {% for value in tuple.value %} | ||||
|       {{ tuple.key }} {{ value }} | ||||
|       {% endfor %} | ||||
|       {% endif %} | ||||
|       {% endfor %} | ||||
|     dest: "{{ valkey_config_file }}" | ||||
|     owner: "{{ valkey_run_user_id }}" | ||||
|     group: "{{ valkey_run_group_id }}" | ||||
|     mode: "0640" | ||||
|   when: valkey_state == 'present' | ||||
|   notify: valkey-restart | ||||
|  | ||||
| - name: Deploy valkey using {{ valkey_deployment_method }} | ||||
|   ansible.builtin.include_tasks: | ||||
|     file: "deploy-{{ valkey_deployment_method }}.yml" | ||||
							
								
								
									
										6
									
								
								roles/valkey/vars/main.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								roles/valkey/vars/main.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| --- | ||||
| valkey_states: | ||||
|   - present | ||||
|   - absent | ||||
| valkey_deployment_methods: | ||||
|   - docker | ||||
		Reference in New Issue
	
	Block a user