-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Smoke test for cou plan check the stdout for the following scenarios: * plan with backup * plan without backup * Use absolute path instead of relative for snap file * - add log about cou executable path * - use pathlib instead of os. - use the full snap path to not use the python package when using the snap. * - cou wrapper to run commands - not remove the cou python package on tearDown. * - add error log message if subprocess fail. * Explicitly pass the model name - Using juju switch it’s not possible because it uses JUJU_MODEL and python libjuju doesn't support this env var. - Running without explicitly passing the model can make cou run in a different model that it’s not on the recently deployed by zaza. * - remove comment to skip test. * - apply suggestions * - added custom exception for install commands - snap_installed logic inside configure_executable_path * - remove get_or_create_libjuju_thread and clean_up_libjuju_thread - use COU_DATA to create local share folder. --------- Co-authored-by: TQ <[email protected]>
- Loading branch information
1 parent
c216634
commit 8692508
Showing
4 changed files
with
163 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
import logging | ||
import os | ||
import unittest | ||
from pathlib import Path | ||
from subprocess import CalledProcessError, CompletedProcess, check_call, run | ||
|
||
import zaza | ||
|
||
from cou.utils import COU_DATA | ||
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
class FuncSmokeException(Exception): | ||
"""Default Func Smoke exception.""" | ||
|
||
|
||
class SmokeTest(unittest.TestCase): | ||
"""COU smoke functional tests.""" | ||
|
||
@classmethod | ||
def setUpClass(cls) -> None: | ||
cls.create_local_share_folder() | ||
cls.model_name = zaza.model.get_juju_model() | ||
cls.configure_executable_path() | ||
|
||
@classmethod | ||
def tearDownClass(cls) -> None: | ||
cls.remove_snap_package() | ||
|
||
def create_local_share_folder() -> None: | ||
"""Create the .local/share/ folder if does not exist.""" | ||
COU_DATA.mkdir(parents=True, exist_ok=True) | ||
|
||
@classmethod | ||
def configure_executable_path(cls) -> None: | ||
cls.snap_installed = False | ||
cou_snap = os.environ.get("TEST_SNAP") | ||
if cou_snap: | ||
cls.install_snap_package(cou_snap) | ||
cls.exc_path = "/snap/bin/cou" | ||
cls.snap_installed = True | ||
else: | ||
# functest already installs cou as python package | ||
log.warning("using cou as python package") | ||
cls.exc_path = os.getenv("TEST_PYTHON_PACKAGE") + "/bin/cou" | ||
|
||
log.info("Using cou path: %s", cls.exc_path) | ||
|
||
@classmethod | ||
def install_snap_package(cls, cou_snap: str) -> None: | ||
"""Install cou snap package. | ||
:param cou_snap: Path to the cou snap. | ||
:type cou_snap: str | ||
""" | ||
log.info("Installing %s", cou_snap) | ||
assert Path(cou_snap).is_file(), f"{cou_snap} is not file" | ||
|
||
# install the snap | ||
cls.snap_install_commands( | ||
["sudo", "snap", "install", "--dangerous", cou_snap], | ||
"Cannot install the cou snap. Please check your permission", | ||
) | ||
|
||
# connect interfaces | ||
interfaces_to_connect = [ | ||
"juju-client-observe", | ||
"dot-local-share-cou", | ||
"ssh-public-keys", | ||
] | ||
for interface in interfaces_to_connect: | ||
cls.snap_install_commands( | ||
[ | ||
"sudo", | ||
"snap", | ||
"connect", | ||
f"charmed-openstack-upgrader:{interface}", | ||
"snapd", | ||
], | ||
f"Cannot connect the interface: {interface}", | ||
) | ||
|
||
# make the cou alias | ||
cls.snap_install_commands( | ||
["sudo", "snap", "alias", "charmed-openstack-upgrader.cou", "cou"], | ||
"Cannot create the cou alias", | ||
) | ||
|
||
# check that the executable path exists | ||
assert Path("/snap/bin/cou").exists(), "Cannot find the cou executable snap path." | ||
cls.exc_path = "/snap/bin/cou" | ||
|
||
def snap_install_commands(cmd: list[str], custom_err_msg: str): | ||
"""Commands to run and install the cou snap. | ||
:param cmd: The command to be executed. | ||
:type cmd: list[str] | ||
:param custom_err_msg: Custom error message if the command fails. | ||
:type custom_err_msg: str | ||
:raises FuncSmokeException: When the command fails. | ||
""" | ||
try: | ||
check_call(cmd) | ||
except CalledProcessError as err: | ||
raise FuncSmokeException(custom_err_msg) from err | ||
|
||
@classmethod | ||
def remove_snap_package(cls) -> None: | ||
"""Remove cou package.""" | ||
if cls.snap_installed: | ||
log.info("Removing snap package cou") | ||
check_call(["sudo", "snap", "remove", "charmed-openstack-upgrader", "--purge"]) | ||
|
||
def cou(self, cmd: list[str]) -> CompletedProcess: | ||
"""Run cou commands. | ||
:param cmd: Command to run. | ||
:type cmd: list[str] | ||
:return: Response of the command. | ||
:rtype: CompletedProcess | ||
""" | ||
return run([self.exc_path] + cmd, capture_output=True, text=True) | ||
|
||
def test_plan_default(self) -> None: | ||
"""Test plan with backup.""" | ||
result = self.cou(["plan", "--model", self.model_name]).stdout | ||
expected_plan = ( | ||
"Upgrade cloud from 'ussuri' to 'victoria'\n" | ||
"\tVerify that all OpenStack applications are in idle state\n" | ||
"\tBackup mysql databases\n" | ||
"\tControl Plane principal(s) upgrade plan\n" | ||
"\t\tUpgrade plan for 'designate-bind' to victoria\n" | ||
"\t\t\tUpgrade software packages of 'designate-bind' " | ||
"from the current APT repositories\n" | ||
"\t\t\tUpgrade 'designate-bind' to the new channel: 'victoria/stable'\n" | ||
"\t\t\tWait 300s for app designate-bind to reach the idle state.\n" | ||
"\t\t\tCheck if the workload of 'designate-bind' has been upgraded\n" | ||
) | ||
self.assertIn(expected_plan, result) | ||
|
||
def test_plan_no_backup(self) -> None: | ||
"""Test plan with no backup.""" | ||
result = self.cou(["plan", "--model", self.model_name, "--no-backup"]).stdout | ||
expected_plan = ( | ||
"Upgrade cloud from 'ussuri' to 'victoria'\n" | ||
"\tVerify that all OpenStack applications are in idle state\n" | ||
"\tControl Plane principal(s) upgrade plan\n" | ||
"\t\tUpgrade plan for 'designate-bind' to victoria\n" | ||
"\t\t\tUpgrade software packages of 'designate-bind' " | ||
"from the current APT repositories\n" | ||
"\t\t\tUpgrade 'designate-bind' to the new channel: 'victoria/stable'\n" | ||
"\t\t\tWait 300s for app designate-bind to reach the idle state.\n" | ||
"\t\t\tCheck if the workload of 'designate-bind' has been upgraded\n" | ||
) | ||
self.assertIn(expected_plan, result) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters