From 89527526f50660d7671d8e4a96a01165454ddcf2 Mon Sep 17 00:00:00 2001 From: Chris MacNaughton Date: Tue, 9 Oct 2018 17:34:12 +0200 Subject: [PATCH 1/4] Add support for removing machine placement in a bundle --- setup.py | 1 + tox.ini | 7 ++ .../utilities/test_zaza_utilities_bundle.py | 108 ++++++++++++++++++ zaza/utilities/bundle.py | 74 ++++++++++++ 4 files changed, 190 insertions(+) create mode 100644 unit_tests/utilities/test_zaza_utilities_bundle.py create mode 100644 zaza/utilities/bundle.py diff --git a/setup.py b/setup.py index 070495e..4e5de3f 100644 --- a/setup.py +++ b/setup.py @@ -99,6 +99,7 @@ setup( 'functest-test = zaza.charm_lifecycle.test:main', 'current-apps = zaza.model:main', 'tempest-config = zaza.tempest_config:main', + 'flatten-bundle = zaza.utilities.bundle:main', ] }, license='Apache-2.0: http://www.apache.org/licenses/LICENSE-2.0', diff --git a/tox.ini b/tox.ini index 4ce2bb5..23559e7 100644 --- a/tox.ini +++ b/tox.ini @@ -51,3 +51,10 @@ passenv = USER commands = {envdir}/bin/python3 setup.py install sudo su {env:USER} -c 'source {envdir}/bin/activate && functest-run-suite --keep-model' + +[testenv:flatten] +basepython = python3 +deps = -r{toxinidir}/requirements.txt +commands = + {envdir}/bin/python3 setup.py install + flatten-bundle {posargs} \ No newline at end of file diff --git a/unit_tests/utilities/test_zaza_utilities_bundle.py b/unit_tests/utilities/test_zaza_utilities_bundle.py new file mode 100644 index 0000000..5a0c175 --- /dev/null +++ b/unit_tests/utilities/test_zaza_utilities_bundle.py @@ -0,0 +1,108 @@ +# Copyright 2018 Canonical Ltd. +# +# 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 mock + +import unit_tests.utils as ut_utils +import zaza.utilities.bundle as bundle + +import yaml + +TEST_BUNDLE_WITH_PLACEMENT = """ +machines: + '0': + series: bionic + '1': + series: bionic + '2': + series: bionic +relations: +- - ceph-osd:mon + - ceph-mon:osd +series: bionic +services: + ceph-mon: + annotations: + gui-x: '750' + gui-y: '500' + charm: cs:ceph-mon-26 + num_units: 3 + options: + expected-osd-count: 3 + source: cloud:bionic-rocky + to: + - lxd:0 + - lxd:1 + - lxd:2 + ceph-osd: + annotations: + gui-x: '1000' + gui-y: '500' + charm: cs:ceph-osd-269 + num_units: 3 + options: + osd-devices: /dev/sdb + source: cloud:bionic-rocky + to: + - '0' + - '1' + - '2' +""" + + +TEST_BUNDLE_WITHOUT_PLACEMENT = """ +relations: +- - ceph-osd:mon + - ceph-mon:osd +series: bionic +services: + ceph-mon: + annotations: + gui-x: '750' + gui-y: '500' + charm: cs:ceph-mon-26 + num_units: 3 + options: + expected-osd-count: 3 + source: cloud:bionic-rocky + ceph-osd: + annotations: + gui-x: '1000' + gui-y: '500' + charm: cs:ceph-osd-269 + num_units: 3 + options: + osd-devices: /dev/sdb + source: cloud:bionic-rocky +""" + + +class TestUtilitiesBundle(ut_utils.BaseTestCase): + + def test_flatten_bundle(self): + self.maxDiff = 1500 + input_yaml = yaml.safe_load(TEST_BUNDLE_WITH_PLACEMENT) + flattened = bundle.remove_machine_specification(input_yaml) + expected = yaml.safe_load(TEST_BUNDLE_WITHOUT_PLACEMENT) + + self.assertEqual(expected, flattened) + + def test_add_series(self): + self.maxDiff = 1500 + input_yaml = yaml.safe_load(TEST_BUNDLE_WITH_PLACEMENT) + input_yaml.pop('series', None) + flattened = bundle.remove_machine_specification(input_yaml) + expected = yaml.safe_load(TEST_BUNDLE_WITHOUT_PLACEMENT) + + self.assertEqual(expected, flattened) diff --git a/zaza/utilities/bundle.py b/zaza/utilities/bundle.py new file mode 100644 index 0000000..411e3dc --- /dev/null +++ b/zaza/utilities/bundle.py @@ -0,0 +1,74 @@ +# Copyright 2018 Canonical Ltd. +# +# 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. +"""Module for disfiguring Juju bundles.""" + + +import argparse +import yaml +import sys + + +def remove_machine_specification(input_yaml): + """ + Will remove the machien specifications from a supplied bundle. + + :param input_yaml: Juju bundle to strip machinens from + :type input_yaml: dict + :returns: bundle without machine placements + :rtype: dict + """ + machines = input_yaml.pop("machines", None) + if not input_yaml.get('series'): + if machines: + for (name, details) in machines.items(): + if details['series']: + input_yaml['series'] = details['series'] + break + + for (application_name, application) in input_yaml['services'].items(): + application.pop("to", None) + return input_yaml + + +def parse_args(args): + """Parse command line arguments. + + :param args: List of configure functions functions + :type list: [str1, str2,...] List of command line arguments + :returns: Parsed arguments + :rtype: Namespace + """ + parser = argparse.ArgumentParser() + parser.add_argument('-i', '--input', + help='Bundle to flatten', + required=True) + parser.add_argument('-o', '--output', + help='Where to output', + default="/dev/stdout") + return parser.parse_args(args) + + +def main(): + """Run the configuration defined by the command line args. + + Run the configuration defined by the command line args or if none were + provided read the configuration functions from the charms tests.yaml + config file + """ + args = parse_args(sys.argv[1:]) + with open(args.input, 'r') as file: + input_yaml = yaml.safe_load(file) + stripped_yaml = remove_machine_specification(input_yaml) + with open(args.output, 'w') as output: + print(yaml.dump(stripped_yaml), file=output) From 362ce7bac5ad22a0e94dec9f5e665d0390ab2972 Mon Sep 17 00:00:00 2001 From: Chris MacNaughton Date: Wed, 10 Oct 2018 11:34:31 +0200 Subject: [PATCH 2/4] rename flatten-bundle to remove-placement --- setup.py | 2 +- tox.ini | 4 ++-- zaza/utilities/bundle.py | 6 ++---- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/setup.py b/setup.py index 4e5de3f..168e850 100644 --- a/setup.py +++ b/setup.py @@ -99,7 +99,7 @@ setup( 'functest-test = zaza.charm_lifecycle.test:main', 'current-apps = zaza.model:main', 'tempest-config = zaza.tempest_config:main', - 'flatten-bundle = zaza.utilities.bundle:main', + 'remove-placement = zaza.utilities.bundle:main', ] }, license='Apache-2.0: http://www.apache.org/licenses/LICENSE-2.0', diff --git a/tox.ini b/tox.ini index 23559e7..e2b6f65 100644 --- a/tox.ini +++ b/tox.ini @@ -52,9 +52,9 @@ commands = {envdir}/bin/python3 setup.py install sudo su {env:USER} -c 'source {envdir}/bin/activate && functest-run-suite --keep-model' -[testenv:flatten] +[testenv:remove-placement] basepython = python3 deps = -r{toxinidir}/requirements.txt commands = {envdir}/bin/python3 setup.py install - flatten-bundle {posargs} \ No newline at end of file + remove-placement {posargs} \ No newline at end of file diff --git a/zaza/utilities/bundle.py b/zaza/utilities/bundle.py index 411e3dc..412050e 100644 --- a/zaza/utilities/bundle.py +++ b/zaza/utilities/bundle.py @@ -51,7 +51,7 @@ def parse_args(args): """ parser = argparse.ArgumentParser() parser.add_argument('-i', '--input', - help='Bundle to flatten', + help='Bundle to remove placement from', required=True) parser.add_argument('-o', '--output', help='Where to output', @@ -62,9 +62,7 @@ def parse_args(args): def main(): """Run the configuration defined by the command line args. - Run the configuration defined by the command line args or if none were - provided read the configuration functions from the charms tests.yaml - config file + Remove machine placement as specified in the command line args """ args = parse_args(sys.argv[1:]) with open(args.input, 'r') as file: From 69c44551ffd70e2b2af442f68642b2dde882ef28 Mon Sep 17 00:00:00 2001 From: Chris MacNaughton Date: Wed, 10 Oct 2018 12:14:15 +0200 Subject: [PATCH 3/4] add unit testing and fix typo --- unit_tests/utilities/test_zaza_utilities_bundle.py | 13 +++++++++++++ zaza/utilities/bundle.py | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/unit_tests/utilities/test_zaza_utilities_bundle.py b/unit_tests/utilities/test_zaza_utilities_bundle.py index 5a0c175..eb30477 100644 --- a/unit_tests/utilities/test_zaza_utilities_bundle.py +++ b/unit_tests/utilities/test_zaza_utilities_bundle.py @@ -106,3 +106,16 @@ class TestUtilitiesBundle(ut_utils.BaseTestCase): expected = yaml.safe_load(TEST_BUNDLE_WITHOUT_PLACEMENT) self.assertEqual(expected, flattened) + + def test_parser(self): + args = bundle.parse_args([ + '-i', 'bundle.yaml']) + self.assertEqual(args.input, 'bundle.yaml') + self.assertEqual(args.output, '/dev/stdout') + + def test_parser_output(self): + args = bundle.parse_args([ + '-i', 'bundle.yaml', + '-o', 'bundle_out.yaml']) + self.assertEqual(args.input, 'bundle.yaml') + self.assertEqual(args.output, 'bundle_out.yaml') diff --git a/zaza/utilities/bundle.py b/zaza/utilities/bundle.py index 412050e..3e4e843 100644 --- a/zaza/utilities/bundle.py +++ b/zaza/utilities/bundle.py @@ -21,7 +21,7 @@ import sys def remove_machine_specification(input_yaml): """ - Will remove the machien specifications from a supplied bundle. + Will remove the machine specifications from a supplied bundle. :param input_yaml: Juju bundle to strip machinens from :type input_yaml: dict From bc37046851f32f6d796fe368b3140d41fcd09ceb Mon Sep 17 00:00:00 2001 From: Chris MacNaughton Date: Fri, 12 Oct 2018 09:05:26 +0200 Subject: [PATCH 4/4] raise exception when trying to mix series --- zaza/utilities/bundle.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/zaza/utilities/bundle.py b/zaza/utilities/bundle.py index 3e4e843..2db5301 100644 --- a/zaza/utilities/bundle.py +++ b/zaza/utilities/bundle.py @@ -29,12 +29,15 @@ def remove_machine_specification(input_yaml): :rtype: dict """ machines = input_yaml.pop("machines", None) - if not input_yaml.get('series'): - if machines: - for (name, details) in machines.items(): - if details['series']: - input_yaml['series'] = details['series'] - break + + input_series = input_yaml.get('series', None) + if machines: + for (name, details) in machines.items(): + if details['series']: + if input_series and details['series'] != input_series: + raise Exception("Mixing series is not supported") + input_yaml['series'] = details['series'] + input_series = input_yaml['series'] for (application_name, application) in input_yaml['services'].items(): application.pop("to", None)