Add Windows Gitea runner role with Podman and Docker support
- Created templates for configuration files for both Podman and Docker-based Windows Gitea runners. - Added default variables for Windows Gitea runner role, including instance URL, registration token, and image settings. - Implemented tasks for validating settings, ensuring Docker service is running, and managing Docker users. - Developed logic for building and managing Windows runner images and containers, including checks for existing images and containers. - Updated inventory to include new groups for Windows Gitea runners. - Adjusted Terraform configurations for timeout settings in ingress resources.
This commit is contained in:
@@ -0,0 +1,429 @@
|
||||
---
|
||||
- name: Resolve runner profile
|
||||
ansible.builtin.set_fact:
|
||||
__windows_gitea_runner_podman_profile: >-
|
||||
{{
|
||||
windows_gitea_runner_podman_runner.profile
|
||||
| default(windows_gitea_runner_podman_runner.name | default('runner'))
|
||||
}}
|
||||
|
||||
- name: Resolve runner-specific settings
|
||||
ansible.builtin.set_fact:
|
||||
__windows_gitea_runner_podman_name: >-
|
||||
{{
|
||||
windows_gitea_runner_podman_runner.name | default(
|
||||
'gitea-runner-' ~ __windows_gitea_runner_podman_profile
|
||||
)
|
||||
}}
|
||||
__windows_gitea_runner_podman_container_name: >-
|
||||
{{
|
||||
windows_gitea_runner_podman_runner.container_name | default(
|
||||
'gitea-runner-' ~ __windows_gitea_runner_podman_profile
|
||||
)
|
||||
}}
|
||||
__windows_gitea_runner_podman_image: >-
|
||||
{{
|
||||
windows_gitea_runner_podman_runner.image | default(
|
||||
windows_gitea_runner_podman_image_prefix ~ ':' ~ __windows_gitea_runner_podman_profile
|
||||
)
|
||||
}}
|
||||
__windows_gitea_runner_podman_labels: >-
|
||||
{{
|
||||
windows_gitea_runner_podman_runner.labels | default(
|
||||
__windows_gitea_runner_podman_profile ~ ':host'
|
||||
)
|
||||
}}
|
||||
__windows_gitea_runner_podman_dockerfile_src: >-
|
||||
{{
|
||||
windows_gitea_runner_podman_runner.dockerfile_src | default(
|
||||
'Dockerfile.' ~ __windows_gitea_runner_podman_profile
|
||||
)
|
||||
}}
|
||||
__windows_gitea_runner_podman_config_file: >-
|
||||
{{
|
||||
windows_gitea_runner_podman_runner.config_file | default(
|
||||
windows_gitea_runner_podman_config_root ~ '\\' ~ __windows_gitea_runner_podman_profile ~ '\\config.yaml'
|
||||
)
|
||||
}}
|
||||
__windows_gitea_runner_podman_config_name: >-
|
||||
{{
|
||||
(
|
||||
windows_gitea_runner_podman_runner.config_file | default(
|
||||
windows_gitea_runner_podman_config_root ~ '\\' ~ __windows_gitea_runner_podman_profile ~ '\\config.yaml'
|
||||
)
|
||||
) | regex_search('[^\\\\]+$')
|
||||
}}
|
||||
__windows_gitea_runner_podman_data_dir: >-
|
||||
{{
|
||||
windows_gitea_runner_podman_runner.data_dir | default(
|
||||
windows_gitea_runner_podman_data_root ~ '\\' ~ __windows_gitea_runner_podman_profile ~ '\\data'
|
||||
)
|
||||
}}
|
||||
__windows_gitea_runner_podman_log_dir: >-
|
||||
{{
|
||||
windows_gitea_runner_podman_runner.log_dir | default(
|
||||
windows_gitea_runner_podman_log_root ~ '\\' ~ __windows_gitea_runner_podman_profile
|
||||
)
|
||||
}}
|
||||
__windows_gitea_runner_podman_build_dir: >-
|
||||
{{ windows_gitea_runner_podman_build_root ~ '\\' ~ __windows_gitea_runner_podman_profile }}
|
||||
__windows_gitea_runner_podman_build_dockerfile_dest: >-
|
||||
{{ windows_gitea_runner_podman_build_root ~ '\\' ~ __windows_gitea_runner_podman_profile ~ '\\Dockerfile' }}
|
||||
__windows_gitea_runner_podman_dockerfile_source_path: >-
|
||||
{{
|
||||
windows_gitea_runner_podman_dockerfile_source_root ~ '/' ~ (
|
||||
windows_gitea_runner_podman_runner.dockerfile_src | default(
|
||||
'Dockerfile.' ~ __windows_gitea_runner_podman_profile
|
||||
)
|
||||
)
|
||||
}}
|
||||
__windows_gitea_runner_podman_enable_nested_build: >-
|
||||
{{
|
||||
windows_gitea_runner_podman_runner.enable_nested_build
|
||||
| default(windows_gitea_runner_podman_container_enable_nested_build)
|
||||
}}
|
||||
__windows_gitea_runner_podman_storage_dir: >-
|
||||
{{
|
||||
(
|
||||
windows_gitea_runner_podman_runner.storage_dir | default(
|
||||
windows_gitea_runner_podman_container_storage_root ~ '\\' ~ __windows_gitea_runner_podman_profile
|
||||
)
|
||||
)
|
||||
if (
|
||||
windows_gitea_runner_podman_runner.enable_nested_build
|
||||
| default(windows_gitea_runner_podman_container_enable_nested_build)
|
||||
)
|
||||
else ''
|
||||
}}
|
||||
__windows_gitea_runner_podman_run_args: >-
|
||||
{{ windows_gitea_runner_podman_runner.run_args | default(windows_gitea_runner_podman_container_run_args) }}
|
||||
|
||||
- name: Resolve runner runtime config path
|
||||
ansible.builtin.set_fact:
|
||||
__windows_gitea_runner_podman_runtime_config_file: "{{ __windows_gitea_runner_podman_data_dir }}\\config.yaml"
|
||||
|
||||
- name: Read runner Dockerfile checksum
|
||||
ansible.builtin.set_fact:
|
||||
__windows_gitea_runner_podman_base_dockerfile_checksum: >-
|
||||
{{
|
||||
lookup(
|
||||
'file',
|
||||
windows_gitea_runner_podman_dockerfile_source_root ~ '/' ~ windows_gitea_runner_podman_base_dockerfile_src
|
||||
) | hash('sha1')
|
||||
}}
|
||||
__windows_gitea_runner_podman_profile_dockerfile_checksum: >-
|
||||
{{ lookup('file', __windows_gitea_runner_podman_dockerfile_source_path) | hash('sha1') }}
|
||||
|
||||
- name: Compute desired runner image hash
|
||||
ansible.builtin.set_fact:
|
||||
__windows_gitea_runner_podman_desired_image_hash: >-
|
||||
{{ {
|
||||
'base': __windows_gitea_runner_podman_base_dockerfile_checksum,
|
||||
'profile': __windows_gitea_runner_podman_profile_dockerfile_checksum
|
||||
} | to_json | hash('sha1') }}
|
||||
|
||||
- name: Compute desired runner container hash
|
||||
ansible.builtin.set_fact:
|
||||
__windows_gitea_runner_podman_desired_container_hash: >-
|
||||
{{ {
|
||||
'image': __windows_gitea_runner_podman_image,
|
||||
'name': __windows_gitea_runner_podman_name,
|
||||
'labels': __windows_gitea_runner_podman_labels,
|
||||
'instance': windows_gitea_runner_podman_instance_url,
|
||||
'config': __windows_gitea_runner_podman_runtime_config_file,
|
||||
'config_dir': __windows_gitea_runner_podman_data_dir,
|
||||
'config_name': (
|
||||
(__windows_gitea_runner_podman_runtime_config_file | regex_search('[^\\\\]+$'))
|
||||
| default('config.yaml', true)
|
||||
),
|
||||
'config_mount_mode': 'data',
|
||||
'data': __windows_gitea_runner_podman_data_dir,
|
||||
'log': __windows_gitea_runner_podman_log_dir,
|
||||
'nested_build': __windows_gitea_runner_podman_enable_nested_build,
|
||||
'storage': __windows_gitea_runner_podman_storage_dir,
|
||||
'run_args': __windows_gitea_runner_podman_run_args,
|
||||
'restart': windows_gitea_runner_podman_restart_policy,
|
||||
'image_hash': __windows_gitea_runner_podman_desired_image_hash
|
||||
} | to_json | hash('sha1') }}
|
||||
|
||||
- name: Ensure runner directories exist
|
||||
ansible.windows.win_file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
loop:
|
||||
- "{{ windows_gitea_runner_podman_build_root }}"
|
||||
- "{{ __windows_gitea_runner_podman_build_dir }}"
|
||||
- "{{ __windows_gitea_runner_podman_data_dir }}"
|
||||
- "{{ __windows_gitea_runner_podman_log_dir }}"
|
||||
|
||||
- name: Ensure nested build storage directory exists
|
||||
ansible.windows.win_file:
|
||||
path: "{{ __windows_gitea_runner_podman_storage_dir }}"
|
||||
state: directory
|
||||
when: __windows_gitea_runner_podman_enable_nested_build
|
||||
|
||||
- name: Grant podman service user access to runner directories
|
||||
ansible.windows.win_acl:
|
||||
path: "{{ item }}"
|
||||
user: ".\\{{ windows_gitea_runner_podman_service_user }}"
|
||||
rights: FullControl
|
||||
type: allow
|
||||
state: present
|
||||
inherit: ContainerInherit, ObjectInherit
|
||||
propagation: None
|
||||
loop:
|
||||
- "{{ windows_gitea_runner_podman_build_root }}"
|
||||
- "{{ __windows_gitea_runner_podman_data_dir }}"
|
||||
- "{{ __windows_gitea_runner_podman_log_dir }}"
|
||||
become: true
|
||||
become_method: ansible.builtin.runas
|
||||
become_user: SYSTEM
|
||||
|
||||
- name: Grant podman service user access to nested build storage directory
|
||||
ansible.windows.win_acl:
|
||||
path: "{{ __windows_gitea_runner_podman_storage_dir }}"
|
||||
user: ".\\{{ windows_gitea_runner_podman_service_user }}"
|
||||
rights: FullControl
|
||||
type: allow
|
||||
state: present
|
||||
inherit: ContainerInherit, ObjectInherit
|
||||
propagation: None
|
||||
become: true
|
||||
become_method: ansible.builtin.runas
|
||||
become_user: SYSTEM
|
||||
when: __windows_gitea_runner_podman_enable_nested_build
|
||||
|
||||
- name: Render runner config
|
||||
ansible.windows.win_template:
|
||||
src: config.yaml.j2
|
||||
dest: "{{ __windows_gitea_runner_podman_runtime_config_file }}"
|
||||
|
||||
- name: Copy runner Dockerfile to build context
|
||||
ansible.windows.win_copy:
|
||||
src: "{{ __windows_gitea_runner_podman_dockerfile_source_path }}"
|
||||
dest: "{{ __windows_gitea_runner_podman_build_dockerfile_dest }}"
|
||||
|
||||
- name: Read current runner image hash label
|
||||
ansible.windows.win_shell: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
$podman = "{{ windows_gitea_runner_podman_install_dir }}\podman.exe"
|
||||
$image = "{{ __windows_gitea_runner_podman_image }}"
|
||||
|
||||
$null = & $podman image exists $image 2>$null
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Output "__MISSING__"
|
||||
exit 0
|
||||
}
|
||||
|
||||
$raw = & $podman image inspect $image --format json 2>$null
|
||||
if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($raw)) {
|
||||
Write-Output "__MISSING__"
|
||||
exit 0
|
||||
}
|
||||
|
||||
$obj = $raw | ConvertFrom-Json
|
||||
if ($obj -is [System.Array]) {
|
||||
$obj = $obj[0]
|
||||
}
|
||||
|
||||
$labels = $obj.Config.Labels
|
||||
if ($null -eq $labels) {
|
||||
Write-Output "__UNLABELED__"
|
||||
exit 0
|
||||
}
|
||||
|
||||
$key = "{{ windows_gitea_runner_podman_image_hash_label }}"
|
||||
$current = $labels.$key
|
||||
if ([string]::IsNullOrWhiteSpace($current)) {
|
||||
Write-Output "__UNLABELED__"
|
||||
exit 0
|
||||
}
|
||||
|
||||
Write-Output $current.Trim()
|
||||
become: true
|
||||
become_method: ansible.builtin.runas
|
||||
become_user: "{{ windows_gitea_runner_podman_service_user }}"
|
||||
register: __windows_gitea_runner_podman_current_image_hash
|
||||
changed_when: false
|
||||
|
||||
- name: Determine if runner image needs rebuild
|
||||
ansible.builtin.set_fact:
|
||||
__windows_gitea_runner_podman_needs_image_rebuild: >-
|
||||
{{
|
||||
(__windows_gitea_runner_podman_current_image_hash.stdout | trim)
|
||||
!= (__windows_gitea_runner_podman_desired_image_hash | trim)
|
||||
}}
|
||||
|
||||
- name: Rebuild runner image when Dockerfile changed
|
||||
ansible.windows.win_shell: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
$podman = "{{ windows_gitea_runner_podman_install_dir }}\podman.exe"
|
||||
& $podman build `
|
||||
--label "{{
|
||||
windows_gitea_runner_podman_image_hash_label
|
||||
}}={{ __windows_gitea_runner_podman_desired_image_hash }}" `
|
||||
--tag "{{ __windows_gitea_runner_podman_image }}" `
|
||||
--file "{{ __windows_gitea_runner_podman_build_dockerfile_dest }}" `
|
||||
"{{ __windows_gitea_runner_podman_build_dir }}"
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
exit 1
|
||||
}
|
||||
Write-Output "__BUILT__"
|
||||
become: true
|
||||
become_method: ansible.builtin.runas
|
||||
become_user: "{{ windows_gitea_runner_podman_service_user }}"
|
||||
register: __windows_gitea_runner_podman_build
|
||||
changed_when: "'__BUILT__' in __windows_gitea_runner_podman_build.stdout"
|
||||
when: __windows_gitea_runner_podman_needs_image_rebuild
|
||||
|
||||
- name: Read current runner container hash label
|
||||
ansible.windows.win_shell: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
$name = "{{ __windows_gitea_runner_podman_container_name }}"
|
||||
$podman = "{{ windows_gitea_runner_podman_install_dir }}\podman.exe"
|
||||
|
||||
$null = & $podman container exists $name 2>$null
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Output "__MISSING__"
|
||||
exit 0
|
||||
}
|
||||
|
||||
$raw = & $podman inspect $name --format json 2>$null
|
||||
if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($raw)) {
|
||||
Write-Output "__MISSING__"
|
||||
exit 0
|
||||
}
|
||||
|
||||
$obj = $raw | ConvertFrom-Json
|
||||
if ($obj -is [System.Array]) {
|
||||
$obj = $obj[0]
|
||||
}
|
||||
|
||||
$labels = $obj.Config.Labels
|
||||
if ($null -eq $labels) {
|
||||
Write-Output "__UNLABELED__"
|
||||
exit 0
|
||||
}
|
||||
|
||||
$key = "{{ windows_gitea_runner_podman_container_hash_label }}"
|
||||
$current = $labels.$key
|
||||
if ([string]::IsNullOrWhiteSpace($current)) {
|
||||
Write-Output "__UNLABELED__"
|
||||
exit 0
|
||||
}
|
||||
|
||||
Write-Output $current.Trim()
|
||||
become: true
|
||||
become_method: ansible.builtin.runas
|
||||
become_user: "{{ windows_gitea_runner_podman_service_user }}"
|
||||
register: __windows_gitea_runner_podman_current_hash
|
||||
changed_when: false
|
||||
|
||||
- name: Determine if runner container needs recreation
|
||||
ansible.builtin.set_fact:
|
||||
__windows_gitea_runner_podman_needs_recreate: >-
|
||||
{{
|
||||
(__windows_gitea_runner_podman_current_hash.stdout | trim)
|
||||
!= (__windows_gitea_runner_podman_desired_container_hash | trim)
|
||||
}}
|
||||
|
||||
- name: Remove stale runner container before recreate
|
||||
ansible.windows.win_shell: |
|
||||
$podman = "{{ windows_gitea_runner_podman_install_dir }}\podman.exe"
|
||||
& $podman rm -f "{{ __windows_gitea_runner_podman_container_name }}" 2>$null
|
||||
become: true
|
||||
become_method: ansible.builtin.runas
|
||||
become_user: "{{ windows_gitea_runner_podman_service_user }}"
|
||||
when: __windows_gitea_runner_podman_needs_recreate
|
||||
changed_when: true
|
||||
failed_when: false
|
||||
|
||||
- name: Ensure runner container is running
|
||||
ansible.windows.win_shell: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
$podman = "{{ windows_gitea_runner_podman_install_dir }}\podman.exe"
|
||||
$name = "{{ __windows_gitea_runner_podman_container_name }}"
|
||||
$exists = & $podman container exists $name
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
& $podman start $name 2>$null | Out-Null
|
||||
Write-Output "__STARTED_EXISTING__"
|
||||
exit 0
|
||||
}
|
||||
|
||||
& $podman run -d --name $name --restart "{{ windows_gitea_runner_podman_restart_policy }}" `
|
||||
@({{ __windows_gitea_runner_podman_run_args | map('to_json') | join(', ') }}) `
|
||||
--label "{{
|
||||
windows_gitea_runner_podman_container_hash_label
|
||||
}}={{ __windows_gitea_runner_podman_desired_container_hash }}" `
|
||||
-v "{{ __windows_gitea_runner_podman_data_dir }}:/data" `
|
||||
-e "CONFIG_FILE=/data/config.yaml" `
|
||||
-e "GITEA_INSTANCE_URL={{ windows_gitea_runner_podman_instance_url }}" `
|
||||
-e "GITEA_RUNNER_REGISTRATION_TOKEN={{ windows_gitea_runner_podman_registration_token }}" `
|
||||
-e "GITEA_RUNNER_NAME={{ __windows_gitea_runner_podman_name }}" `
|
||||
-e "GITEA_RUNNER_LABELS={{ __windows_gitea_runner_podman_labels }}" `
|
||||
{% if __windows_gitea_runner_podman_enable_nested_build %}
|
||||
-v "{{ __windows_gitea_runner_podman_storage_dir }}:/var/lib/containers" `
|
||||
-e "BUILDAH_ISOLATION=chroot" `
|
||||
-e "STORAGE_DRIVER=vfs" `
|
||||
{% endif %}
|
||||
"{{ __windows_gitea_runner_podman_image }}" | Out-Null
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Output "__CREATED__"
|
||||
become: true
|
||||
become_method: ansible.builtin.runas
|
||||
become_user: "{{ windows_gitea_runner_podman_service_user }}"
|
||||
register: __windows_gitea_runner_podman_container
|
||||
changed_when: "'__CREATED__' in __windows_gitea_runner_podman_container.stdout"
|
||||
no_log: true
|
||||
|
||||
- name: Verify runner container state
|
||||
ansible.windows.win_shell: |
|
||||
$podman = "{{ windows_gitea_runner_podman_install_dir }}\podman.exe"
|
||||
& $podman inspect "{{ __windows_gitea_runner_podman_container_name }}" --format "{{ '{{' }}.State.Status{{ '}}' }}"
|
||||
become: true
|
||||
become_method: ansible.builtin.runas
|
||||
become_user: "{{ windows_gitea_runner_podman_service_user }}"
|
||||
register: __windows_gitea_runner_podman_status
|
||||
changed_when: false
|
||||
failed_when: (__windows_gitea_runner_podman_status.stdout | trim) != 'running'
|
||||
|
||||
- name: Show tail of runner logs
|
||||
ansible.windows.win_shell: |
|
||||
$podman = "{{ windows_gitea_runner_podman_install_dir }}\podman.exe"
|
||||
& $podman logs --tail {{
|
||||
windows_gitea_runner_podman_container_log_tail }} "{{
|
||||
__windows_gitea_runner_podman_container_name }}"
|
||||
become: true
|
||||
become_method: ansible.builtin.runas
|
||||
become_user: "{{ windows_gitea_runner_podman_service_user }}"
|
||||
register: __windows_gitea_runner_podman_logs
|
||||
changed_when: false
|
||||
|
||||
- name: Print runner logs
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ __windows_gitea_runner_podman_logs.stdout | default('') }}"
|
||||
|
||||
- name: Build normalized runner log text
|
||||
ansible.builtin.set_fact:
|
||||
__windows_gitea_runner_podman_logs_all: >-
|
||||
{{
|
||||
[
|
||||
__windows_gitea_runner_podman_logs.stdout | default(''),
|
||||
__windows_gitea_runner_podman_logs.stderr | default('')
|
||||
] | join('\n') | lower
|
||||
}}
|
||||
|
||||
- name: Assert runner did not fail registration
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- "'invalid token' not in __windows_gitea_runner_podman_logs_all"
|
||||
- "'unauthorized' not in __windows_gitea_runner_podman_logs_all"
|
||||
- "'open config file' not in __windows_gitea_runner_podman_logs_all"
|
||||
- "'is a directory' not in __windows_gitea_runner_podman_logs_all"
|
||||
fail_msg: >-
|
||||
Gitea runner logs indicate a registration/startup failure. Check token,
|
||||
instance URL, and config mount path.
|
||||
Reference in New Issue
Block a user