ansible
ansible copied to clipboard
Name of task containing block is not printed to stdout
ISSUE TYPE
- Feature Idea
COMPONENT NAME
Ansible Blocks
ANSIBLE VERSION
ansible 2.4.0.0
config file = /etc/ansible/ansible.cfg
configured module search path = [~/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.5 (default, May 3 2017, 07:55:04) [GCC 4.8.5 20150623 (Red Hat 4.8.5-14)]
CONFIGURATION
OS / ENVIRONMENT
Red Hat Enterprise Linux Server release 7.4 (Maipo) (master and target)
SUMMARY
When a block is included in a named task the stdout when running the playbook does not include the name of the task containing the block.
STEPS TO REPRODUCE
- name: apply-custom-error-pages
block:
- copy:
src=files/{{ env }}/404.jsp
dest={{ liferay_webapps_portal }}
notify:
- apply-puppet-config
- copy:
src=files/{{ env }}/500.html
dest={{ liferay_webapps_portal }}
notify:
- apply-puppet-config
EXPECTED RESULTS
The task name is echoed to stdout, perhaps with output like follows:
TASK [base-liferay : apply-custom-error-pages : copy] *******************************************************************************************************************************************************************************
changed: [hostname]
TASK [base-liferay : apply-custom-error-pages : copy] *******************************************************************************************************************************************************************************
changed: [hostname]
ACTUAL RESULTS
The task name is not echoed to stdout
TASK [base-liferay : copy] *******************************************************************************************************************************************************************************
changed: [hostname]
TASK [base-liferay : copy] *******************************************************************************************************************************************************************************
changed: [hostname]
You can (also) give a name to each individual task in the block. I haven't tested it, but IIRC that name is printed.
Blocks are not tasks and name is not an 'inheritable' property, that said this could be optionally added, but can get very complex with nested blocks and roles
To add some clarification to my comment in a now closed thread. I was expecting the name to be printed in ansible output. If it's not printed, I'm not sure what purpose it serves.
I agree with @cdosborn 's comment. What's the intent of the name parameter? What value do you get from setting it?
none for execution, it was intended as a 'documentation' for those reading the playbook
@bcoca Why would this get complicated? The ansible output is flat regardless of nested blocks, so all you need to do is print BLOCK TASKS [ ROLE : NAME_OF_BLOCK ].
Could even print it again when the block ends: BLOCK END ...
But maybe I'm misunderstanding the complexity...
The complicated thing is that Ansible used blocks implicitly for the internal structure of tasks to run.
Every task always has a block for a parent. Whether explicit or implicit. Additionally blocks can be deeply nested. To what end do we include parent blocks in the naming?
@sivel Ah I see. That complicates things slightly.
The end is User Experience and POLA (it's downright surprising that the block names don't show up). Just think of the number of poor playbook/role writers who have refactored their playbooks to make them easier to follow and then had to revert all those changes upon realizing that "this name" isn't the same as "the other name".
"Grouping" tasks like this is pretty useful for the readability of playbook runs because of the modular, idempotent nature of tasks: it often takes a number of small steps to achieve a desired goal. It doesn't often make much sense to output these small steps, or necessarily give a human-readable explanation of them when you could explain the whole block of tasks, which represents some human-comprehensible goal and hence is easier to reason about.
In any case, the solution still seems relatively straightforward:
- If a block contains a name (presuming these internal blocks do not), output the name and make a note to output the block end as well. This limits to scope to affect only named blocks as well (which is desirable since blocks can function both as logical groupings and as error catches or simply ways of grouping shared parameters, which may have no intrinsic human meaning). Outputting named block ends could be a configurable setting (and even named block starts).
As for the nesting, you should just be able to push the names onto a stack as you enter them and pop them as you leave.
I was trying to use a block level name to reconcile the part of me that needs each action name to be explicit and the part of me that HATES repeating himself using tools that are supposed to simplify maintenance.
I'd love to do this:
- name: Patch Folding@Home service to start idle timer
block:
- name: Create directory
...
- name: Install Systemd unit file
...
But I have to do this:
- block:
- name: "Patch Folding@Home service to start idle timer: Create directory"
...
- name: "Patch Folding@Home service to start idle timer: Install Systemd unit file"
...
Note: I could almost work around this insanity if YAML supported concatenation...
- name: &myname "Patch Folding@Home service to start idle timer" block: - name: *myname + "Create directory" ... - name: *myname + "Install Systemd unit file" ...But that's admittedly a separate can of worms.
Let's get names on blocks working as described above, please!
Aye. I'm definitely expecting similar output to loop tasks. Nesting will certainly not scale, but that needs separate consideration.
Every task always has a block for a parent. Whether explicit or implicit. Additionally blocks can be deeply nested. To what end do we include parent blocks in the naming?
How about using box drawing characters roughly like below? You get the idea. Especially for multiple nestings this would be hell of a lot of help for getting an easy to grasp overview of the Ansible output log! Especially when you have a look over playbooks/roles you haven’t written yourself. Having some sort header and a clearly defined end (of that headers scope) also is necessary, as this is the only solution which avoids repeating the subject.
That scales pretty good, and I don’t think that that nesting levels of greater than 2 or 3 are common. Higher nesting levels might be used, but I guess are a pretty rare and special occurrence. Additionally, we aren’t in the 70s anymore, so we usually have widths of more than 80 characters available. In fact we can even save vastly more space compared to the current situation, where we have to prefix every block task by the block title, for the task group to be correctly interpreted.
• Normal task 1
┏ ━ OUTER BLOCK
┃ • Bla
┃
┃┏━ INNER BLOCK 1
┃┃ • A
┃┃ • B
┃┃ • C
┃┗━
┃
┃ • Blubb
┃
┃┏━ INNER BLOCK 2
┃┃ • A
┃┃ • B
┃┃ • C
┃┗━
┗━
• Normal task 2
Or as Ansible currently draws full border lines, you can also completely draw those boxes (with optional space-saving on the right side in this case). Also the rescue/always options of blocks could be marked up more clearly.
┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
• Normal task 1
┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
┏━━━━━━━ OUTER BLOCK ━━━━━━━━━━━━━━━━━┓
┃ • Bla 1 ┃
┠┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┨
┃ • Bla 2 ┃
┃┏━━━━━ INNER BLOCK 1 ━━━━━━━━━━━━━━━┨
┃┃ • A ┃
┃┠┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┨
┃┃ • B ┃
┃┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ • Blubb 1 ┃
┠┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┨
┃ • Blubb 2 ┃
┃┏━━━━━━ INNER BLOCK 2 ━━━━━━━━━━━━━━━┫
┃┃ • A ┃
┃┠┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┨
┃┃ • B ┃
┃┣━━━━━━ ❗ Rescue ━━━━━━━━━━━━━━━━━━━┫
┃┃ • X ┃
┃┠┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┨
┃┃ • Y ┃
┃┣━━━━━━ Always ━━━━━━━━━━━━━━━━━━━━━━┫
┃┃ • C ┃
┃┠┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┨
┃┃ • D ┃
┃┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
• Normal task 2
┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
@samdoran Do you mind answering us here? This issue doesn't seem so complicated as to deserve being ignored, when its presence could enable better play designs.
This issue seems like a speedier compromise would be better than bleeding for perfection.
Every task always has a block for a parent. Whether explicit or implicit.
-
We could ignore the internal underlying layer and start wherever the user's blocks actually start in the internal structures.
-
The internal block structure could gain a flag that the internals use and that user roles/tasks/plays don't - or vice versa. Then the outputter can behave like now on the one flag and print out the others.
Additionally blocks can be deeply nested. To what end do we include parent blocks in the naming?
Here are some possible compromises:
- Limit nesting. If nesting exceeds, behave as it does now. Some shallow printing would be heaps better than none, as CNG demonstrated.
- Embrace/ignore nesting. Between the three related threads there are numerous examples that support deep nesting with messiness put in the user's hands. Much better than forcing poor play designs. Even my proposal in https://github.com/ansible/ansible/issues/65099 would work by just getting additional colons and spaces. Not much worse than hardcoded prefixes.
- Opt-in flag. Behave as now but run ansible with a dedicated verbosity flag to let users who don't mind being barraged with extraneous info to get this sort of output.
- Only include downward parents. In every user submitted case, the user controls the root of their tree through their playbook. Don't worry about including parents all the way up? I may need to dig into how Ansible is written so that we are on the same page, perhaps I am misunderstanding the structure layout? Can we give them a "" title and have the string builder collapse "" sections so they don't get redundant structural output?
Do you mind answering us here? This issue doesn't seem so complicated as to deserve being ignored...
I'm not sure what more to add beyond what @sivel has mentioned. It would be more complicated to implement this than it seems, especially with the output formatting @fbruetting illustrated. Even the proposed solution above is fairly complex.
It could be done because anything is possible in software. But a lot of Ansible internals would need to be reworked in order to accommodate this feature. And I'm not sure the benefit outweighs the cost of refactoring and added complexity.
That being said, we would look at PR adding this feature (because we have had a lot of requests to show the block name in playbook output). But it would most likely get a lot of scrutiny and has a low likelihood of being merged, depending on how much code it changes.
Just stumbled upon this. Would be great to have this feature, as it avoids copy/paste and oblivions.
I have been frustrated with this issue for some time now, and so today spent the time to find the current issue. Read most of the above and I do understand the complexity. Spent a little bit of time looking at the code (which I do not know) and eventually gave up on a fix - even a beginning of one - for now. I did manage to come up with a patch to our existing callback which essentially "gets the job done", although it's by no means nice (uses several things from ansible that are likely considered private):
https://gerrit.ovirt.org/c/ovirt-hosted-engine-setup/+/115775
I don't know about implementation of course, but the behaviour of this should be very simple: the scope of all named blocks should appear in the output task messages. If a block is unnamed, it wouldn't be part of the message.
I don't think we need fancy box-drawing. Just the scope so we don't have to constantly replicate text in task names.
This was bugging me so much, so I wrote a small patch for me. (Please be advised that is the first python I wrote in like 15 years.)
Index: ansible/playbook/task.py
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/ansible/playbook/task.py b/ansible/playbook/task.py
--- a/ansible/playbook/task.py (revision f42ffe16d29f00cca38b7b53566e18d36edfc461)
+++ b/ansible/playbook/task.py (date 1636371302621)
@@ -104,18 +104,24 @@
def get_name(self, include_role_fqcn=True):
''' return the name of the task '''
- if self._role:
- role_name = self._role.get_name(include_role_fqcn=include_role_fqcn)
-
- if self._role and self.name:
- return "%s : %s" % (role_name, self.name)
- elif self.name:
- return self.name
+ names = []
+ if self.name:
+ names.append(self.name)
else:
- if self._role:
- return "%s : %s" % (role_name, self.action)
- else:
- return "%s" % (self.action,)
+ names.append(self.action)
+
+ that = self
+ while that._parent:
+ that = that._parent
+ if len(that.name):
+ names.append(that.name)
+
+ if self._role:
+ role_name = self._role.get_name(include_role_fqcn=include_role_fqcn)
+ names.append(role_name)
+
+ names.reverse()
+ return " : ".join(names)
def _merge_kv(self, ds):
if ds is None:
@Magnum5234 does this actually fix the problem? If so, maybe make a PR?
+1
I agree with the general sentiment that this feature (even in its simplest form) would be highly appreciated. +1
The diff suggested above has the general idea, but would introduce some issues.
- the feature should be behind a toggle
- names of any implicit blocks/tasks should be excluded
- roles aren't represented in the chain of task _parent objects
- adding the role name last instead of the task name is unexpected
- the original suggestion was to incorporate the block name - the diff merges all names which seems like it could get very noisy
This isn't complete either by any means (needs tests and a fix or documentation for roles) but here's another attempt https://github.com/s-hertel/ansible/commit/e8783f9f52006dd1380ed0691481afb1217e1b06. I'm not going to open a pull request until I plan on dedicating more time to it though, so if anyone else wants to run with it, feel free (it's at the stage of needing feedback - not sure it would be merged).
Any updates? This sounds relatively simple to implement.
I was surprised to find out that it's not already supported. I think most people would expect the block name to be printed to stdout, what even is the point otherwise?! The documentation literally implies this:
Names for blocks have been available since Ansible 2.3. We recommend using names in all tasks, within blocks or elsewhere, for better visibility into the tasks being executed when you run the playbook.
(emphasis mine)
yes, 'it sounds' so, but it is not that simple.
name is and always has been there for documentation purposes. We shoudl update the docs above to separate blocks from the 'visibility'.
yes, 'it sounds' so, but it is not that simple.
How so? Just prepend the name of the containing task(s) recursively to the name of inner tasks, as people have already suggested.
- there are implicit blocks
- blocks stack
- existing consumers need to be able to handle the differences in output
there are implicit blocks
Omit those from the output, since it's reasonable to say the user won't expect to see them.
blocks stack
Won't be a problem in 99% of the cases. No? You can set an arbitrary limit for now.
existing consumers need to be able to handle the differences in output
What consumers are doing this, why are they doing it, and why should they be allowed to depend on the exact human-facing output format?
ara, ansible-runner, awx/controller/AAP that i know of.
Currently we add 'role name' to tasks as a specific format and YES, that was agreed for downstream consumption. It does not have to do with the human output but the data sent to the event.
If consumers need a stable output (btw. using a user output as input for your tool is never a good idea) we could introduce a switch that enables this behaviour (and maybe other user friendly output).
I.e. a block like structure as suggested above would be awesome. There are quite a number of python libs like rich that could help creating nice output.
Note: git provides a --procleain flag for certain command, maybe something similar could be added to ansible-playbook if consumers depend on it.
I like the simple suggested "expected results" from the issue description.