Browse Source

Initial commit of documentation

cmacrae 10 năm trước cách đây
mục cha
commit
20bc9a0100

+ 18 - 0
LICENSE

@@ -0,0 +1,18 @@
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 37 - 0
docs/afewwords.md

@@ -0,0 +1,37 @@
+# A few words from the author
+Well, thanks for bothering to even visit this page!
+
+This role was born out of my own passion for the absolutely excellent projects that it uses.
+I figure I have to list them, in no particular order, here they are. __Make sure to check them all out!__
+
+- [Ansible](http://ansible.com/home)
+- [Sensu](https://sensuapp.org/)
+- [Uchiwa](https://uchiwa.io/#/)
+- [SmartOS](https://smartos.org/)
+- [RabbitMQ](https://rabbitmq.com/)
+- [Redis](http://redis.io/)
+
+## What about support for other operating systems?
+It's planned! I've done development for this role entirely on [SmartOS](https://smartos.org/).
+It makes development fast, easy, and cheap! Just a few reasons it really is the perfect operating system ;)
+
+I've already started support for OpenBSD, other BSDs and some Linuxes will follow, notably:
+
+- FreeBSD
+- NetBSD
+- EL
+- Ubuntu/Debian
+
+I'd be happy to add any others to the list if high demand shows.
+
+## About updates
+This is a personal project of mine that I work on in my own free time.
+Most of the real "meat" is there, I just need to restructure and implement conditional includes based on facts.
+
+That said, I'm a busy man! And when I do get time, all development takes place on [a little HP microserver](http://drentheweer.nl/img/hpn54l.png)... which, when straying from [Zones](https://wiki.smartos.org/display/DOC/Zones), can get a little sluggish.
+
+So please, [bear with me](http://i.imgur.com/bGhY7oX.jpg). I'll happily accept any contributions, both in [additions to the code](https://github.com/cmacrae/ansible-sensu/pulls), and any [bug reports](https://github.com/cmacrae/ansible-sensu/issues) :)
+
+## If you like it
+Share it! Get it out there; link it all over the place!
+It's not just about awesome deployment, it's about exposing people to excellent open source software!

+ 59 - 0
docs/custom_client_config.md

@@ -0,0 +1,59 @@
+# Custom Client Configuration
+When this Ansible role deploys the Sensu client configuration - defined in `client.json` in the Sensu configuration directory, it works out [subscriptions](https://sensuapp.org/docs/0.18/clients#definition-attributes) based on group membership within the Ansible inventory.
+For example, if you have a `webservers` group within your Ansible inventory, any nodes listed in that group will automatically gain a subscription to `webservers` within Sensu.
+This is quite a powerful, convenient feature. It's coupled with the deployment of [checks](https://sensuapp.org/docs/0.18/checks). If you add a new webserver to your infrastructure, Sensu will dynamically pick it up, subscribe it to 'webservers', and deploy webserver checks, without you having to do anything other than add that node into the `webservers` group within your Ansible inventory. Instantaneous monitoring of your web services!
+
+The above is all very nice and fancy, but, what if you want to define some other properties for a specific node, or override its subscriptions altogether?
+
+Well, I've added the ability to define the client template to deploy with the use of a variable. This means you can deploy a specific client configuration for a single node, or a group, or really whatever you want. A nice property of this is that it's still a Jinja2 template (if you want it to be), so you can still include dynamic data whilst making your desired modifications.
+
+## Setting a custom client configuration for a single node
+Setting a custom client configuration is done using the `sensu_client_config` variable.
+By default, this is set to `client.json.j2`, which resides within the `templates` directory of this role.
+
+It's contents (as of writing) are as follows:
+``` jinja2
+{
+  "client": {
+    "name": "{{ ansible_hostname }}",
+    "address": "{{ ansible_default_ipv4['address'] }}",
+      "subscriptions": {{ group_names | to_nice_json }}
+  }
+}
+```
+As you can see from above, this configuration's values are all populated using [facts](http://docs.ansible.com/playbooks_variables.html#information-discovered-from-systems-facts).
+
+To override this for a single node, this can be set in the `host_vars/node_name.domain.name.yml` file.
+
+Let's say we have a node, called `custom.cmacr.ae`, that we'd like to set the `subscriptions` value for.
+We could drop a template somewhere into our Ansible codebase called `custom_sensu.client.json.j2` then populate like so:
+``` jinja2
+{
+  "client": {
+    "name": "{{ ansible_hostname }}",
+    "address": "{{ ansible_default_ipv4['address'] }}",
+      "subscriptions": [
+	    "production",
+	    "custom"
+      ]
+  }
+}
+```
+
+Then we would need to set the `sensu_client_config` variable for `custom.cmacr.ae` in `host_vars/custom.cmacr.ae.yml`:
+``` yaml
+sensu_client_config: path/to/custom_sensu.client.json.j2
+```
+This would override this particular node's value(s) for the `subscriptions` field, therefore changing what monitoring streams it subscribes to.
+
+
+## Setting a custom client configuration for a group
+Setting a custom client configuration for a group of nodes is done just the same as a single node instance, just using something like `group_vars/group_name.yml` instead of `host_vars/node.domain.name.yml`
+
+Alright, we've got some servers that we don't want to bother all that much in a group called `thelazyones`.
+Let's set their `keepalive` value to a higher value than usual (20 seconds).
+An easy and logical way of approaching this would be to set `group_vars/thelazyones.yml` like so:
+``` yaml
+sensu_client_config: path/to/lazy_sensu.client.json.j2
+```
+Where `path/to/lazy_sensu.client.json.j2` is a Jinja2 template setting the `keepalive` value to something greater than usual.

+ 95 - 0
docs/deploy_plugins.md

@@ -0,0 +1,95 @@
+# Deployment of Handlers, Filters, and Mutators
+_Note:_ _If you haven't familiarized yourself with the concept of the static data store please read 'Dynamic check deployment'_
+
+Deployment of [handlers](https://sensuapp.org/docs/0.18/handlers), [filters](https://sensuapp.org/docs/0.18/filters), and [mutators](https://sensuapp.org/docs/0.18/mutators) is handled by leveraging templates and other data placed in the static data store.
+
+## Static data store hierarchy with respect to handlers/filters/mutators
+To deploy your handlers, filters, and mutators, you'll need to have directories named after each under a directory called 'sensu' in your static data store:
+```
+$ tree data/static
+data/static
+`-- sensu
+    |-- definitions
+    |   |-- check_nginx.json.j2
+    |   |-- check_rabbitmq.json.j2
+    |   |-- check_redis.json.j2
+    |   |-- pushover.json.j2
+    |   |-- pushover_handler.json.j2
+    |   |-- smartos_check_cpu.json.j2
+    |   |-- smartos_check_disk.json.j2
+    |   `-- smartos_check_mem.json.j2
+    |-- handlers
+    |   `-- pushover.rb
+	|-- filters
+    `-- mutators
+```
+
+## How handlers, filters, and mutators are deployed
+All three are deployed using Ansible's [template]() module. This allows the use of variables within your configurations, which can come in quite handy!
+
+Let's take a look at the stuff I've got for [Pushover](https://pushover.net/).
+First off, the [handler](https://sensuapp.org/docs/0.18/getting-started-with-handlers) json file `pushover_handler.json.j2`:
+``` json
+{
+  "handlers": {
+    "pushover": {
+      "type": "pipe",
+      "command": "{{ sensu_config_path }}/plugins/pushover.rb",
+      "timeout": 10,
+      "severites": ["critical"]
+    }
+  }
+}
+```
+This is a simple handler definition, registering the `pushover` handler, and its properties, so that it can be used for any checks that trigger it.
+
+[This particular handler](https://github.com/sensu/sensu-community-plugins/blob/master/handlers/notification/pushover.rb) needs a configuration file, `pushover.json.j2`:
+``` json
+{
+        "pushover": {
+                "apiurl": "https://api.pushover.net/1/messages",
+                "userkey": "{{ sensu_pushover_userkey }}",
+                "token": "{{ sensu_pushover_token }}"
+        }
+}
+
+```
+As mentioned above, you can see here how the use of variables within these definitions can come in useful.
+To use this, I have `sensu_pushover_userkey` & `sensu_pushover_token` defined in the `host_var` file of my Sensu "master" node.
+
+Not all handler's require a config file like this, but I figured I'd use this example to show how useful the templates can be.
+
+Finally, we have the actual handler script [`pushover.rb`](https://github.com/sensu/sensu-community-plugins/blob/master/handlers/notification/pushover.rb), which resides in the `handlers` directory.  
+
+
+These are all deployed when the role runs through the `tasks/plugins.yml` playbook, in particular these plays:
+```
+  - name: Deploy handler plugins
+    copy: src={{ static_data_store }}/sensu/handlers/
+          dest={{ sensu_config_path }}/plugins/ mode=755
+          owner={{ sensu_user_name }} group={{ sensu_group_name }}
+    notify: restart sensu-client service
+
+  - name: Deploy filter plugins
+    copy: src={{ static_data_store }}/sensu/filters/
+          dest={{ sensu_config_path }}/plugins/ mode=755
+          owner={{ sensu_user_name }} group={{ sensu_group_name }}
+    notify: restart sensu-client service
+
+  - name: Deploy mutator plugins
+    copy: src={{ static_data_store }}/sensu/mutators/
+          dest={{ sensu_config_path }}/plugins/ mode=755
+          owner={{ sensu_user_name }} group={{ sensu_group_name }}
+    notify: restart sensu-client service
+
+  - name: Deploy check/handler/filter/mutator definitions to the master
+    template: src={{ static_data_store }}/sensu/definitions/{{ item }}.j2
+          dest={{ sensu_config_path }}/conf.d/{{ item }}
+          owner={{ sensu_user_name }} group={{ sensu_group_name }}
+    when: sensu_master
+    with_lines:
+      - ls {{ static_data_store }}/sensu/definitions | cut -d. --fields=1,2
+    notify: restart sensu-api service
+
+```
+Quite straight forward and repetitive. If you skim this code, it may become clear that failures could be introduced if the source directories don't exist within your static data store. That's correct. You may have noticed that the example output `tree` shows both the `filters` & `mutators` directories are empty. It's expected that such features will be used, but if you don't wish to use filters or mutators, you still need to ensure these directories exist.

+ 137 - 0
docs/dynamic_checks.md

@@ -0,0 +1,137 @@
+# Dynamic Check Deployment
+One of the awesome features of this role (if I do say so myself) is the deployment of Sensu [checks](https://sensuapp.org/docs/0.18/checks) on a dynamic basis. Deployment of which checks should be distributed to which nodes is determined from group membership within the Ansible inventory.
+
+Have a group of webservers you need to monitor webservices on? Well, I'm sure you've bunched them together in your inventory under the `[webservers]` group, right? Or perhaps you only want to monitor disk space on your production systems; if they're a member of `[production]` within the inventory, you can do this easily.
+
+## How it works
+Much like the dynamic datastore, I have also defined a static data store within my Ansible codebase, by setting the variable `static_data_store`.
+Within this static datastore resides the following directory structure:
+```
+$ tree data/static
+data/static
+`-- sensu
+    |-- checks
+    |   |-- rabbitmq_servers
+    |   |   `-- check_rabbitmq.sh
+    |   |-- redis_servers
+    |   |   `-- check_redis.sh
+    |   |-- webservers
+    |   |   `-- check_nginx.sh
+    |   `-- zones
+    |       |-- check_cpu.rb
+    |       |-- check_disk.rb
+    |       `-- check_mem.rb
+    |-- definitions
+    |   |-- check_nginx.json.j2
+    |   |-- check_rabbitmq.json.j2
+    |   |-- check_redis.json.j2
+    |   |-- pushover.json.j2
+    |   |-- pushover_handler.json.j2
+    |   |-- smartos_check_cpu.json.j2
+    |   |-- smartos_check_disk.json.j2
+    |   `-- smartos_check_mem.json.j2
+    |-- handlers
+    |   `-- pushover.rb
+    `-- mutators
+```
+As you can see, in the `sensu/checks` directory, there are the `rabbitmq_servers`, `redis_servers`, `webservers` & `zones` subdirectories.
+If you've had a peruse through some of the other documentation here, you'll know that these groups are defined within my Ansible inventory:
+``` ini
+[rabbitmq_servers]
+test.cmacr.ae
+
+[redis_servers]
+redis.cmacr.ae
+
+[sensu_masters]
+sensu.cmacr.ae
+
+[webservers]
+blog.cmacr.ae
+web.cmacr.ae
+sab.cmacr.ae
+tater.cmacr.ae
+beardy.cmacr.ae
+pkgsrc.cmacr.ae
+
+[zones]
+ansible.cmacr.ae
+beardy.cmacr.ae
+blog.cmacr.ae
+bunny.cmacr.ae
+git.cmacr.ae
+irc.cmacr.ae
+pkgsrc.cmacr.ae
+redis.cmacr.ae
+sab.cmacr.ae
+sensu.cmacr.ae
+tater.cmacr.ae
+web.cmacr.ae
+test.cmacr.ae
+```
+Under these subdirectories, you can see [checks](https://sensuapp.org/docs/0.18/checks) that relate to directory they're placed in.
+The `webservers` subdirectory includes a `check_nginx.sh` script, whilst the `rabbitmq_servers` subdirectory has one that most likely checks for RabbitMQ problems (it does... trust me).  
+
+So how do these checks actually get deployed to their associated nodes?
+With this pair of plays, in the `tasks/plugins.yml` playbook:
+``` yaml
+  - name: Register available checks
+    local_action: command ls {{ static_data_store }}/sensu/checks
+    register: sensu_available_checks
+    changed_when: False
+
+  - name: Deploy check plugins
+    copy: src={{ static_data_store }}/sensu/checks/{{ item }}/
+          dest={{ sensu_config_path }}/plugins/ mode=755
+          owner={{ sensu_user_name }} group={{ sensu_group_name }}
+    when: sensu_available_checks.stdout.find('{{ item }}') != -1
+    with_flattened:
+      - group_names
+    notify: restart sensu-client service
+```
+This will [register](http://docs.ansible.com/playbooks_conditionals.html#register-variables) a list of available checks, then deploy them to their intended groups based on node membership, as set within the Ansible inventory.
+
+And, because nodes can of course be members of more than just one group, checks will be deployed in full to nodes that belong to several groups!
+
+## Defining your static data store
+Just like defining the dynamic data store, this needs to be done somewhere it can be made available to all the nodes you'll be applying this role to. I do this in the same place I define `dynamic_data_store`: `group_vars/all.yml`, like so:
+``` yaml
+static_data_store: path/to/ansible/codebase/data/static
+```
+Once you've defined where you'd like your static data store to be, you can drop in some checks by creating a similar data structure to mine:
+```
+data/static
+`-- sensu
+    `-- checks
+        |-- rabbitmq_servers
+        |   `-- check_rabbitmq.sh
+        |-- redis_servers
+        |   `-- check_redis.sh
+        |-- webservers
+        |   `-- check_nginx.sh
+        `-- zones
+            |-- check_cpu.rb
+            |-- check_disk.rb
+            `-- check_mem.rb
+```
+
+## Picking up changes on the fly
+Let's say, for some reason, one of your nodes decides to switch roles, or take on the responsibility of another role.
+You've got a webserver, who all of a sudden you decide "this guy should be running Redis too". No problem!
+You probably had something like:
+```
+[webservers]
+mime.domain.name
+```
+In your Ansible inventory, after this spontaneous decision to have your webserver act as a key-value store, you may change it to the following:
+```
+[webservers]
+mime.domain.name
+
+[redis_servers]
+mime.domain.name
+```
+Not to worry, the next time your playbook applying this Sensu role runs through (notably the `tasks/client.yml` & `tasks/plugins.yml` playbooks), the new checks for Redis will be deployed to `mime.domain.name` and it'll be subscribed to the `redis_servers` stream within Sensu. Pretty slick, right?
+
+The same goes for the removal of a node from a group. Did you just realize you really don't want `mime.domain.name` to act as a Redis server?
+It's cool, we all make mistakes, just take him out of the `[redis_servers]` group in your inventory. When your play comes through again, applying this Sensu role, he'll be unsubscribed from the `redis_servers` stream, and Redis'll stop being monitored!

+ 89 - 0
docs/dynamic_data.md

@@ -0,0 +1,89 @@
+# Dynamic Data Store
+Throughout this role, you may notice the use of the variable `dynamic_data_store`.
+This is a convention that I have implemented personally within my infrastructure, though it stems from a feature that I'm sure many people leverage in their own way - probably in a very similar manner.
+
+## The concept
+The dynamic data store is a directory on the node acting as the Ansible "master" (where you're pushing all your Ansible code from).
+This directory, in version control, is practically empty, with the exception of a `.gitignore` with the following contents:
+```
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
+```
+Using this `.gitignore` ensures that the directory (and the `.gitignore`) are kept within version control, but anything that may be placed in it is not tracked. As you may have figured out from the name "dynamic", that's because the data here will be subject to change with your infrastructure.
+
+The idea behind having this "empty" directory within your codebase is that, when deploying your Ansible code repo to your Ansible "master", it ensures the directory is there. This directory is then used in conjunction with some roles to store node specific data that you may wish to distribute amongst other nodes.
+
+## Use of the dynamic data store in this Sensu role
+If you take a look at the `tasks/ssl.yml` playbook, there's a use of the handy [`fetch`](http://docs.ansible.com/fetch_module.html) module.
+
+>This module works like `copy`, but in reverse. It is used for fetching files from remote machines and storing them locally in a file tree, organized by hostname.
+
+Very handy!
+
+I've coupled this with the generation of SSL certs on the Sensu "master". So, when applying this role to a node on which `sensu_master` evaluates to `true`, SSL several SSL certs are generated, then stashed on the Ansible "master" node in the dynamic data store for distribution to client nodes at a later point in the playbook.
+
+I've defined my `dynamic_data_store` variable at the top level of my Ansible codebase, in the file `group_vars/all.yml`:
+``` yaml
+dynamic_data_store: /path/to/ansible/config/data/dynamic
+```
+Let's take a look at this directory:
+```
+$ tree data/dynamic
+data/dynamic/
+`-- sensu.cmacr.ae
+    `-- opt
+        `-- local
+            `-- etc
+                `-- sensu
+                    `-- ssl_generation
+                        `-- ssl_certs
+                            |-- client
+                            |   |-- cert.pem
+                            |   `-- key.pem
+                            |-- sensu_ca
+                            |   `-- cacert.pem
+                            `-- server
+                                |-- cert.pem
+                                `-- key.pem
+```
+As you can see, it resembles the file tree from the node it fetched the data from. This is configurable behavior, and can be set otherwise if you find this inconvenient/unsightly. See [ the `fetch` documentation](http://docs.ansible.com/fetch_module.html) for more information.
+
+## Deployment of the data fetched to the dynamic data store
+Next up is this rather unsightly play (still from the `tasks/ssl.yml` playbook):
+``` yaml
+  - name: Deploy the Sensu client SSL cert/key
+    copy: src={{ dynamic_data_store }}/{{ groups['sensu_masters'][0] }}/{{ sensu_config_path }}/ssl_generation/ssl_certs/client/{{ item }}
+          owner={{ sensu_user_name }} group={{ sensu_group_name }}
+          dest={{ sensu_config_path }}/ssl
+    with_items:
+      - cert.pem
+      - key.pem
+
+```
+Blegh! Pretty ugly, right? Well, it may not be so great looking, but it's pretty nifty.
+It takes care of distributing the SSL certificates to the client systems so they can interact with the Sensu API.
+
+The same method is used for node communication with RabbitMQ:
+`tasks/rabbitmq.yml`
+``` yaml
+  - name: Ensure RabbitMQ SSL certs/keys are in place
+    copy: src={{ dynamic_data_store }}/{{ groups['sensu_masters'][0] }}/{{ sensu_config_path }}/ssl_generation/ssl_certs/{{ item }}
+          dest={{ rabbitmq_config_path }}/ssl
+    with_items:
+      - sensu_ca/cacert.pem
+      - server/cert.pem
+      - server/key.pem
+```
+
+## So, what do I need to do?
+Well, you simply need to decide where, on your Ansible "master" node's filesystem, where you'd like your dynamic data store to reside.
+Then simply set the `dynamic_data_store` value to that path for all nodes that are going to be using this Sensu role, as described above.
+
+This variable's value, like any other in Ansible, can include variable(s) itself also.
+I have a role that deploys an Ansible "master" node, and use a variable for where I want my Ansible codebase to sit.
+So my `dynamic_data_store` (again) defined in `group_vars/all.yml` is actually set to:
+``` yaml
+dynamic_data_store: {{ ansible_conf_path }}/data/dynamic
+```

+ 81 - 0
docs/example_infra.md

@@ -0,0 +1,81 @@
+# Example Infrastructure Layout
+
+This document showcases an example layout for use with the Sensu role within your infrastructure.  
+It ties in with use of inventory grouping and variables.
+
+## Inventory & Variables
+
+### Sensu/Uchiwa variables
+Let's start with an example Ansible Inventory:
+
+``` ini
+[rabbitmq_servers]
+test.cmacr.ae
+
+[redis_servers]
+redis.cmacr.ae
+
+[sensu_masters]
+sensu.cmacr.ae
+
+[webservers]
+blog.cmacr.ae
+web.cmacr.ae
+sab.cmacr.ae
+tater.cmacr.ae
+beardy.cmacr.ae
+pkgsrc.cmacr.ae
+
+[zones]
+ansible.cmacr.ae
+beardy.cmacr.ae
+blog.cmacr.ae
+bunny.cmacr.ae
+git.cmacr.ae
+irc.cmacr.ae
+pkgsrc.cmacr.ae
+redis.cmacr.ae
+sab.cmacr.ae
+sensu.cmacr.ae
+tater.cmacr.ae
+web.cmacr.ae
+test.cmacr.ae
+```
+
+Here we have some nodes grouped into `rabbitmq_servers`, `redis_servers`, `sensu_masters`, `webservers`, and `zones`.
+
+Since we only want one Sensu "master", the default to act as a master in this role is set to `false` - defined by `sensu_master`.
+
+There are several ways to approach setting `sensu_master` to `true` for the node you'd like to act as the Sensu "master".  
+Personally, I do this by setting the following in `group_vars/sensu_masters.yml`:
+``` yaml
+sensu_master: true
+sensu_include_dashboard: true
+```
+You can see I decided I want the Uchiwa dashboard to be deployed also, so I set `sensu_include_dashboard` to `true`.
+
+The above code could also be set straight in the node's `host_vars` file: `host_vars/sensu.cmacr.ae.yml` or set straight in a playbook intended just for the `sensu_masters` node:
+``` yaml
+  - hosts: sensu_masters
+    roles:
+	  - { role: cmacrae.sensu, sensu_master: true, sensu_include_dashboard: true  }
+```
+
+### RabbitMQ/Redis variables
+You'll probably have noticed the two groups `rabbitmq_servers` and `redis_servers` in the example inventory.
+Quite self explanatory what these are, but - as with the `sensu_master` variable in the previous section - both the `rabbitmq_server` & `redis_server` values are set to `false` by default (defined in `defaults/main.yml`).
+
+The same approach of setting these to `true` is taken here again.
+Once more, I opt to set these in `group_vars`, like so:
+
+`group_vars/rabbitmq_servers.yml`
+``` yaml
+rabbitmq_server: true
+```
+
+`group_vars/redis_servers.yml`
+``` yaml
+redis_server: true
+```
+
+The same can, again, be set directly in your RabbitMQ/Redis nodes' `host_vars` files, or done so in the playbook as shown in the previous section for the values `sensu_master` & `sensu_include_uchiwa`.

+ 17 - 0
docs/index.md

@@ -0,0 +1,17 @@
+# Welcome to MkDocs
+
+For full documentation visit [mkdocs.org](http://mkdocs.org).
+
+## Commands
+
+* `mkdocs new [dir-name]` - Create a new project.
+* `mkdocs serve` - Start the live-reloading docs server.
+* `mkdocs build` - Build the documentation site.
+* `mkdocs help` - Print this help message.
+
+## Project layout
+
+    mkdocs.yml    # The configuration file.
+    docs/
+        index.md  # The documentation homepage.
+        ...       # Other markdown pages, images and other files.

+ 52 - 0
docs/sensitive_info.md

@@ -0,0 +1,52 @@
+# Sensitive Information in Version Control
+The Sensu framework is a distributed one, requiring different components to communicate over the network.
+Naturally, a means of authentication falls into place. This can require setting credentials to ensure secure communications are made.
+
+You might have noticed, in this role's `defaults/main.yml` that there are a few variables you can set for password properties.
+If you're keeping your Ansible configuration in version control (as you really should be) - or anywhere for that matter - you most likely don't want such information to be expressed in plain text, readable to anyone/anything that may stumble upon it.
+
+Ansible has an excellent feature called [Vault](http://docs.ansible.com/playbooks_vault.html) - introduced in version 1.5.
+It offers a means of encrypting various pieces of data throughout your Ansible codebase.
+
+As mentioned already throughout this documentation: Ansible really is quite versatile, so this can be approached in quite a few ways, but here's how I would suggest encrypting the sensitive variables necessary for use with this Sensu role.
+
+### Encrypting the various `host_vars` files
+Let's say we want to set the Uchiwa username and password for the node we have acting as the dashboard for our Sensu setup.
+If it were a host called `uchiwa.cmacr.ae`, we could set the following in `host_vars/uchiwa.cmacr.ae.yml`:
+``` yaml
+uchiwa_user_name: mordecai
+uchiwa_password: rigby
+```
+Then, using `ansible-vault` we can encrypt this file: `$ ansible-vault encrypt host_vars/uchiwa.cmacr.ae.yml`
+
+Or, if we want to set the Sensu API credentials; `host_vars/sapi.cmacr.ae.yml`:
+``` yaml
+sensu_api_user_name: muscleman
+sensu_api_password: highfiveghost
+```
+Same deal with encrypting it: `$ ansible-vault encrypt host_vars/uchiwa.cmacr.ae.yml`
+
+It'll prompt for a password to encrypt with, so make sure you remember this!
+
+### Encrypting some other `vars` file
+You don't have to set these variables directly in specific a node's variables.
+These could also be defined in, say, `vars/sensitive.yml` at the top of your Ansible codebase:
+
+``` yaml
+uchiwa_user_name: mordecai
+uchiwa_password: rigby
+sensu_api_user_name: muscleman
+sensu_api_password: highfiveghost
+```
+Next up: `$ ansible-vault encrypt vars/sensitive.yml`
+Then, to ensure the variables are picked up during the play, you can add `vars/sensitive.yml` to the `vars_files` list directly in your playbook:
+``` yaml
+  - name: Apply the Sensu role to all nodes
+    hosts: all
+    vars_files:
+      - /path/to/ansible_codebase/vars/sensitive.yml
+```
+
+### Editing encrypted data
+Editing encrypted data is as easy as `$ ansible-vault edit path/to/data.yml`
+See [the Ansible Vault page for more information](http://docs.ansible.com/playbooks_vault.html)

+ 41 - 0
docs/single_master.md

@@ -0,0 +1,41 @@
+# Deploy the stack to a single node
+Hopefully after a quick read of the example infrastructure document, it becomes clear that this could all be applied to one node in your infrastructure.  
+If you're just wanting to test this out, or if you don't want to distribute your services for some other reason; you can simply deploy the components to a single node.
+
+This is achieved in the exact same way, setting each of the variables listed to `true`, but for one node only.
+There are, however, a couple tweaks that can be made to keep your inventory a little cleaner. That is to say; if you didn't want to define `rabbitmq_servers` or `redis_servers` to simply include one node.
+
+This can be done with the following snippets.
+
+## One node to rule them all
+`host_vars/master.cmacr.ae.yml`
+``` yaml
+sensu_master: true
+sensu_include_dashboard: true
+rabbitmq_server: true
+redis_server: true
+```
+This would set the node `master.cmacr.ae` to act as the Sensu, RabbitMQ, and Redis server for all Sensu communications across your infrastructure.
+
+## Statically setting the communication endpoints
+In `defaults/main.yml` the following keys have the following values:
+``` yaml
+rabbitmq_host: "{{ groups['rabbitmq_servers'][0] }}"
+redis_host: "{{ groups['redis_servers'][0] }}"
+sensu_api_host: "{{ groups['sensu_masters'][0] }}"
+```
+This is an example of using [Ansible's awesome lookups](http://docs.ansible.com/playbooks_lookups.html).  
+
+These are very important values, they determine the points of communication for each component of Sensu.  
+If you're just deploying the stack to a single node and you've decided you'd like to leave any of the `rabbitmq_servers`/`redis_servers`/`sensu_masters` groups out of your inventory, you'll need to statically set the communication endpoints.
+
+Where you set this is, again, up to you - Ansible really is quite versatile!
+If you're deploying the Sensu client to all your nodes - as you should be ;) - it's only logical to set these values globally.
+You can do so by setting them in `group_vars/all.yml`:
+``` yaml
+rabbitmq_host: master.cmacr.ae
+redis_host: master.cmacr.ae
+sensu_api_host: master.cmacr.ae
+```
+This will tell your entire environment that if they're looking to communicate with RabbitMQ, Redis, or the Sensu API, they can talk to `master.cmacr.ae`. Of course, if you're just distributing Sensu to just the `zones` group or `some_other_group`, the same could be set in `group_vars/zones.yml`/`group_vars/some_other_group.yml`.
+

+ 17 - 0
mkdocs.yml

@@ -0,0 +1,17 @@
+site_name: Ansible Sensu
+site_url: https://galaxy.ansible.com/list#/roles/3802
+repo_url: https://github.com/cmacrae/ansible-sensu/
+site_description: An Ansible role to deploy a fully dynamic Sensu stack!
+site_author: Calum MacRae
+
+pages:
+  - [ '../README.md', 'README' ]
+  - [ 'example_infra.md', 'Usage', 'Example infrastructure layout' ]
+  - [ 'single_master.md', 'Usage', 'Deploy the stack to a single node' ]
+  - [ 'custom_client_config.md', 'Usage', 'Custom client configuration' ]
+  - [ 'deploy_plugins.md', 'Usage', 'Deployment of handlers/filters/mutators' ]
+  - [ 'sensitive_info.md', 'Usage', 'Sensitive information in version control' ]
+  - [ 'dynamic_data.md','Conventions','Dynamic data store' ]
+  - [ 'dynamic_checks.md','Conventions','Dynamic check deployment' ]
+  - [ '../LICENSE','About','LICENSE' ]
+  - [ 'afewwords.md','About','A few words from the author' ]