Skip to content

Commit

Permalink
Chore/no ref/improve os app (#266)
Browse files Browse the repository at this point in the history
Fix unitests, which was broken after merging #262 and add better string
representation of OpenStackApplication. This is used currently only in
logging, but it's important for to be able to reproduce on what cloud
COU was run.
  • Loading branch information
rgildein committed Feb 29, 2024
1 parent c3a966e commit 824996d
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 69 deletions.
42 changes: 28 additions & 14 deletions cou/apps/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@
import logging
from collections import defaultdict
from dataclasses import dataclass, field
from io import StringIO
from typing import Any, Iterable, Optional

from ruamel.yaml import YAML
import yaml

from cou.exceptions import (
ApplicationError,
Expand All @@ -46,6 +45,8 @@
logger = logging.getLogger(__name__)

DEFAULT_WAITING_TIMEOUT = 5 * 60 # 5 min
ORIGIN_SETTINGS = ("openstack-origin", "source")
REQUIRED_SETTINGS = ("enable-auto-restarts", "action-managed-upgrade", *ORIGIN_SETTINGS)


@dataclass(frozen=True)
Expand Down Expand Up @@ -99,23 +100,38 @@ def __str__(self) -> str:
summary = {
self.name: {
"model_name": self.model.name,
"can_upgrade_to": self.can_upgrade_to,
"charm": self.charm,
"charm_origin": self.origin,
"os_origin": self.os_origin,
"channel": self.channel,
# Note (rgildein): sanitized the config
"config": {
key: self.config[key] for key in self.config if key in REQUIRED_SETTINGS
},
"origin": self.origin,
"series": self.series,
"subordinate_to": self.subordinate_to,
"workload_version": self.workload_version,
"units": {
unit.name: {
"name": unit.name,
"machine": unit.machine.machine_id,
"workload_version": unit.workload_version,
"os_version": str(self._get_latest_os_version(unit)),
}
for unit in self.units.values()
},
"machines": {
machine.machine_id: {
"id": machine.machine_id,
"apps": machine.apps,
"az": machine.az,
}
for machine in self.machines.values()
},
}
}
yaml = YAML()
with StringIO() as stream:
yaml.dump(summary, stream)
return stream.getvalue()

return yaml.dump(summary, sort_keys=False)

def _verify_channel(self) -> None:
"""Verify app channel from current data.
Expand Down Expand Up @@ -155,7 +171,7 @@ def origin_setting(self) -> Optional[str]:
:return: return name of charm origin setting, e.g. "source", "openstack-origin" or None
:rtype: Optional[str]
"""
for origin in ("openstack-origin", "source"):
for origin in ORIGIN_SETTINGS:
if origin in self.config:
return origin

Expand Down Expand Up @@ -470,10 +486,8 @@ def _get_refresh_charm_step(self, target: OpenStackRelease) -> PreUpgradeStep:
# corner case for rabbitmq and hacluster.
if len(self.possible_current_channels) > 1:
logger.info(
(
"'%s' has more than one channel compatible with the current OpenStack "
"release: '%s'. '%s' will be used"
),
"'%s' has more than one channel compatible with the current OpenStack release: "
"'%s'. '%s' will be used",
self.name,
self.current_os_release.codename,
channel,
Expand Down Expand Up @@ -573,7 +587,7 @@ def _get_resume_unit_step(self, unit: COUUnit, dependent: bool = False) -> UnitU
:rtype: UnitUpgradeStep
"""
return UnitUpgradeStep(
description=(f"Resume the unit: '{unit.name}'."),
description=f"Resume the unit: '{unit.name}'.",
coro=self.model.run_action(
unit_name=unit.name, action_name="resume", raise_on_failure=True
),
Expand Down
1 change: 0 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ install_requires =
oslo.config
juju<3.0
colorama
ruamel.yaml
packaging
aioconsole
halo
Expand Down
8 changes: 4 additions & 4 deletions tests/unit/apps/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -890,7 +890,7 @@ def test_nova_compute_upgrade_plan(model):
Upgrade software packages on unit nova-compute/1
Upgrade software packages on unit nova-compute/2
Refresh 'nova-compute' to the latest revision of 'ussuri/stable'
Change charm config of 'nova-compute' 'action-managed-upgrade' to True.
Change charm config of 'nova-compute' 'action-managed-upgrade' to True
Upgrade 'nova-compute' to the new channel: 'victoria/stable'
Change charm config of 'nova-compute' 'source' to 'cloud:focal-victoria'
Upgrade plan for units: nova-compute/0, nova-compute/1, nova-compute/2
Expand Down Expand Up @@ -933,7 +933,7 @@ def test_nova_compute_upgrade_plan(model):
can_upgrade_to="ussuri/stable",
charm="nova-compute",
channel="ussuri/stable",
config={"source": {"value": "distro"}},
config={"source": {"value": "distro"}, "action-managed-upgrade": {"value": False}},
machines=machines,
model=model,
origin="ch",
Expand All @@ -957,7 +957,7 @@ def test_nova_compute_upgrade_plan_single_unit(model):
Upgrade software packages of 'nova-compute' from the current APT repositories
Upgrade software packages on unit nova-compute/0
Refresh 'nova-compute' to the latest revision of 'ussuri/stable'
Change charm config of 'nova-compute' 'action-managed-upgrade' to True.
Change charm config of 'nova-compute' 'action-managed-upgrade' to True
Upgrade 'nova-compute' to the new channel: 'victoria/stable'
Change charm config of 'nova-compute' 'source' to 'cloud:focal-victoria'
Upgrade plan for units: nova-compute/0
Expand Down Expand Up @@ -986,7 +986,7 @@ def test_nova_compute_upgrade_plan_single_unit(model):
can_upgrade_to="ussuri/stable",
charm="nova-compute",
channel="ussuri/stable",
config={"source": {"value": "distro"}},
config={"source": {"value": "distro"}, "action-managed-upgrade": {"value": False}},
machines=machines,
model=model,
origin="ch",
Expand Down
170 changes: 120 additions & 50 deletions tests/unit/steps/test_steps_analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# 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.
from textwrap import dedent
from unittest.mock import AsyncMock, MagicMock, patch

import pytest
Expand All @@ -22,61 +23,129 @@
from cou.steps.analyze import Analysis
from cou.utils.juju_utils import COUApplication, COUMachine, COUUnit
from cou.utils.openstack import OpenStackRelease
from tests.unit.utils import generate_cou_machine


def test_analysis_dump(model):
"""Test analysis dump."""
expected_result = (
"Control Plane:\n"
"keystone:\n"
" model_name: test_model\n"
" charm: keystone\n"
" charm_origin: ch\n"
" os_origin: distro\n"
" channel: ussuri/stable\n"
" units:\n"
" keystone/0:\n"
" workload_version: 17.0.1\n"
" os_version: ussuri\n"
" keystone/1:\n"
" workload_version: 17.0.1\n"
" os_version: ussuri\n"
" keystone/2:\n"
" workload_version: 17.0.1\n"
" os_version: ussuri\n"
"\n"
"cinder:\n"
" model_name: test_model\n"
" charm: cinder\n"
" charm_origin: ch\n"
" os_origin: distro\n"
" channel: ussuri/stable\n"
" units:\n"
" cinder/0:\n"
" workload_version: 16.4.2\n"
" os_version: ussuri\n"
" cinder/1:\n"
" workload_version: 16.4.2\n"
" os_version: ussuri\n"
" cinder/2:\n"
" workload_version: 16.4.2\n"
" os_version: ussuri\n"
"\n"
"rabbitmq-server:\n"
" model_name: test_model\n"
" charm: rabbitmq-server\n"
" charm_origin: ch\n"
" os_origin: distro\n"
" channel: 3.8/stable\n"
" units:\n"
" rabbitmq-server/0:\n"
" workload_version: '3.8'\n"
" os_version: yoga\n"
"Data Plane:\n"
"\nCurrent minimum OS release in the cloud: ussuri\n"
"\nCurrent minimum Ubuntu series in the cloud: focal\n"
expected_result = dedent(
"""\
Control Plane:
keystone:
model_name: test_model
can_upgrade_to: ussuri/stable
charm: keystone
channel: ussuri/stable
config:
source:
value: distro
origin: ch
series: focal
subordinate_to: []
workload_version: 17.0.1
units:
keystone/0:
name: keystone/0
machine: '0'
workload_version: 17.0.1
os_version: ussuri
keystone/1:
name: keystone/1
machine: '1'
workload_version: 17.0.1
os_version: ussuri
keystone/2:
name: keystone/2
machine: '2'
workload_version: 17.0.1
os_version: ussuri
machines:
'0':
id: '0'
apps: !!python/tuple []
az: null
'1':
id: '1'
apps: !!python/tuple []
az: null
'2':
id: '2'
apps: !!python/tuple []
az: null
cinder:
model_name: test_model
can_upgrade_to: ussuri/stable
charm: cinder
channel: ussuri/stable
config:
source:
value: distro
origin: ch
series: focal
subordinate_to: []
workload_version: 16.4.2
units:
cinder/0:
name: cinder/0
machine: '0'
workload_version: 16.4.2
os_version: ussuri
cinder/1:
name: cinder/1
machine: '1'
workload_version: 16.4.2
os_version: ussuri
cinder/2:
name: cinder/2
machine: '2'
workload_version: 16.4.2
os_version: ussuri
machines:
'0':
id: '0'
apps: !!python/tuple []
az: null
'1':
id: '1'
apps: !!python/tuple []
az: null
'2':
id: '2'
apps: !!python/tuple []
az: null
rabbitmq-server:
model_name: test_model
can_upgrade_to: 3.8/stable
charm: rabbitmq-server
channel: 3.8/stable
config:
source:
value: distro
origin: ch
series: focal
subordinate_to: []
workload_version: '3.8'
units:
rabbitmq-server/0:
name: rabbitmq-server/0
machine: '0'
workload_version: '3.8'
os_version: yoga
machines:
'0':
id: '0'
apps: !!python/tuple []
az: null
Data Plane:
Current minimum OS release in the cloud: ussuri
Current minimum Ubuntu series in the cloud: focal
"""
)
machines = {f"{i}": MagicMock(spec_set=COUMachine) for i in range(3)}
machines = {f"{i}": generate_cou_machine(f"{i}") for i in range(3)}
keystone = Keystone(
name="keystone",
can_upgrade_to="ussuri/stable",
Expand Down Expand Up @@ -142,6 +211,7 @@ def test_analysis_dump(model):
apps_control_plane=[keystone, cinder, rabbitmq_server],
apps_data_plane=[],
)

assert str(result) == expected_result


Expand Down
1 change: 1 addition & 0 deletions tests/unit/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def generate_cou_machine(machine_id: str, az: str | None = None) -> MagicMock:
machine = MagicMock(spec_set=COUMachine)()
machine.machine_id = machine_id
machine.az = az
machine.apps = tuple()
return machine


Expand Down

0 comments on commit 824996d

Please sign in to comment.