Molecule aids in the development and testing of Ansible roles
—
Molecule provides a comprehensive exception system for handling errors during testing workflows, with specific exception types for different failure scenarios and detailed error reporting capabilities.
Base exception classes for handling Molecule-specific errors and failures.
class MoleculeError(Exception):
"""
Generic Molecule error.
Custom exception to handle scenario run failures with support
for exit codes, detailed messages, and warning aggregation.
Args:
message (str): The message to display about the problem
code (int): Exit code to use when exiting (default: 1)
warns (Sequence[WarningMessage]): Warnings about the problem to issue
Attributes:
code (int): Exit code for process termination
"""
def __init__(self, message="", code=1, warns=()):
"""Initialize MoleculeError with message, code, and warnings."""
class ScenarioFailureError(MoleculeError):
"""
Details about a scenario that failed.
Specialized exception for scenario execution failures,
inheriting all capabilities from MoleculeError.
"""Warning classes for handling runtime issues and compatibility problems.
class MoleculeRuntimeWarning(RuntimeWarning):
"""
A runtime warning used by Molecule and its plugins.
Base warning class for Molecule-specific runtime issues
that don't prevent execution but should be reported.
"""
class IncompatibleMoleculeRuntimeWarning(MoleculeRuntimeWarning):
"""
A warning noting an unsupported runtime environment.
Issued when Molecule detects compatibility issues with
the current runtime environment or dependencies.
"""from molecule.exceptions import MoleculeError, ScenarioFailureError
try:
# Molecule operation that might fail
config = Config()
result = config.driver.status()
except MoleculeError as e:
print(f"Molecule error occurred: {e}")
print(f"Exit code: {e.code}")
# Handle the error appropriately
exit(e.code)
except ScenarioFailureError as e:
print(f"Scenario failed: {e}")
# Specific handling for scenario failures
exit(e.code)from molecule.exceptions import MoleculeError
import warnings
def validate_configuration():
"""Validate Molecule configuration and raise errors if invalid."""
# Check for missing required files
if not os.path.exists("molecule.yml"):
raise MoleculeError(
message="molecule.yml configuration file not found",
code=4 # RC_SETUP_ERROR
)
# Check for compatibility issues
warning_msgs = []
if incompatible_version_detected():
warning = warnings.WarningMessage(
message="Incompatible version detected",
category=UserWarning,
filename=__file__,
lineno=0
)
warning_msgs.append(warning)
if warning_msgs:
raise MoleculeError(
message="Configuration validation failed",
code=1,
warns=warning_msgs
)from molecule.driver.base import Driver
from molecule.exceptions import MoleculeError
class CustomDriver(Driver):
def sanity_checks(self):
"""Validate driver prerequisites."""
# Check for required external tools
if not self._tool_available("custom-tool"):
raise MoleculeError(
message="custom-tool is required but not found in PATH",
code=4 # RC_SETUP_ERROR
)
# Check for valid configuration
if not self.options.get("api_key"):
raise MoleculeError(
message="API key is required for custom driver",
code=4
)
def _tool_available(self, tool_name):
"""Check if external tool is available."""
import subprocess
try:
subprocess.run([tool_name, "--version"],
capture_output=True, check=True)
return True
except (subprocess.CalledProcessError, FileNotFoundError):
return Falsefrom molecule.verifier.base import Verifier
from molecule.exceptions import MoleculeError
class CustomVerifier(Verifier):
def execute(self, action_args):
"""Execute verification tests with error handling."""
try:
result = self._run_tests(action_args)
if result.returncode != 0:
raise ScenarioFailureError(
message=f"Verification tests failed: {result.stderr}",
code=result.returncode
)
return result
except FileNotFoundError as e:
raise MoleculeError(
message=f"Test runner not found: {e}",
code=4 # RC_SETUP_ERROR
)
except TimeoutError:
raise MoleculeError(
message="Verification tests timed out",
code=3 # RC_TIMEOUT
)import warnings
from molecule.api import MoleculeRuntimeWarning, IncompatibleMoleculeRuntimeWarning
def check_runtime_compatibility():
"""Check runtime environment and issue warnings."""
# Check Python version compatibility
import sys
if sys.version_info < (3, 10):
warnings.warn(
"Python version < 3.10 is not officially supported",
IncompatibleMoleculeRuntimeWarning,
stacklevel=2
)
# Check for deprecated features
if using_deprecated_feature():
warnings.warn(
"This feature is deprecated and will be removed in a future version",
MoleculeRuntimeWarning,
stacklevel=2
)
# Configure warning filters
warnings.filterwarnings("always", category=MoleculeRuntimeWarning)
warnings.filterwarnings("error", category=IncompatibleMoleculeRuntimeWarning)from molecule.constants import (
RC_SUCCESS, # 0
RC_TIMEOUT, # 3
RC_SETUP_ERROR, # 4
RC_UNKNOWN_ERROR # 5
)
def handle_molecule_operation():
"""Handle Molecule operation with proper exit codes."""
try:
# Perform Molecule operation
result = run_molecule_test()
return RC_SUCCESS
except TimeoutError:
return RC_TIMEOUT
except MoleculeError as e:
if "setup" in str(e).lower():
return RC_SETUP_ERROR
return e.code
except Exception:
return RC_UNKNOWN_ERRORMoleculeError for consistent error handlingInstall with Tessl CLI
npx tessl i tessl/pypi-molecule