From c27af2667f456dbba57e25094012193984dfe241 Mon Sep 17 00:00:00 2001 From: Jay Dobies Date: Fri, 13 Mar 2015 14:45:25 -0400 Subject: [PATCH] Add support for subdirs in templates listing With the addition of Puppet support, it's possible that the files returned for the stack will be nested into directories. This directory information will be carried in the key values for the templates dict (e.g. 'hieradata/common.yaml' : ). This change looks for one or more directories in the template name and creates the necessary structure in the template output directory. Change-Id: Ic7dc65427ab9fdb981db1663c400e4e0cc3cc53d --- tuskarclient/tests/v2/test_plans_shell.py | 42 ++++++++++++++++++----- tuskarclient/v2/plans_shell.py | 13 ++++++- 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/tuskarclient/tests/v2/test_plans_shell.py b/tuskarclient/tests/v2/test_plans_shell.py index bc42ee1..50a69ab 100644 --- a/tuskarclient/tests/v2/test_plans_shell.py +++ b/tuskarclient/tests/v2/test_plans_shell.py @@ -280,35 +280,61 @@ class PlansShellTest(BasePlansShellTest): @mock.patch('tuskarclient.v2.plans_shell.os.mkdir', create=True) @mock.patch('tuskarclient.v2.plans_shell.os.path.isdir', create=True) @mock.patch('tuskarclient.v2.plans_shell.open', create=True) + @mock.patch('tuskarclient.v2.plans_shell.os.path.exists', create=True) + @mock.patch('tuskarclient.v2.plans_shell.os.makedirs', create=True) def test_plan_templates( - self, mock_open, mock_isdir, mock_mkdir, mock_print): + self, mock_makedirs, mock_exists, mock_open, mock_isdir, + mock_mkdir, mock_print): args = empty_args() args.plan_uuid = 'plan_uuid' args.output_dir = 'outdir/subdir' + # Simulate the first exists check being false and the subsequent check + # being true so as to exercise that makesdirs is only called once + # per nested directory. + exists_return_values = [False, True] + + def toggle_exists_result(*e_args, **e_kwargs): + return exists_return_values.pop(0) + mock_exists.side_effect = toggle_exists_result + mock_isdir.return_value = False self.tuskar.plans.templates.return_value = { 'name_foo': 'value_foo', - 'name_bar': 'value_bar' + 'name_bar': 'value_bar', + 'nested/name_baz': 'value_baz', + 'nested/name_zom': 'value_zom' } self.shell.do_plan_templates(self.tuskar, args, outfile=self.outfile) - mock_isdir.assert_called_with('outdir/subdir') - mock_mkdir.assert_called_with('outdir/subdir') + # Initial check and creation of the output directory + mock_isdir.assert_any_call('outdir/subdir') + mock_mkdir.assert_any_call('outdir/subdir') + + # Checks and creation of nested directory + self.assertEqual(mock_exists.call_count, 2) + self.assertEqual(mock_makedirs.call_count, 1) + mock_makedirs.assert_called_with('outdir/subdir/nested') self.tuskar.plans.templates.assert_called_with('plan_uuid') mock_open.assert_any_call('outdir/subdir/name_foo', 'w+') mock_open.assert_any_call('outdir/subdir/name_bar', 'w+') - self.assertEqual(mock_open.call_count, 2) + mock_open.assert_any_call('outdir/subdir/nested/name_baz', 'w+') + mock_open.assert_any_call('outdir/subdir/nested/name_zom', 'w+') + self.assertEqual(mock_open.call_count, 4) mock_opened_file = mock_open.return_value.__enter__.return_value mock_opened_file.write.assert_any_call('value_foo') mock_opened_file.write.assert_any_call('value_bar') - self.assertEqual(mock_opened_file.write.call_count, 2) + mock_opened_file.write.assert_any_call('value_baz') + mock_opened_file.write.assert_any_call('value_zom') + self.assertEqual(mock_opened_file.write.call_count, 4) - mock_print.assert_any_call('Following templates has been written:') + mock_print.assert_any_call('The following templates will be written:') mock_print.assert_any_call('outdir/subdir/name_foo') mock_print.assert_any_call('outdir/subdir/name_bar') - self.assertEqual(mock_print.call_count, 3) + mock_print.assert_any_call('outdir/subdir/nested/name_baz') + mock_print.assert_any_call('outdir/subdir/nested/name_zom') + self.assertEqual(mock_print.call_count, 5) diff --git a/tuskarclient/v2/plans_shell.py b/tuskarclient/v2/plans_shell.py index 26378ad..68bf24b 100644 --- a/tuskarclient/v2/plans_shell.py +++ b/tuskarclient/v2/plans_shell.py @@ -265,8 +265,19 @@ def do_plan_templates(tuskar, args, outfile=sys.stdout): templates = tuskar.plans.templates(args.plan_uuid) # write file for each key-value in templates - print("Following templates has been written:") + print("The following templates will be written:") for template_name, template_content in templates.items(): + + # It's possible to organize the role templates and their dependent + # files into directories, in which case the template_name will carry + # the directory information. If that's the case, first create the + # directory structure (if it hasn't already been created by another + # file in the templates list). + template_dir = os.path.dirname(template_name) + output_template_dir = os.path.join(output_dir, template_dir) + if template_dir and not os.path.exists(output_template_dir): + os.makedirs(output_template_dir) + filename = os.path.join(output_dir, template_name) with open(filename, 'w+') as template_file: template_file.write(template_content)