blob: 7ff09365c06ee04d1785ac8db215ec4b43e61d20 [file] [log] [blame]
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
#
from collections.abc import Iterable
from functools import wraps
from pydoc import locate
# struct to hold information about ansible vars defined via decorators.
# var_name indicates the desired variable name
# class_name indicates the class name where the variable was defined
# property_name indicates the class property/function where the variable was
# defined
class _ansible_var(object):
def __init__(self, var_name, class_name, property_name, module_name):
self.var_name = var_name
self.class_name = class_name
self.property_name = property_name
self.module_name = module_name
def __str__(self):
return (
"var_name={}, class_name={}, " "property_name={}, module_name={}"
).format(
self.var_name,
self.class_name,
self.property_name,
self.module_name,
)
# each entry of _ansible_vars will contain a list of _ansible_var instances
_ansible_vars = dict(host=[], play=[], extra=[])
def get_ansible_vars(var_type, class_in_scope):
# return variables for the complete class hierarchy
return list(
filter(
lambda v: issubclass(
class_in_scope, locate(v.module_name + "." + v.class_name)
),
_ansible_vars.get(var_type),
)
)
# ansible hosts inventory variables
def ansible_host_var(name=None):
return ansible_var_decorator("host", name)
# ansible group/all variables
def ansible_play_var(name=None):
return ansible_var_decorator("play", name)
# ansible extra variables
def ansible_extra_var(name=None):
return ansible_var_decorator("extra", name)
def ansible_var_decorator(var_type, name):
def _decorator(func):
ansible_var = _ansible_var(
var_name=name if isinstance(name, str) else func.__name__,
class_name=func.__qualname__.split(".")[0],
property_name=func.__name__,
module_name=func.__module__,
)
_ansible_vars[var_type].append(ansible_var)
return func
if callable(name):
return _decorator(name)
return _decorator
def default(val):
def _default(func):
@wraps(func)
def wrapper(*args, **kwargs):
try:
res = func(*args, **kwargs)
except: # noqa
return val
else:
if res is None or (isinstance(res, str) and len(res) == 0):
return val
return res
return wrapper
return _default
def required(func):
@wraps(func)
def wrapper(*args, **kwargs):
res = func(*args, **kwargs)
if res in [None, 0, ""] or len(res) == 0:
raise ConfigMissingError(func.__name__)
return res
return wrapper
def is_valid(validators):
if not isinstance(validators, Iterable):
validators = [validators]
def _validate(func):
@wraps(func)
def wrapper(*args, **kwargs):
res = func(*args, **kwargs)
failed_checks = list(
filter(lambda f: f(res) is not True, validators)
)
if len(failed_checks) > 0:
raise Exception(
"{}={} checked validation {}".format(
func.__name__, res, [str(v) for v in failed_checks]
)
)
return res
return wrapper
return _validate
class ConfigMissingError(Exception):
def __init__(self, name):
super(ConfigMissingError, self).__init__(
"{} is missing from the configuration".format(name)
)