From c15ed69b18dfbf4de69d8bf2ca01c934cb4fbf54 Mon Sep 17 00:00:00 2001
From: Pierre Riteau <pierre@stackhpc.com>
Date: Tue, 2 Feb 2021 16:59:36 +0100
Subject: [PATCH] Support passing multiple Kayobe inventory arguments

Change-Id: I875d73cfe056dc505beffdec9bf348b3dc8bd910
Story: 2002009
Task: 41738
---
 kayobe/ansible.py                 | 27 +++++++++++++++------------
 kayobe/tests/unit/test_ansible.py | 26 ++++++++++++++++++++++++++
 2 files changed, 41 insertions(+), 12 deletions(-)

diff --git a/kayobe/ansible.py b/kayobe/ansible.py
index 51634eed..5b154db2 100644
--- a/kayobe/ansible.py
+++ b/kayobe/ansible.py
@@ -56,6 +56,7 @@ def add_args(parser):
                         help="set additional variables as key=value or "
                              "YAML/JSON")
     parser.add_argument("-i", "--inventory", metavar="INVENTORY",
+                        action="append",
                         help="specify inventory host path "
                              "(default=$%s/inventory or %s/inventory) or "
                              "comma-separated host list" %
@@ -85,13 +86,13 @@ def _get_kayobe_environment_path(parsed_args):
     return env_path
 
 
-def _get_inventory_path(parsed_args, env_path):
-    """Return the path to the Kayobe inventory."""
+def _get_inventories_paths(parsed_args, env_path):
+    """Return the paths to the Kayobe inventories."""
     if parsed_args.inventory:
         return parsed_args.inventory
     else:
-        return os.path.join(env_path if env_path else parsed_args.config_path,
-                            "inventory")
+        return [os.path.join(env_path if env_path else parsed_args.config_path,
+                             "inventory")]
 
 
 def _validate_args(parsed_args, playbooks):
@@ -111,12 +112,13 @@ def _validate_args(parsed_args, playbooks):
                       env_path, result["message"])
             sys.exit(1)
 
-    inventory = _get_inventory_path(parsed_args, env_path)
-    result = utils.is_readable_dir(inventory)
-    if not result["result"]:
-        LOG.error("Kayobe inventory %s is invalid: %s",
-                  inventory, result["message"])
-        sys.exit(1)
+    inventories = _get_inventories_paths(parsed_args, env_path)
+    for inventory in inventories:
+        result = utils.is_readable_dir(inventory)
+        if not result["result"]:
+            LOG.error("Kayobe inventory %s is invalid: %s",
+                      inventory, result["message"])
+            sys.exit(1)
 
     for playbook in playbooks:
         result = utils.is_readable_file(playbook)
@@ -158,8 +160,9 @@ def build_args(parsed_args, playbooks,
         cmd += ["--list-tasks"]
     cmd += vault.build_args(parsed_args, "--vault-password-file")
     env_path = _get_kayobe_environment_path(parsed_args)
-    inventory = _get_inventory_path(parsed_args, env_path)
-    cmd += ["--inventory", inventory]
+    inventories = _get_inventories_paths(parsed_args, env_path)
+    for inventory in inventories:
+        cmd += ["--inventory", inventory]
     vars_paths = [parsed_args.config_path]
     if env_path:
         vars_paths.append(env_path)
diff --git a/kayobe/tests/unit/test_ansible.py b/kayobe/tests/unit/test_ansible.py
index c501e307..34f4cecc 100644
--- a/kayobe/tests/unit/test_ansible.py
+++ b/kayobe/tests/unit/test_ansible.py
@@ -561,3 +561,29 @@ class TestCase(unittest.TestCase):
         self.assertTrue(result)
         mock_is_readable.assert_called_once_with(
             "/path/to/config/kolla/passwords.yml")
+
+    @mock.patch.object(utils, "run_command")
+    @mock.patch.object(ansible, "_get_vars_files")
+    @mock.patch.object(ansible, "_validate_args")
+    def test_multiple_inventory_args(self, mock_validate, mock_vars, mock_run):
+        mock_vars.return_value = []
+        parser = argparse.ArgumentParser()
+        ansible.add_args(parser)
+        vault.add_args(parser)
+        args = [
+            "--inventory", "/etc/kayobe/inventory",
+            "--inventory", "/etc/kayobe/environments/foobar/inventory",
+        ]
+        parsed_args = parser.parse_args(args)
+        ansible.run_playbooks(parsed_args, ["playbook1.yml", "playbook2.yml"])
+        expected_cmd = [
+            "ansible-playbook",
+            "--inventory", "/etc/kayobe/inventory",
+            "--inventory", "/etc/kayobe/environments/foobar/inventory",
+            "playbook1.yml",
+            "playbook2.yml",
+        ]
+        expected_env = {"KAYOBE_CONFIG_PATH": "/etc/kayobe"}
+        mock_run.assert_called_once_with(expected_cmd, check_output=False,
+                                         quiet=False, env=expected_env)
+        mock_vars.assert_called_once_with(["/etc/kayobe"])
-- 
GitLab