register variable in conjunction with when_changed

Notify handler in each, should restart only once if either or both changed

Brian Coca

Indeed, that's the cleaner way to do it. Exactly right.

Good job Brian for answering the root use case question and not the
technical one! :slight_smile:

He, I inverted our roles for once!

Still, we should fix the register issue.

Brian Coca

yes, let us make sure there is a ticket filed for this.

Nice, thanks for your response, that’s very useful !

So that brings me to a second note, something I’ve been meaning to post for a couple of days.
The above code-snippet (unfortunately) is in a task. From what I’ve seen handlers are only usable at the playbook level.
(And I’d love to know if I’m wrong here)
What is your thinking on generalizing handlers so tasks can notify their calling plays/tasks?

(BTW, mostly for my own edification, I created a quick init_changed module that in effect initializes the register variable - while pre-setting changed to a desired value. This way the task looks a bit cleaner - until the basic bug gets fixed)

Nice, thanks for your response, that's very useful !

So that brings me to a second note, something I've been meaning to post for
a couple of days.
The above code-snippet (unfortunately) is in a task. From what I've seen
handlers are only usable at the playbook level.
(And I'd love to know if I'm wrong here)
What is your thinking on generalizing handlers so tasks can notify their
calling plays/tasks?

Tasks notify handlers in the same play (and run in that play).

If you do want to reuse a handler in a different play, you *can* do
that in an include.

I guess I would say generally that I don't understand the use case
thoroughly and could benefit from seeing some proposed syntax on
gist.github.com,
but think it is unlikely.

Notifying tasks doesn't make sense, as tasks always run, it is
handlers that run when they are notified.

I'm probably misunderstanding a part of your question/proposal, so
seeming an example on gist might help.

(BTW, mostly for my own edification, I created a quick init_changed module
that in effect initializes the register variable - while pre-setting changed
to a desired value. This way the task looks a bit cleaner - until the basic
bug gets fixed)

Nice workaround!

I was afraid you would ask me for the use-case lol
Yes, I didn’t express myself clearly.
Yes, I can put a notifier in a task, and the parent playbook can and will handle it properly, that works (yay)

My question arose from a desire of writing self-contained tasks (usually the deployment of a single application), that I could instantiate very quickly in a playbook targeted at a particular type or class of server e.g. a tomcat task would take care of ensuring that tomcat was at a given version (a group var would define what tomcat version is sanctioned for that group - a la “version” in chef) and could be invoked in the playbooks of all our various J2EE app-servers. (We develop and add application types frequently, and the simplicity and quickness of setup/expression of Ansible, and the ease of reuse, has been very appealing in that regard). I confess that the 1.0 infinite task includes feature was too tempting a morsel to ignore :slight_smile:

But having to place a handler in the task’s parent playbook means that the task isn’t quite self-contained - each playbook now needs to make sure it has a handler for the tomcat restart - that action needs to be copied for any playbook/task that invokes the tomcat task. (The dependency distance is further exacerbated by the new powerful 1.0 capability of infinitely nested includes). As tasks get updated, and perhaps handlers added/modified, all playbooks that somehow invoke the task (possibly through a chain of includes) now need to be updated as well.

playbook n (targeting a type of host)

  • coarse granularity task (say tasks related to java/tomcat vs php/apache vs ruby)
  • finer granularity sub-task (say tomcat)
    notifier x
    handler x

That is what was behind my original question (and experimenting with alternatives led to my original defect observation) - I wasn’t prescribing a solution or a syntax per se.

(The task nature is that of a macro. Tasks live in the environment of the playbook (variables/handlers etc.). At one level this is clear and clean, and keeps the language simple - understood.)

Various alternatives I’ve mulled:

  • use playbooks for encapsulation e.g. have a tomcat playbook? Quickly abandoned, playbooks express whats to be done on a specific group of hosts and this isn’t their natural use (- even with parametrized hosts).
  • figure out if I can: include a generic handler in all playbooks, and marshal to a specific sub-handler via parametrization. Just an idea - haven’t played with it yet, not the cleanest, but may be workable.
  • just not use handlers, confine to only_if/when
  • change thinking: move away from server-construction-hierarchy and multi-level includes, to mostly flat 1-level includes. Compose playbooks by mixing-matching 1-level includes.

Finally, I hope that I’m not entirely missing some powerful Ansible use-pattern that addresses the above; but if I am, I would love to incorporate/utilise it, thanks.

Tasks aren't a complete description of how to interact with the
system, playbooks are.

The concept of whether something is "self contained" is somewhat of an
arbitrary constraint, IMHO.

You could keep all of your handlers in one file if you want.

At worst case, it means when you include a task list you also need to
include the accompanying handlers file, but that's just two lines
instead of one -- still reasonably organized.

Yeah, that is indeed much better, each task to be “contained” within 2 files. (Kicks myself for not thinking of that)
I have another question, but I will defer to that another post :slight_smile: