ansiblehostnameansible-factsalmalinux

How do I `hostnamectl set-icon-name` via Ansible?


Red Hat has a command called hostnamectl set-icon-name. Is it correct to configure this using Ansible?

The usual command

ansible.builtin.shell: "hostnamectl set-icon-name {{ inventory_hostname }}"

is possible, of course, but with each pass the Ansible thinks that it is changing this parameter, which is not good.


Solution

  • "Red Hat has a command called hostnamectl ..."

    That's right. It is usually used in order to Changing a hostname. See also hostnamectl — Control the system hostname.

    Plase take note about What is different between Static hostname and Icon name and Pretty hostname in RHEL? and the fact that hostname != icon-name.

    icon-name [NAME]

    If no argument is given, print the icon name of the system. If an optional argument NAME is provided then the command changes the icon name to NAME. The icon name is used by some graphical applications to visualize this host. The icon name should follow the Icon Naming Specification.

    So, for a server the Icon name should probably set to computer, computer-vm or computer-server if not already

    ~/test$ hostnamectl
       Static hostname: test.example.com
             Icon name: computer-vm
               Chassis: vm
            Machine ID: 1234567890abcdefghijkl1234567890
               Boot ID: 1234567890abcdefghijkl1234567890
        Virtualization: microsoft
      Operating System: RHEL
           CPE OS Name: cpe:/o:redhat:enterprise_linux:7.9:GA:server
                Kernel: Linux 3.10.0-1160.105.1.el7.x86_64
          Architecture: x86-64
    
    ~/test$ hostnamectl
       Static hostname: test.example.com
             Icon name: computer-server
               Chassis: server
            Machine ID: 1234567890abcdefghijkl1234567890
               Boot ID: 1234567890abcdefghijkl1234567890
      Operating System: Red Hat Enterprise Linux 8.9 (Ootpa)
           CPE OS Name: cpe:/o:redhat:enterprise_linux:8::baseos
                Kernel: Linux 4.18.0-513.9.1.el8_9.x86_64
          Architecture: x86-64
    

    or according the mentioned naming convention to

    Icons for hardware that is contained within or connected to the computing device. Naming for extended devices in this group, is of the form <primary function>-<manufacturer>-<model>. This allows ease of fallback to the primary function device name, or ones more targeted for a specific series of models from a manufacturer.

    Since the Ansible hostname module – Manage hostname is for setting the hostname only

    Set system’s hostname. Supports most OSs/Distributions including those using systemd.

    one is left with a command module – Execute commands on targets and Defining "changed" since the hostname Exit status will be just be

    On success, 0 is returned, a non-zero failure code otherwise.

    and in order to gain Idempotency. This is also due to the fact that Ansible facts do not gather the Icon name and if no additional Custom facts are implemented.

    Is it correct to configure this using Ansible? The usual command ansible.builtin.shell: "hostnamectl set-icon-name {{ inventory_hostname }} is possible, of course, but with each pass the Ansible thinks that it is changing this parameter, which is not good.

    Finally, a minimal example playbook

    ---
    - hosts: localhost
      become: true
      gather_facts: false
    
      vars:
    
        ICON_NAME: computer-vm
    
      tasks:
    
      - name: Gather Facts via 'hostnamectl' without leading white-space
        shell: hostnamectl | sed "s/^[ \t]*//"
        register: HOSTNAMECTL
        # Since it is reporting task which should run in any case, set
        check_mode: false
        changed_when: false
    
      - name: Show Facts to get familiar with the data structure
        debug:
          msg: "{{ (HOSTNAMECTL.stdout | from_yaml) }}"
    
      - name: Set 'Icon name' via 'hostnamectl' idempotent
        command: hostnamectl set-icon-name {{ ICON_NAME }}
        when: (HOSTNAMECTL.stdout | from_yaml)['Icon name'] != ICON_NAME
    

    will result into an output of

    TASK [Gather Facts via 'hostnamectl' without leading white-spaces] *********************
    ok: [localhost]
    
    TASK [Show Facts to get familiar with the data structure] ******************************
    ok: [localhost] =>
      msg:
        Architecture: x86-64
        Boot ID: 1234567890abcdefghijkl1234567890
        CPE OS Name: cpe:/o:redhat:enterprise_linux:7.9:GA:server
        Chassis: vm
        Icon name: computer-vm
        Kernel: Linux 3.10.0-1160.105.1.el7.x86_64
        Machine ID: 1234567890abcdefghijkl1234567890
        Operating System: RHEL
        Static hostname: test.example.com
        Virtualization: microsoft
    
    PLAY RECAP *****************************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=1
    

    If a skipped tasks is not the desired behavior one could change the condition to

      - name: Set 'Icon name' via 'hostnamectl' idempotent
        command: hostnamectl set-icon-name {{ ICON_NAME }}
        changed_when: (HOSTNAMECTL.stdout | from_yaml)['Icon name'] != ICON_NAME