# S3 keys and buckets tasks - name: Get list of existing S3 keys community.docker.docker_container_exec: container: "{{ garage_service_name }}" command: /garage key list register: _existing_keys_output changed_when: false when: garage_s3_keys | length > 0 - name: Parse existing key names ansible.builtin.set_fact: # `garage key list` columns: ID Created Name Expiration. # Data rows begin with a GK key ID; header is "ID Created ..." # and INFO log lines may interleave on stderr (kept separate by # docker_container_exec). Strip ANSI escapes defensively, filter to # GK-prefixed rows, then take the 3rd whitespace-separated field. _existing_keys: "{{ _existing_keys_output.stdout_lines | map('regex_replace', '\\x1b\\[[0-9;]*m', '') | select('match', '^GK[0-9a-fA-F]+') | map('regex_replace', '^\\S+\\s+\\S+\\s+(\\S+).*$', '\\1') | list }}" when: garage_s3_keys | length > 0 - name: Create S3 keys community.docker.docker_container_exec: container: "{{ garage_service_name }}" command: /garage key create {{ item.name }} loop: "{{ garage_s3_keys }}" register: _key_create_result when: - garage_s3_keys | length > 0 - item.name not in _existing_keys - name: Get key IDs for all keys community.docker.docker_container_exec: container: "{{ garage_service_name }}" command: /garage key info {{ item.name }} loop: "{{ garage_s3_keys }}" register: _key_info_results changed_when: false when: garage_s3_keys | length > 0 - name: Extract key IDs from info ansible.builtin.set_fact: _key_id_map: "{{ _key_id_map | default({}) | combine({item.item.name: item.stdout | regex_search('Key ID:\\s+(\\S+)', '\\1') | first}) }}" loop: "{{ _key_info_results.results }}" when: - garage_s3_keys | length > 0 - item.stdout is defined - name: Get list of existing buckets community.docker.docker_container_exec: container: "{{ garage_service_name }}" command: /garage bucket list register: _existing_buckets_output changed_when: false when: garage_s3_keys | length > 0 - name: Parse existing bucket names ansible.builtin.set_fact: # `garage bucket list` columns: ID Created Global aliases Local aliases # Data rows start with a hex bucket ID; filter to those and take the # third whitespace-separated field (the global alias = bucket name). _existing_buckets: >- {{ _existing_buckets_output.stdout_lines | select('match', '^[0-9a-f]{16}\\s') | map('regex_replace', '^\\S+\\s+\\S+\\s+(\\S+).*$', '\\1') | list }} when: garage_s3_keys | length > 0 - name: Get unique bucket names ansible.builtin.set_fact: _unique_buckets: "{{ garage_s3_keys | subelements('buckets', skip_missing=True) | map(attribute='1.name') | unique | list }}" when: garage_s3_keys | length > 0 - name: Create buckets community.docker.docker_container_exec: container: "{{ garage_service_name }}" command: /garage bucket create {{ item }} loop: "{{ _unique_buckets }}" when: - garage_s3_keys | length > 0 - item not in _existing_buckets failed_when: false - name: Get current bucket permissions community.docker.docker_container_exec: container: "{{ garage_service_name }}" command: /garage bucket info {{ item.1.name }} loop: "{{ garage_s3_keys | subelements('buckets', skip_missing=True) }}" loop_control: label: "{{ item.1.name }}" register: _bucket_info_results changed_when: false when: garage_s3_keys | length > 0 - name: Set bucket permissions using key IDs community.docker.docker_container_exec: container: "{{ garage_service_name }}" command: /garage bucket allow {{ item.item.1.name }} {% for perm in item.item.1.permissions %}--{{ perm }} {% endfor %}--key {{ _key_id_map[item.item.0.name] }} loop: "{{ _bucket_info_results.results }}" loop_control: label: "{{ item.item.1.name }} -> {{ item.item.0.name }}" when: - garage_s3_keys | length > 0 - >- (item.stdout | regex_search( '(?m)^\s*' ~ _wanted_flags ~ '\s+' ~ _key_id_map[item.item.0.name] )) is none vars: _wanted_flags: >- {{ ('R' if 'read' in item.item.1.permissions else '-') ~ ('W' if 'write' in item.item.1.permissions else '-') ~ ('O' if 'owner' in item.item.1.permissions else '-') }} # Export key credentials for use by other roles - name: Get detailed key information for all keys community.docker.docker_container_exec: container: "{{ garage_service_name }}" command: /garage key info {{ item.name }} --show-secret loop: "{{ garage_s3_keys }}" register: _key_details_results changed_when: false when: garage_s3_keys | length > 0 - name: Build garage S3 credentials map ansible.builtin.set_fact: garage_s3_credentials: "{{ garage_s3_credentials | default({}) | combine({item.item.name: {'key_id': item.stdout | regex_search('Key ID:\\s+(\\S+)', '\\1') | first, 'secret_key': item.stdout | regex_search('Secret key:\\s+(\\S+)', '\\1') | first}}) }}" loop: "{{ _key_details_results.results }}" when: - garage_s3_keys | length > 0 - item.stdout is defined - name: Export garage S3 credentials as cacheable fact ansible.builtin.set_fact: garage_s3_credentials: "{{ garage_s3_credentials }}" cacheable: true when: garage_s3_keys | length > 0