Skip to content

Commit

Permalink
Add pre-commit to project (#28)
Browse files Browse the repository at this point in the history
* Add pre-commit to project

Signed-off-by: Jan-Marten Brüggemann <[email protected]>

* add github workflow for pre-commit

Signed-off-by: Jan-Marten Brüggemann <[email protected]>

* run pre-commit hook on all files

Signed-off-by: Jan-Marten Brüggemann <[email protected]>

---------

Signed-off-by: Jan-Marten Brüggemann <[email protected]>
  • Loading branch information
brueggemann authored Mar 7, 2024
1 parent b2f286e commit 14541a6
Show file tree
Hide file tree
Showing 17 changed files with 177 additions and 108 deletions.
14 changes: 14 additions & 0 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: pre-commit

on:
pull_request:
push:
branches: [main]

jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v3
- uses: pre-commit/[email protected]
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,4 @@ cython_debug/
# Project specific
data.yaml
config.yaml
.ceph
.ceph
17 changes: 17 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.1
hooks:
- id: ruff
args: [ --fix ]
- id: ruff-format
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: check-yaml
- id: check-json
- id: check-toml
- id: check-merge-conflict
- id: mixed-line-ending
- id: end-of-file-fixer
- id: trailing-whitespace
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[build-system]
requires = [ "setuptools", "wheel" ]
build-backend = "setuptools.build_meta"

[project]
requires-python = ">=3.9"
24 changes: 13 additions & 11 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,33 @@
limitations under the License.
"""

from os import makedirs, path

try:
from setuptools import find_packages, setup
except ImportError:
from distutils import find_packages, setup
#


def get_version():
"""
Returns the version currently in development.
Returns the version currently in development.
:return: (str) Version string
:since: v0.0.1
:return: (str) Version string
:since: v0.0.1
"""

return "v0.0.1"


#

_setup = { "version": get_version()[1:],
"data_files": [ ( "docs", [ "LICENSE", "README.md" ]) ],
"test_suite": "tests"
}
_setup = {
"version": get_version()[1:],
"data_files": [("docs", ["LICENSE", "README.md"])],
"test_suite": "tests",
}

_setup['package_dir'] = { "": "src" }
_setup['packages'] = find_packages("src")
_setup["package_dir"] = {"": "src"}
_setup["packages"] = find_packages("src")

setup(**_setup)
22 changes: 15 additions & 7 deletions src/rookify/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,46 @@
from types import MappingProxyType
from .yaml import load_yaml, save_yaml


def main():
try:
config = load_yaml("config.yaml")
except FileNotFoundError as err:
raise SystemExit(f'Could not load config: {err}')
preflight_modules, migration_modules = rookify.modules.load_modules(config['migration_modules'])
raise SystemExit(f"Could not load config: {err}")
preflight_modules, migration_modules = rookify.modules.load_modules(
config["migration_modules"]
)

module_data = dict()
try:
module_data.update(load_yaml(config['general']['module_data_file']))
module_data.update(load_yaml(config["general"]["module_data_file"]))
except FileNotFoundError:
pass

# Run preflight requirement modules
for preflight_module in preflight_modules:
handler = preflight_module.HANDLER_CLASS(config=MappingProxyType(config), data=MappingProxyType(module_data))
handler = preflight_module.HANDLER_CLASS(
config=MappingProxyType(config), data=MappingProxyType(module_data)
)
result = handler.run()
module_data[preflight_module.MODULE_NAME] = result

# Run preflight checks and append handlers to list
handlers = list()
for migration_module in migration_modules:
handler = migration_module.HANDLER_CLASS(config=MappingProxyType(config), data=MappingProxyType(module_data))
handler = migration_module.HANDLER_CLASS(
config=MappingProxyType(config), data=MappingProxyType(module_data)
)
handler.preflight_check()
handlers.append((migration_module, handler))

# Run migration modules
for migration_module, handler in handlers:
result = handler.run()
module_data[migration_module.MODULE_NAME] = result

save_yaml(config['general']['module_data_file'], module_data)
save_yaml(config["general"]["module_data_file"], module_data)


if __name__ == "__main__":
main()
49 changes: 34 additions & 15 deletions src/rookify/modules/__init__.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
# -*- coding: utf-8 -*-

import functools
import importlib
import types

from typing import Optional
from collections import OrderedDict
from .module import ModuleHandler


class ModuleLoadException(Exception):
"""
ModuleLoadException is an exception class that can be raised during the dynamic load process for modules.
"""

def __init__(self, module_name: str, message: str):
"""
Construct a new 'ModuleLoadException' object.
Expand All @@ -21,6 +22,7 @@ def __init__(self, module_name: str, message: str):
self.module_name = module_name
self.message = message


def load_modules(module_names: list) -> tuple[list, list]:
"""
Dynamically loads modules from the 'modules' package.
Expand All @@ -30,60 +32,76 @@ def load_modules(module_names: list) -> tuple[list, list]:
"""

# Sanity checks for modules
def check_module_sanity(module_name: str, module: module):
def check_module_sanity(module_name: str, module: types.ModuleType):
for attr_type, attr_name in (
(ModuleHandler, 'HANDLER_CLASS'),
(str, 'MODULE_NAME'),
(list, 'REQUIRES'),
(list, 'AFTER'),
(list, 'PREFLIGHT_REQUIRES')
(ModuleHandler, "HANDLER_CLASS"),
(str, "MODULE_NAME"),
(list, "REQUIRES"),
(list, "AFTER"),
(list, "PREFLIGHT_REQUIRES"),
):
if not hasattr(module, attr_name):
raise ModuleLoadException(module_name, f'Module has no attribute {attr_name}')
raise ModuleLoadException(
module_name, f"Module has no attribute {attr_name}"
)

attr = getattr(module, attr_name)
if not isinstance(attr, attr_type) and not issubclass(attr, attr_type):
raise ModuleLoadException(module_name, f'Attribute {attr_name} is not type {attr_type}')
raise ModuleLoadException(
module_name, f"Attribute {attr_name} is not type {attr_type}"
)

# Load the modules in the given list and recursivley load required modules
required_modules = OrderedDict()

def load_required_modules(modules_out: OrderedDict, module_names: list) -> None:
for module_name in module_names:
if module_name in modules_out:
continue

module = importlib.import_module(f".{module_name}", 'rookify.modules')
module = importlib.import_module(f".{module_name}", "rookify.modules")
check_module_sanity(module_name, module)

load_required_modules(modules_out, module.REQUIRES)
module.AFTER.extend(module.REQUIRES)

modules_out[module_name] = module

load_required_modules(required_modules, module_names)

# Recursively load the modules in the PREFLIGHT_REQUIRES attribute of the given modules
preflight_modules = OrderedDict()
def load_preflight_modules(modules_in: OrderedDict, modules_out: OrderedDict, module_names: list) -> None:

def load_preflight_modules(
modules_in: OrderedDict, modules_out: OrderedDict, module_names: list
) -> None:
for module_name in module_names:
if module_name in modules_out:
continue

module = importlib.import_module(f".{module_name}", 'rookify.modules')
module = importlib.import_module(f".{module_name}", "rookify.modules")
check_module_sanity(module_name, module)

# We have to check, if the preflight_requires list is already loaded as migration requirement
for preflight_requirement in module.PREFLIGHT_REQUIRES:
if preflight_requirement in modules_in:
raise ModuleLoadException(module_name, f'Module {preflight_requirement} is already loaded as migration requirement')
raise ModuleLoadException(
module_name,
f"Module {preflight_requirement} is already loaded as migration requirement",
)

load_preflight_modules(modules_in, modules_out, module.PREFLIGHT_REQUIRES)
if module_name not in modules_in:
modules_out[module_name] = module

load_preflight_modules(required_modules, preflight_modules, required_modules.keys())

# Sort the modules by the AFTER keyword
modules = OrderedDict()
def sort_modules(modules_in: OrderedDict, modules_out: OrderedDict, module_names: list) -> None:

def sort_modules(
modules_in: OrderedDict, modules_out: OrderedDict, module_names: list
) -> None:
for module_name in module_names:
if module_name not in modules_in:
continue
Expand All @@ -95,6 +113,7 @@ def sort_modules(modules_in: OrderedDict, modules_out: OrderedDict, module_names
sort_modules(modules_in, modules_out, after_modules_name)

modules_out[module_name] = modules_in[module_name]

sort_modules(required_modules, modules, list(required_modules.keys()))

return list(preflight_modules.values()), list(modules.values())
4 changes: 2 additions & 2 deletions src/rookify/modules/analyze_ceph/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

from .main import AnalyzeCephHandler

MODULE_NAME = 'analyze_ceph'
MODULE_NAME = "analyze_ceph"
HANDLER_CLASS = AnalyzeCephHandler
REQUIRES = []
AFTER = []
PREFLIGHT_REQUIRES = []
PREFLIGHT_REQUIRES = []
26 changes: 8 additions & 18 deletions src/rookify/modules/analyze_ceph/main.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
# -*- coding: utf-8 -*-

import json

from ..module import ModuleHandler

class AnalyzeCephHandler(ModuleHandler):

class AnalyzeCephHandler(ModuleHandler):
def run(self) -> dict:

commands = [
'mon dump',
'osd dump',
'device ls',
'fs dump',
'node ls'
]
commands = ["mon dump", "osd dump", "device ls", "fs dump", "node ls"]

results = dict()
for command in commands:
parts = command.split(' ')
parts = command.split(" ")
leaf = results
for idx, part in enumerate(parts):
if idx < len(parts) - 1:
Expand All @@ -27,12 +19,10 @@ def run(self) -> dict:
leaf[part] = self.ceph.mon_command(command)
leaf = leaf[part]

results['ssh'] = dict()
results['ssh']['osd'] = dict()
for node, values in results['node']['ls']['osd'].items():
devices = self.ssh.command(node, 'find /dev/ceph-*/*').stdout.splitlines()
results['ssh']['osd'][node] = {
'devices': devices
}
results["ssh"] = dict()
results["ssh"]["osd"] = dict()
for node, values in results["node"]["ls"]["osd"].items():
devices = self.ssh.command(node, "find /dev/ceph-*/*").stdout.splitlines()
results["ssh"]["osd"][node] = {"devices": devices}

return results
14 changes: 9 additions & 5 deletions src/rookify/modules/example/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

from .main import ExampleHandler

MODULE_NAME = 'example' # Name of the module
HANDLER_CLASS = ExampleHandler # Define the handler class for this module
REQUIRES = [] # A list of modules that are required to run before this module. Modules in this list will be imported, even if they are not configured
AFTER = ['migrate_monitors'] # A list of modules that should be run before this module, if they are defined in config
PREFLIGHT_REQUIRES = ['analyze_ceph'] # A list of modules that are required to run the preflight_check of this module. Modules in this list will be imported and run in preflight stage.
MODULE_NAME = "example" # Name of the module
HANDLER_CLASS = ExampleHandler # Define the handler class for this module
REQUIRES = [] # A list of modules that are required to run before this module. Modules in this list will be imported, even if they are not configured
AFTER = [
"migrate_monitors"
] # A list of modules that should be run before this module, if they are defined in config
PREFLIGHT_REQUIRES = [
"analyze_ceph"
] # A list of modules that are required to run the preflight_check of this module. Modules in this list will be imported and run in preflight stage.
4 changes: 2 additions & 2 deletions src/rookify/modules/example/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

from ..module import ModuleHandler, ModuleException

class ExampleHandler(ModuleHandler):

class ExampleHandler(ModuleHandler):
def preflight_check(self):
# Do something for checking if all needed preconditions are met else throw ModuleException
raise ModuleException('Example module was loaded, so aborting!')
raise ModuleException("Example module was loaded, so aborting!")

def run(self) -> dict:
# Run the migration tasks
Expand Down
4 changes: 2 additions & 2 deletions src/rookify/modules/migrate_monitors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

from .main import MigrateMonitorsHandler

MODULE_NAME = 'migrate_monitors'
MODULE_NAME = "migrate_monitors"
HANDLER_CLASS = MigrateMonitorsHandler
REQUIRES = []
AFTER = []
PREFLIGHT_REQUIRES = ['analyze_ceph']
PREFLIGHT_REQUIRES = ["analyze_ceph"]
1 change: 1 addition & 0 deletions src/rookify/modules/migrate_monitors/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@

from ..module import ModuleHandler


class MigrateMonitorsHandler(ModuleHandler):
pass
6 changes: 3 additions & 3 deletions src/rookify/modules/migrate_osds/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

from .main import MigrateOSDsHandler

MODULE_NAME = 'migrate_osds'
MODULE_NAME = "migrate_osds"
HANDLER_CLASS = MigrateOSDsHandler
REQUIRES = []
AFTER = ['migrate_monitors']
PREFLIGHT_REQUIRES = [ 'analyze_ceph' ]
AFTER = ["migrate_monitors"]
PREFLIGHT_REQUIRES = ["analyze_ceph"]
Loading

0 comments on commit 14541a6

Please sign in to comment.