Need help with deprecation warnings

Hey all,

Just trying to figure out how to fix the deprecation warnings (recently updated to 2.1.1.0 from 1.7). I used to have the 4 individual tasks in the block below (I left the commented out when statements from the original 1.7 tasks). I tried refactoring a couple of times, but with the current setup, I still get “Skipping task due to undefined Error, in the future this will be a fatal error.: ‘project_config’ is undefined.” on all 4 tasks when project_config is undefined. Shouldn’t the block just skip the tasks? Is there something I’m missing about how blocks are executed? Is there a better way to rewrite this set of tasks?

  • block:
  • name: Install system dependencies for project
    become: True
    apt: pkg={{ item }} state=installed
    with_items: " {{ project_config.apt|default() }}"

when: project_config is defined and ‘apt’ in project_config

  • name: Install pip dependencies for project from files
    pip: requirements={{ full_project_root }}/project_config/{{ item }}
    virtualenv_command=virtualenv
    virtualenv={{ venvdir }}
    virtualenv_python={{ venv_python }}
    virtualenv_site_packages=no
    state=present
    with_items: “{{ project_config.pip_files|default() }}”

when: project_config is defined and ‘pip_files’ in project_config

environment: “{{ pip_internal }}”

  • name: Install npm dependencies
    npm: path=“{{ full_project_root }}/project_config/{{ item }}”
    state=latest
    production={{ npm_production }}
    with_items: “{{ project_config.npm_package_json_path|default() }}”

when: project_config is defined and ‘npm_package_json_path’ in project_config

  • name: Run Django server setup commands
    django_manage: command={{ item }}
    app_path={{ django_manage_path }}
    virtualenv={{ venvdir }}
    settings={{ app_module }}.settings.{{ env }}
    with_items: “{{ project_config.django_commands|default() }}”

when: project_config is defined and ‘django_commands’ in project_config

when: project_config is defined

Thanks.

Hey all,

Just trying to figure out how to fix the deprecation warnings (recently
updated to 2.1.1.0 from 1.7). I used to have the 4 individual tasks in the
block below (I left the commented out when statements from the original 1.7
tasks). I tried refactoring a couple of times, but with the current setup,
I still get "Skipping task due to undefined Error, in the future this will
be a fatal error.: 'project_config' is undefined." on all 4 tasks when
project_config is undefined. Shouldn't the block just skip the tasks?

You would think so, since the documentation says
"...tasks will be executed after appending the when condition from the block and evaluating it in the task’s context."

Is
there something I'm missing about how blocks are executed? Is there a
better way to rewrite this set of tasks?

- block:
    - name: Install system dependencies for project
      become: True
      apt: pkg={{ item }} state=installed
      with_items: " {{ project_config.apt|default() }}"
      # when: project_config is defined and 'apt' in project_config

If project_config is not defined this will work
   with_items: "{{ project_config | default() }}"

but thees two will give a deprecation warning
   with_items: "{{ project_config.apt | default() }}"
   with_items: "{{ project_config['apt'] | default() }}"

To me this looks like a bug.

Is
there something I'm missing about how blocks are executed? Is there a
better way to rewrite this set of tasks?

- block:
    - name: Install system dependencies for project
      become: True
      apt: pkg={{ item }} state=installed
      with_items: " {{ project_config.apt|default() }}"
      # when: project_config is defined and 'apt' in project_config

This will work.
First project_config need to be filtered through default, and then project_config.apt.

   with_items: " {{ (project_config | default()).apt | default() }}"

If project_config is not defined this will work
  with_items: "{{ project_config | default() }}"

but thees two will give a deprecation warning
  with_items: "{{ project_config.apt | default() }}"
  with_items: "{{ project_config['apt'] | default() }}"

To me this looks like a bug.

This is not a bug, please disregards my statement.

Thanks for the sleuthing.

It seems like using a “is-defined” check as a conditional is pointless if we have to send everything through default anyway. I understand the change for loops (since it checks each item now), but this behavior seems really counter-intuitive for blocks. What’s even the point of grouping it into a block if I have to set those default filters on each task? It’s just going back to being 4 separate tasks.

blocks let you do 2 things, handle errors and ‘share settings’, the conditional does not affect the block itself, it is a way to allow all tasks to inherit it, instead of writing it N times.

I’ve been bitten by this too. In my case I had this:

  • name: Create plain FTP groups
    group: name={{ item.user }} gid={{ item.uid }} state={{ item.state|default(‘present’) }}
    with_items: “{{ customer_ftp_accounts[inventory_hostname] }}”

when: inventory_hostname in customer_ftp_account

I got this error:

TASK [customer_sftp : Create plain FTP groups] *********************************
[DEPRECATION WARNING]: Skipping task due to undefined Error, in the future this will be a fatal error.: ‘dict object’ has no attribute u’internal’.
This feature will be removed in a future release. Deprecation warnings can be disabled by setting
deprecation_warnings=False in ansible.cfg.
skipping: [myserver]

It threw me off because it’s purple and says “DEPRECATION WARNING”, but it’s just a regular error really. It does what I want, in so much as it skips hosts not in a particular list, but I could do without the error. It’s of course fixed like this:

  • name: Create plain FTP groups
    group: name={{ item.user }} gid={{ item.uid }} state={{ item.state|default(‘present’) }}
    with_items: “{{ customer_ftp_accounts[inventory_hostname]|default() }}”

I’ve put a comment in the file which describes it like this:

If using “with_items”, the “when” is evaluated on each iteration of the loop, and not when looking at the task as a whole. As such, trying to ‘lock out’ the task with a “when” won’t work, and instead we have to default the “with_items” with an empty list if we don’t want to run the loop at all.

Taking a ‘step back’ from this, it makes sense for Ansible to work this way, but it can easily catch you out as a single task (with no “with_items”) works in a way you may mentally extrapolate out to loops.

…Ralph

This does not remove the deprecation warning for me in 2.1.2.0

It does, if it doesn't work for you, you should show us your code so we can help.

Sorry, I was wrong. This does indeed remove the warning.

note the change, only the last one is an empty list , if
project_config is undefined it should be an empty hash/dictionary, as
.apt can only be part of that and not a list. Default will need to
return what is expected of the 'next step'

with_items: " {{ (project_config | default({})).apt | default() }}"

My experience is that it doesn't matter it I use {}, or a mix, it works either way.

   - name: " "
     debug: msg="This will not print {{ item }}"
     with_items: " {{ (project_config | default()).apt | default() }}"

   - name: "{} "
     debug: msg="This will not print {{ item }}"
     with_items: " {{ (project_config | default({})).apt | default() }}"

   - name: " {}"
     debug: msg="This will not print {{ item }}"
     with_items: " {{ (project_config | default()).apt | default({}) }}"

   - name: "{} {}"
     debug: msg="This will not print {{ item }}"
     with_items: " {{ (project_config | default({})).apt | default({}) }}"

TASK [ ] ************************************************************

TASK [{} ] ************************************************************

TASK [ {}] ************************************************************

TASK [{} {}] ************************************************************

PLAY RECAP **************************************************************
localhost : ok=0 changed=0 unreachable=0 failed=0

As long as project_config is defined, if not you'll get an attribute
error exception

I don't get any errors, here is the full playbook.