390 lines
14 KiB
YAML
390 lines
14 KiB
YAML
|
|
---
|
||
|
|
# ── Phase 1: Podman installer download & install ─────────────────────────
|
||
|
|
|
||
|
|
- name: Check if Podman is already installed
|
||
|
|
ansible.windows.win_shell: |
|
||
|
|
if (Get-Command podman -ErrorAction SilentlyContinue) {
|
||
|
|
Write-Output "__PODMAN_INSTALLED__"
|
||
|
|
exit 0
|
||
|
|
}
|
||
|
|
exit 1
|
||
|
|
become: true
|
||
|
|
become_method: ansible.builtin.runas
|
||
|
|
become_user: SYSTEM
|
||
|
|
register: __podman_installed_check
|
||
|
|
changed_when: false
|
||
|
|
failed_when: false
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
- name: Download Podman installer on remote host
|
||
|
|
ansible.windows.win_get_url:
|
||
|
|
url: "{{ windows_containers_installer_url }}"
|
||
|
|
dest: "{{ ansible_env.TEMP | default('C:\\Windows\\Temp') }}\\podman-installer.exe"
|
||
|
|
force: false
|
||
|
|
become: true
|
||
|
|
become_method: ansible.builtin.runas
|
||
|
|
become_user: SYSTEM
|
||
|
|
when: __podman_installed_check.rc != 0
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
- name: Install Podman silently
|
||
|
|
ansible.windows.win_shell: |
|
||
|
|
Start-Process "{{ ansible_env.TEMP | default('C:\\Windows\\Temp') }}\podman-installer.exe" -ArgumentList @("/S", "/D={{ windows_containers_install_dir }}") -Wait
|
||
|
|
exit $LASTEXITCODE
|
||
|
|
become: true
|
||
|
|
become_method: ansible.builtin.runas
|
||
|
|
become_user: SYSTEM
|
||
|
|
register: __podman_install_result
|
||
|
|
changed_when: __podman_install_result.rc == 0
|
||
|
|
when: __podman_installed_check.rc != 0
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
- name: Clean up Podman installer
|
||
|
|
ansible.windows.win_file:
|
||
|
|
path: "{{ ansible_env.TEMP | default('C:\\Windows\\Temp') }}\\podman-installer.exe"
|
||
|
|
state: absent
|
||
|
|
become: true
|
||
|
|
become_method: ansible.builtin.runas
|
||
|
|
become_user: SYSTEM
|
||
|
|
when: __podman_installed_check.rc != 0
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
- name: Add Podman to PATH if not already present
|
||
|
|
ansible.windows.win_path:
|
||
|
|
name: Path
|
||
|
|
elements:
|
||
|
|
- "{{ windows_containers_install_dir }}"
|
||
|
|
state: present
|
||
|
|
become: true
|
||
|
|
become_method: ansible.builtin.runas
|
||
|
|
become_user: SYSTEM
|
||
|
|
when: __podman_installed_check.rc != 0
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
# ── Phase 2: Dedicated service user ──────────────────────────────────────
|
||
|
|
|
||
|
|
- name: Fail when podman service password is missing
|
||
|
|
ansible.builtin.fail:
|
||
|
|
msg: >-
|
||
|
|
windows_containers_service_password must be provided to configure service account
|
||
|
|
.\\{{ windows_containers_service_user }} for NSSM.
|
||
|
|
when: windows_containers_service_password | length == 0
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
- name: Create dedicated podman service user
|
||
|
|
ansible.windows.win_user:
|
||
|
|
name: "{{ windows_containers_service_user }}"
|
||
|
|
password: "{{ windows_containers_service_password }}"
|
||
|
|
account_disabled: false
|
||
|
|
password_never_expires: true
|
||
|
|
user_cannot_change_password: true
|
||
|
|
state: present
|
||
|
|
become: true
|
||
|
|
become_method: ansible.builtin.runas
|
||
|
|
become_user: SYSTEM
|
||
|
|
when:
|
||
|
|
- windows_containers_service_password | length > 0
|
||
|
|
no_log: true
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
- name: Get localized Users group name via PowerShell
|
||
|
|
ansible.windows.win_powershell:
|
||
|
|
script: |
|
||
|
|
$sid = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-545")
|
||
|
|
$ntAccount = $sid.Translate([System.Security.Principal.NTAccount])
|
||
|
|
# Handle both local and domain accounts - take the last part after backslash
|
||
|
|
$parts = $ntAccount.Value -split '\\'
|
||
|
|
$parts[-1]
|
||
|
|
register: __users_group_name
|
||
|
|
changed_when: false
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
- name: Debug localized Users group name
|
||
|
|
ansible.builtin.debug:
|
||
|
|
msg: "Localized Users group name is '{{ __users_group_name.output | first }}'"
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
- name: Add podman service user to Users group for interactive login
|
||
|
|
ansible.windows.win_group_membership:
|
||
|
|
name: "{{ __users_group_name.output | first }}"
|
||
|
|
members:
|
||
|
|
- ".\\{{ windows_containers_service_user }}"
|
||
|
|
state: present
|
||
|
|
become: true
|
||
|
|
become_method: ansible.builtin.runas
|
||
|
|
become_user: SYSTEM
|
||
|
|
when:
|
||
|
|
- windows_containers_service_password | length > 0
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
- name: Grant "Log on as a service" right to podman service account
|
||
|
|
ansible.windows.win_user_right:
|
||
|
|
name: SeServiceLogonRight
|
||
|
|
users:
|
||
|
|
- ".\\{{ windows_containers_service_user }}"
|
||
|
|
action: add
|
||
|
|
become: true
|
||
|
|
become_method: ansible.builtin.runas
|
||
|
|
become_user: SYSTEM
|
||
|
|
when:
|
||
|
|
- windows_containers_service_password | length > 0
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
- name: Grant "Log on locally" right to podman service account (required for Ansible become)
|
||
|
|
ansible.windows.win_user_right:
|
||
|
|
name: SeInteractiveLogonRight
|
||
|
|
users:
|
||
|
|
- ".\\{{ windows_containers_service_user }}"
|
||
|
|
action: add
|
||
|
|
become: true
|
||
|
|
become_method: ansible.builtin.runas
|
||
|
|
become_user: SYSTEM
|
||
|
|
when:
|
||
|
|
- windows_containers_service_password | length > 0
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
- name: Grant "Log on as a batch job" right to podman service account
|
||
|
|
ansible.windows.win_user_right:
|
||
|
|
name: SeBatchLogonRight
|
||
|
|
users:
|
||
|
|
- ".\\{{ windows_containers_service_user }}"
|
||
|
|
action: add
|
||
|
|
become: true
|
||
|
|
become_method: ansible.builtin.runas
|
||
|
|
become_user: SYSTEM
|
||
|
|
when:
|
||
|
|
- windows_containers_service_password | length > 0
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
# ── Phase 3: Podman machine setup ──────────────────────────────────────
|
||
|
|
|
||
|
|
- name: Get Podman executable path
|
||
|
|
ansible.windows.win_shell: where.exe podman.exe 2>&1
|
||
|
|
become: true
|
||
|
|
become_method: ansible.builtin.runas
|
||
|
|
become_user: SYSTEM
|
||
|
|
register: __podman_where
|
||
|
|
changed_when: false
|
||
|
|
failed_when: false
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
- name: Set Podman executable path from where output
|
||
|
|
ansible.builtin.set_fact:
|
||
|
|
__podman_exe: "{{ (__podman_where.stdout_lines | last).strip() }}"
|
||
|
|
when:
|
||
|
|
- __podman_where is not failed
|
||
|
|
- __podman_where.stdout | trim != ""
|
||
|
|
|
||
|
|
- name: Default Podman executable path if not on PATH or where failed
|
||
|
|
ansible.builtin.set_fact:
|
||
|
|
__podman_exe: "{{ windows_containers_install_dir }}\\podman.exe"
|
||
|
|
when: __podman_where is failed or __podman_where.stdout | trim == ""
|
||
|
|
|
||
|
|
# ── Phase 4: Podman machine init ────────────────────────────────────────
|
||
|
|
|
||
|
|
- name: Initialize Podman machine
|
||
|
|
ansible.windows.win_shell: |
|
||
|
|
$machinesJson = (podman machine ls --format json 2>$null | Out-String).Trim()
|
||
|
|
$machines = @()
|
||
|
|
if ($machinesJson) {
|
||
|
|
$machines = $machinesJson | ConvertFrom-Json
|
||
|
|
}
|
||
|
|
|
||
|
|
$machine = $machines | Where-Object { $_.Name -eq "{{ windows_containers_machine_name }}" } | Select-Object -First 1
|
||
|
|
if (-not $machine) {
|
||
|
|
podman machine init "{{ windows_containers_machine_name }}" --cpus {{ windows_containers_machine_cpus }} --memory {{ windows_containers_machine_memory }} --disk-size {{ windows_containers_machine_disk_size }}
|
||
|
|
if ($LASTEXITCODE -ne 0) {
|
||
|
|
Write-Error "Failed to initialize Podman machine {{ windows_containers_machine_name }}"
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
|
||
|
|
$afterInitJson = (podman machine ls --format json 2>$null | Out-String).Trim()
|
||
|
|
$afterInitMachines = @()
|
||
|
|
if ($afterInitJson) {
|
||
|
|
$afterInitMachines = $afterInitJson | ConvertFrom-Json
|
||
|
|
}
|
||
|
|
|
||
|
|
$createdMachine = $afterInitMachines | Where-Object { $_.Name -eq "{{ windows_containers_machine_name }}" } | Select-Object -First 1
|
||
|
|
if (-not $createdMachine) {
|
||
|
|
Write-Error "Podman machine {{ windows_containers_machine_name }} is still missing after init"
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
|
||
|
|
Write-Output "__PODMAN_MACHINE_CREATED__"
|
||
|
|
}
|
||
|
|
become: true
|
||
|
|
become_method: ansible.builtin.runas
|
||
|
|
become_user: "{{ windows_containers_service_user }}"
|
||
|
|
register: __podman_init
|
||
|
|
changed_when: "'__PODMAN_MACHINE_CREATED__' in (__podman_init.stdout + __podman_init.stderr)"
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
- name: Start Podman machine on boot via NSSM service only
|
||
|
|
ansible.windows.win_shell: |
|
||
|
|
# Podman machine will be started on boot via NSSM service (PodmanAutoStart)
|
||
|
|
# No need to start it during playbook execution
|
||
|
|
podman machine status "{{ windows_containers_machine_name }}" 2>$null | Out-Null
|
||
|
|
$status = $LASTEXITCODE
|
||
|
|
if ($status -eq 0) {
|
||
|
|
Write-Output "Podman machine {{ windows_containers_machine_name }} is already running"
|
||
|
|
exit 0
|
||
|
|
}
|
||
|
|
Write-Output "Podman machine not running (will start on boot)"
|
||
|
|
exit 0
|
||
|
|
become: true
|
||
|
|
become_method: ansible.builtin.runas
|
||
|
|
become_user: "{{ windows_containers_service_user }}"
|
||
|
|
register: __podman_status_check
|
||
|
|
changed_when: false
|
||
|
|
failed_when: false
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
- name: Deploy Podman auto-start PowerShell script
|
||
|
|
ansible.windows.win_template:
|
||
|
|
src: podman-auto-start.ps1.j2
|
||
|
|
dest: "{{ windows_containers_install_dir }}\\auto-start-podman.ps1"
|
||
|
|
mode: "0644"
|
||
|
|
become: true
|
||
|
|
become_method: ansible.builtin.runas
|
||
|
|
become_user: SYSTEM
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
- name: Deploy batch wrapper to avoid path-with-spaces issues in NSSM
|
||
|
|
ansible.windows.win_template:
|
||
|
|
src: podman-auto-start.bat.j2
|
||
|
|
dest: "{{ windows_containers_install_dir }}\\auto-start-podman.bat"
|
||
|
|
mode: "0644"
|
||
|
|
become: true
|
||
|
|
become_method: ansible.builtin.runas
|
||
|
|
become_user: SYSTEM
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
- name: Delete existing PodmanAutoStart service via NSSM
|
||
|
|
ansible.windows.win_shell: |
|
||
|
|
$existing = Get-CimInstance Win32_Service -Filter "Name='PodmanAutoStart'" -ErrorAction SilentlyContinue
|
||
|
|
if ($existing) {
|
||
|
|
Stop-Service -Name PodmanAutoStart -Force -ErrorAction SilentlyContinue
|
||
|
|
Start-Sleep -Seconds 2
|
||
|
|
$null = nssm.exe remove PodmanAutoStart confirm
|
||
|
|
Start-Sleep -Seconds 2
|
||
|
|
}
|
||
|
|
become: true
|
||
|
|
become_method: ansible.builtin.runas
|
||
|
|
become_user: SYSTEM
|
||
|
|
changed_when: true
|
||
|
|
failed_when: false
|
||
|
|
no_log: true
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
- name: Register Podman auto-start service via NSSM (batch wrapper for proper path quoting)
|
||
|
|
ansible.windows.win_shell: |
|
||
|
|
$installDir = "{{ windows_containers_install_dir }}"
|
||
|
|
$batchPath = Join-Path $installDir "auto-start-podman.bat"
|
||
|
|
nssm.exe install PodmanAutoStart "`"$batchPath`""
|
||
|
|
become: true
|
||
|
|
become_method: ansible.builtin.runas
|
||
|
|
become_user: SYSTEM
|
||
|
|
changed_when: false
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
- name: Create log directory for Podman auto-start
|
||
|
|
ansible.windows.win_file:
|
||
|
|
path: C:\Logs\Podman
|
||
|
|
state: directory
|
||
|
|
become: true
|
||
|
|
become_method: ansible.builtin.runas
|
||
|
|
become_user: SYSTEM
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
- name: Grant podman service user full control over log directory
|
||
|
|
ansible.windows.win_acl:
|
||
|
|
path: C:\Logs\Podman
|
||
|
|
user: ".\\{{ windows_containers_service_user }}"
|
||
|
|
rights: FullControl
|
||
|
|
type: allow
|
||
|
|
state: present
|
||
|
|
inherit: ContainerInherit, ObjectInherit
|
||
|
|
propagation: None
|
||
|
|
become: true
|
||
|
|
become_method: ansible.builtin.runas
|
||
|
|
become_user: SYSTEM
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
- name: Configure Podman auto-start service via NSSM
|
||
|
|
ansible.windows.win_shell: |
|
||
|
|
$installDir = "{{ windows_containers_install_dir }}"
|
||
|
|
nssm.exe set PodmanAutoStart AppDirectory $installDir
|
||
|
|
nssm.exe set PodmanAutoStart DisplayName "Podman Auto Start"
|
||
|
|
nssm.exe set PodmanAutoStart Description "Starts Podman machine and containers on boot"
|
||
|
|
nssm.exe set PodmanAutoStart Start SERVICE_AUTO_START
|
||
|
|
nssm.exe set PodmanAutoStart AppRestartDelay 30000
|
||
|
|
nssm.exe set PodmanAutoStart AppStdout "C:\Logs\Podman\auto-start.log"
|
||
|
|
nssm.exe set PodmanAutoStart AppStderr "C:\Logs\Podman\auto-start-error.log"
|
||
|
|
become: true
|
||
|
|
become_method: ansible.builtin.runas
|
||
|
|
become_user: SYSTEM
|
||
|
|
changed_when: false
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
- name: Set PodmanAutoStart service account via NSSM
|
||
|
|
ansible.windows.win_shell: |
|
||
|
|
nssm.exe set PodmanAutoStart ObjectName ".\{{ windows_containers_service_user }}" "{{ windows_containers_service_password }}"
|
||
|
|
become: true
|
||
|
|
become_method: ansible.builtin.runas
|
||
|
|
become_user: SYSTEM
|
||
|
|
changed_when: true
|
||
|
|
no_log: true
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
|
||
|
|
- name: Start PodmanAutoStart service
|
||
|
|
ansible.windows.win_shell: |
|
||
|
|
$svc = Get-CimInstance Win32_Service -Filter "Name='PodmanAutoStart'" -ErrorAction SilentlyContinue
|
||
|
|
if ($svc -and $svc.State -ne 'Running') {
|
||
|
|
nssm.exe start PodmanAutoStart
|
||
|
|
Start-Sleep -Seconds 5
|
||
|
|
$svc = Get-CimInstance Win32_Service -Filter "Name='PodmanAutoStart'"
|
||
|
|
Write-Output "PodmanAutoStart service state: $($svc.State)"
|
||
|
|
} else {
|
||
|
|
Write-Output "PodmanAutoStart service already running or not found"
|
||
|
|
}
|
||
|
|
become: true
|
||
|
|
become_method: ansible.builtin.runas
|
||
|
|
become_user: SYSTEM
|
||
|
|
register: __podman_auto_start_service
|
||
|
|
changed_when: "'state: Running' in (__podman_auto_start_service.stdout)"
|
||
|
|
failed_when: false
|
||
|
|
tags:
|
||
|
|
- roles::windows_containers::podman_install
|
||
|
|
# ansible.windows.win_shell: podman pull "{{ windows_containers_image }}"
|
||
|
|
# become: true
|
||
|
|
# become_method: ansible.builtin.runas
|
||
|
|
# become_user: "{{ windows_containers_service_user }}"
|
||
|
|
# register: __podman_pull
|
||
|
|
# changed_when: false
|
||
|
|
# tags:
|
||
|
|
# - roles::windows_containers::podman_install
|