From b247da54f1d8ac8f044aa579c753537d9ed5a1e1 Mon Sep 17 00:00:00 2001 From: John Callender Date: Tue, 1 May 2012 22:35:02 -0700 Subject: [PATCH 1/2] Issue #82: Minor edits to doc text and formatting --- rst/api.rst | 4 ++-- rst/examples.rst | 15 ++++++++------- rst/gettingstarted.rst | 2 +- rst/index.rst | 5 ++--- rst/moduledev.rst | 8 ++++---- rst/modules.rst | 42 +++++++++++++++++++++--------------------- rst/patterns.rst | 4 ++-- rst/playbooks.rst | 24 +++++++++++++----------- 8 files changed, 53 insertions(+), 51 deletions(-) diff --git a/rst/api.rst b/rst/api.rst index fe19e844f74..4fdbaa46429 100644 --- a/rst/api.rst +++ b/rst/api.rst @@ -87,7 +87,7 @@ External Inventory Often a user of a configuration management system will want to keep inventory in a different system. Frequent examples include LDAP, `Cobbler `_, or a piece of expensive enterprisey CMDB software. Ansible easily supports all -of these options via an external interventory system. +of these options via an external inventory system. If you have a data store system where an Ansible external inventory script doesn't already exist, this may require a little coding, but we have a `Cobbler example `_ in the main source tree -- but it's pretty simple, as we'll explain below -- that would provide a good starting point. Like with modules, it's possible to build an external inventory script in any language, as long as it returns JSON. @@ -165,7 +165,7 @@ And technically, though there is no major good reason to do it, this also works ansible webserver -m shell -a "echo {{ a }}" So in other words, you can use those variables in arguments/actions as well. You might use this to name -a conf.d file appropriately or something similar. Who knows. +a conf.d file appropriately or something similar. Who knows? So that's the Cobbler integration support -- using the cobbler script as an example, it should be trivial to adapt Ansible to pull inventory, as well as variable information, from any data source. If you create anything interesting, please share with the mailing list, and we can keep it in the source code tree for others to use. diff --git a/rst/examples.rst b/rst/examples.rst index 3345ac97d7b..0403a6d8dbd 100644 --- a/rst/examples.rst +++ b/rst/examples.rst @@ -25,7 +25,7 @@ If you want to run commands as a different user than root:: ansible atlanta -a "/usr/bin/foo" -u yourname -If you want to run commands through sudo: +If you want to run commands through sudo:: ansible atlanta -a "/usr/bin/foo" -u yourname --sudo [--ask-sudo-pass] @@ -45,13 +45,13 @@ module looks like this:: ansible raleigh -m shell -a 'echo $TERM' When running any command with the ansible "ad hoc" CLI (as opposed to playbooks), pay particular attention -to shell quoting rules, so the shell doesn't eat a variable before it gets passed to Ansible. For example, u -using double vs single quotes would evaluate the variable on the box you were on. +to shell quoting rules, so the shell doesn't eat a variable before it gets passed to Ansible. For example, +using double vs single quotes in the above example would evaluate the variable on the box you were on. So far we've been demoing simple command execution, but most ansible modules usually do not work like simple scripts. They make the remote system look like you state, and run the commands necessary to get it there. This is commonly referred to as 'idempotence', and is a core design goal of ansible. -However, we also recognize that running ad-hoc commands is equally imporant, so Ansible easily supports both. +However, we also recognize that running ad-hoc commands is equally important, so Ansible easily supports both. File Transfer & Templating @@ -62,7 +62,7 @@ Here's another use case for the `/usr/bin/ansible` command line. Ansible can SCP lots of files to multiple machines in parallel, and optionally use them as template sources. -To just transfer a file directly to many different servers:: +To transfer a file directly to many different servers:: ansible atlanta -m copy -a "src=/etc/hosts dest=/tmp/hosts" @@ -70,7 +70,8 @@ To use templating, first run the setup module to put the template variables you would like to use on the remote host. Then use the template module to write the files using those templates. -Templates are written in Jinja2 format. Playbooks (covered elsewhere in the +Templates are written in `Jinja2 `_ format. +Playbooks (covered elsewhere in the documentation) will run the setup module for you, making this even simpler:: @@ -131,7 +132,7 @@ Ensure a package is not installed:: ansible-webservers -m yum -a "pkg=acme state=removed" -Currently Ansible only has a module for managing packages with yum. You can install +Currently Ansible only has modules for managing packages with yum and apt. You can install for other packages for now using the command module or (better!) contribute a module for other package managers. Stop by the mailing list for info/details. diff --git a/rst/gettingstarted.rst b/rst/gettingstarted.rst index b919c310e0f..62001b00076 100644 --- a/rst/gettingstarted.rst +++ b/rst/gettingstarted.rst @@ -89,7 +89,7 @@ build an RPM you can distribute and install:: Note that if you are tracking the upstream source (i.e. git), the RPM revision will not be bumped with every source code change. To get around this, you can use -rpm `-Uvh` with `--force` when RPM tells you the package is still at the +``rpm -Uvh`` with ``--force`` when RPM tells you the package is still at the same version. This is perfectly safe to do. Debian, Gentoo, Arch, Others diff --git a/rst/index.rst b/rst/index.rst index 737bde3f2d0..54c2d64f35f 100644 --- a/rst/index.rst +++ b/rst/index.rst @@ -27,8 +27,7 @@ Multi-machine software deployment is poorly solved by most systems management to Deployment and Configuration, Unified ````````````````````````````````````` -Other deployment (compared to config) oriented frameworks similarly cover deployment well but lack a strongly defined resource model and devolve into glorified remote scripts. Ansible playbooks -- having been designed with this problem in mind -- are good at both deployment & idempotent configuration, meaning you don't have to spread your infrastructure management out between different tools (Puppet+Capistrano, Chef+Fabric, etc), and performing ordered steps between different classes of machines is no problem, yet our modules affect system state only when required -- while avoiding the problem of fragile scripting that assumes certain starting -or ending states. +Other deployment (compared to config) oriented frameworks similarly cover deployment well but lack a strongly defined resource model and devolve into glorified remote scripts. Ansible playbooks -- having been designed with this problem in mind -- are good at both deployment & idempotent configuration, meaning you don't have to spread your infrastructure management out between different tools (Puppet+Capistrano, Chef+Fabric, etc). Performing ordered steps between different classes of machines is no problem, yet our modules affect system state only when required -- while avoiding the problem of fragile scripting that assumes certain starting or ending states. Ansible is also unique in other ways. Extending ansible does not require programming in any particular language -- you can write :doc:`modules` as idempotent scripts or programs that return simple JSON. Ansible is also pragmatic, so when you need to, it's also trivially easy to just execute useful shell commands. @@ -139,6 +138,6 @@ internet infrastructure, finance, chip design, and more. Michael also helped co-author `Func `_, a precursor to Ansible, which is used to orchestrate systems in lots of diverse places. He's worked on systems software for IBM, Motorola, Red Hat's Emerging Technologies Group, -Puppet Labs, and is now with `rPath `_ Reach Michael by email `here `_. +Puppet Labs, and is now with `rPath `_. Reach Michael by email `here `_. diff --git a/rst/moduledev.rst b/rst/moduledev.rst index 43448788403..28f84036fd3 100644 --- a/rst/moduledev.rst +++ b/rst/moduledev.rst @@ -5,7 +5,7 @@ Ansible modules are reusable units of magic that can be used by the Ansible API, or by the `ansible` or `ansible-playbook` programs. Modules can be written in any language and are found in the path specified -by `ANSIBLE_LIBRARY_PATH` or the `--module-path` command line option. +by `ANSIBLE_LIBRARY_PATH` or the ``--module-path`` command line option. Tutorial ```````` @@ -53,7 +53,7 @@ You should see output that looks something like this:: {u'time': u'2012-03-14 22:13:48.539183'} -If you did not, you might have a typo in your module, so recheck it and try again +If you did not, you might have a typo in your module, so recheck it and try again. Reading Input ````````````` @@ -76,7 +76,7 @@ If no time parameter is set, we'll just leave the time as is and return the curr use the shell module. However, it probably makes a decent tutorial. Let's look at the code. Read the comments as we'll explain as we go. Note that this -highly verbose because it's intended as an educational example. You can write modules +is highly verbose because it's intended as an educational example. You can write modules a lot shorter than this:: #!/usr/bin/python @@ -203,7 +203,7 @@ Conventions As a reminder from the example code above, here are some basic conventions and guidelines: -* Include a minimum of dependencies if possible. If there are dependencies, document them at the top of the module file +* Include a minimum of dependencies if possible. If there are dependencies, document them at the top of the module file. * Modules must be self contained in one file to be auto-transferred by ansible diff --git a/rst/modules.rst b/rst/modules.rst index ceba10939bf..09d039de96b 100644 --- a/rst/modules.rst +++ b/rst/modules.rst @@ -26,7 +26,7 @@ From playbooks, Ansible modules are executed in a very similar way:: All modules technically return JSON format data, though if you are using the command line or playbooks, you don't really need to know much about that. If you're writing your own module, you care, and this means you do -not have to write modules in any particular language -- you get tho choose. +not have to write modules in any particular language -- you get to choose. Most modules other than command are `idempotent`, meaning they will seek to avoid changes to the system unless a change needs to be made. When using Ansible @@ -52,7 +52,7 @@ Manages apt-packages (such as for Debian/Ubuntu). *update-cache*: -* Whether apt cache must be updated prior operation. Optional, and can be +* Whether the apt cache must be updated prior to operation. Optional, and can be 'yes', or 'no'. The default is 'no'. This can be done as the part of a package operation or as a seperate step. @@ -96,7 +96,7 @@ paths to commands must be fully qualified. This module does not support change hooks and returns the return code from the program as well as timing information about how long the -command was running for. +command was running. Example action from Ansible :doc:`playbooks`:: @@ -196,7 +196,7 @@ All parameters available to the file module are also available when running the *owner*: -* name of user that should own the file or directory, as would be given to `chown`. +* name of user that should own the file or directory, as would be given to `chown` *group*: @@ -208,7 +208,7 @@ All parameters available to the file module are also available when running the *dest*: -* location where the symlink will be created for 'link' state, also an alias for 'path'. +* location where the symlink will be created for 'link' state, also an alias for 'path' *seuser*: @@ -224,11 +224,11 @@ All parameters available to the file module are also available when running the *selevel*: -* 'level' part of SELinux file context. This is the MLS and MCS attribute of the file context. It defaults to 's0'. Only used only used on hosts with SELinux present. +* 'level' part of SELinux file context. This is the MLS and MCS attribute of the file context. It defaults to 's0'. Only used on hosts with SELinux present. *context*: -* accepts only 'default' as value. This will restore a file's selinux context to the default context in the policy. Does nothing if no default is available. +* accepts only 'default' as value. This will restore a file's selinux context to the default context in the policy. Does nothing if no default is available. Only used on hosts with SELinux present. Example action from Ansible :doc:`playbooks`:: @@ -351,7 +351,7 @@ will execute this module automatically as the first step in each play using the variables section, so it is unnecessary to make explicit calls to setup within a playbook. -Ansible provides may 'facts' about the system, automatically. +Ansible provides many 'facts' about the system, automatically. Some of the variables that are supplied are listed below. These in particular are from a VMWare Fusion 4 VM running CentOS 6.2:: @@ -425,13 +425,13 @@ also be snapshotted into the JSON file for usage in templating. These variables are prefixed with ``facter_`` and ``ohai_`` so it's easy to tell their source. -All variables are bubbled up to the caller. Using the ansible facts and chosing +All variables are bubbled up to the caller. Using the ansible facts and choosing to not install facter and ohai means you can avoid ruby-dependencies on your remote systems. -*anything*: +*variablename*: - * Any other parameters can be named basically anything, and set a ``key=value`` pair in the JSON file for use in templating. + * Arbitrary names can be used as variables. 'variablename' can be basically anything, and sets a ``key=value`` pair in the JSON file for use in templating. Example action from Ansible :doc:`playbooks`:: @@ -463,7 +463,7 @@ use your best judgement. This module does not support change hooks and returns the return code from the program as well as timing information about how long the -command was running for. +command was running. Example action from a playbook:: @@ -477,8 +477,8 @@ template Templates a file out to a remote server. Call the :ref:`setup` module prior to usage if you are not running from a playbook. In addition to the options -listed below, the arguments available to the `file` module can also be passed to the copy -module. +listed below, the arguments available to the `file` and `copy` modules can also be passed +to the template module. *src*: @@ -487,7 +487,7 @@ module. *dest*: -* Location to render the template on the remote server. +* Location to render the template on the remote server This module also returns md5sum information about the resultant file. @@ -513,19 +513,19 @@ Creates user accounts, manipulates existing user accounts, and removes user acco *group*: -* Optionally sets the user's primary group, takes a group name. +* Optionally sets the user's primary group, takes a group name *groups*: -* Put the user in the specified groups, takes comma delimited group names. +* Put the user in the specified groups, takes comma delimited group names *append*: -* If true, will only add additional groups to the user listed in 'groups', rather than making the user only be in those specified groups. +* If true, will only add additional groups to the user listed in 'groups', rather than making the user only be in those specified groups *shell*: -* Optionally sets the user's shell. +* Optionally sets the user's shell *createhome*: @@ -541,11 +541,11 @@ Creates user accounts, manipulates existing user accounts, and removes user acco *force*: -* When used with a state of 'absent', the behavior denoted in the 'userdel' manpage for --force is also used when removing the user. Value is 'yes' or 'no', default is 'no'. +* When used with a state of 'absent', the behavior denoted in the 'userdel' manpage for ``--force`` is also used when removing the user. Value is 'yes' or 'no', default is 'no'. *remove*: -* When used with a state of 'absent', the behavior denoted in the 'userdel' manpage for --remove is also used when removing the user. Value is 'yes' or 'no', default is 'no'. +* When used with a state of 'absent', the behavior denoted in the 'userdel' manpage for ``--remove`` is also used when removing the user. Value is 'yes' or 'no', default is 'no'. Example action from Ansible :doc:`playbooks`:: diff --git a/rst/patterns.rst b/rst/patterns.rst index 8d0486484d5..4158e0740fe 100644 --- a/rst/patterns.rst +++ b/rst/patterns.rst @@ -25,7 +25,7 @@ The format for /etc/ansible/hosts looks like this:: two.example.com three.example.com -The things in brackets are group names, you don't have to have them, +The things in brackets are group names. You don't have to have them, but they are useful. If you have hosts that run on non-standard SSH ports you can put the port number @@ -127,7 +127,7 @@ style file with a YAML one.:: vars: - asdf: 1234 -Tip: Be sure to start your YAML file with the YAML record designator "---". +Tip: Be sure to start your YAML file with the YAML record designator ``---``. NOTE: variables specified in playbooks will override variables specified in the host file. Further, if a host is in multiple groups, currently, the diff --git a/rst/playbooks.rst b/rst/playbooks.rst index acc8f24c4fd..0ae6d69c288 100644 --- a/rst/playbooks.rst +++ b/rst/playbooks.rst @@ -80,7 +80,7 @@ Support for running things from sudo is also available:: user: yourname sudo: True -If you need to specify a password to sudo, run `ansible-playbook` with `--ask-sudo-pass` (`-K`). +If you need to specify a password to sudo, run `ansible-playbook` with ``--ask-sudo-pass`` (`-K`). If you run a sudo playbook and the playbook seems to hang, it's probably stuck at the sudo prompt. Just `Control-C` to kill it and run it again with `-K`. @@ -138,13 +138,13 @@ playbook. If things fail, simply correct the playbook file and rerun. The goal of each task is to execute a module, with very specific arguments. Variables, as mentioned above, can be used in arguments to modules. -Modules other than `command` are 'idempotent', meaning if you run them +Modules other than `command` and `shell` are 'idempotent', meaning if you run them again, they will make the changes they are told to make to bring the system to the desired state. This makes it very safe to rerun the same playbook multiple times. They won't change things unless they have to change things. -Command will actually rerun the same command again, +The `command` and `shell` modules will actually rerun the same command again, which is totally ok if the command is something like 'chmod' or 'setsebool', etc. @@ -159,9 +159,9 @@ the service module takes key=value arguments:: - name: make sure apache is running action: service name=httpd state=running -The command module is the one module that just takes a list -of arguments, and doesn't use the key=value form. This makes -it work just like you would expect. Simple:: +The `command` and `shell` modules are the one modules that just takes a list +of arguments, and don't use the key=value form. This makes +them work just like you would expect. Simple:: tasks: - name: disable selinux @@ -181,7 +181,7 @@ Running Operations On Change ```````````````````````````` As we've mentioned, nearly all modules are written to be 'idempotent' and can relay when -they have affected a change on the remote system. Playbooks recognize this and +they have made a change on the remote system. Playbooks recognize this and have a basic event system that can be used to respond to change. These 'notify' actions are triggered at the end of each 'play' in a playbook, and @@ -255,7 +255,7 @@ within a template or even an action line:: NOTE: No database or other complex system is required to exchange data between hosts. The hosts that you want to reference data from must be included in either the current play or any previous play. -External Variables And Prompted or Sensitive Data +External Variables and Prompted or Sensitive Data +++++++++++++++++++++++++++++++++++++++++++++++++ It's a great idea to keep your playbooks under source control, but @@ -355,6 +355,8 @@ but it is easily handled with a minimum of syntax in an Ansible Playbook:: - name: make sure apache is running action: service name=$apache state=running +Note that a variable (`$facter_operatingsystem`) is being interpolated into the list of +filenames being defined for vars_files. As a reminder, the various YAML files contain just keys and values:: @@ -432,7 +434,7 @@ inside 'action' lines and in templates. Includes can also be used in the 'handlers' section, for instance, if you want to define how to restart apache, you only have to do that once for all -of your playbooks. You might make a notifiers.yaml that looked like:: +of your playbooks. You might make a handlers.yml that looks like:: ---- # this might be in a file like handlers/handlers.yml @@ -505,7 +507,7 @@ Asynchronous Actions and Polling By default tasks in playbooks block, meaning the connections stay open until the task is done on each node. If executing playbooks with -a small parallelism value (aka `--forks`), you may wish that long +a small parallelism value (aka ``--forks``), you may wish that long running operations can go faster. The easiest way to do this is to kick them off all at once and then poll until they are done. @@ -548,7 +550,7 @@ Alternatively, if you do not need to wait on the task to complete, you may commands later in the playbook against those same resources. .. note:: - Using a higher value for `--forks` will result in kicking off asynchronous + Using a higher value for ``--forks`` will result in kicking off asynchronous tasks even faster. This also increases the efficiency of polling. Executing A Playbook From 26c141e96e46af2d705a7f7b60ddcba66f5d9e00 Mon Sep 17 00:00:00 2001 From: John Callender Date: Wed, 2 May 2012 06:53:29 -0700 Subject: [PATCH 2/2] Issue #84: Doc tweaks for modules, moduledev, and playbooks --- rst/moduledev.rst | 8 +++++--- rst/modules.rst | 6 ++++-- rst/playbooks.rst | 6 ++++++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/rst/moduledev.rst b/rst/moduledev.rst index 28f84036fd3..8eb767c020a 100644 --- a/rst/moduledev.rst +++ b/rst/moduledev.rst @@ -188,11 +188,13 @@ You should also never do this in a module:: Because the output is supposed to be valid JSON. Except that's not quite true, but we'll get to that later. -Further, modules must not output anything on stderr, even if the JSON returned -out stdout is valid. This is due to the internals of our SSH library, more or less. +Modules must not output anything on standard error, because the system will merge +standard out with standard error and prevent the JSON from parsing. Capturing standard +error and returning it as a variable in the JSON on standard out is fine, and is, in fact, +how the command module is implemented. If a module returns stderr or otherwise fails to produce valid JSON, the actual output -will still be shown in Ansible, however, but the command will not succeed. +will still be shown in Ansible, but the command will not succeed. Always use the hacking/test-module script when developing modules and it will warn you about these kind of things. diff --git a/rst/modules.rst b/rst/modules.rst index 09d039de96b..c8a3492f60e 100644 --- a/rst/modules.rst +++ b/rst/modules.rst @@ -431,7 +431,9 @@ on your remote systems. *variablename*: - * Arbitrary names can be used as variables. 'variablename' can be basically anything, and sets a ``key=value`` pair in the JSON file for use in templating. +* Arbitrary variable names, which must be a mix of alphanumeric characters and +underscores, can also be defined. Setting a variable creates a +``key=value`` pair in the JSON file for use in templating. Example action from Ansible :doc:`playbooks`:: @@ -451,7 +453,7 @@ shell The shell module takes the command name followed by a list of arguments, space delimited. It is almost exactly like the command module -but runs the command through the shell rather than directly. +but runs the command through the user's configured shell on the remote node. The given command will be executed on all selected nodes. diff --git a/rst/playbooks.rst b/rst/playbooks.rst index 0ae6d69c288..ff510affe5f 100644 --- a/rst/playbooks.rst +++ b/rst/playbooks.rst @@ -501,6 +501,12 @@ To save some typing, repeated tasks can be written in short-hand like so:: - testuser1 - testuser2 +The above would be the equivalent of:: + + - name: add user testuser1 + action: user name=testuser1 state=present groups=wheel + - name: add user testuser2 + action: user name=testuser2 state=present groups=wheel Asynchronous Actions and Polling ++++++++++++++++++++++++++++++++