Ansible

Seems the Ansible users must belong to the local administrators of the machines it tries to manipulate (on Windows 10 at least, the Remote Management group is not even enough to gather facts).

Tasks

Do not stop when a task fails

- name: do something
  win_shell: something
  failed_when: False
  changed_when: False

https://medium.com/@sbarnea/why-ansible-ignore-errors-is-evil-500fb6e81229

Run a role

---
- hosts: all
  gather_facts: False
  tasks:
    - include_role:
        name: rolename

Retry an intermittent error

- name: Test failure
  command: "bash -c 'exit $(( $RANDOM % 4 ))'"
  register: result
  retries: 5
  delay: 10
  until: result is not failed
  ignore_errors: True

- debug: var=result

https://curiousdba.netlify.app/post/ansibleretries/

Loops

https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html

Simple loop

- name: Create a temporary directory
  ansible.builtin.tempfile:
    path: /my/path
    state: directory
  register: tempdir

- name: Download files
  get_url:
    url: "ftp://my.anonymous.server/files/{{ item }}"
    dest: "{{ tempdir.path }}/{{ item }}"
    mode: +x
  loop:
    - "file01.txt"
    - "file02.txt"
    - "file03.txt"

The mode: +x is only needed there’s an executable that is supposed to be run afterwards.

Advanced loop

- name: DaVinci resolve - Set Firewall rule
  vars:
    applications:
    - name: DaVinci Resolve
      path: C:\program files\blackmagic design\davinci resolve\resolve.exe
    - name: FusionScript services for Fusion
      path: C:\program files\blackmagic design\davinci resolve\fuscript.exe
    - name: dpdecoder
      path: C:\program files\blackmagic design\davinci resolve\dpdecoder.exe
  community.windows.win_firewall_rule:
    name: '{{ item[0].name }} ({{ item[1] }})'
    group: DaVinci Resolve
    description: '{{ item[0].name }}'
    program: '{{ item[0].path }}'
    profiles: domain
    localport: any
    protocol: '{{ item[1] }}'
  loop: "{{ applications |product(['udp', 'tcp'])|list }}"

https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#combining-lists

Conditional execution

With when

- name: Remove previous splashtop versions
  ansible.windows.win_package:
    product_id: '{C8BC0F03-D53F-4f19-B42F-06CB733C09E4}'
    state: absent
  become: yes
  when: software_version.win_file_version.file_version != "3.46.9.7769"

With block – when

- name: fetch Splashtop Streamer version
  ansible.builtin.command: defaults read "/Applications/Splashtop Streamer.app/Contents/Info.plist" CFBundleShortVersionString
  register: app_version

- block:
  - name: Create a temporary directory
    ansible.builtin.tempfile:
      path: /my/path
      state: directory
    register: tempdir
  - name: Use the registered var and the file module to remove the temporary folder
    ansible.builtin.file:
      path: "{{ tempdir.path }}"
      state: absent
    when: tempdir.path is defined
  when: app_version.stdout != "3.4.6.1"

Collections

Install an ansible galaxy collection

ansible-galaxy collection install ansible.windows

ansible.builtin

ansible.builtin.command – Execute commands on targets

- name: fetch Splashtop Streamer version
  ansible.builtin.command: defaults read "/Applications/Splashtop Streamer.app/Contents/Info.plist" CFBundleShortVersionString
  register: app_version

ansible.builtin.debug – Print statements during execution

Debug message
# Example that prints return information from the previous task
- shell: /usr/bin/uptime
  register: result

- debug:
    var: result
    verbosity: 2
Conditional debug message
- name: fetch Cinema4D R21 version
  community.windows.win_file_version:
    path: 'C:\Program Files\Maxon Cinema 4D R21\CINEMA 4D.exe'
  register: C4DR21_version
  failed_when: False
- debug:
    msg: "C4DR21 version: {% if C4DR21_version.win_file_version.file_version is defined %}{{ C4DR21_version.win_file_version.file_version }}{% else %}Not installed{% endif %}"

ansible.builtin.setup – Gathers facts about remote hosts

- name: Collect facts
  ansible.builtin.setup:
    gather_subset:
      - min

gather_subset: Possible values: all, min, hardware, network, virtual, ohai, and facter.

ansible.builtin.slurp – Slurps a file from remote nodes

- name: get content of remote file
  slurp:
    src: "{{remote_path}}"
  register: remote_content_encoded

- name: decode remote content
  set_fact:
    remote_content: "{{remote_content_encoded.content | b64decode}}"

- debug:
    msg: "content of remote file {{remote_path}}: {{remote_content}}"

https://fabianlee.org/2021/05/25/ansible-creating-a-variable-from-a-remote-or-local-file-content/

ansible.windows

ansible.windows.win_shell – Execute shell commands on target hosts

- name: Uninstall AWS Thinkbox Deadline Client
  ansible.windows.win_shell: '& "$Env:ProgramFiles\Thinkbox\Deadline10\uninstall.exe" --mode unattended'
  become: yes

So the path to the exe must be in double quotes, the entire command in single quotes and $Env:ProgramFiles is used (instead of %programfiles% which only works with cmd.exe).

ansible.windows.win_package – Installs/uninstalls an installable package

- name: Install Maxon Cinema4D_S26_26.014
  ansible.windows.win_package:
    path: '{{ deployment_folder }}\Maxon\C4Dr26\Cinema4D_S26_26.014_Win.exe'
    arguments: --mode unattended --unattendedmodeui none
    creates_path: 'C:\Program Files\Maxon Cinema 4D R26\Cinema 4D.exe'
    creates_version: 26.0.1.4
    product_id: "Maxon Cinema 4D R26"
    state: present
  become: yes
Uninstall registry path
HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall
HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall
HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall
HKCU:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall

Doc: https://docs.ansible.com/ansible/latest/collections/ansible/windows/win_package_module.html#ansible-windows-win-package-module-installs-uninstalls-an-installable-package

community.windows

community.windows.win_robocopy – Synchronizes the contents of two directories using Robocopy

If flags is set, purge and recurse will be ignored.

- name: Ensure the Redshift Core folder is copied to C:\ProgramData
  become: yes
  community.windows.win_robocopy:
    src: '{{ library_folder }}\PLUGINS\C4D_v002\redshift\redshift_v2.6.52_flt\Redshift\'
    dest: C:\ProgramData\Redshift\
    recurse: yes
    purge: yes
    #flags: /v
  register: result

- debug:
    var: result.output

https://docs.ansible.com/ansible/latest/collections/community/windows/win_robocopy_module.html

community.windows.psexec – Runs commands on a remote Windows host based on the PsExec model

- name: Test the PsExec connection to the local system (target node) with your user
  win_psexec:
    command: 'Powershell Add-WindowsCapability -Online -Name "SNMP.Client~~~~0.0.1.0"'

community.windows.win_file_version – Get DLL or EXE file build version

- name: fetch software version
  community.windows.win_file_version:
    path: 'C:\Program Files\Maxon Cinema 4D R24\Cinema 4D.exe'
  register: software_version

Utilities

ansible-playbook – run an ansible playbook

--ask-vault-password, --ask-vault-passask for vault password
--vault-password-file, --vault-pass-filevault password file
-e, --extra-varsset additional variables as key=value or YAML/JSON, if filename prepend with @
-i, --inventory, --inventory-filespecify inventory host path or comma separated host list. –inventory-file is deprecated
-l <SUBSET>, --limit <SUBSET>further limit selected hosts to an additional pattern
-v, --verboseverbose mode (-vvv for more, -vvvv to enable connection debugging)

https://docs.ansible.com/ansible/latest/cli/ansible-playbook.html

Add variables in command line

ansible-playbook -i production.yml --vault-password-file ~/vault_password add_new_project.yml --extra-vars "new_project=XXXX_Testpermissions"
ansible-playbook -i production.yml --vault-password-file ~/vault_password add_new_project.yml --extra-vars "client=myclient new_project=myproject"
ansible-playbook -i production.yml play_test.yml --limit rendernodes
ansible-playbook --ask-vault-pass -i production.yml play_test.yml --limit test

https://linux.die.net/man/1/ansible-playbook

Installation

Kerberos python plugin needed on Turnkey Ansible:

apt install python3-kerberos krb5-user

edit /etc/krb5.conf (change only realms and domain_realm):

[logging]
  default = FILE:/var/log/krb5libs.log
  kdc = FILE:/var/log/krb5kdc.log
  admin_server = FILE:/var/log/kadmind.log

[libdefaults]
        default_realm = EXAMPLE.COM

[realms]
        EXAMPLE.COM = {
                kdc = domain-controller1.example.com
                kdc = domain-controller2.example.com
                default_domain = example.com
        }

[domain_realm]
        .example.com = EXAMPLE.COM
        example.com = EXAMPLE.COM

[login]

test (case is important !):

klist
kinit myuser@EXAMPLE.COM

https://blog.geralexgr.com/ansible/bad-http-response-returned-from-server-code-500-ansible-authentication

GPO to allow WinRM for Ansible

TODO

Archived

Run an arbitrary powershell one liner (the double quotes must be escaped inside)

this seems wrong, there’s a powershell module: “ansible.windows.win_shell”

---
- name: Uninstall Office ProPlus
  hosts: all
  gather_facts: no
  tasks:
    - name: removes old shortcuts
      win_command: powershell -command "Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList' | ForEach-Object { $profilePath = $_.GetValue('ProfileImagePath') ; Remove-Item -Path \"$profilePath\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\*2010*\" }"

Check C4D version

the right way to go is to use ‘community.windows.win_file_version’

---
- name: fetch Cinema4D r19 version
  hosts: all
  gather_facts: no
  tasks:
    - win_shell: '& "C:\Program Files\MAXON\Cinema 4D R19\Commandline.exe" | Select-String -Pattern "Version / Build"'
      register: C4Dr19_version
    - debug:
        var: C4Dr19_version.stdout_lines[1]