idempotency of service state=reloaded

Hi,

I've noticed that if I define a handler to restart a service, when my playbook runs for the first time and notifies it, the service does *not* start, because state=reloaded simply invokes "service blah reload", and that won't start the service it if isn't already.

Ok, so possibly there's a work-around (add a task to restart the service). Besides the point, however, assuming Ansible's tasks are intended to be idempotent as far as possible. This case seems to be one where it falls short of idempotence, because the end state depends on the initial state (started or stopped).

Besides, simply from a usabillity standpoint, if I request a service to be in "state=reloaded", surely I could reasonably expect to end up with the service running, whether or not it was to start with?

Is there a known case in which one would want to reload but only if the service is running?

Cheers,

N

When using reloaded or restarted, you’re changing something, and therefore it would never be idempotent by definition. Also typically reload doesn’t start the service if it’s not up, but instead issues a HUP to the process so it reloads, so the behavior you describe above is exactly what I would expect.

So to handle the above, I would first have a task that ensured the service was running and enabled, which would register a variable. The next task would be your state=reloaded task, with a when: clause set so it would run only if the previous did not change.

“the service does not start, because state=reloaded simply invokes “service blah reload”, and that won’t start the service it if isn’t already.”

State=restarted does this

When using reloaded or restarted, you're changing something, and therefore it would never be idempotent by definition.

(Ok, mathematically, "idempotence" means you can re-run an operation N times in sequence and the result is the same as running it once. If you're saying you can't call something idempotent if it changes something, I don't understand.)

Anyway, "idempotence" is of course a desirable property, but perhaps not the term I should have used here.

I had thought a central idea of system configuration systems was to be able to say "put the system in state X", and have it taken care if, whichever state it was in to start with (or fail noisily if it cannot be). This is in fact a different thing to idempotence. However, I believe it *is* what Ansible, Puppet, Chef et al. aspire to, correct?

If so then I think my point stands.

Also typically reload doesn't start the service if it's not up, but instead issues a HUP to the process so it reloads, so the behavior you describe above is exactly what I would expect.

I totally understand and agree with this in the context of simply running "service <blah> reload" from the command line.

However, I would expect Ansible to do more than that to ensure that I don't have to nanny it into doing what I actually intend. In the case of 'reload' this would be to ensure the service is running, *and* if it is, issue a HUP to ensure it reloads its configuration gracefully. On the command line I'd do exactly the same - start it first. It makes little sense HUP a service I haven't already started.

My point is not that I can't work around what Ansible does now with more long-winded constructions, but that surely Ansible *ought* to just do what I want, taking care of the details for me? What use is a "reload" option which doesn't start the service first?

> State=restarted does this

True, and probably what I shall in fact do in practice. Debian services typically don't even have the 'reloaded' operation, so if I want my playbooks to run on both I presume I shall need to use 'restart' anyway.

But it is still different: it *restarts* a service, and in the case of services like Apache, this might be too heavy-handed compared to a reload/HUP, and introduce unwanted downtime on a busy site.

Thanks,

N

Please file a ticket on github about reload.

I think most people are restarting but I don’t object to this.

Done: https://github.com/ansible/ansible/issues/4448

Thanks

N

Personally I would tend to have:-

   - a task within a play that starts/ensures a service is running

   - a handler for the play, triggered by appropriate config changes
     that would do a reload on the service.

So the issue that a reload does not imply you ensure the service is stared does not make a practical difference to me.

  Nigel.

I agree this is a way to do it.

Life would still be easier if 'restart' were smarter: fewer tasks to write, less chance of getting it wrong.

Cheers,

N

FYI – The issue filed was about reload, not restart.

If you are asking about a behavior of both, please make that clear in the ticket.

Thanks!

Assuming you are wanting this service to be started on boot a:

service: name=apache started=yes enabled=yes

would start the service if not running, and set it to start on boot. In subsequent plays this would be skipped. Your handler could then simply reload apache to get config changes.