Пример #1
0
    def test_armada_override_exception(self, mock_tiller, mock_source):
        """Test Armada checks with invalid chart override."""
        yaml_documents = list(yaml.safe_load_all(TEST_YAML))
        override = ('chart:example-chart-2:name=' 'overridden', )

        error_re = ('is not a valid override statement')
        with self.assertRaisesRegexp(InvalidOverrideValueException, error_re):
            armada.Armada(yaml_documents, set_ovr=override)
Пример #2
0
    def test_pre_flight_ops(self, MockChartDownload):
        """Test pre-flight checks and operations."""
        yaml_documents = list(yaml.safe_load_all(TEST_YAML))
        m_helm = mock.Mock()
        armada_obj = armada.Armada(yaml_documents, m_helm)

        self._test_pre_flight_ops(armada_obj, MockChartDownload)

        MockChartDownload.return_value.get_chart.assert_called()
Пример #3
0
    def test_armada_manifest_exception_override_none(self, mock_source):
        """Test Armada checks with invalid manifest."""
        yaml_documents = list(yaml.safe_load_all(TEST_YAML))
        example_document = [
            d for d in yaml_documents
            if d['metadata']['name'] == 'example-chart-4'
        ][0]
        del example_document['data']['release']

        error_re = ('Invalid document .*')
        with self.assertRaisesRegexp(InvalidManifestException, error_re):
            armada.Armada(yaml_documents, mock.MagicMock(), set_ovr=None)
Пример #4
0
    def test_pre_flight_ops(self, mock_tiller, mock_source):
        """Test pre-flight checks and operations."""
        yaml_documents = list(yaml.safe_load_all(TEST_YAML))
        armada_obj = armada.Armada(yaml_documents)

        # Mock methods called by `pre_flight_ops()`.
        mock_tiller.tiller_status.return_value = True
        mock_source.git_clone.return_value = CHART_SOURCES[0][0]

        self._test_pre_flight_ops(armada_obj)

        mock_tiller.assert_called_once_with(tiller_host=None,
                                            tiller_namespace='kube-system',
                                            tiller_port=44134)
        mock_source.git_clone.assert_called_once_with(
            'git://github.com/dummy/armada', 'master', None)
Пример #5
0
    def test_pre_flight_ops(self, mock_source):
        """Test pre-flight checks and operations."""
        yaml_documents = list(yaml.safe_load_all(TEST_YAML))
        m_tiller = mock.Mock()
        m_tiller.tiller_status.return_value = True
        armada_obj = armada.Armada(yaml_documents, m_tiller)

        # Mock methods called by `pre_flight_ops()`.
        mock_source.git_clone.return_value = CHART_SOURCES[0][0]

        self._test_pre_flight_ops(armada_obj)

        mock_source.git_clone.assert_called_once_with(
            'git://github.com/dummy/armada',
            'master',
            auth_method=None,
            proxy_server=None)
Пример #6
0
    def test_post_flight_ops(self, mock_tiller, mock_source):
        """Test post-flight operations."""
        yaml_documents = list(yaml.safe_load_all(TEST_YAML))
        armada_obj = armada.Armada(yaml_documents)

        # Mock methods called by `pre_flight_ops()`.
        mock_tiller.tiller_status.return_value = True
        mock_source.git_clone.return_value = CHART_SOURCES[0][0]

        self._test_pre_flight_ops(armada_obj)

        armada_obj.post_flight_ops()

        for group in armada_obj.manifest['armada']['chart_groups']:
            for counter, chart in enumerate(group.get('chart_group')):
                if chart.get('chart').get('source').get('type') == 'git':
                    mock_source.source_cleanup.assert_called_with(
                        CHART_SOURCES[counter][0])
Пример #7
0
    def test_post_flight_ops(self, MockChartDownload):
        """Test post-flight operations."""
        yaml_documents = list(yaml.safe_load_all(TEST_YAML))

        # Mock methods called by `pre_flight_ops()`.
        m_helm = mock.Mock()

        armada_obj = armada.Armada(yaml_documents, m_helm)

        self._test_pre_flight_ops(armada_obj, MockChartDownload)

        armada_obj.post_flight_ops()

        for group in armada_obj.manifest['data']['chart_groups']:
            for counter, chart in enumerate(
                    group.get(const.KEYWORD_DATA).get(const.KEYWORD_CHARTS)):
                if chart.get(
                        const.KEYWORD_DATA).get('source').get('type') == 'git':
                    MockChartDownload.return_value.cleanup.assert_called_with()
Пример #8
0
    def test_install(self, mock_tiller, mock_chartbuilder, mock_pre_flight,
                     mock_post_flight):
        '''Test install functionality from the sync() method'''

        # Instantiate Armada object.
        yaml_documents = list(yaml.safe_load_all(TEST_YAML))
        armada_obj = armada.Armada(yaml_documents)

        charts = armada_obj.manifest['armada']['chart_groups'][0][
            'chart_group']
        chart_1 = charts[0]['chart']
        chart_2 = charts[1]['chart']

        # Mock irrelevant methods called by `armada.sync()`.
        mock_tiller.list_charts.return_value = []
        mock_chartbuilder.get_source_path.return_value = None
        mock_chartbuilder.get_helm_chart.return_value = None

        armada_obj.sync()

        # Check params that should be passed to `tiller.install_release()`.
        method_calls = [
            mock.call(
                mock_chartbuilder().get_helm_chart(),
                "{}-{}".format(armada_obj.manifest['armada']['release_prefix'],
                               chart_1['release']),
                chart_1['namespace'],
                dry_run=armada_obj.dry_run,
                values=yaml.safe_dump(chart_1['values']),
                timeout=10,
                wait=True),
            mock.call(
                mock_chartbuilder().get_helm_chart(),
                "{}-{}".format(armada_obj.manifest['armada']['release_prefix'],
                               chart_2['release']),
                chart_2['namespace'],
                dry_run=armada_obj.dry_run,
                values=yaml.safe_dump(chart_2['values']),
                timeout=10,
                wait=True)
        ]
        mock_tiller.return_value.install_release.assert_has_calls(method_calls)
Пример #9
0
        def _do_test(mock_test_release_for_success, mock_tiller,
                     mock_chartbuilder, mock_pre_flight, mock_post_flight):
            # Instantiate Armada object.
            yaml_documents = list(yaml.safe_load_all(TEST_YAML))
            armada_obj = armada.Armada(yaml_documents)
            armada_obj.get_diff = mock.Mock()

            chart_group = armada_obj.manifest['armada']['chart_groups'][0]
            charts = chart_group['chart_group']
            cg_test_all_charts = chart_group.get('test_charts', True)

            m_tiller = mock_tiller.return_value
            m_tiller.list_charts.return_value = known_releases

            if test_failure_to_run:

                def fail(tiller, release, timeout=None, cleanup=False):
                    status = AttrDict(
                        **{'info': AttrDict(**{'Description': 'Failed'})})
                    raise tiller_exceptions.ReleaseException(
                        release, status, 'Test')

                mock_test_release_for_success.side_effect = fail
            else:
                mock_test_release_for_success.return_value = test_success

            # Stub out irrelevant methods called by `armada.sync()`.
            mock_chartbuilder.get_source_path.return_value = None
            mock_chartbuilder.get_helm_chart.return_value = None

            # Simulate chart diff, upgrade should only happen if non-empty.
            armada_obj.get_diff.return_value = diff

            armada_obj.sync()

            expected_install_release_calls = []
            expected_update_release_calls = []
            expected_uninstall_release_calls = []
            expected_test_release_for_success_calls = []

            for c in charts:
                chart = c['chart']
                release = chart['release']
                prefix = armada_obj.manifest['armada']['release_prefix']
                release_name = release_prefixer(prefix, release)
                # Simplified check because the actual code uses logical-or's
                # multiple conditions, so this is enough.
                this_chart_should_wait = chart['wait']['timeout'] > 0

                expected_apply = True
                if release_name not in [x[0] for x in known_releases]:
                    expected_install_release_calls.append(
                        mock.call(mock_chartbuilder().get_helm_chart(),
                                  "{}-{}".format(
                                      armada_obj.manifest['armada']
                                      ['release_prefix'], chart['release']),
                                  chart['namespace'],
                                  values=yaml.safe_dump(chart['values']),
                                  wait=this_chart_should_wait,
                                  timeout=chart['wait']['timeout']))
                else:
                    target_release = None
                    for known_release in known_releases:
                        if known_release[0] == release_name:
                            target_release = known_release
                            break
                    if target_release:
                        status = target_release[4]
                        if status == const.STATUS_FAILED:
                            protected = chart.get('protected', {})
                            if not protected:
                                expected_uninstall_release_calls.append(
                                    mock.call(release_name))
                                expected_install_release_calls.append(
                                    mock.call(
                                        mock_chartbuilder().get_helm_chart(),
                                        "{}-{}".format(
                                            armada_obj.manifest['armada']
                                            ['release_prefix'],
                                            chart['release']),
                                        chart['namespace'],
                                        values=yaml.safe_dump(chart['values']),
                                        wait=this_chart_should_wait,
                                        timeout=chart['wait']['timeout']))
                            else:
                                p_continue = protected.get(
                                    'continue_processing', False)
                                if p_continue:
                                    continue
                                else:
                                    break

                        if status == const.STATUS_DEPLOYED:
                            if not diff:
                                expected_apply = False
                            else:
                                upgrade = chart.get('upgrade', {})
                                disable_hooks = upgrade.get('no_hooks', False)
                                force = upgrade.get('force', False)
                                recreate_pods = upgrade.get(
                                    'recreate_pods', False)

                                expected_update_release_calls.append(
                                    mock.call(
                                        mock_chartbuilder().get_helm_chart(),
                                        "{}-{}".format(
                                            armada_obj.manifest['armada']
                                            ['release_prefix'],
                                            chart['release']),
                                        chart['namespace'],
                                        pre_actions={},
                                        post_actions={},
                                        disable_hooks=disable_hooks,
                                        force=force,
                                        recreate_pods=recreate_pods,
                                        values=yaml.safe_dump(chart['values']),
                                        wait=this_chart_should_wait,
                                        timeout=chart['wait']['timeout']))

                test_chart_override = chart.get('test')
                # Use old default value when not using newer `test` key
                test_cleanup = True
                if test_chart_override is None:
                    test_this_chart = cg_test_all_charts
                elif isinstance(test_chart_override, bool):
                    test_this_chart = test_chart_override
                else:
                    test_this_chart = test_chart_override.get('enabled', True)
                    test_cleanup = test_chart_override.get('options', {}).get(
                        'cleanup', False)

                if test_this_chart and expected_apply:
                    expected_test_release_for_success_calls.append(
                        mock.call(m_tiller,
                                  release_name,
                                  timeout=mock.ANY,
                                  cleanup=test_cleanup))

            # Verify that at least 1 release is either installed or updated.
            self.assertTrue(
                len(expected_install_release_calls) >= 1
                or len(expected_update_release_calls) >= 1)
            # Verify that the expected number of non-deployed releases are
            # installed with expected arguments.
            self.assertEqual(len(expected_install_release_calls),
                             m_tiller.install_release.call_count)
            m_tiller.install_release.assert_has_calls(
                expected_install_release_calls)
            # Verify that the expected number of deployed releases are
            # updated with expected arguments.
            self.assertEqual(len(expected_update_release_calls),
                             m_tiller.update_release.call_count)
            m_tiller.update_release.assert_has_calls(
                expected_update_release_calls)
            # Verify that the expected number of deployed releases are
            # uninstalled with expected arguments.
            self.assertEqual(len(expected_uninstall_release_calls),
                             m_tiller.uninstall_release.call_count)
            m_tiller.uninstall_release.assert_has_calls(
                expected_uninstall_release_calls)
            # Verify that the expected number of deployed releases are
            # tested with expected arguments.
            self.assertEqual(len(expected_test_release_for_success_calls),
                             mock_test_release_for_success.call_count)
            mock_test_release_for_success.assert_has_calls(
                expected_test_release_for_success_calls)
Пример #10
0
        def _do_test(mock_test, mock_chartbuilder, MockChartDownload,
                     mock_post_flight):
            MockChartDownload.return_value.get_chart.side_effect = \
                set_source_dir
            # Instantiate Armada object.
            yaml_documents = list(yaml.safe_load_all(TEST_YAML))
            m_helm = mock.MagicMock()
            armada_obj = armada.Armada(yaml_documents, m_helm)
            prefix = armada_obj.manifest['data']['release_prefix']

            def release_metadata(release_id, **kwargs):
                try:
                    return next(r for r in known_releases
                                if release_id.name == r['name']
                                and release_id.namespace == r['namespace'])
                except StopIteration:
                    return None

            m_helm.release_metadata.side_effect = release_metadata
            armada_obj.chart_deploy.get_diff = mock.Mock()

            cg = armada_obj.manifest['data']['chart_groups'][0]
            chart_group = cg['data']
            charts = chart_group['chart_group']
            cg_test_all_charts = chart_group.get('test_charts')

            mock_test_release = mock_test.return_value.test_release
            if test_failure_to_run:
                mock_test_release.side_effect = Exception('test failed to run')
            else:
                if not test_success:
                    mock_test_release.side_effect = Exception('test failed')
            mock_test.return_value.timeout = const.DEFAULT_TEST_TIMEOUT

            # Stub out irrelevant methods called by `armada.sync()`.
            mock_chartbuilder.get_helm_chart.return_value = None

            # Simulate chart diff, upgrade should only happen if non-empty.
            armada_obj.chart_deploy.get_diff.return_value = diff

            armada_obj.sync()

            expected_install_release_calls = []
            expected_upgrade_release_calls = []
            expected_uninstall_release_calls = []
            expected_test_constructor_calls = []

            for c in charts:
                chart = c['data']
                release = chart['release']
                release_name = release_prefixer(prefix, release)
                release_id = helm.HelmReleaseId(chart['namespace'],
                                                release_name)
                source_dir = chart['source_dir']
                source_directory = os.path.join(*source_dir)

                # Simplified check because the actual code uses logical-or's
                # multiple conditions, so this is enough.
                native_wait_enabled = (chart['wait'].get('native', {}).get(
                    'enabled', True))

                if release_name not in [x['name'] for x in known_releases]:
                    expected_install_release_calls.append(
                        mock.call(source_directory,
                                  release_id,
                                  values=chart['values'],
                                  wait=native_wait_enabled,
                                  timeout=mock.ANY))
                else:
                    target_release = None
                    for known_release in known_releases:
                        if known_release['name'] == release_name:
                            target_release = known_release
                            break
                    if target_release:
                        status = get_release_status(target_release)
                        if status == helm.STATUS_FAILED:
                            protected = chart.get('protected', {})
                            if not protected:
                                expected_uninstall_release_calls.append(
                                    mock.call(
                                        release_id,
                                        purge=True,
                                        timeout=const.DEFAULT_DELETE_TIMEOUT))
                                expected_install_release_calls.append(
                                    mock.call(source_directory,
                                              release_id,
                                              values=chart['values'],
                                              wait=native_wait_enabled,
                                              timeout=mock.ANY))
                            else:
                                p_continue = protected.get(
                                    'continue_processing', False)
                                if p_continue:
                                    continue
                                else:
                                    if chart_group['sequenced']:
                                        break

                        if status == helm.STATUS_DEPLOYED:
                            if diff:
                                upgrade = chart.get('upgrade', {})
                                disable_hooks = upgrade.get('no_hooks', False)
                                options = upgrade.get('options', {})
                                force = options.get('force', False)

                                expected_upgrade_release_calls.append(
                                    mock.call(source_directory,
                                              release_id,
                                              disable_hooks=disable_hooks,
                                              force=force,
                                              values=chart['values'],
                                              wait=native_wait_enabled,
                                              timeout=mock.ANY))

                expected_test_constructor_calls.append(
                    mock.call(chart,
                              release_id,
                              m_helm,
                              cg_test_charts=cg_test_all_charts))

            any_order = not chart_group['sequenced']
            # Verify that at least 1 release is either installed or updated.
            self.assertTrue(
                len(expected_install_release_calls) >= 1
                or len(expected_upgrade_release_calls) >= 1)
            # Verify that the expected number of non-deployed releases are
            # installed with expected arguments.
            self.assertEqual(len(expected_install_release_calls),
                             m_helm.install_release.call_count)
            m_helm.install_release.assert_has_calls(
                expected_install_release_calls, any_order=any_order)
            # Verify that the expected number of deployed releases are
            # updated with expected arguments.
            self.assertEqual(len(expected_upgrade_release_calls),
                             m_helm.upgrade_release.call_count)
            m_helm.upgrade_release.assert_has_calls(
                expected_upgrade_release_calls, any_order=any_order)
            # Verify that the expected number of deployed releases are
            # uninstalled with expected arguments.
            self.assertEqual(len(expected_uninstall_release_calls),
                             m_helm.uninstall_release.call_count)
            m_helm.uninstall_release.assert_has_calls(
                expected_uninstall_release_calls, any_order=any_order)
            # Verify that the expected number of deployed releases are
            # tested with expected arguments.
            self.assertEqual(len(expected_test_constructor_calls),
                             mock_test.call_count)

            mock_test.assert_has_calls(expected_test_constructor_calls,
                                       any_order=True)
Пример #11
0
        def _do_test(mock_test, mock_chartbuilder, mock_pre_flight,
                     mock_post_flight):
            # Instantiate Armada object.
            yaml_documents = list(yaml.safe_load_all(TEST_YAML))

            m_tiller = mock.MagicMock()
            m_tiller.list_releases.return_value = known_releases

            armada_obj = armada.Armada(yaml_documents, m_tiller)
            armada_obj.chart_deploy.get_diff = mock.Mock()

            chart_group = armada_obj.manifest['armada']['chart_groups'][0]
            charts = chart_group['chart_group']
            cg_test_all_charts = chart_group.get('test_charts')

            mock_test_release = mock_test.return_value.test_release_for_success
            if test_failure_to_run:

                def fail(tiller, release, timeout=None, cleanup=False):
                    status = AttrDict(
                        **{'info': AttrDict(**{'Description': 'Failed'})})
                    raise tiller_exceptions.ReleaseException(
                        release, status, 'Test')

                mock_test_release.side_effect = fail
            else:
                mock_test_release.return_value = test_success

            # Stub out irrelevant methods called by `armada.sync()`.
            mock_chartbuilder.get_source_path.return_value = None
            mock_chartbuilder.get_helm_chart.return_value = None

            # Simulate chart diff, upgrade should only happen if non-empty.
            armada_obj.chart_deploy.get_diff.return_value = diff

            armada_obj.sync()

            expected_install_release_calls = []
            expected_update_release_calls = []
            expected_uninstall_release_calls = []
            expected_test_constructor_calls = []

            for c in charts:
                chart = c['chart']
                release = chart['release']
                prefix = armada_obj.manifest['armada']['release_prefix']
                release_name = release_prefixer(prefix, release)
                # Simplified check because the actual code uses logical-or's
                # multiple conditions, so this is enough.
                native_wait_enabled = (chart['wait'].get('native', {}).get(
                    'enabled', True))

                if release_name not in [x.name for x in known_releases]:
                    expected_install_release_calls.append(
                        mock.call(
                            mock_chartbuilder().get_helm_chart(),
                            "{}-{}".format(
                                armada_obj.manifest['armada']
                                ['release_prefix'], chart['release']),
                            chart['namespace'],
                            values=yaml.safe_dump(chart['values']),
                            wait=native_wait_enabled,
                            timeout=mock.ANY))
                else:
                    target_release = None
                    for known_release in known_releases:
                        if known_release.name == release_name:
                            target_release = known_release
                            break
                    if target_release:
                        status = get_release_status(target_release)
                        if status == const.STATUS_FAILED:
                            protected = chart.get('protected', {})
                            if not protected:
                                expected_uninstall_release_calls.append(
                                    mock.call(
                                        release_name,
                                        purge=True,
                                        timeout=const.DEFAULT_DELETE_TIMEOUT))
                                expected_install_release_calls.append(
                                    mock.call(
                                        mock_chartbuilder().get_helm_chart(),
                                        "{}-{}".format(
                                            armada_obj.manifest['armada']
                                            ['release_prefix'],
                                            chart['release']),
                                        chart['namespace'],
                                        values=yaml.safe_dump(chart['values']),
                                        wait=native_wait_enabled,
                                        timeout=mock.ANY))
                            else:
                                p_continue = protected.get(
                                    'continue_processing', False)
                                if p_continue:
                                    continue
                                else:
                                    if chart_group['sequenced']:
                                        break

                        if status == const.STATUS_DEPLOYED:
                            if diff:
                                upgrade = chart.get('upgrade', {})
                                disable_hooks = upgrade.get('no_hooks', False)
                                options = upgrade.get('options', {})
                                force = options.get('force', False)
                                recreate_pods = options.get(
                                    'recreate_pods', False)

                                expected_update_release_calls.append(
                                    mock.call(
                                        mock_chartbuilder().get_helm_chart(),
                                        "{}-{}".format(
                                            armada_obj.manifest['armada']
                                            ['release_prefix'],
                                            chart['release']),
                                        chart['namespace'],
                                        pre_actions={},
                                        post_actions={},
                                        disable_hooks=disable_hooks,
                                        force=force,
                                        recreate_pods=recreate_pods,
                                        values=yaml.safe_dump(chart['values']),
                                        wait=native_wait_enabled,
                                        timeout=mock.ANY))

                expected_test_constructor_calls.append(
                    mock.call(
                        chart,
                        release_name,
                        m_tiller,
                        cg_test_charts=cg_test_all_charts))

            any_order = not chart_group['sequenced']
            # Verify that at least 1 release is either installed or updated.
            self.assertTrue(
                len(expected_install_release_calls) >= 1 or
                len(expected_update_release_calls) >= 1)
            # Verify that the expected number of non-deployed releases are
            # installed with expected arguments.
            self.assertEqual(
                len(expected_install_release_calls),
                m_tiller.install_release.call_count)
            m_tiller.install_release.assert_has_calls(
                expected_install_release_calls, any_order=any_order)
            # Verify that the expected number of deployed releases are
            # updated with expected arguments.
            self.assertEqual(
                len(expected_update_release_calls),
                m_tiller.update_release.call_count)
            m_tiller.update_release.assert_has_calls(
                expected_update_release_calls, any_order=any_order)
            # Verify that the expected number of deployed releases are
            # uninstalled with expected arguments.
            self.assertEqual(
                len(expected_uninstall_release_calls),
                m_tiller.uninstall_release.call_count)
            m_tiller.uninstall_release.assert_has_calls(
                expected_uninstall_release_calls, any_order=any_order)
            # Verify that the expected number of deployed releases are
            # tested with expected arguments.
            self.assertEqual(
                len(expected_test_constructor_calls), mock_test.call_count)

            mock_test.assert_has_calls(
                expected_test_constructor_calls, any_order=True)