Playbooks … what don't you think you can do now?

So in light of recent upgrades to:

https://github.com/ansible/ansible/tree/master/examples/playbooks

I think that nearly all things that can be done with most Puppet/Chef are decently doable from the playbook language, assuming the underlying modules all existed (some are pending, like the users module).

There are some obvious things we INTENTIONALLY don’t have – if/then/else/case blocks and so forth, but that may not be immediately clear from the docs how you would do various things, but in the end, I think Ansible actually makes them simpler, and all those things remain possible. I’m deliberately trying to keep things from not developing programming language type constructs while still keeping the capabilities of those constructs. I’ve deliberately tried to avoid doing if/then/else in YAML too, which I think is disastrously verbose :slight_smile:

The end result is things should be a lot easier to read, understand, and audit – even by non-developers. Do folks agree?

If you can share some snippet of something that is missing we can probably talk about how it could be done now, or not. Maybe it’s not clear – maybe something is genuinely missing. I want to know.

I’ve deliberately left a lot of complexity out of the system – it’s not something you port 1:1, you would think about it differently… but in general I think between vars, vars_files, conditional imports, and only_if, nearly all the things you REALLY want to model are possible, and easily reusable.

Any thing people think are still not possible? (If so, maybe I can talk about how I’d try to do it? And maybe we would identify some remaining gaps). How do we stand?

–Michael

Michael,

How can I do conditional execution of a task based on the state of the client machine? Specifically, we have some servers with Plesk 9.5 and some with Plesk 10.4 (same operating system). A script can check the contents of /var/opt/psa/version and the string (something like “10.4.4 Ubuntu 8.04 1013111102.18”) requires a little bit of parsing to strip the version number off the front.

I guess what I am asking is how I would get the Plesk version number, which will be the result of running a little shell script, into a variable in a playbook.

Thanks,
– Art Z.

So basically you have access to ansible facts, chef facts, and ohai facts right now. Ansible facts are not yet extensible, but this seems like it is calling out for the idea that you should be able to have user supplied facts in Ansible proper (since writing custom facts in facter isn’t easy).

I am thinking we could auto-transfer a “user_facts” module if it exists, maybe, and just treat it as a script that returns JSON, just like ohai or facter are treated…. thus you have a really easy way of writing your own facts and it won’t require forking the setup module.

This would be a really small patch to the “setup” wrapper code in Runner to transfer the file if it exists, and a small couple of line patch to the setup module to call that file if present on the file system.

File an RFE ticket in github and I’ll knock it out sometime soon (unless someone wants to beat me to it).

–Michael

Michael,

How can I do conditional execution of a task based on the state of the client machine? Specifically, we have some servers with Plesk 9.5 and some with Plesk 10.4 (same operating system). A script can check the contents of /var/opt/psa/version and the string (something like “10.4.4 Ubuntu 8.04 1013111102.18”) requires a little bit of parsing to strip the version number off the front.

So basically you have access to ansible facts, chef facts, and ohai facts right now. Ansible facts are not yet extensible, but this seems like it is calling out for the idea that you should be able to have user supplied facts in Ansible proper (since writing custom facts in facter isn’t easy).

I mean “facter facts” and “ohai facts”, not “chef facts”.

Hi,

How can I do conditional execution of a task based on the state of the
client machine? Specifically, we have some servers with Plesk 9.5 and some
with Plesk 10.4 (same operating system). A script can check the contents of
/var/opt/psa/version and the string (something like "10.4.4 Ubuntu 8.04
1013111102.18") requires a little bit of parsing to strip the version number
off the front.

So basically you have access to ansible facts, chef facts, and ohai facts
right now. Ansible facts are not yet extensible, but this seems like it is
calling out for the idea that you should be able to have user supplied facts
in Ansible proper (since writing custom facts in facter isn't easy).

I am thinking we could auto-transfer a "user_facts" module if it exists,
maybe, and just treat it as a script that returns JSON, just like ohai or
facter are treated…. thus you have a really easy way of writing your own
facts and it won't require forking the setup module.

This would be a really small patch to the "setup" wrapper code in Runner to
transfer the file if it exists, and a small couple of line patch to the
setup module to call that file if present on the file system.

I believe a more flexible approach is to avoid changing the setup
module, but reuse the module system to transfer custom facts. That
could mean that any module could return facts by for example returning
a 'ansible_facts' key in the stdout json. If you need your custom
facts in a playbook, just include you own facts module first. That
way, you only pay the price for facts that you actually use (per Dags
feedback) and it integrates nicely into things ansible users already
know, no magic involved.

File an RFE ticket in github and I'll knock it out sometime soon (unless
someone wants to beat me to it).

I saw that sfromm opened issue #203. If he's working on it, all fine.
Otherwise you may assign it to me.

Greetings,

Jeroen

I like this *much* better. We have a ton of configuration info that we
*might* need but definitely don't want to pay the price of fetching 100%
of it 100% of the time.

    -- Art Z.

I believe a more flexible approach is to avoid changing the setup
module, but reuse the module system to transfer custom facts. That
could mean that any module could return facts by for example returning
a ‘ansible_facts’ key in the stdout json. If you need your custom
facts in a playbook, just include you own facts module first. That
way, you only pay the price for facts that you actually use (per Dags
feedback) and it integrates nicely into things ansible users already
know, no magic involved.

Sorry, this isn’t how it works. The setup module must return the facts.

Ok, I see the patch now.

It adds facts when the modules are run, rather than editing the setup metadata file.

This is reasonable and pretty awesome.

–Michael

Hi all, I’m new and wondering what the best way would be for creating dynamic variables to use in a playbook for a file name as an example. If I want the playbook to just install the latest version and the file name includes a version number or I want to copy a file to a target machine with a version or timestamp in the name as a couple of examples…

Also, is there any thought on a way to define a set of playbooks? So if i have app foo that has: install, upgrade, remove playbooks, then i could type something like: “ansible- install_foo” and because “install_foo” points to foo/playbooks/install.yml it would be run? I could obviously do this outside, but it’s almost a playbook of playbooks, so just wanted to see if there was any thinking in this area.

thanks!
-jeff

–Michael

Hi all, I’m new and wondering what the best way would be for creating dynamic variables to use in a playbook for a file name as an example. If I want the playbook to just install the latest version and the file name includes a version number or I want to copy a file to a target machine with a version or timestamp in the name as a couple of examples…

I am having difficulty following what you are asking about here.

“If I want to just install the latest version”

pkg name=foo state=latest

“and the file name includes a version number”

I don’t understand this part

It sounds like you mean you want to use a playbook but with different things changed in it. I would highly recommend keeping a playbook in version control if it’s version related, so you can see how you have edited it over time.

The thing about including the time in the filename is a bit different of a question. You would probably want to break out into Jinja2 and do something like {{ time.time() }} though I really haven’t looked at how to do imports from within that yet.

To be honest, I’m not sure I understand the real world use case around this one and knowing more about it would be better than talking about it abstractly, I think?

Also, is there any thought on a way to define a set of playbooks? So if i have app foo that has: install, upgrade, remove playbooks, then i could type something like: “ansible- install_foo” and because “install_foo” points to foo/playbooks/install.yml it would be run? I could obviously do this outside, but it’s almost a playbook of playbooks, so just wanted to see if there was any thinking in this area.

So, think more idempotently. Generally you don’t want a different playbook for install and upgrade. You want one that says “deploy this at version X and upgrade it if needed”.

This is why you would do stuff like:

yum package=foo version=X

It makes sure things are at version X.

Anyway, playbooks can contain multiple plays, but what you ask for does not exist – I would just do that by convention if you want.

This is why you would do stuff like:

yum package=foo version=X

Correcting myself:

pkg=foo state=X

For the file naming, i was thinking about a flow more like capistrano, where i would want to take a file, service-1.2.3.tgz and send it to a set of targets and explode to /opt/service/1.2.3 (or timestamp in some cases) and update symlinks and such, rather than using rpm or deb. Basically I want to be able to keep at least 1 previous version on the targets for rollback if needed, and i want to do this automated so i’d rather not be changing playbooks for every source file name change.

thanks,
-jeff

–Michael

For the file naming, i was thinking about a flow more like capistrano, where i would want to take a file, service-1.2.3.tgz and send it to a set of targets and explode to /opt/service/1.2.3 (or timestamp in some cases) and update symlinks and such, rather than using rpm or deb. Basically I want to be able to keep at least 1 previous version on the targets for rollback if needed, and i want to do this automated so i’d rather not be changing playbooks for every source file name change.

Yeah, we used to have a --extra-args=“key=value key=value” feature for feeding in arguments to the playbooks from the ansible-playbooks command line. It was lost in a refactoring because it was a bit hard to follow and was overloaded in some confusing ways with another feature. It probably could be reinstated quite easily and more simply.

So you could do something like:

ansible-playbook deployStuff.yml --extra-args=“myapp_version=1234”

and inside the playbook use the variable $myapp_version

sound reasonable?

Yeah, that sounds perfect. Since it’s plural (args), hopefully it would be a comma separated list of key/value or something similar?

thanks,

The previous implementation was space delimited, but yes.

I’ll file a ticket and see about getting this back in a few days. The previous implementation crossed things with our external script variable implementation, which made it weird.

Until then, I’d suggest keeping the variables in the playbook and editing them for now.

–Michael