""" Example plugin for deb-mock This plugin demonstrates how to create custom plugins for deb-mock and provides examples of common plugin patterns. """ import os import logging from typing import Dict, Any, List from ..plugin import BasePlugin, HookStages class ExamplePlugin(BasePlugin): """ Example plugin demonstrating deb-mock plugin capabilities This plugin shows how to: - Register hooks for different stages - Access configuration and deb-mock context - Perform custom operations during build lifecycle - Log information and errors """ # Plugin metadata requires_api_version = "1.0" plugin_name = "example" plugin_version = "1.0.0" plugin_description = "Example plugin for deb-mock" def __init__(self, plugin_manager, config, deb_mock): super().__init__(plugin_manager, config, deb_mock) # Plugin-specific configuration self.enabled = self.get_config('enabled', True) self.log_level = self.get_config('log_level', 'INFO') self.custom_option = self.get_config('custom_option', 'default_value') # Setup logging self.logger.setLevel(getattr(logging, self.log_level.upper())) self.log_info(f"ExamplePlugin initialized with config: {config}") def _register_hooks(self): """Register hooks for different build stages""" # Chroot lifecycle hooks self.plugin_manager.add_hook(HookStages.PRECHROOT_INIT, self.prechroot_init) self.plugin_manager.add_hook(HookStages.POSTCHROOT_INIT, self.postchroot_init) self.plugin_manager.add_hook(HookStages.PRECHROOT_CLEAN, self.prechroot_clean) self.plugin_manager.add_hook(HookStages.POSTCHROOT_CLEAN, self.postchroot_clean) # Build lifecycle hooks self.plugin_manager.add_hook(HookStages.PREBUILD, self.prebuild) self.plugin_manager.add_hook(HookStages.POSTBUILD, self.postbuild) self.plugin_manager.add_hook(HookStages.BUILD_START, self.build_start) self.plugin_manager.add_hook(HookStages.BUILD_END, self.build_end) # Package management hooks self.plugin_manager.add_hook(HookStages.PRE_INSTALL_DEPS, self.pre_install_deps) self.plugin_manager.add_hook(HookStages.POST_INSTALL_DEPS, self.post_install_deps) # Mount management hooks self.plugin_manager.add_hook(HookStages.PRE_MOUNT, self.pre_mount) self.plugin_manager.add_hook(HookStages.POST_MOUNT, self.post_mount) # Cache management hooks self.plugin_manager.add_hook(HookStages.PRE_CACHE_CREATE, self.pre_cache_create) self.plugin_manager.add_hook(HookStages.POST_CACHE_CREATE, self.post_cache_create) # Error handling hooks self.plugin_manager.add_hook(HookStages.ON_ERROR, self.on_error) self.plugin_manager.add_hook(HookStages.ON_WARNING, self.on_warning) self.log_debug("Registered all hooks for ExamplePlugin") def prechroot_init(self, chroot_name: str, **kwargs): """Called before chroot initialization""" self.log_info(f"Pre-chroot init for {chroot_name}") # Example: Create custom directory structure if self.get_config('create_custom_dirs', False): custom_dirs = self.get_config('custom_dirs', ['/build/custom']) for dir_path in custom_dirs: self.log_debug(f"Would create directory: {dir_path}") def postchroot_init(self, chroot_name: str, **kwargs): """Called after chroot initialization""" self.log_info(f"Post-chroot init for {chroot_name}") # Example: Install additional packages extra_packages = self.get_config('extra_packages', []) if extra_packages: self.log_info(f"Installing extra packages: {extra_packages}") try: result = self.deb_mock.install_packages(extra_packages) if result.get('success', False): self.log_info("Extra packages installed successfully") else: self.log_warning(f"Failed to install extra packages: {result}") except Exception as e: self.log_error(f"Error installing extra packages: {e}") def prechroot_clean(self, chroot_name: str, **kwargs): """Called before chroot cleanup""" self.log_info(f"Pre-chroot clean for {chroot_name}") # Example: Backup important files before cleanup if self.get_config('backup_before_clean', False): self.log_info("Backing up important files before cleanup") # Implementation would backup files here def postchroot_clean(self, chroot_name: str, **kwargs): """Called after chroot cleanup""" self.log_info(f"Post-chroot clean for {chroot_name}") def prebuild(self, source_package: str, **kwargs): """Called before package build""" self.log_info(f"Pre-build for {source_package}") # Example: Validate source package if not os.path.exists(source_package): self.log_error(f"Source package not found: {source_package}") raise FileNotFoundError(f"Source package not found: {source_package}") # Example: Check build dependencies if self.get_config('check_deps', True): self.log_info("Checking build dependencies") # Implementation would check dependencies here def postbuild(self, build_result: Dict[str, Any], source_package: str, **kwargs): """Called after package build""" self.log_info(f"Post-build for {source_package}") success = build_result.get('success', False) if success: self.log_info("Build completed successfully") artifacts = build_result.get('artifacts', []) self.log_info(f"Generated {len(artifacts)} artifacts") else: self.log_error("Build failed") def build_start(self, source_package: str, chroot_name: str, **kwargs): """Called when build starts""" self.log_info(f"Build started: {source_package} in {chroot_name}") # Example: Set build environment variables if self.get_config('set_build_env', False): env_vars = self.get_config('build_env_vars', {}) for key, value in env_vars.items(): os.environ[key] = value self.log_debug(f"Set environment variable: {key}={value}") def build_end(self, build_result: Dict[str, Any], source_package: str, chroot_name: str, **kwargs): """Called when build ends""" self.log_info(f"Build ended: {source_package} in {chroot_name}") # Example: Collect build statistics if self.get_config('collect_stats', True): stats = { 'package': source_package, 'chroot': chroot_name, 'success': build_result.get('success', False), 'artifacts_count': len(build_result.get('artifacts', [])), 'duration': build_result.get('duration', 0) } self.log_info(f"Build statistics: {stats}") def pre_install_deps(self, dependencies: List[str], chroot_name: str, **kwargs): """Called before installing dependencies""" self.log_info(f"Pre-install deps: {dependencies} in {chroot_name}") # Example: Filter dependencies if self.get_config('filter_deps', False): filtered_deps = [dep for dep in dependencies if not dep.startswith('lib')] self.log_info(f"Filtered dependencies: {filtered_deps}") return filtered_deps def post_install_deps(self, dependencies: List[str], chroot_name: str, **kwargs): """Called after installing dependencies""" self.log_info(f"Post-install deps: {dependencies} in {chroot_name}") def pre_mount(self, mount_type: str, mount_path: str, chroot_name: str, **kwargs): """Called before mounting""" self.log_debug(f"Pre-mount: {mount_type} at {mount_path} in {chroot_name}") def post_mount(self, mount_type: str, mount_path: str, chroot_name: str, **kwargs): """Called after mounting""" self.log_debug(f"Post-mount: {mount_type} at {mount_path} in {chroot_name}") def pre_cache_create(self, cache_path: str, chroot_name: str, **kwargs): """Called before creating cache""" self.log_info(f"Pre-cache create: {cache_path} for {chroot_name}") def post_cache_create(self, cache_path: str, chroot_name: str, **kwargs): """Called after creating cache""" self.log_info(f"Post-cache create: {cache_path} for {chroot_name}") def on_error(self, error: Exception, stage: str, **kwargs): """Called when an error occurs""" self.log_error(f"Error in {stage}: {error}") # Example: Send error notification if self.get_config('notify_on_error', False): self.log_info("Would send error notification") def on_warning(self, warning: str, stage: str, **kwargs): """Called when a warning occurs""" self.log_warning(f"Warning in {stage}: {warning}") def get_plugin_info(self) -> Dict[str, Any]: """Return plugin information""" return { 'name': self.plugin_name, 'version': self.plugin_version, 'description': self.plugin_description, 'enabled': self.enabled, 'config': { 'log_level': self.log_level, 'custom_option': self.custom_option } } # Plugin initialization function (required by deb-mock) def init(plugin_manager, config, deb_mock): """ Initialize the plugin This function is called by deb-mock when the plugin is loaded. It should create and return an instance of the plugin class. """ return ExamplePlugin(plugin_manager, config, deb_mock)