From 271ff6a09c104f97f23511973877e8b1502c1c40 Mon Sep 17 00:00:00 2001
From: Kevin Carter <kevin.carter@rackspace.com>
Date: Wed, 16 Jan 2019 12:30:09 -0600
Subject: [PATCH] Add project directory to overlay inventories

The use of an overlay inventory has now been added to a stand alone
directory which should help deployers understand how this could work
within their environments. Inventory configuration has been updated to
show this working in the various projects that have tests and could
benefit from an overlay inventory.

Change-Id: I1681fce160b43e9127851f06ae05ff5eaabe852f
Signed-off-by: Kevin Carter <kevin.carter@rackspace.com>
---
 grafana/ansible-role-requirements.yml         |   5 +
 grafana/installGrafana.yml                    |   6 +-
 grafana/inventory.example.yml                 |   2 +-
 grafana/site.yml                              |  16 ++
 osquery/env.d/fleet.yml                       |   6 +-
 osquery/installDB.yml                         |   4 +-
 osquery/installOSquery.yml                    |   2 +-
 osquery/roles/fleet/tasks/createFleetDB.yml   |   4 +-
 .../inventory/test-container-inventory.yml    |  11 +-
 .../tests/inventory/test-metal-inventory.yml  |   7 +-
 overlay-inventories/README.md                 |  85 +++++++++
 .../osa-integration-inventory.yml             | 161 ++++++++++++++++++
 skydive/README.md                             |   9 +-
 .../inventory/osa-integration-inventory.yml   |  63 -------
 14 files changed, 296 insertions(+), 85 deletions(-)
 create mode 100644 grafana/ansible-role-requirements.yml
 create mode 100644 grafana/site.yml
 create mode 100644 overlay-inventories/README.md
 create mode 100644 overlay-inventories/osa-integration-inventory.yml
 delete mode 100644 skydive/inventory/osa-integration-inventory.yml

diff --git a/grafana/ansible-role-requirements.yml b/grafana/ansible-role-requirements.yml
new file mode 100644
index 00000000..6bc583d6
--- /dev/null
+++ b/grafana/ansible-role-requirements.yml
@@ -0,0 +1,5 @@
+---
+- name: grafana
+  scm: git
+  src: https://github.com/cloudalchemy/ansible-grafana
+  version: master
diff --git a/grafana/installGrafana.yml b/grafana/installGrafana.yml
index cef7579e..94a7849d 100644
--- a/grafana/installGrafana.yml
+++ b/grafana/installGrafana.yml
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 - name: Deploy Grafana
-  hosts: grafana
+  hosts: grafana_all
   become: true
   vars_files:
     - vars/variables.yml
@@ -36,6 +36,10 @@
           when:
             - galera_root_password is undefined
 
+        - name: Install PyMySQL
+          package:
+            name: python-pymysql
+
         - name: Create DB for service
           mysql_db:
             login_user: "{{ galera_root_user }}"
diff --git a/grafana/inventory.example.yml b/grafana/inventory.example.yml
index 43032048..dc4ae3a9 100644
--- a/grafana/inventory.example.yml
+++ b/grafana/inventory.example.yml
@@ -24,6 +24,6 @@ hosts:
     logging01:
 
 # This is the location where grafana(s) will live
-grafana:
+grafana_all:
   hosts:
     logging01:
diff --git a/grafana/site.yml b/grafana/site.yml
new file mode 100644
index 00000000..ef61ddc2
--- /dev/null
+++ b/grafana/site.yml
@@ -0,0 +1,16 @@
+---
+# Copyright 2019, Rackspace US, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+- import_playbook: installGrafana.yml
diff --git a/osquery/env.d/fleet.yml b/osquery/env.d/fleet.yml
index d8cf81d0..f44c5346 100644
--- a/osquery/env.d/fleet.yml
+++ b/osquery/env.d/fleet.yml
@@ -5,10 +5,10 @@ component_skel:
       - fleet_all
       - kolide-fleet_all
 
-  mariadb:
+  kolide-db:
     belongs_to:
       - fleet_all
-      - mariadb_all
+      - kolide-db_all
 
 container_skel:
   kolide-fleet_container:
@@ -16,7 +16,7 @@ container_skel:
       - kolide_containers
     contains:
       - kolide-fleet
-      - mariadb
+      - kolide-db
 
 physical_skel:
   kolide_containers:
diff --git a/osquery/installDB.yml b/osquery/installDB.yml
index 0759dfb0..61ea0b4e 100644
--- a/osquery/installDB.yml
+++ b/osquery/installDB.yml
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 - name: Install MariaDB Galera Cluster
-  hosts: "mariadb_all"
+  hosts: "kolide-db_all"
   become: true
   user: root
   gather_facts: "{{ osa_gather_facts | default(True) }}"
@@ -34,7 +34,7 @@
 
   roles:
     - role: galera_server
-      galera_cluster_members: "{{ groups['mariadb_all'] }}"
+      galera_cluster_members: "{{ groups['kolide-db_all'] }}"
       galera_wsrep_node_name: "{{ inventory_hostname }}"
       galera_cluster_name: telemetry_galera_cluster
       galera_monitoring_allowed_source: "0.0.0.0/0"
diff --git a/osquery/installOSquery.yml b/osquery/installOSquery.yml
index eede075f..a479024c 100644
--- a/osquery/installOSquery.yml
+++ b/osquery/installOSquery.yml
@@ -64,7 +64,7 @@
 
 
 - name: Install osquery
-  hosts: "hosts:all_containers"
+  hosts: "osquery_all"
   become: true
   vars_files:
     - vars/variables.yml
diff --git a/osquery/roles/fleet/tasks/createFleetDB.yml b/osquery/roles/fleet/tasks/createFleetDB.yml
index 2220e035..2ad524d7 100644
--- a/osquery/roles/fleet/tasks/createFleetDB.yml
+++ b/osquery/roles/fleet/tasks/createFleetDB.yml
@@ -20,7 +20,7 @@
     login_host: "127.0.0.1"
     name: "{{ kolide_fleet_db_name }}"
     state: "present"
-  delegate_to: "{{ groups['mariadb_all'][0] }}"
+  delegate_to: "{{ groups['kolide-db_all'][0] }}"
   no_log: False
   run_once: true
 
@@ -35,7 +35,7 @@
     state: "present"
     priv: "{{ kolide_fleet_db_name }}.*:ALL"
     append_privs: "{{ kolide_fleet_db_append_privs | default(omit) }}"
-  delegate_to: "{{ groups['mariadb_all'][0] }}"
+  delegate_to: "{{ groups['kolide-db_all'][0] }}"
   with_items:
     - 'localhost'
     - '127.0.0.1'
diff --git a/osquery/tests/inventory/test-container-inventory.yml b/osquery/tests/inventory/test-container-inventory.yml
index 1bcadca4..f49606e9 100644
--- a/osquery/tests/inventory/test-container-inventory.yml
+++ b/osquery/tests/inventory/test-container-inventory.yml
@@ -20,7 +20,9 @@ all:
       ansible_user: root
 
 
-hosts:
+osquery_all:
+  hosts:
+    localhost: {}
   vars:
     physical_host: localhost
     management_cidr: "172.29.236.0/24"
@@ -30,9 +32,6 @@ hosts:
         netmask: "255.255.255.0"
         bridge: "{{ hostvars[physical_host]['ansible_default_ipv4']['alias'] }}"
 
-  hosts:
-    localhost: {}
-
 
 all_containers:
   vars:
@@ -45,9 +44,9 @@ all_containers:
         bridge: "{{ hostvars[physical_host]['ansible_default_ipv4']['alias'] }}"
 
   children:
-    mariadb_all:
+    kolide-db_all:
       children:
-        mariadb:
+        kolide-db:
           hosts:
             kolide-fleet0: {}
             kolide-fleet1: {}
diff --git a/osquery/tests/inventory/test-metal-inventory.yml b/osquery/tests/inventory/test-metal-inventory.yml
index 99055900..f97b50d0 100644
--- a/osquery/tests/inventory/test-metal-inventory.yml
+++ b/osquery/tests/inventory/test-metal-inventory.yml
@@ -7,14 +7,15 @@ all:
       ansible_host: 127.0.0.1
       ansible_user: root
 
-hosts:
+
+osquery_all:
   hosts:
     localhost: {}
 
 
-mariadb_all:
+kolide-db_all:
   children:
-    mariadb:
+    kolide-db:
       hosts:
         localhost: {}
 
diff --git a/overlay-inventories/README.md b/overlay-inventories/README.md
new file mode 100644
index 00000000..90e33cfc
--- /dev/null
+++ b/overlay-inventories/README.md
@@ -0,0 +1,85 @@
+# Overlay Ansible inventories
+
+To deploy any of the operational tooling within an existing OpenStack-Ansible
+deployment environment, or any environment that is using Ansible, it's
+possible to use an overlay inventory to deploy systems without having to make
+configuration changes in an environment or it's given inventory.
+
+> An overlay inventory is nothing more than a second inventory source which
+  contains meta groups that reference other groups as children.
+
+This project folder contains reference overlay inventories that can be used
+to deploy all of the tested operational tooling.
+
+####### What's currently included
+
+* elk_metrics_6x
+* grafana
+* osquery
+* skydive
+
+#### Deploying | The environment
+
+The example overlay inventory file `osa-integration-inventory.yml` in this
+directory is being used in this example to deploy all of the operational
+tooling in an already online OpenStack-Ansible deployed cloud.
+
+> The use of overlay inventories requires modern versions of Ansible. In
+  this deployment example the embedded Ansible solution is being used to
+  ensure all of the requirements are met.
+
+``` shell
+# Clone this repo into place
+git clone https://github.com/openstack/openstack-ansible-ops /opt/openstack-ansible-ops
+
+# Source the embedded ansible
+source /opt/openstack-ansible-ops/bootstrap-embedded-ansible/bootstrap-embedded-ansible.sh
+
+# Deploy osquery and kolide/fleet
+pushd /opt/openstack-ansible-ops/osquery
+    ansible-galaxy install -r ansible-role-requirements.yml
+    ansible-playbook -i /opt/openstack-ansible/inventory/dynamic_inventory.py \
+                     -i /opt/openstack-ansible-ops/overlay-inventories/osa-integration-inventory.yml \
+                     -e @/etc/openstack_deploy/user_secrets.yml \
+                     site.yml
+popd
+
+# Deploy the elastic-stack
+pushd /opt/openstack-ansible-ops/elk_metrics_6x
+    ansible-galaxy install -r ansible-role-requirements.yml
+    ansible-playbook -i /opt/openstack-ansible/inventory/dynamic_inventory.py \
+                     -i /opt/openstack-ansible-ops/overlay-inventories/osa-integration-inventory.yml \
+                     -e @/etc/openstack_deploy/user_secrets.yml \
+                     site.yml
+popd
+
+# Deploy skydive
+pushd /opt/openstack-ansible-ops/skydive
+    ansible-galaxy install -r ansible-role-requirements.yml
+    ansible-playbook -i /opt/openstack-ansible/inventory/dynamic_inventory.py \
+                     -i /opt/openstack-ansible-ops/overlay-inventories/osa-integration-inventory.yml \
+                     -e @/etc/openstack_deploy/user_secrets.yml \
+                     site.yml
+popd
+
+# Deploy grafana
+pushd /opt/openstack-ansible-ops/grafana
+    ansible-galaxy install -r ansible-role-requirements.yml
+    ansible-playbook -i /opt/openstack-ansible/inventory/dynamic_inventory.py \
+                     -i /opt/openstack-ansible-ops/overlay-inventories/osa-integration-inventory.yml \
+                     -e @/etc/openstack_deploy/user_secrets.yml \
+                     -e @/opt/openstack-ansible-ops/elk_metrics_6x/vars/variables.yml \
+                     site.yml -e grafana_use_provisioning=no -e grafana_admin_password=secrete
+popd
+
+# Disable the embedded ansible post deployment
+deactivate
+
+# If using haproxy, run the haproxy playbook using the multiple inventory sources.
+pushd /opt/openstack-ansible/playbooks
+    openstack-ansible -i /opt/openstack-ansible/inventory/dynamic_inventory.py \
+                      -i /opt/openstack-ansible-ops/overlay-inventories/osa-integration-inventory.yml \
+                      -e @/etc/openstack_deploy/user_secrets.yml \
+                      haproxy-install.yml
+popd
+```
diff --git a/overlay-inventories/osa-integration-inventory.yml b/overlay-inventories/osa-integration-inventory.yml
new file mode 100644
index 00000000..ca656549
--- /dev/null
+++ b/overlay-inventories/osa-integration-inventory.yml
@@ -0,0 +1,161 @@
+---
+
+all_systems:
+  vars: {}
+  children:
+    systems:
+      vars:
+        # General Ansible options for OSA
+        ansible_become: yes
+        ansible_become_user: "root"
+        ansible_user: "root"
+        ## Grafana options
+        grafana_admin_password: "{{ haproxy_stats_password }}"
+        ## Kolide options
+        kolide_fleet_db_password: "{{ haproxy_stats_password }}"
+        kolide_fleet_jwt_key: "{{ haproxy_stats_password }}"
+        kolide_fleet_admin_password: "{{ haproxy_stats_password }}"
+        galera_root_password: "{{ galera_root_password | default(haproxy_stats_password) }}"
+        ## Skydive options
+        skydive_password: "{{ haproxy_stats_password }}"
+        skydive_elasticsearch_servers: "{{ groups['elastic-logstash'] | map('extract', hostvars, ['ansible_host']) | list | join(',') }}"
+        skydive_bind_address: "{{ container_address | default(ansible_host) }}"
+        ## Elastic-stack options
+        elastic_skydive_retention: 2  # Elastic retention set to 2 days max
+        elastic_skydive_size: 51200   # Elastic retention set to 50GiB max
+        ## Beat options
+        beat_service_states:
+          true:
+            state: restarted
+          false:
+            state: stopped
+        elastic_retention_refresh: true
+        auditbeat_service_state: "{{ beat_service_states[(inventory_hostname in (groups['hosts'] | default([])) | string | lower)]['state'] }}"
+        filebeat_service_state: "{{ beat_service_states[(inventory_hostname in (groups['hosts'] | default([])) | string | lower)]['state'] }}"
+        heartbeat_service_state: "{{ beat_service_states[(inventory_hostname in (groups['utility_all'] | default([])) | string | lower)]['state'] }}"
+        journalbeat_service_state: "{{ beat_service_states[(inventory_hostname in (groups['hosts'] | default([])) | string | lower)]['state'] }}"
+        metricbeat_service_state: "{{ beat_service_states[(inventory_hostname in (groups['hosts'] | default([])) | string | lower)]['state'] }}"
+        packetbeat_service_state: "{{ beat_service_states[(inventory_hostname in (groups['network_hosts'] | default([])) | string | lower)]['state'] }}"
+        ## HAProxy options
+        haproxy_extra_services:
+          - service:
+              haproxy_service_name: skydive_analyzer
+              haproxy_backend_nodes: "{{ groups['skydive_analyzers'] | default([]) }}"
+              haproxy_bind: "{{ [internal_lb_vip_address] }}"
+              haproxy_port: 8082
+              haproxy_balance_type: http
+              haproxy_ssl: true
+              haproxy_backend_options:
+                - "httpchk HEAD / HTTP/1.0\\r\\nUser-agent:\\ osa-haproxy-healthcheck"
+          - service:
+              haproxy_service_name: traefik
+              haproxy_backend_nodes: "{{ groups['skydive_analyzers'] | default([]) }}"
+              haproxy_bind: "{{ [internal_lb_vip_address] }}"
+              haproxy_port: 8090
+              haproxy_balance_type: http
+              haproxy_ssl: true
+              haproxy_backend_options:
+                - "httpchk HEAD / HTTP/1.0\\r\\nUser-agent:\\ osa-haproxy-healthcheck"
+              haproxy_backend_httpcheck_options:
+                - expect rstatus 200|401
+          - service:
+              haproxy_service_name: elasticsearch
+              haproxy_backend_nodes: "{{ groups['elastic-logstash'] | default([]) }}"
+              haproxy_ssl: True
+              haproxy_port: 9201
+              haproxy_backend_port: 9200
+              haproxy_balance_type: http
+              haproxy_backend_options:
+                - "httpchk HEAD / HTTP/1.0\\r\\nUser-agent:\\ osa-haproxy-healthcheck"
+          - service:
+              haproxy_service_name: kibana_ssl
+              haproxy_backend_nodes: "{{ groups['kibana'] | default([]) }}"
+              haproxy_ssl: True
+              haproxy_port: 8443
+              haproxy_backend_port: 81
+              haproxy_balance_type: tcp
+              haproxy_backend_options:
+                - tcpka
+          - service:
+              haproxy_service_name: apm-server
+              haproxy_backend_nodes: "{{ groups['apm-server'] | default([]) }}"
+              haproxy_ssl: True
+              haproxy_port: 8200
+              haproxy_balance_type: tcp
+              haproxy_backend_options:
+                - tcpka
+          - service:
+              haproxy_service_name: kolide-fleet
+              haproxy_backend_nodes: "{{ groups['kolide-fleet_all'] | default([]) }}"
+              haproxy_ssl: True
+              haproxy_port: 6443
+              haproxy_check_port: 443
+              haproxy_backend_port: 443
+              haproxy_balance_type: tcp
+              haproxy_backend_options:
+                - tcpka
+          - service:
+              haproxy_service_name: grafana
+              haproxy_backend_nodes: "{{ groups['grafana_all'] | default([]) }}"
+              haproxy_ssl: True
+              haproxy_port: 3000
+              haproxy_balance_type: http
+              haproxy_backend_options:
+                - "httpchk HEAD / HTTP/1.0\\r\\nUser-agent:\\ osa-haproxy-healthcheck"
+
+      children:
+        traefik_all:
+          children:
+            traefik_build_nodes: {}
+
+        skydive_all:
+          children:
+            skydive_build_nodes: {}
+
+            skydive_agents:
+              children:
+                hosts: {}  # This is an osa native group, as such nothing needs to be added. Values will be inherited.
+
+            skydive_analyzers:
+              children:
+                utility_all: {}  # This is an osa native group, as such nothing needs to be added. Values will be inherited.
+
+        elk_all:
+          children:
+            elastic-logstash_all:
+              children:
+                elastic-logstash:
+                  children:
+                    log_hosts: {}  # This is an osa native group, as such nothing needs to be added. Values will be inherited.
+
+            kibana_all:
+              children:
+                kibana:
+                  children:
+                    log_hosts: {}  # This is an osa native group, as such nothing needs to be added. Values will be inherited.
+
+        fleet_all:
+          children:
+            kolide-db_all:
+              children:
+                kolide-db:
+                  children:
+                    log_hosts: {}  # This is an osa native group, as such nothing needs to be added. Values will be inherited.
+
+            kolide-fleet_all:
+              children:
+                kolide-fleet:
+                  children:
+                    log_hosts: {}  # This is an osa native group, as such nothing needs to be added. Values will be inherited.
+
+            osquery_all:
+              children:
+                osquery:
+                  children:
+                    hosts: {}  # This is an osa native group, as such nothing needs to be added. Values will be inherited.
+
+        grafana_all:
+          children:
+            grafana:
+              children:
+                utility_all: {}  # This is an osa native group, as such nothing needs to be added. Values will be inherited.
diff --git a/skydive/README.md b/skydive/README.md
index 2b03585a..e7ebd45f 100644
--- a/skydive/README.md
+++ b/skydive/README.md
@@ -106,7 +106,7 @@ While it is possible to integrate skydive into an OSA cloud using environment
 extensions and `openstack_user_config.yml` additions, the deployment of this
 system is possible through the use of an inventory overlay.
 
-> The example overlay inventory file inventory/osa-integration-inventory.yml
+> The example overlay inventory file `inventory/osa-integration-inventory.yml`
   assumes elasticsearch is already deployed and is located on the baremetal
   machine(s) within the log_hosts group. If this is not the case, adjust the
   overlay inventory for your environment.
@@ -117,7 +117,7 @@ source bootstrap-embedded-ansible.sh
 
 # Run the skydive deployment NOTE: This is using multiple inventories.
 ansible-playbook -i /opt/openstack-ansible/inventory/dynamic_inventory.py \
-                 -i /opt/openstack-ansible/ops/skydive/inventory/osa-integration-inventory.yml \
+                 -i /opt/openstack-ansible-ops/overlay-inventories/osa-integration-inventory.yml \
                  -e @/etc/openstack_deploy/user_secrets.yml \
                  site.yml
 
@@ -127,10 +127,13 @@ deactivate
 # If using haproxy, run the haproxy playbook using the multiple inventory sources.
 cd /opt/openstack-ansible/playbooks
 openstack-ansible -i /opt/openstack-ansible/inventory/dynamic_inventory.py \
-                  -i /opt/openstack-ansible/ops/skydive/inventory/osa-integration-inventory.yml \
+                  -i /opt/openstack-ansible-ops/overlay-inventories/osa-integration-inventory.yml \
                   haproxy-install.yml
 ```
 
+More on using overlay inventories can be seen in the `overlay-inventory`
+directory.
+
 ##### Configuration | Haproxy
 
 The example overlay inventory contains a section for general haproxy
diff --git a/skydive/inventory/osa-integration-inventory.yml b/skydive/inventory/osa-integration-inventory.yml
deleted file mode 100644
index a634a66e..00000000
--- a/skydive/inventory/osa-integration-inventory.yml
+++ /dev/null
@@ -1,63 +0,0 @@
----
-
-all_systems:
-  vars: {}
-  children:
-    systems:
-      vars:
-        ansible_become: yes
-        ansible_become_user: "root"
-        ansible_user: "root"
-        skydive_password: "{{ haproxy_stats_password }}"
-        skydive_elasticsearch_servers: "{{ groups['elastic-logstash'] | map('extract', hostvars, ['ansible_host']) | list | join(',') }}"
-        skydive_bind_address: "{{ container_address | default(ansible_host) }}"
-        elastic_skydive_retention: 2  # Elastic retention set to 2 days max
-        elastic_skydive_size: 51200  # Elastic retention set to 50GiB max
-        haproxy_extra_services:
-          - service:
-              haproxy_service_name: skydive_analyzer
-              haproxy_backend_nodes: "{{ groups['skydive_analyzers'] | default([]) }}"
-              haproxy_bind: "{{ [internal_lb_vip_address] }}"
-              haproxy_port: 8082
-              haproxy_balance_type: http
-              haproxy_ssl: true
-              haproxy_backend_options:
-                - "httpchk HEAD / HTTP/1.0\\r\\nUser-agent:\\ osa-haproxy-healthcheck"
-          - service:
-              haproxy_service_name: traefik
-              haproxy_backend_nodes: "{{ groups['skydive_analyzers'] | default([]) }}"
-              haproxy_bind: "{{ [internal_lb_vip_address] }}"
-              haproxy_port: 8090
-              haproxy_balance_type: http
-              haproxy_ssl: true
-              haproxy_backend_options:
-                - "httpchk HEAD / HTTP/1.0\\r\\nUser-agent:\\ osa-haproxy-healthcheck"
-              haproxy_backend_httpcheck_options:
-                - expect rstatus 200|401
-
-      children:
-        traefik_all:
-          children:
-            traefik_build_nodes: {}
-
-        skydive_all:
-          children:
-            skydive_build_nodes: {}
-
-            skydive_agents:
-              children:
-                hosts: {}  # This is an osa native group, as such nothing needs to be added. Values will be inherited.
-
-            skydive_analyzers:
-              children:
-                utility_all: {}  # This is an osa native group, as such nothing needs to be added. Values will be inherited.
-
-        elk_all:
-          children:
-            elastic-logstash:
-              children:
-                log_hosts: {}  # This is an osa native group, as such nothing needs to be added. Values will be inherited.
-
-            kibana:
-              children:
-                log_hosts: {}  # This is an osa native group, as such nothing needs to be added. Values will be inherited.