From ae20e3b9e1aaadb178e33defbdc6d25eb07661d0 Mon Sep 17 00:00:00 2001 From: Liam Young Date: Sat, 5 Feb 2022 07:38:06 +0000 Subject: [PATCH] Github workflow --- charms/nova-k8s/.github/workflows/tox.yaml | 27 +++++++ charms/nova-k8s/src/charm.py | 12 --- charms/nova-k8s/tests/test_charm.py | 66 ---------------- charms/nova-k8s/tox.ini | 22 ++---- .../{tests => unit_tests}/__init__.py | 0 charms/nova-k8s/unit_tests/test_nova_charm.py | 76 +++++++++++++++++++ 6 files changed, 109 insertions(+), 94 deletions(-) create mode 100644 charms/nova-k8s/.github/workflows/tox.yaml delete mode 100644 charms/nova-k8s/tests/test_charm.py rename charms/nova-k8s/{tests => unit_tests}/__init__.py (100%) create mode 100644 charms/nova-k8s/unit_tests/test_nova_charm.py diff --git a/charms/nova-k8s/.github/workflows/tox.yaml b/charms/nova-k8s/.github/workflows/tox.yaml new file mode 100644 index 00000000..ddfeff1e --- /dev/null +++ b/charms/nova-k8s/.github/workflows/tox.yaml @@ -0,0 +1,27 @@ +name: Python package + +on: + - push + - pull_request + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [3.8, 3.9] + + steps: + - uses: actions/checkout@v1 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install tox tox-gh-actions + - name: Lint with tox + run: tox -e pep8 + - name: Test with tox + run: tox -e py${{ matrix.python-version }} diff --git a/charms/nova-k8s/src/charm.py b/charms/nova-k8s/src/charm.py index 9b2c5930..b371153b 100755 --- a/charms/nova-k8s/src/charm.py +++ b/charms/nova-k8s/src/charm.py @@ -16,9 +16,6 @@ import advanced_sunbeam_openstack.core as sunbeam_core import advanced_sunbeam_openstack.container_handlers as sunbeam_chandlers import advanced_sunbeam_openstack.config_contexts as sunbeam_ctxts -from charms.observability_libs.v0.kubernetes_service_patch \ - import KubernetesServicePatch - logger = logging.getLogger(__name__) NOVA_SCHEDULER_CONTAINER = "nova-scheduler" @@ -117,15 +114,6 @@ class NovaOperatorCharm(sunbeam_charm.OSBaseOperatorAPICharm): ['sudo', '-u', 'nova', 'nova-manage', 'cell_v2', 'map_cell0'], ['sudo', '-u', 'nova', 'nova-manage', 'db', 'sync']] - def __init__(self, framework): - super().__init__(framework) - self.service_patcher = KubernetesServicePatch( - self, - [ - ('public', self.default_public_ingress_port), - ] - ) - @property def service_conf(self) -> str: """Service default configuration file.""" diff --git a/charms/nova-k8s/tests/test_charm.py b/charms/nova-k8s/tests/test_charm.py deleted file mode 100644 index e1ccaa76..00000000 --- a/charms/nova-k8s/tests/test_charm.py +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright 2022 liam -# See LICENSE file for licensing details. -# -# Learn more about testing at: https://juju.is/docs/sdk/testing - -import unittest -from unittest.mock import Mock - -from charm import SunbeamNovaOperatorCharm -from ops.model import ActiveStatus -from ops.testing import Harness - - -class TestCharm(unittest.TestCase): - def setUp(self): - self.harness = Harness(SunbeamNovaOperatorCharm) - self.addCleanup(self.harness.cleanup) - self.harness.begin() - - def test_config_changed(self): - self.assertEqual(list(self.harness.charm._stored.things), []) - self.harness.update_config({"thing": "foo"}) - self.assertEqual(list(self.harness.charm._stored.things), ["foo"]) - - def test_action(self): - # the harness doesn't (yet!) help much with actions themselves - action_event = Mock(params={"fail": ""}) - self.harness.charm._on_fortune_action(action_event) - - self.assertTrue(action_event.set_results.called) - - def test_action_fail(self): - action_event = Mock(params={"fail": "fail this"}) - self.harness.charm._on_fortune_action(action_event) - - self.assertEqual(action_event.fail.call_args, [("fail this",)]) - - def test_httpbin_pebble_ready(self): - # Check the initial Pebble plan is empty - initial_plan = self.harness.get_container_pebble_plan("httpbin") - self.assertEqual(initial_plan.to_yaml(), "{}\n") - # Expected plan after Pebble ready with default config - expected_plan = { - "services": { - "httpbin": { - "override": "replace", - "summary": "httpbin", - "command": "gunicorn -b 0.0.0.0:80 httpbin:app -k gevent", - "startup": "enabled", - "environment": {"thing": "🎁"}, - } - }, - } - # Get the httpbin container from the model - container = self.harness.model.unit.get_container("httpbin") - # Emit the PebbleReadyEvent carrying the httpbin container - self.harness.charm.on.httpbin_pebble_ready.emit(container) - # Get the plan now we've run PebbleReady - updated_plan = self.harness.get_container_pebble_plan("httpbin").to_dict() - # Check we've got the plan we expected - self.assertEqual(expected_plan, updated_plan) - # Check the service was started - service = self.harness.model.unit.get_container("httpbin").get_service("httpbin") - self.assertTrue(service.is_running()) - # Ensure we set an ActiveStatus with no message - self.assertEqual(self.harness.model.unit.status, ActiveStatus()) diff --git a/charms/nova-k8s/tox.ini b/charms/nova-k8s/tox.ini index 31301b80..987807e9 100644 --- a/charms/nova-k8s/tox.ini +++ b/charms/nova-k8s/tox.ini @@ -35,26 +35,16 @@ whitelist_externals = passenv = HOME TERM CS_* OS_* TEST_* deps = -r{toxinidir}/test-requirements.txt -[testenv:py35] -basepython = python3.5 -# python3.5 is irrelevant on a focal+ charm. -commands = /bin/true - -[testenv:py36] -basepython = python3.6 -deps = -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt - -[testenv:py37] -basepython = python3.7 -deps = -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt - -[testenv:py38] +[testenv:py3.8] basepython = python3.8 deps = -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt +[testenv:py3.9] +basepython = python3.9 +deps = -r{toxinidir}/requirements.txt + -r{toxinidir}/test-requirements.txt + [testenv:py3] basepython = python3 deps = -r{toxinidir}/requirements.txt diff --git a/charms/nova-k8s/tests/__init__.py b/charms/nova-k8s/unit_tests/__init__.py similarity index 100% rename from charms/nova-k8s/tests/__init__.py rename to charms/nova-k8s/unit_tests/__init__.py diff --git a/charms/nova-k8s/unit_tests/test_nova_charm.py b/charms/nova-k8s/unit_tests/test_nova_charm.py new file mode 100644 index 00000000..d89f77d2 --- /dev/null +++ b/charms/nova-k8s/unit_tests/test_nova_charm.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 + +# Copyright 2021 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 sys + +sys.path.append('lib') # noqa +sys.path.append('src') # noqa + +import charm +import advanced_sunbeam_openstack.test_utils as test_utils + + +class _NovaWallabyOperatorCharm(charm.NovaWallabyOperatorCharm): + + def __init__(self, framework): + self.seen_events = [] + self.render_calls = [] + super().__init__(framework) + + def _log_event(self, event): + self.seen_events.append(type(event).__name__) + + def renderer(self, containers, container_configs, template_dir, + openstack_release, adapters): + self.render_calls.append( + ( + containers, + container_configs, + template_dir, + openstack_release, + adapters)) + + def configure_charm(self, event): + super().configure_charm(event) + self._log_event(event) + + +class TestNovaOperatorCharm(test_utils.CharmTestCase): + + PATCHES = [] + + @mock.patch( + 'charms.observability_libs.v0.kubernetes_service_patch.' + 'KubernetesServicePatch') + def setUp(self, mock_patch): + self.container_calls = { + 'push': {}, + 'pull': [], + 'remove_path': []} + super().setUp(charm, self.PATCHES) + self.harness = test_utils.get_harness( + _NovaWallabyOperatorCharm, + container_calls=self.container_calls) + self.addCleanup(self.harness.cleanup) + self.harness.begin() + + def test_pebble_ready_handler(self): + self.assertEqual(self.harness.charm.seen_events, []) + self.harness.container_pebble_ready('nova-api') + self.harness.container_pebble_ready('nova-scheduler') + self.harness.container_pebble_ready('nova-conductor') + self.assertEqual(len(self.harness.charm.seen_events), 3)