Server Fault
Server Fault

Reputation: 635

Changing ansible loop due to v2.11 deprecation

I'm running a playbook which defined several packages to install via apt:

    - name: Install utility packages common to all hosts
      apt:
        name: "{{ item }}"
        state: present
        autoclean: yes
      with_items:
        - aptitude
        - jq
        - curl
        - git-core
        - at
...

A recent ansible update on my system now renders this message concerning the playbook above:

[DEPRECATION WARNING]: Invoking "apt" only once while using a loop via squash_actions is deprecated. Instead of
 using a loop to supply multiple items and specifying `name: {{ item }}`, please use `name: [u'aptitude', 
u'jq', u'curl', u'git-core', u'at', u'heirloom-mailx', u'sudo-ldap', u'sysstat', u'vim', u'at', u'ntp', 
u'stunnel', u'sysstat', u'arping', u'net-tools', u'lshw', u'screen', u'tmux', u'lsscsi']` and remove the loop. 

If I'm understanding this correctly, Ansible now wants this list of packages as an array which leaves this:

name: [u'aptitude', u'jq', u'curl', u'git-core', u'at','heirloom-mailx', u'sudo-ldap', u'sysstat', u'vim', u'at', u'ntp',u'stunnel', u'sysstat', u'arping', u'net-tools', u'lshw', u'screen', u'tmux', u'lsscsi']

Is there a better way? Just seems like I'll be scrolling right forever in VIM trying to maintain this. Either that, or word wrap it and deal with a word-cloud of packages.

Upvotes: 25

Views: 15100

Answers (4)

Marcin Orlowski
Marcin Orlowski

Reputation: 75645

For a record, you can have this written this way:

    - name: Install utility packages common to all hosts
      apt:
        state: present
        autoclean: yes
        pkg: [
          "aptitude",
          "jq",
          "curl",
          "git-core",
          "at",
        ]

however if you are upgrading existing roles to new apt's requirements, Ignacio's accepted answer is far better as all you need is just to add some indentation to already existing entries.

Upvotes: 0

Nick
Nick

Reputation: 91

I came across this exact same problem , but with a much longer list of apps , held in a vars file. This is the code I implemented to get around that problem. The list of the apps is placed into the "apps" variable and Ansible iterates over that.

- name: Install default applications
  apt:
    name: "{{item}}"
    state: latest
  loop: "{{ apps }}"
  when: ansible_distribution == 'Ubuntu' or ansible_distribution == 'Debian'
  tags:
     - instapps

The file holding the list of apps to install is in the Defaults directory in the role directory for this task - namely the "common" role directory.

roles
    - common
      - Defaults
        - main.yml

Upvotes: 2

Sikh
Sikh

Reputation: 21

I had this same question and it looks like each set of packages with the same states will have to be their own block. Looking at Ansible's documentation, they have a block for each state as an example so I took that example, cut up my packages based off their states and followed ignacio's example and it ended up working perfectly.

So basically it would look like this

- name: Install packages required for log-deployment
  apt:
    name:
      - gcc
      - python-devel
    state: latest
    autoclean: yes

- name: Install packages required for log-deployment
  apt:
    name:
      - python
      - mariadb
      - mysql-devel
    state: installed

Hope that makes sense and helps!

Upvotes: 2

Ignacio Millán
Ignacio Millán

Reputation: 8076

You can code the array in YAML style to make it more readable:

- name: Install utility packages common to all hosts
  apt:
    name:
      - aptitude
      - jq
      - curl
      - git-core
      - at
    state: present
    autoclean: yes

Upvotes: 78

Related Questions