kolla-ansible/kolla_ansible/filters.py
Mark Goddard af2e7fd73e Add custom filters for checking services
These filters can be used to capture a lot of the logic that we
currently have in 'when' statements, about which services are enabled
for a particular host.

In order to use these filters, it is necessary to install the
kolla_ansible python module, and not just the dependencies listed in
requirements.txt. The CI test and quickstart install from source
documentation has been updated accordingly.

Ansible is not currently in OpenStack global requirements, so for unit
tests we avoid a direct dependency on Ansible and provide fakes where
necessary.

Change-Id: Ib91cac3c28e2b5a834c9746b1d2236a309529556
2019-09-16 12:48:52 +00:00

108 lines
3.6 KiB
Python

# Copyright (c) 2019 StackHPC Ltd.
#
# 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 jinja2
from kolla_ansible import exception
def _call_bool_filter(context, value):
"""Pass a value through the 'bool' filter.
:param context: Jinja2 Context object.
:param value: Value to pass through bool filter.
:returns: A boolean.
"""
return context.environment.call_filter("bool", value, context=context)
@jinja2.contextfilter
def service_enabled(context, service):
"""Return whether a service is enabled.
:param context: Jinja2 Context object.
:param service: Service definition, dict.
:returns: A boolean.
"""
enabled = service.get('enabled')
if enabled is None:
raise exception.FilterError(
"Service definition for '%s' does not have an 'enabled' attribute"
% service.get("container_name", "<unknown>"))
return _call_bool_filter(context, enabled)
@jinja2.contextfilter
def service_mapped_to_host(context, service):
"""Return whether a service is mapped to this host.
There are two ways to describe the service to host mapping. The most common
is via a 'group' attribute, where the service is mapped to all hosts in the
group. The second approach is via a 'host_in_groups' attribute, which is a
boolean expression which should be evaluated for every host. The latter
approach takes precedence over the first.
:param context: Jinja2 Context object.
:param service: Service definition, dict.
:returns: A boolean.
"""
host_in_groups = service.get("host_in_groups")
if host_in_groups is not None:
return _call_bool_filter(context, host_in_groups)
group = service.get("group")
if group is not None:
return group in context.get("groups")
raise exception.FilterError(
"Service definition for '%s' does not have a 'group' or "
"'host_in_groups' attribute" %
service.get("container_name", "<unknown>"))
@jinja2.contextfilter
def service_enabled_and_mapped_to_host(context, service):
"""Return whether a service is enabled and mapped to this host.
:param context: Jinja2 Context object.
:param service: Service definition, dict.
:returns: A boolean.
"""
return (service_enabled(context, service) and
service_mapped_to_host(context, service))
@jinja2.contextfilter
def select_services_enabled_and_mapped_to_host(context, services):
"""Select services that are enabled and mapped to this host.
:param context: Jinja2 Context object.
:param services: Service definitions, dict.
:returns: A dict containing enabled services mapped to this host.
"""
return {service_name: service
for service_name, service in services.items()
if service_enabled_and_mapped_to_host(context, service)}
def get_filters():
return {
"service_enabled": service_enabled,
"service_mapped_to_host": service_mapped_to_host,
"service_enabled_and_mapped_to_host": (
service_enabled_and_mapped_to_host),
"select_services_enabled_and_mapped_to_host": (
select_services_enabled_and_mapped_to_host),
}