ospurge/ospurge/utils.py

97 lines
3.1 KiB
Python

# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import copy
import functools
import importlib
import logging
import os
import pkgutil
import re
from ospurge.resources import base
def get_resource_classes(resources=None):
"""
Import all the modules in the `resources` package and return all the
subclasses of the `ServiceResource` ABC that match the `resources` arg.
This way we can easily extend OSPurge by just adding a new file in the
`resources` dir.
"""
iter_modules = pkgutil.iter_modules(
[os.path.join(os.path.dirname(__file__), 'resources')],
prefix='ospurge.resources.'
)
for (_, name, ispkg) in iter_modules:
if not ispkg:
importlib.import_module(name)
all_classes = base.ServiceResource.__subclasses__()
# If we don't want to filter out which classes to return, use a global
# wildcard regex.
if not resources:
regex = re.compile(".*")
# Otherwise, build a regex by concatenation.
else:
regex = re.compile('|'.join(resources))
return [c for c in all_classes if regex.match(c.__name__)]
def monkeypatch_oscc_logging_warning(f):
"""
Monkey-patch logging.warning() method to silence 'os_client_config' when
it complains that a Keystone catalog entry is not found. This warning
benignly happens when, for instance, we try to cleanup a Neutron resource
but Neutron is not available on the target cloud environment.
"""
oscc_target = 'os_client_config.cloud_config'
orig_logging = logging.getLogger(oscc_target).warning
def logging_warning(msg: str, *args, **kwargs):
if 'catalog entry not found' not in msg:
orig_logging(msg, *args, **kwargs)
@functools.wraps(f)
def wrapper(*args: list, **kwargs):
try:
setattr(logging.getLogger(oscc_target), 'warning', logging_warning)
return f(*args, **kwargs)
finally:
setattr(logging.getLogger(oscc_target), 'warning', orig_logging)
return wrapper
def call_and_ignore_exc(exc, f, *args):
try:
f(*args)
except exc as e:
logging.debug("The following exception was ignored: %r", e)
def replace_project_info(config, new_project_id):
"""
Replace all tenant/project info in a `os_client_config` config dict with
a new project. This is used to bind/scope to another project.
"""
new_conf = copy.deepcopy(config)
new_conf.pop('cloud', None)
new_conf['auth'].pop('project_name', None)
new_conf['auth'].pop('project_id', None)
new_conf['auth']['project_id'] = new_project_id
return new_conf