flajann2 / ansible-powerplay

Run your Ansible playbooks in parallel with Powerplay!
MIT License
11 stars 3 forks source link

** Synopsis

+ATTR_HTML: title="Join the chat at https://gitter.im/flajann2/ansible-powerplay"

[[https://gitter.im/flajann2/ansible-powerplay?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge][file:https://badges.gitter.im/flajann2/ansible-powerplay.svg]]

Powerplay allows you to run multiple Ansible playbooks in parallel. Depending on how you organize your playbooks, this can be a solid win. I basically before this had been doing a playbook with multiple includes for other playbooks representing different servers in our stack. Playbook launching of playbooks is slow and very serial.

Basically, the playbooks are all contained, so no interdependencies. And in my case, running in the cloud, so no reason why they can't be running in parallel

Powerplay allows you to specify vars common to all playbooks, and also vars specific to some playbooks so by which you can make your setup very DRY.

All the Ansible playbooks are executed in seperate processes, and thus avoiding a number of the "side effects" you would normally encounter with running multiple playbooks with Ansible includes.

For example, here is Powerplay integrated with tmux:

+CAPTION: Powerplay writing to tmux panes, one pane per playbook.

+NAME: Powerplay Example

[[./examples/powerplay_screenshot.jpeg]]

* Hilights ** DSL The version 1.x releases adds new features to the DSL, most notably, nestable groups, and being able to label each group as :sync or :async. **** STDOUT from ansible-playbook The capture of the output from ansible-powerplay is handled a bit more intelligently. If you do not specify the --tmux (or -m) option, all output is now currently captured by Powerplay and redumped to the console.

 Because you may still want to see the color from
 ansible-powerplay, you can alter ansible.cfg and
 add the following line:

 + force_color = 1

 Please see [[New STDOUT capturing with 1.0.x][New STDOUT capturing with 1.0.x]]

**** Group Sequence Numers We now allow groups to have sequence numbers, as of 1.1. Basically, if you specify a sequence, the variable you designate will be assigned a value in each of the sequence, with the group re-excuted. for example:

 #+begin_src ruby
 group :first, "async group with sequencing",
             seq: { iter: [1, 5, 9, :dodo] } do
   book :nat, "nat.yml"
   book :dat, "dat.yml"
   book :rat, "rat.yml"
 end
 #+end_src

 as you can see (in the development.play sample)
 the variable "iter" will be successively assigned
 the element in the [] array, with the underlying
 playbooks called. The is the function equivalent
 of the following:

 #+begin_src ruby
 group :first, "async group without sequencing" do
   configuration do
     iter 1
   end
   book :nat, "nat.yml"
   book :dat, "dat.yml"
   book :rat, "rat.yml"
 end

 group :first, "async group without sequencing" do
   configuration do
     iter 5
   end
   book :nat, "nat.yml"
   book :dat, "dat.yml"
   book :rat, "rat.yml"
 end

 group :first, "async group without sequencing" do
   configuration do
     iter 9
   end
   book :nat, "nat.yml"
   book :dat, "dat.yml"
   book :rat, "rat.yml"
 end

 group :first, "async group without sequencing" do
   configuration do
     iter :dodo
   end
   book :nat, "nat.yml"
   book :dat, "dat.yml"
   book :rat, "rat.yml"
 end
 #+end_src

 As you can see, the new sequencing can be quite
 succinct.

** Features and Cavets *** Integration with TMUX When running multiple Ansible Playbooks concurrently, one would like to be able to see the output of each in a reasonable manner. To faciliate this in this initial realse, we shall make heavy use of TMUX panes to dump the output.

So basically, you need as many panes as you have
concurrent Ansible Playbooks in this initial
release. In subsequent releases, Curses will be
directly leveraged to create "tabs" for the
multiple output streams. We may even do this,
still, through TMUX.

Your input on this is strongly encouarged. We will
not be supporting Screen at all. Sorry.

*** New STDOUT capturing with 1.0.x The new capture, while properly capturing the STDOUT of concurrent async runs, does not display until ansible-playbook completes. If you are like me, you'll like to see the progress as it runs. You still can using tmux with the --tmux (-m) option.

*** New TMUX Pane indexing with 1.3.0 You can now explicity provide a list of pane indicies with your -m command. for example, if you want to output to panes 2 and 3 on window 2, you would do it thusly:

  -m=2:2,3

Note that the '=' is now required for the use of -m if there is no intervening
spaces. This might break some Bash scripting, so please be aware of this.

You can easily see your pane's indices for any TMUX window by doing
the "<TMUX key> q" sequence (or whowever you have that functionality mapped).

*** New Sequencing with 1.4.x We already had sequencing, but now we will allow you to use a predefined sequence in the configuration section. This will allow you to make proper lists of resources in your Ansible playbooks of resources created by sequencing in another playbook.

Please see [[examples/development.play][development.play]] for an example.

The "predefined list" can only currently be used in the context of sequencing.
Later on, we wish to make this more general. But Ruby underlies the DSL, so you
can accomplish quite a bit already with just a little Ruby added!

** DSL Terminology & Documentation Note that this is the DSL for version 1.x of PowerPlay. For 0.x, please see those tags in GitHub.

*** DSL The DSL is straightforward as possible, simple and elegant to allow you to write your Powerplays in a DRY manner.

For examples, please see the following:
| [[examples/stack.play][stack.play]]       | This is loaded by default, and you must be in your current directory     |
| [[examples/development.play][development.play]] | This is a fullblown Power Playbook for a hypothetical development stack. |
| [[examples/production.play][production.play]]  | This is a fullblown Power Playbook for a hypothetical production stack.  |
| [[examples/playbooks][playbooks]]        | Sample Ansible playbooks called by Powerplay.                            |

To run the powerplay example:

1. Install Ansible Powerplay
   + gem install ansible-powerplay
2. Clone this project locally, then cd into the examples directory
   + git clone https://github.com/flajann2/ansible-powerplay.git
   + cd ansible-powerplay/examples
3. source ansible-paths and run Powerplay
   + source ansible-paths.sh
   + powerplay play -p development -v2

Note that I deliberately left a missing "elasticsearch.yml" so you
can see how Powerplay handles the errors.

configuration You can intersperse configuration blocks anywhere, and the expected nested scoping will take effect. playbooks playbooks are a collection of groups, and a group defaults to async mode for its members.

 Group are normally executed serially. This will
 allow you to organize your plays in an intelligent
 manner to deploy and manage resources and assets
 that may have to be done in a serial manner.

**** group A group is a collection of books or other groups that all execute in parallel by default. Books are required to be independent of each other. If they are not, you can set them up to execute serially.

**** book A book has a direct correspondence to an Ansible playbook, and will execute that Yaml file given the configuration variables as parameters.

 Here is where var inheritance becomes useful.
 Note that all the configuration variables
 set at the time the book is called are all
 passed in as --extra-vars to Ansible Playbook.
 The Playbook may not need all the vars passed
 in, but care must be taken that no vars
 are used in a different manner than expected.
 We currently have no way of knowing which
 vars are needed or not, and to specifiy that
 would make the syntax messy and loose some
 of the advantages of var inheritance.

** Installation Easy installation. From command-line:

+BEGIN_SRC bash

gem install ansible-powerplay

+END_SRC

Or from a gemfile:

+BEGIN_SRC ruby

gem 'ansible-powerplay'

+END_SRC

** Use Basically, cd to the root of your Ansible directory, and a .play file (see the example at: [[https://github.com/flajann2/ansible-powerplay/blob/master/examples/stack.play][stack.play]].)

You can place a config clause either globally, inside of playbooks, inside of groups, and the variable set up this way are inherited to the inner clauses, thus allowing you to keep your specifications DRYer.

For example:

+BEGIN_SRC ruby

This is a global system configuration

configuration :system do playbook_directory "playbooks" end

+END_SRC

Note that 'playbook_directory' is special, as it allows you to define the directory all of your Ansible playbooks can be found. You can also specify this anywhere you can use the configuration clause, so you may set up different playbook directories for different playbook collections.

+BEGIN_SRC ruby

sṕecific configuration for :development

configuration do stack :development krell_type "t2.small" servers 1 rolling 3 krell_disk_size 20 end

+END_SRC

The above shows Ansible variables for my specialiezd setup that is geared with work with AWS. You are free to specify any variables here, which will be injected into ansible-playbook through the '--extra-vars' parameter.

Here is a group clause with a single book in it:

+BEGIN_SRC ruby

Groups are executed serially.

group :first, "our very first group" do

Books within a group are executed in parallel,

 # and therefore must be independent of each other.
 book :nat, "nat.yml"

end

+END_SRC

Which issues the following command to Ansible (based on the earlier configuration):

+BEGIN_SRC bash

ansible-playbook playbooks/nat.yml \ --extra-vars "playbook_directory=playbooks stack=development krell_type=t2.small servers=1 rolling=3 krell_disk_size=20"

+END_SRC

And if our group had more book entries, as in the second example:

+BEGIN_SRC ruby

group :second, "our second group" do book :rabbit, "rabbitmq_cluster.yml" do krell_type "t2.medium" end

 book :es_cluster, "elasticsearch_cluster.yml" do
   esver "1.7.4"
   cluster_name :es
   servers 3
   heapsize "2g"
   krell_type "t2.medium"
   krell_disk_size 200
 end

end

+END_SRC

Both the :rabbit and :es_cluster books would be executed in parallel.

*** Dividing up your specs in other PowerPlay files Ruby, the underlying language, give you a lot of things for "free", like allowing you to load other powerplay files, for example:

#+BEGIN_SRC ruby
load 'production.play'
#+END_SRC

We mention this here for those who may not be familiar with Ruby,
but may wish to section off your specifications thusly.

You don't really need to know any Ruby, but it could increase
the span of what you might want to do. To get a quick taste,
please checkout [[https://www.ruby-lang.org/en/documentation/quickstart/][Ruby in 20 Minutes]].

It is also possible to leverage Ruby's metaprogramming techniques to
create templates for your specificaitons, but at some point, as time
allows, I may directly support this in the DSL. Please let your
wishes be known to me for this and any other feature you might want to
see.

*** Running Powerplay If you type 'powerplay' without parameters, you are greeted with:

+BEGIN_SRC doc

Commands: powerplay help [COMMAND] # Describe available commands or one specific command powerplay play Githubissues.

  • Githubissues is a development platform for aggregating issues.