The convenience of variables - and how can I achieve something similar in tasks

In playbooks, one can achieve brevity of expression by assigning some complex expression to a variable, then using the variable in subsequent actions.

However, I can’t achieve that in a task - unless I pre-declare all variables the task will use in the calling playbook. With a proliferation of tasks and sub-tasks and multiple playbooks that include tasks at all include levels, this isn’t manageable/scalable.

I was wondering if there’s any way of memorializing (complex) expressions in a task?

My specific experience with this: Some of my tasks require hand-crafting actions via commands/scripts then inspecting their response to determine change - so as to achieve idempotency, and then to proceed with further actions.These boolean expressions can be complex, and often need to be reused through the task. For now I’m just copying/pasting the expression to all subsequent actions that need it, but it would be nice to have a local variable that memorialized the boolean expression.

Thoughts: I can definitely write my own module that encapsulates the command/script work and then everything would be clean and concise, with registered variables. However, coding up a module takes time, and existing Ansible modules (along with command/script) pretty much accomplish most of what’s needed.

However, I can't achieve that in a task - unless I pre-declare all variables
the task will use in the calling playbook. With a proliferation of tasks and
sub-tasks and multiple playbooks that include tasks at all include levels,
this isn't manageable/scalable.

Define your variables in the playbook or inventory and they can be
used just fine in the task file.

Task files are simple lists, we are not going to make them contain
anything more than lists of tasks.

I wasn’t quite asking for tasks to be changed, was more looking for methodology/best-practices/techniques ( I already have a working prototype as I stated in my post)

Beyond making it work , I need to ensure that multiple people are able to author and maintain tasks and playbooks, and that they’re easily readable and understandable. Task reuse is very important, so I need to ensure that as the DevOps team modifies/enhances tasks, all the different consumers of these tasks (other teams in-house, outsourced data-center personnel) will not break.

Based on your reply, I see 3 choices:

  • keep doing what I’m doing, just copy/paste/repeat boolean expressions in a task
  • develop custom modules that save us from having to parse stdout from command/script returns
  • specify that every task have a dedicated section in group-vars/all, where it keeps it’s “local” variables. A task will be a 3-piece affair: this var section, the task itself, and the task handler (from our other conversation). I’m inclined towards this.

Sorry for being obtuse - my Ansible experience is 6 days old so there’s a lot I don’t know.
So far I don’t see a blocker, there seem to be good techniques/workarounds for all my concerns.
As always I have one more question that I will formulate in a bit - thanks for your response :slight_smile:

Are you looking for something like this? (taken from one of my playbooks):

vars:
   - is_fbsd: $ansible_system == 'FreeBSD'

tasks:
    - name: asdf
      action: echo hello world
      only_if: $is_fbsd

You have to quote 'only_if' statements around variables. (It's the
older syntax).

If you change 'only_if' to "when_string" you should be able to use
that verbatim.

Yes I understand this, my question was a bit related.

Let’s say I have a task, within which there is an action (this is mostly an illustration, so please don’t focus on why I might want to do specifically this use-case)
yum list $package
The stdout is parsed to see if the package is installed on the server.
i.e. “‘${yumlist_contents.stdout}’.find(‘Installed Packages’) == -1”
Based on this answer certain other subsequent actions are taken:

action1:
only_if " “‘${yumlist_contents.stdout}’.find(‘Installed Packages’) == -1”

action2:
when_boolean “‘${yumlist_contents.stdout}’.find(‘Installed Packages’) == -1’ and ‘${nonstandardappquery_contents.stdout}’.find(‘No such process’) == -1’”

It would be so much more readable (and maintainable) to write:

action1:
only_if: $package_already_installed

action2:
when_boolean: $package_already_installed and $service_stopped

But I don’t see any way to do the above (yet), since this all is in a task.

Please ignore my erroneous thinking here - this issue has nothing to do with tasks, it’s just as relevant in a playbook.
How can one store the evaluated result of an expression for later reference, that’s the crux of it.