|
| 1 | +from __future__ import (absolute_import, division, print_function) |
| 2 | +__metaclass__ = type |
| 3 | + |
| 4 | +from ansible.plugins.callback import CallbackBase |
| 5 | +import pathlib |
| 6 | +import yaml |
| 7 | +import os |
| 8 | + |
| 9 | +BASE_DIR = pathlib.Path(__file__).parent.parent |
| 10 | +STATE_DIR = pathlib.Path(os.environ.get('OBSAH_STATE', '.var/lib/foremanctl')) |
| 11 | + |
| 12 | +def load_yaml(path: pathlib.Path) -> dict: |
| 13 | + try: |
| 14 | + with path.open() as f: |
| 15 | + return yaml.safe_load(f) or {} |
| 16 | + except FileNotFoundError: |
| 17 | + return {} |
| 18 | + |
| 19 | + |
| 20 | +class CallbackModule(CallbackBase): |
| 21 | + """Features listing callback.""" |
| 22 | + |
| 23 | + CALLBACK_VERSION = 2.0 |
| 24 | + CALLBACK_TYPE = 'stdout' |
| 25 | + CALLBACK_NAME = 'foremanctl_features' |
| 26 | + |
| 27 | + def __init__(self): |
| 28 | + super().__init__() |
| 29 | + self.feature_metadata = self._load_features_metadata() |
| 30 | + |
| 31 | + def _load_features_metadata(self): |
| 32 | + features_yaml = BASE_DIR / 'features.yaml' |
| 33 | + return load_yaml(features_yaml) |
| 34 | + |
| 35 | + def v2_runner_on_ok(self, result): |
| 36 | + if result._task.action in ('ansible.builtin.debug', 'debug'): |
| 37 | + self._display_features() |
| 38 | + |
| 39 | + def _display_features(self): |
| 40 | + params_yaml = STATE_DIR / "parameters.yaml" |
| 41 | + params = load_yaml(params_yaml) |
| 42 | + |
| 43 | + flavor = params.get('flavor') |
| 44 | + added_features = params.get('features', []) |
| 45 | + |
| 46 | + flavor_file = BASE_DIR / f"vars/flavors/{flavor}.yml" |
| 47 | + flavor_config = load_yaml(flavor_file) |
| 48 | + flavor_features = flavor_config.get('flavor_features', []) |
| 49 | + |
| 50 | + enabled_features = flavor_features + added_features |
| 51 | + |
| 52 | + enabled_list = [] |
| 53 | + available_list = [] |
| 54 | + |
| 55 | + for name in sorted(self.feature_metadata.keys()): |
| 56 | + meta = self.feature_metadata.get(name, {}) or {} |
| 57 | + |
| 58 | + if meta.get('internal', False): |
| 59 | + continue |
| 60 | + |
| 61 | + description = meta.get('description', '') |
| 62 | + |
| 63 | + if name in enabled_features: |
| 64 | + enabled_list.append((name, 'enabled', description)) |
| 65 | + else: |
| 66 | + available_list.append((name, 'available', description)) |
| 67 | + |
| 68 | + self._display.display(f"{'FEATURE':<25} {'STATE':<12} DESCRIPTION") |
| 69 | + |
| 70 | + for name, state, description in enabled_list: |
| 71 | + self._display.display(f"{name:<25} {state:<12} {description}") |
| 72 | + |
| 73 | + for name, state, description in available_list: |
| 74 | + self._display.display(f"{name:<25} {state:<12} {description}") |
| 75 | + |
| 76 | + total = len(enabled_list) + len(available_list) |
| 77 | + self._display.display("") |
| 78 | + self._display.display( |
| 79 | + f"{total} features listed ({len(enabled_list)} enabled, {len(available_list)} available)." |
| 80 | + ) |
0 commit comments