New get-devstack-os-environment role

The role reads the OS_* variables set by devstack through openrc
for the specified user and project and exports them as
the os_env_vars fact. It is meant to be used as a porting aid
for the jobs of the non-unified *clients only.

This is useful to run functional tests against the generated
environment. A slightly less generic version of this role
is currently used by python-cinderclient and python-novaclient
(get-os-environment).

In order to make this more useful, call it from
devstack-tox-functional and derived jobs. The role
execution is disabled by default and it can be enabled
by setting openrc_enable_export: true.

Change-Id: I15f5a187dbc54c82e8f4a08b4bb58d56e0d66961
diff --git a/playbooks/tox/run-both.yaml b/playbooks/tox/run-both.yaml
index e85c2ee..0528b46 100644
--- a/playbooks/tox/run-both.yaml
+++ b/playbooks/tox/run-both.yaml
@@ -7,4 +7,6 @@
       bindep_dir: "{{ zuul_work_dir }}"
     - test-setup
     - ensure-tox
-    - tox
+    - get-devstack-os-environment
+    - role: tox
+      tox_environment: "{{ os_env_vars|default({}) }}"
diff --git a/playbooks/tox/run.yaml b/playbooks/tox/run.yaml
index 22f8209..6e549d3 100644
--- a/playbooks/tox/run.yaml
+++ b/playbooks/tox/run.yaml
@@ -1,3 +1,5 @@
 - hosts: all
   roles:
-    - tox
+    - get-devstack-os-environment
+    - role: tox
+      tox_environment: "{{ os_env_vars|default({}) }}"
diff --git a/roles/get-devstack-os-environment/README.rst b/roles/get-devstack-os-environment/README.rst
new file mode 100644
index 0000000..68ddce8
--- /dev/null
+++ b/roles/get-devstack-os-environment/README.rst
@@ -0,0 +1,40 @@
+Reads the OS_* variables set by devstack through openrc
+for the specified user and project and exports them as
+the os_env_vars fact.
+
+**WARNING**: this role is meant to be used as porting aid
+for the non-unified python-<service>client jobs which
+are already around, as those clients do not use clouds.yaml
+as openstackclient does.
+When those clients and their jobs are deprecated and removed,
+or anyway when the new code is able to read from clouds.yaml
+directly, this role should be removed as well.
+
+
+**Role Variables**
+
+.. zuul:rolevar:: devstack_base_dir
+   :default: /opt/stack
+
+   The devstack base directory.
+
+.. zuul:rolevar:: openrc_file
+   :default: {{ devstack_base_dir }}/devstack/openrc
+
+   The location of the generated openrc file.
+
+.. zuul:rolevar:: openrc_user
+   :default: admin
+
+   The user whose credentials should be retrieved.
+
+.. zuul:rolevar:: openrc_project
+   :default: admin
+
+   The project (which openrc_user is part of) whose
+   access data should be retrieved.
+
+.. zuul:rolevar:: openrc_enable_export
+   :default: false
+
+   Set it to true to export os_env_vars.
diff --git a/roles/get-devstack-os-environment/defaults/main.yaml b/roles/get-devstack-os-environment/defaults/main.yaml
new file mode 100644
index 0000000..73ecfe9
--- /dev/null
+++ b/roles/get-devstack-os-environment/defaults/main.yaml
@@ -0,0 +1,5 @@
+devstack_base_dir: "/opt/stack"
+openrc_file: "{{ devstack_base_dir }}/devstack/openrc"
+openrc_user: admin
+openrc_project: admin
+openrc_enable_export: false
diff --git a/roles/get-devstack-os-environment/tasks/main.yaml b/roles/get-devstack-os-environment/tasks/main.yaml
new file mode 100644
index 0000000..8c8df7f
--- /dev/null
+++ b/roles/get-devstack-os-environment/tasks/main.yaml
@@ -0,0 +1,14 @@
+- when: openrc_enable_export
+  block:
+    - name: Extract the OS_ environment variables
+      shell:
+        cmd: |
+          source {{ openrc_file }} {{ openrc_user }} {{ openrc_project }} &>/dev/null
+          env | awk -F= 'BEGIN {print "---" } /^OS_/ { print "  "$1": \""$2"\""} '
+      args:
+        executable: "/bin/bash"
+      register: env_os
+
+    - name: Save the OS_ environment variables as a fact
+      set_fact:
+        os_env_vars: "{{ env_os.stdout|from_yaml }}"