diff --git a/ansible/inventory/group_vars/all/kolla b/ansible/inventory/group_vars/all/kolla
index e34613f3f..17575639b 100644
--- a/ansible/inventory/group_vars/all/kolla
+++ b/ansible/inventory/group_vars/all/kolla
@@ -571,6 +571,16 @@ kolla_enable_vitrage: "no"
kolla_enable_watcher: "no"
kolla_enable_zun: "no"
+###############################################################################
+# Kolla custom config generation.
+
+# Feature flag to add $KAYOBE_CONFIG_PATH to the list of search paths used
+# when searching for Kolla custom service configuration. Only has an effect in
+# a multiple environments setup. This allows you to configure merging between
+# your environment and the base layer. Defaults to true. Set to false for
+# backwards compatibility.
+kolla_openstack_custom_config_environment_merging_enabled: true
+
###############################################################################
# Passwords and credentials.
diff --git a/ansible/kolla-openstack.yml b/ansible/kolla-openstack.yml
index cd331f15e..b6daaf0c1 100644
--- a/ansible/kolla-openstack.yml
+++ b/ansible/kolla-openstack.yml
@@ -100,53 +100,6 @@
ipa_image_name: "ipa"
pre_tasks:
- block:
- - name: Check whether Kolla extra configuration files exist
- stat:
- path: "{{ kayobe_env_config_path }}/kolla/config/{{ item.file }}"
- get_checksum: False
- get_md5: False
- mime: False
- register: stat_result
- with_items:
- - { name: aodh, file: aodh.conf }
- - { name: barbican, file: barbican.conf }
- - { name: blazar, file: blazar.conf }
- - { name: ceilometer, file: ceilometer.conf }
- - { name: cinder, file: cinder.conf }
- - { name: cloudkitty, file: cloudkitty.conf }
- - { name: designate, file: designate.conf }
- - { name: glance, file: glance.conf }
- - { name: global, file: global.conf }
- - { name: gnocchi, file: gnocchi.conf }
- - { name: grafana, file: grafana.ini }
- - { name: heat, file: heat.conf }
- - { name: inspector, file: ironic-inspector.conf }
- - { name: ironic, file: ironic.conf }
- - { name: keystone, file: keystone.conf }
- - { name: magnum, file: magnum.conf }
- - { name: manila, file: manila.conf }
- - { name: mariabackup, file: backup.my.cnf }
- - { name: mariadb, file: galera.cnf }
- - { name: masakari, file: masakari.conf }
- - { name: multipathd, file: multipath.conf }
- - { name: murano, file: murano.conf }
- - { name: neutron, file: neutron.conf }
- - { name: neutron_ml2, file: neutron/ml2_conf.ini }
- - { name: nova, file: nova.conf }
- - { name: octavia, file: octavia.conf }
- - { name: placement, file: placement.conf }
- - { name: sahara, file: sahara.conf }
-
- - name: Initialise a fact containing extra configuration
- set_fact:
- kolla_extra_config: {}
-
- - name: Update a fact containing extra configuration
- set_fact:
- kolla_extra_config: "{{ kolla_extra_config | combine({item.item.name: lookup('template', '{{ item.stat.path }}')}) }}"
- with_items: "{{ stat_result.results }}"
- when: item.stat.exists
-
- name: Validate switch configuration for Neutron ML2 genericswitch driver
fail:
msg: >
@@ -217,35 +170,11 @@
kolla_inspector_swift_auth:
auth_type: none
endpoint_override: "http://{% raw %}{{ api_interface_address }}{% endraw %}:{{ inspector_store_port }}"
- # Extra free-form user-provided configuration.
- kolla_extra_aodh: "{{ kolla_extra_config.aodh | default }}"
- kolla_extra_barbican: "{{ kolla_extra_config.barbican | default }}"
- kolla_extra_blazar: "{{ kolla_extra_config.blazar | default }}"
- kolla_extra_ceilometer: "{{ kolla_extra_config.ceilometer | default }}"
- kolla_extra_cinder: "{{ kolla_extra_config.cinder | default }}"
- kolla_extra_cloudkitty: "{{ kolla_extra_config.cloudkitty | default }}"
- kolla_extra_designate: "{{ kolla_extra_config.designate | default }}"
- kolla_extra_glance: "{{ kolla_extra_config.glance | default }}"
- kolla_extra_global: "{{ kolla_extra_config.global | default }}"
- kolla_extra_gnocchi: "{{ kolla_extra_config.gnocchi | default }}"
- kolla_extra_grafana: "{{ kolla_extra_config.grafana | default }}"
- kolla_extra_heat: "{{ kolla_extra_config.heat | default }}"
- kolla_extra_inspector: "{{ kolla_extra_config.inspector | default }}"
- kolla_extra_ironic: "{{ kolla_extra_config.ironic | default }}"
- kolla_extra_keystone: "{{ kolla_extra_config.keystone | default }}"
- kolla_extra_magnum: "{{ kolla_extra_config.magnum | default }}"
- kolla_extra_manila: "{{ kolla_extra_config.manila | default }}"
- kolla_extra_mariabackup: "{{ kolla_extra_config.mariabackup | default }}"
- kolla_extra_mariadb: "{{ kolla_extra_config.mariadb | default }}"
- kolla_extra_masakari: "{{ kolla_extra_config.masakari | default }}"
- kolla_extra_multipathd: "{{ kolla_extra_config.multipathd | default }}"
- kolla_extra_murano: "{{ kolla_extra_config.murano | default }}"
- kolla_extra_neutron: "{{ kolla_extra_config.neutron | default }}"
- kolla_extra_neutron_ml2: "{{ kolla_extra_config.neutron_ml2 | default }}"
- kolla_extra_nova: "{{ kolla_extra_config.nova | default }}"
- kolla_extra_octavia: "{{ kolla_extra_config.octavia | default }}"
- kolla_extra_placement: "{{ kolla_extra_config.placement | default }}"
- kolla_extra_sahara: "{{ kolla_extra_config.sahara | default }}"
- kolla_extra_config_path: "{{ kayobe_env_config_path }}/kolla/config"
+ kolla_openstack_custom_config_paths_extra_multi_env:
+ - "{{ kayobe_config_path }}"
+ - "{{ kayobe_env_config_path }}"
+ kolla_openstack_custom_config_paths_extra_legacy:
+ - "{{ kayobe_env_config_path }}"
+ kolla_openstack_custom_config_paths_extra: "{{ kolla_openstack_custom_config_paths_extra_multi_env if kolla_openstack_custom_config_environment_merging_enabled | bool else kolla_openstack_custom_config_paths_extra_legacy }}"
kolla_libvirt_tls: "{{ compute_libvirt_enable_tls | bool }}"
kolla_nova_libvirt_certificates_src: "{{ kayobe_env_config_path }}/certificates/libvirt"
diff --git a/ansible/roles/image-download/tasks/main.yml b/ansible/roles/image-download/tasks/main.yml
index 3f905b8bf..4d3f6dc1e 100644
--- a/ansible/roles/image-download/tasks/main.yml
+++ b/ansible/roles/image-download/tasks/main.yml
@@ -1,4 +1,9 @@
---
+- name: Ensure destination directory exists
+ file:
+ state: directory
+ path: "{{ image_download_dest | dirname }}"
+
- block:
- block:
- name: Fail if the checksum algorithm is not set
diff --git a/ansible/roles/kolla-openstack/action_plugins/kolla_custom_config_info.py b/ansible/roles/kolla-openstack/action_plugins/kolla_custom_config_info.py
new file mode 100644
index 000000000..f5ad15429
--- /dev/null
+++ b/ansible/roles/kolla-openstack/action_plugins/kolla_custom_config_info.py
@@ -0,0 +1,229 @@
+# Copyright (c) 2023 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.
+
+from ansible.plugins.action import ActionBase
+import os
+from collections import defaultdict
+import pathlib
+
+from wcmatch import glob
+
+def _dedup(xs):
+ # Deduplicate a list whilst maintaining order
+ seen = set()
+ result = []
+ for x in xs:
+ if x not in seen:
+ seen.add(x)
+ result.append(x)
+ return result
+
+class ConfigCollector(object):
+ def __init__(self, include_globs, ignore_globs, destination, search_paths,
+ rules):
+ # This variable groups together files in the search paths with
+ # the same relative path, for example if the search paths were:
+ # - {{ kayobe_config_env_path }}/
+ # - {{ kayobe_config_path }}/
+ # - {{ role_path }}/templates/
+ # and one of the include_globs matched nova.conf. You'd end up
+ # with the following files grouped together:
+ # - {{ kayobe_env_path }}/etc/kolla/nova.conf
+ # - {{ kayobe_config_path }}/etc/kolla/nova.conf
+ # - {{ role_path }}/templates/etc/kolla/nova.conf
+ # The key in the dictionary is the relative path of the file. The
+ # value is a list of absolute paths. This gets populated by the
+ # collect() method.
+ self.files_in_source = defaultdict(list)
+ # Set of files in destination. This is used to cleanup up files
+ # from a previous run that are no longer templated. Before any templating
+ # this variable is populated with all the files in the output directory.
+ # Each file that would be templated in the current run will be removed
+ # from this set as they are discovered.
+ self.files_in_destination = set()
+ # Determines which files are candidates for templating
+ self.include_globs = include_globs
+ # Some files are templated by external tasks. This is a list of files
+ # to not clean up.
+ self.ignore_globs = ignore_globs
+ # Where the files are being templated to
+ self.destination = destination
+ # Where to search for the source files
+ self.search_paths = search_paths
+
+ # Rules to determine merging strategy when multiple files are found
+ # with the same relative path. Lower priority numbers win.
+ self.rules = sorted(rules, key=lambda d: d['priority'])
+
+ def filter_files_in_destination(self):
+ ignored = set()
+ for f in self.files_in_destination:
+ for item in self.ignore_globs:
+ if not item["enabled"]:
+ continue
+ if glob.globmatch(f, item["glob"], flags=glob.GLOBSTAR):
+ ignored.add(f)
+ result = set(self.files_in_destination) - ignored
+ return list(result)
+
+ def _find_matching_rule(self, relative_path):
+ # First match wins
+ for rule in self.rules:
+ if not rule.get('enabled', True):
+ continue
+ glob_ = rule["glob"]
+ if glob.globmatch(relative_path, glob_, flags=glob.GLOBSTAR):
+ return rule
+
+ def partition_into_actions(self):
+ actions = {
+ "merge_yaml": [],
+ "merge_configs": [],
+ "template": [],
+ "copy": [],
+ "concat": [],
+ "create_dir": [],
+ "delete": []
+ }
+ missing_directories = set()
+ files_to_delete = self.filter_files_in_destination()
+
+ # Convert to absolute paths
+ files_to_delete = {
+ os.path.join(self.destination, x) for x in files_to_delete
+ }
+
+ for relative_path, sources in self.files_in_source.items():
+ found_match = False
+ destination = os.path.join(self.destination, relative_path)
+ # Don't delete any files we are templating
+ files_to_delete.discard(destination)
+
+ dirname = os.path.dirname(destination)
+ if not os.path.exists(dirname):
+ missing_directories.add(dirname)
+
+ rule = self._find_matching_rule(relative_path)
+
+ if not rule:
+ continue
+
+ if rule["strategy"] == 'copy':
+ copy = {
+ "src": sources[-1],
+ "dest": destination,
+ "params": rule.get('params', [])
+ }
+ actions["copy"].append(copy)
+ continue
+
+ if rule["strategy"] == "merge_yaml":
+ merge_yaml = {
+ "sources": sources,
+ "dest": destination,
+ "params": rule.get('params', [])
+ }
+ actions["merge_yaml"].append(merge_yaml)
+ continue
+
+ if rule["strategy"] == "merge_configs":
+ merge_configs = {
+ "sources": sources,
+ "dest": destination,
+ "params": rule.get('params', [])
+ }
+ actions["merge_configs"].append(merge_configs)
+ continue
+
+ if rule["strategy"] == "concat":
+ concat = {
+ "sources": sources,
+ "dest": destination,
+ "params": rule.get('params', [])
+ }
+ actions["concat"].append(concat)
+ continue
+
+ if rule["strategy"] == "template":
+ template = {
+ "src": sources[-1],
+ "dest": destination,
+ "params": rule.get('params', [])
+ }
+ actions["template"].append(template)
+ continue
+
+ actions["create_dir"] = list(missing_directories)
+ # Sort by length so that subdirectories are created after the parent
+ actions["create_dir"].sort(key=len)
+
+ actions["delete"] = list(files_to_delete)
+ return actions
+
+ def collect(self):
+ for item in self.include_globs:
+ self._collect_source(item)
+ self._collect_destination(item)
+
+ def _collect_source(self, item):
+ enabled = item.get("enabled", False)
+ if not isinstance(enabled, bool):
+ raise ValueError("Expecting a boolean: %s" % item)
+ if not enabled:
+ return
+ for search_path in self.search_paths:
+ abs_glob = os.path.join(search_path, item["glob"])
+ files = glob.glob(abs_glob, flags=glob.GLOBSTAR)
+ for abs_path in files:
+ if not os.path.isfile(abs_path):
+ continue
+ relative_path = os.path.relpath(abs_path, search_path)
+ self.files_in_source[relative_path].append(abs_path)
+
+ def _collect_destination(self, item):
+ abs_glob = os.path.join(self.destination, item["glob"])
+ files = glob.glob(abs_glob, flags=glob.GLOBSTAR)
+ for abs_path in files:
+ if not os.path.isfile(abs_path):
+ continue
+ relative_path = os.path.relpath(abs_path, self.destination)
+ self.files_in_destination.add(relative_path)
+
+class ActionModule(ActionBase):
+
+ def run(self, tmp=None, task_vars=None):
+ if task_vars is None:
+ task_vars = dict()
+
+ result = super(ActionModule, self).run(tmp, task_vars)
+
+ # This class never changes anything. We only collect the extra config
+ # files and group by action.
+ result['changed'] = False
+
+ args = self._task.args
+
+ collector = ConfigCollector(
+ destination=args.get("destination"),
+ ignore_globs=args.get("ignore_globs"),
+ include_globs=args.get("include_globs"),
+ rules=args.get("rules"),
+ search_paths=_dedup(args["search_paths"])
+ )
+
+ collector.collect()
+
+ result.update(collector.partition_into_actions())
+
+ return result
diff --git a/ansible/roles/kolla-openstack/defaults/main.yml b/ansible/roles/kolla-openstack/defaults/main.yml
index ed3fb18a4..5a7a96b09 100644
--- a/ansible/roles/kolla-openstack/defaults/main.yml
+++ b/ansible/roles/kolla-openstack/defaults/main.yml
@@ -1,6 +1,19 @@
---
-# Path to extra kolla-ansible configuration files.
-kolla_extra_config_path:
+# Ordered list of paths to default kolla-ansible configuration files. Least
+# specific first. Default is search the role templates in
+# templates/kolla/config.
+kolla_openstack_custom_config_paths_default:
+ - "{{ role_path }}/templates"
+
+# Ordered list of paths to extra kolla-ansible configuration files. Least
+# specific first. Default is an empty list.
+kolla_openstack_custom_config_paths_extra: []
+
+# Ordered list of paths to kolla-ansible configuration files. Least specific
+# first. Default is a combination of
+# kolla_openstack_custom_config_paths_default and
+# kolla_openstack_custom_config_paths_extra.
+kolla_openstack_custom_config_paths: "{{ kolla_openstack_custom_config_paths_default + kolla_openstack_custom_config_paths_extra }}"
# Directory where Kolla custom configuration files will be installed.
kolla_node_custom_config_path: /etc/kolla/config
@@ -8,15 +21,307 @@ kolla_node_custom_config_path: /etc/kolla/config
###############################################################################
# Global configuration.
+# Deprecated:
# Free form extra configuration to append to global.conf.
kolla_extra_global:
+###############################################################################
+# Kolla custom config generation.
+
+# Default value for kolla_openstack_custom_config_include_globs.
+kolla_openstack_custom_config_include_globs_default:
+ - enabled: '{{ kolla_enable_aodh | bool }}'
+ glob: aodh.conf
+ - enabled: '{{ kolla_enable_aodh | bool }}'
+ glob: aodh/**
+ - enabled: '{{ kolla_enable_barbican | bool }}'
+ glob: barbican.conf
+ - enabled: '{{ kolla_enable_barbican | bool }}'
+ glob: barbican/**
+ - enabled: '{{ kolla_enable_barbican | bool }}'
+ glob: barbican-api/**
+ - enabled: '{{ kolla_enable_blazar | bool }}'
+ glob: blazar.conf
+ - enabled: '{{ kolla_enable_blazar | bool }}'
+ glob: blazar/**
+ - enabled: '{{ kolla_enable_ceilometer | bool }}'
+ glob: ceilometer.conf
+ - enabled: '{{ kolla_enable_ceilometer | bool }}'
+ glob: ceilometer/**
+ - enabled: '{{ kolla_enable_cinder | bool }}'
+ glob: cinder.conf
+ - enabled: '{{ kolla_enable_cinder | bool }}'
+ glob: nfs_shares
+ - enabled: '{{ kolla_enable_cinder | bool }}'
+ glob: cinder/**
+ - enabled: '{{ kolla_enable_cloudkitty | bool }}'
+ glob: cloudkitty.conf
+ - enabled: '{{ kolla_enable_cloudkitty | bool }}'
+ glob: cloudkitty/**
+ - enabled: '{{ kolla_enable_designate | bool }}'
+ glob: designate.conf
+ - enabled: '{{ kolla_enable_designate | bool }}'
+ glob: designate/**
+ - enabled: '{{ kolla_enable_fluentd | bool }}'
+ glob: fluentd/**/*.conf
+ - enabled: '{{ kolla_enable_mariadb | bool }}'
+ glob: galera.cnf
+ - enabled: '{{ kolla_enable_glance | bool }}'
+ glob: glance*.conf
+ - enabled: '{{ kolla_enable_glance | bool }}'
+ glob: glance/**
+ - enabled: true
+ glob: global.conf
+ - enabled: '{{ kolla_enable_gnocchi | bool }}'
+ glob: gnocchi.conf
+ - enabled: '{{ kolla_enable_gnocchi | bool }}'
+ glob: gnocchi/**
+ - enabled: '{{ kolla_enable_grafana | bool }}'
+ glob: grafana.ini
+ - enabled: '{{ kolla_enable_grafana | bool }}'
+ glob: grafana/**
+ - enabled: '{{ kolla_enable_haproxy | bool }}'
+ glob: haproxy-config/**
+ - enabled: '{{ kolla_enable_haproxy | bool }}'
+ glob: haproxy/**
+ - enabled: '{{ kolla_enable_heat | bool }}'
+ glob: heat.conf
+ - enabled: '{{ kolla_enable_heat | bool }}'
+ glob: heat/**
+ - enabled: '{{ kolla_enable_horizon | bool }}'
+ glob: horizon/**
+ - enabled: '{{ kolla_enable_influxdb | bool }}'
+ glob: influx*
+ - enabled: '{{ kolla_enable_ironic | bool }}'
+ glob: ironic-inspector.conf
+ - enabled: '{{ kolla_enable_ironic | bool }}'
+ glob: ironic.conf
+ - enabled: '{{ kolla_enable_ironic | bool }}'
+ glob: ironic/**
+ - enabled: '{{ kolla_enable_keepalived | bool }}'
+ glob: keepalived/**
+ - enabled: '{{ kolla_enable_keystone | bool }}'
+ glob: keystone.conf
+ - enabled: '{{ kolla_enable_keystone | bool }}'
+ glob: keystone/**
+ - enabled: true
+ glob: kolla-toolbox/**
+ - enabled: '{{ kolla_enable_magnum | bool }}'
+ glob: magnum.conf
+ - enabled: '{{ kolla_enable_magnum | bool }}'
+ glob: magnum/**
+ - enabled: '{{ kolla_enable_manila | bool }}'
+ glob: manila.conf
+ - enabled: '{{ kolla_enable_manila | bool }}'
+ glob: manila/**
+ - enabled: '{{ kolla_enable_mariadb | bool }}'
+ glob: backup.my.cnf
+ - enabled: '{{ kolla_enable_mariadb | bool }}'
+ glob: mariadb/**
+ - enabled: '{{ kolla_enable_masakari | bool }}'
+ glob: masakari.conf
+ - enabled: '{{ kolla_enable_masakari | bool }}'
+ glob: masakari/**
+ - enabled: '{{ kolla_enable_multipathd | bool }}'
+ glob: multipath.conf
+ - enabled: '{{ kolla_enable_multipathd | bool }}'
+ glob: multipath/**
+ - enabled: '{{ kolla_enable_murano | bool }}'
+ glob: murano.conf
+ - enabled: '{{ kolla_enable_murano | bool }}'
+ glob: murano/**
+ - enabled: '{{ kolla_enable_neutron | bool }}'
+ glob: neutron.conf
+ - enabled: '{{ kolla_enable_neutron | bool }}'
+ glob: neutron/**
+ - enabled: '{{ kolla_enable_nova | bool }}'
+ glob: nova.conf
+ - enabled: '{{ kolla_enable_nova | bool }}'
+ glob: nova/**
+ - enabled: '{{ kolla_enable_nova | bool }}'
+ glob: nova_compute/**
+ - enabled: '{{ kolla_enable_octavia | bool }}'
+ glob: octavia.conf
+ - enabled: '{{ kolla_enable_octavia | bool }}'
+ glob: octavia/**
+ - enabled: '{{ kolla_enable_opensearch | bool }}'
+ glob: opensearch.yml
+ - enabled: '{{ kolla_enable_opensearch | bool }}'
+ glob: opensearch/**
+ - enabled: '{{ kolla_enable_placement | bool }}'
+ glob: placement.conf
+ - enabled: '{{ kolla_enable_placement | bool }}'
+ glob: placement/**
+ - enabled: '{{ kolla_enable_prometheus | bool }}'
+ glob: prometheus/**
+ - enabled: '{{ kolla_enable_sahara | bool }}'
+ glob: sahara.conf
+ - enabled: '{{ kolla_enable_sahara | bool }}'
+ glob: sahara/**
+ - enabled: '{{ kolla_enable_swift | bool }}'
+ glob: swift/**
+
+# Extra items to add to kolla_openstack_custom_config_include_globs_default
+# to produce kolla_openstack_custom_config_include_globs.
+kolla_openstack_custom_config_include_globs_extra: []
+
+# List of dictionaries with the following keys:
+# glob: a glob pattern. Any files matching this pattern will be copied to the
+# the kolla custom config directory
+# enabled: boolean to disable the glob.
+# This determines the list of files to copy to the generated kolla config
+# directory.
+kolla_openstack_custom_config_include_globs: "{{
+ kolla_openstack_custom_config_include_globs_default +
+ kolla_openstack_custom_config_include_globs_extra }}"
+
+# Kolla config generation rules. These operate on the list of files produced by
+# applying kolla_openstack_custom_config_include_globs. Each of the paths in
+# kolla_openstack_custom_config_paths is searched for files matching one of the
+# globs. If a match is found, any files with the same relative path are grouped
+# together. The rules determine what to do with these matching files e.g copy
+# the most specific file without templating, merge the files with
+# merge_configs, etc.
+# List of dictionaries with the following keys:
+# glob: A glob matching files for this rule to match on (relative to the
+# search path)
+# priority: The rules are processed in increasing priority order with the
+# first rule matching taking effect.
+# strategy: How to process the matched file. One of copy, concat, template,
+# merge_configs, merge_yaml
+# params: List of params to pass to module enacting the strategy
+# Strategies:
+# copy: Copy most specific file to kolla config without templating
+# template: Template most specific file to kolla config
+# concat: Concatenate files and copy the result to generated kolla config
+# merge_configs: Use the merge_configs module to merge an ini file, before
+# copying to the generated kolla-config.
+# merge_yaml: Use the merge_yaml module to merge a file, before copying to
+# the generated kolla-config.
+kolla_openstack_custom_config_rules: "{{ kolla_openstack_custom_config_rules_default | rejectattr('glob', 'in', kolla_openstack_custom_config_rules_default_remove) + kolla_openstack_custom_config_rules_extra }}"
+
+# Whether to enable ini merging rules in
+# kolla_openstack_custom_config_rules_default. Default is true.
+kolla_openstack_custom_config_merge_configs_enabled: true
+
+# Whether to enable yaml merging rules in
+# kolla_openstack_custom_config_rules_default. Default is true.
+kolla_openstack_custom_config_merge_yaml_enabled: true
+
+# Default merge strategy for ini files in
+# kolla_openstack_custom_config_rules_default. Default is concat.
+kolla_openstack_custom_config_ini_merge_strategy_default: concat
+
+# Default value for kolla_openstack_custom_config_rules.
+kolla_openstack_custom_config_rules_default:
+ - glob: horizon/themes/**
+ strategy: copy
+ priority: 1000
+ - glob: ironic/ironic-agent.initramfs
+ strategy: copy
+ priority: 1000
+ - glob: ironic/ironic-agent.kernel
+ strategy: copy
+ priority: 1000
+ - glob: swift/*.builder
+ strategy: copy
+ priority: 1000
+ - glob: swift/*.ring.gz
+ strategy: copy
+ priority: 1000
+ - glob: '**/*.pem'
+ strategy: copy
+ priority: 1000
+ # Exceptions for *.conf files which are not INI format
+ - glob: "**/collectd.conf"
+ strategy: template
+ priority: 1000
+ - glob: designate/**/named.conf
+ strategy: template
+ priority: 1000
+ - glob: designate/**/rndc.conf
+ strategy: template
+ priority: 1000
+ - glob: "**/dnsmasq.conf"
+ strategy: template
+ priority: 1000
+ - glob: fluentd/**/*.conf
+ strategy: template
+ priority: 1000
+ - glob: hacluster-corosync/**/corosync.conf
+ strategy: template
+ priority: 1000
+ - glob: horizon/**/horizon.conf
+ strategy: template
+ priority: 1000
+ - glob: "**/*httpd.conf"
+ strategy: template
+ priority: 1000
+ - glob: "**/influxdb.conf"
+ strategy: template
+ priority: 1000
+ - glob: "**/keepalived.conf"
+ strategy: template
+ priority: 1000
+ - glob: "**/multipath.conf"
+ strategy: template
+ priority: 1000
+ - glob: "**/rabbitmq*.conf"
+ strategy: template
+ priority: 1000
+ - glob: "**/*wsgi*.conf"
+ strategy: template
+ priority: 1000
+ # INI files
+ - glob: "**/*.conf"
+ strategy: "{{ kolla_openstack_custom_config_ini_merge_strategy_default }}"
+ priority: 2000
+ enabled: "{{ kolla_openstack_custom_config_merge_configs_enabled | bool }}"
+ - glob: "**/*.ini"
+ strategy: "{{ kolla_openstack_custom_config_ini_merge_strategy_default }}"
+ priority: 2000
+ enabled: "{{ kolla_openstack_custom_config_merge_configs_enabled | bool }}"
+ - glob: "**/galera.cnf"
+ strategy: "{{ kolla_openstack_custom_config_ini_merge_strategy_default }}"
+ priority: 2000
+ enabled: "{{ kolla_openstack_custom_config_merge_configs_enabled | bool }}"
+ - glob: "**/kafka.server.properties"
+ strategy: "{{ kolla_openstack_custom_config_ini_merge_strategy_default }}"
+ priority: 2000
+ enabled: "{{ kolla_openstack_custom_config_merge_configs_enabled | bool }}"
+ - glob: "**/*my.cnf"
+ strategy: "{{ kolla_openstack_custom_config_ini_merge_strategy_default }}"
+ priority: 2000
+ enabled: "{{ kolla_openstack_custom_config_merge_configs_enabled | bool }}"
+ # YAML files
+ - glob: "**/*.yml"
+ strategy: merge_yaml
+ priority: 2000
+ enabled: "{{ kolla_openstack_custom_config_merge_yaml_enabled | bool }}"
+ - glob: "**/*.yaml"
+ strategy: merge_yaml
+ priority: 2000
+ enabled: "{{ kolla_openstack_custom_config_merge_yaml_enabled | bool }}"
+ # Catch all. Fallback to templating to match legacy behaviour.
+ - glob: '**'
+ strategy: template
+ priority: 65535
+
+# List of globs to filter from kolla_openstack_custom_config_rules_default.
+# Default is an empty list.
+kolla_openstack_custom_config_rules_default_remove: []
+
+# Extra items to add to kolla_openstack_custom_config_rules_default
+# to produce kolla_openstack_custom_config_rules.
+kolla_openstack_custom_config_rules_extra: []
+
###############################################################################
# Aodh configuration.
# Whether to enable Aodh.
-kolla_enable_aodh:
+kolla_enable_aodh: false
+# Deprecated:
# Free form extra configuration to append to aodh.conf.
kolla_extra_aodh:
@@ -24,8 +329,9 @@ kolla_extra_aodh:
# Barbican configuration.
# Whether to enable Barbican.
-kolla_enable_barbican:
+kolla_enable_barbican: false
+# Deprecated:
# Free form extra configuration to append to barbican.conf.
kolla_extra_barbican:
@@ -33,8 +339,9 @@ kolla_extra_barbican:
# Blazar configuration.
# Whether to enable Blazar.
-kolla_enable_blazar:
+kolla_enable_blazar: false
+# Deprecated:
# Free form extra configuration to append to blazar.conf.
kolla_extra_blazar:
@@ -42,8 +349,9 @@ kolla_extra_blazar:
# Ceilometer configuration.
# Whether to enable Ceilometer.
-kolla_enable_ceilometer:
+kolla_enable_ceilometer: false
+# Deprecated:
# Free form extra configuration to append to ceilometer.conf.
kolla_extra_ceilometer:
@@ -51,8 +359,9 @@ kolla_extra_ceilometer:
# cinder configuration.
# Whether to enable cinder.
-kolla_enable_cinder:
+kolla_enable_cinder: false
+# Deprecated:
# Free form extra configuration to append to cinder.conf.
kolla_extra_cinder:
@@ -60,8 +369,9 @@ kolla_extra_cinder:
# CloudKitty configuration.
# Whether to enable CloudKitty.
-kolla_enable_cloudkitty:
+kolla_enable_cloudkitty: false
+# Deprecated:
# Free form extra configuration to append to cloudkitty.conf.
kolla_extra_cloudkitty:
@@ -69,17 +379,25 @@ kolla_extra_cloudkitty:
# designate configuration.
# Whether to enable designate.
-kolla_enable_designate:
+kolla_enable_designate: false
+# Deprecated:
# Free form extra configuration to append to designate.conf.
kolla_extra_designate:
+###############################################################################
+# Fluentd configuration.
+
+# Whether to enable Fluentd.
+kolla_enable_fluentd: false
+
###############################################################################
# Glance configuration.
# Whether to enable Glance.
-kolla_enable_glance:
+kolla_enable_glance: false
+# Deprecated:
# Free form extra configuration to append to glance-api.conf and
# glance-registry.conf.
kolla_extra_glance:
@@ -88,8 +406,9 @@ kolla_extra_glance:
# Gnocchi configuration.
# Whether to enable Gnocchi.
-kolla_enable_gnocchi:
+kolla_enable_gnocchi: false
+# Deprecated:
# Free form extra configuration to append to gnocchi.conf.
kolla_extra_gnocchi:
@@ -97,11 +416,12 @@ kolla_extra_gnocchi:
# Grafana configuration.
# Whether to enable Grafana.
-kolla_enable_grafana:
+kolla_enable_grafana: false
# Name of the admin user for Grafana.
grafana_local_admin_user_name:
+# Deprecated:
# Free form extra configuration to append to grafana.ini.
kolla_extra_grafana:
@@ -109,23 +429,15 @@ kolla_extra_grafana:
# HAProxy configuration.
# Whether to enable HAProxy.
-kolla_enable_haproxy:
-
-###############################################################################
-# Keystone configuration.
-
-# Whether to enable Keystone.
-kolla_enable_keystone:
-
-# Free form extra configuration to append to Keystone.conf
-kolla_extra_keystone:
+kolla_enable_haproxy: false
##############################################################################
# Heat configuration.
# Whether to enable Heat.
-kolla_enable_heat:
+kolla_enable_heat: false
+# Deprecated:
# Free form extra configuration to append to heat.conf.
kolla_extra_heat:
@@ -133,19 +445,19 @@ kolla_extra_heat:
# Horizon configuration.
# Whether to enable Horizon.
-kolla_enable_horizon:
+kolla_enable_horizon: false
###############################################################################
# InfluxDB configuration.
# Whether to enable InfluxDB.
-kolla_enable_influxdb:
+kolla_enable_influxdb: false
###############################################################################
# Ironic configuration.
# Whether to enable Ironic.
-kolla_enable_ironic:
+kolla_enable_ironic: false
# List of enabled Ironic drivers.
kolla_ironic_drivers:
@@ -252,6 +564,7 @@ kolla_ironic_provisioning_network:
# List of additional append parameters for baremetal PXE boot.
kolla_ironic_pxe_append_params: []
+# Deprecated:
# Free form extra configuration to append to ironic.conf.
kolla_extra_ironic:
@@ -313,15 +626,33 @@ kolla_inspector_enable_swift:
# store.
kolla_inspector_swift_auth: {}
+# Deprecated:
# Free form extra configuration to append to ironic-inspector.conf.
kolla_extra_inspector:
+###############################################################################
+# Keepalived configuration.
+
+# Whether to enable Keepalived.
+kolla_enable_keepalived: false
+
+###############################################################################
+# Keystone configuration.
+
+# Whether to enable Keystone.
+kolla_enable_keystone: false
+
+# Deprecated:
+# Free form extra configuration to append to Keystone.conf
+kolla_extra_keystone:
+
###############################################################################
# Magnum configuration.
# Whether to enable Magnum.
-kolla_enable_magnum:
+kolla_enable_magnum: false
+# Deprecated:
# Free form extra configuration to append to magnum.conf.
kolla_extra_magnum:
@@ -329,8 +660,9 @@ kolla_extra_magnum:
# Mariabackup configuration.
# Whether to enable Mariabackup.
-kolla_enable_mariabackup:
+kolla_enable_mariabackup: false
+# Deprecated:
# Free form extra configuration to append to backup.my.cnf.
kolla_extra_mariabackup:
@@ -338,8 +670,9 @@ kolla_extra_mariabackup:
# MariaDB configuration.
# Whether to enable MariaDB.
-kolla_enable_mariadb:
+kolla_enable_mariadb: false
+# Deprecated:
# Free form extra configuration to append to galera.cnf.
kolla_extra_mariadb:
@@ -347,14 +680,19 @@ kolla_extra_mariadb:
# Manila configuration.
# Whether to enable Manila.
-kolla_enable_manila:
+kolla_enable_manila: false
+
+# Deprecated:
+# Free form extra configuration to append to manila.conf.
+kolla_extra_manila:
###############################################################################
# Masakari configuration.
# Whether to enable Masakari.
-kolla_enable_masakari:
+kolla_enable_masakari: false
+# Deprecated:
# Free form extra configuration to append to masakari.conf.
kolla_extra_masakari:
@@ -362,7 +700,7 @@ kolla_extra_masakari:
# Multipathd configuration.
# Whether to enable Multipathd.
-kolla_enable_multipathd:
+kolla_enable_multipathd: false
# Free form extra configuration to append to multipath.conf.
kolla_extra_multipathd:
@@ -371,8 +709,9 @@ kolla_extra_multipathd:
# Murano configuration.
# Whether to enable Murano.
-kolla_enable_murano:
+kolla_enable_murano: false
+# Deprecated:
# Free form extra configuration to append to murano.conf.
kolla_extra_murano:
@@ -380,7 +719,7 @@ kolla_extra_murano:
# Neutron configuration.
# Whether to enable Neutron.
-kolla_enable_neutron:
+kolla_enable_neutron: false
# List of Neutron ML2 mechanism drivers to use.
kolla_neutron_ml2_mechanism_drivers: []
@@ -416,9 +755,11 @@ kolla_neutron_ml2_generic_switches: []
# secret: not currently supported
kolla_neutron_ml2_generic_switch_hosts: []
+# Deprecated:
# Free form extra configuration to append to neutron.conf.
kolla_extra_neutron:
+# Deprecated:
# Free form extra configuration to append to ml2_conf.ini.
kolla_extra_neutron_ml2:
@@ -426,11 +767,12 @@ kolla_extra_neutron_ml2:
# Nova configuration.
# Whether to enable Nova.
-kolla_enable_nova:
+kolla_enable_nova: false
# Whether to enable Nova libvirt container.
kolla_enable_nova_libvirt_container:
+# Deprecated:
# Free form extra configuration to append to nova.conf.
kolla_extra_nova:
@@ -441,24 +783,29 @@ kolla_libvirt_tls:
# libvirt on the host.
kolla_nova_libvirt_certificates_src:
+###############################################################################
+# OpenSearch configuration.
+
+# Whether to enable OpenSearch.
+kolla_enable_opensearch: false
+
###############################################################################
# Octavia configuration.
# Whether to enable Octavia.
-kolla_enable_octavia:
+kolla_enable_octavia: false
-###############################################################################
-# OpenSearch configuration.
-
-# Whether to enable opensearch.
-kolla_enable_opensearch:
+# Deprecated:
+# Free form extra configuration to append to octavia.conf
+kolla_extra_octavia:
###############################################################################
# Placement configuration.
# Whether to enable placement.
-kolla_enable_placement:
+kolla_enable_placement: false
+# Deprecated:
# Free form extra configuration to append to placement.conf.
kolla_extra_placement:
@@ -466,14 +813,15 @@ kolla_extra_placement:
# Prometheus configuration.
# Whether to enable Prometheus.
-kolla_enable_prometheus:
+kolla_enable_prometheus: false
###############################################################################
# Sahara configuration.
# Whether to enable sahara.
-kolla_enable_sahara:
+kolla_enable_sahara: false
+# Deprecated:
# Free form extra configuration to append to sahara.conf.
kolla_extra_sahara:
@@ -481,4 +829,4 @@ kolla_extra_sahara:
# Swift configuration.
# Whether to enable swift.
-kolla_enable_swift:
+kolla_enable_swift: false
diff --git a/ansible/roles/kolla-openstack/molecule/default/tests/test_default.py b/ansible/roles/kolla-openstack/molecule/default/tests/test_default.py
index ebd6309f2..e6c0071f8 100644
--- a/ansible/roles/kolla-openstack/molecule/default/tests/test_default.py
+++ b/ansible/roles/kolla-openstack/molecule/default/tests/test_default.py
@@ -25,22 +25,15 @@ testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')
-@pytest.mark.parametrize(
- 'path',
- ['fluentd/filter',
- 'fluentd/input',
- 'fluentd/output'])
-def test_service_config_directory(host, path):
- path = os.path.join('/etc/kolla/config', path)
- utils.test_directory(host, path)
-
-
@pytest.mark.parametrize(
'path',
['aodh',
'cinder',
'cloudkitty',
'designate',
+ 'fluentd/filter',
+ 'fluentd/input',
+ 'fluentd/output',
'glance',
'grafana',
'heat',
diff --git a/ansible/roles/kolla-openstack/molecule/enable-everything/destroy.yml b/ansible/roles/kolla-openstack/molecule/enable-everything/destroy.yml
index 59c2929ce..681850a0e 100644
--- a/ansible/roles/kolla-openstack/molecule/enable-everything/destroy.yml
+++ b/ansible/roles/kolla-openstack/molecule/enable-everything/destroy.yml
@@ -25,3 +25,8 @@
until: docker_jobs.finished
retries: 300
with_items: "{{ server.results }}"
+
+ - name: Clean up temporary path
+ file:
+ path: "{{ lookup('env', 'MOLECULE_TEMP_PATH') | default('/tmp/molecule', true) }}"
+ state: absent
diff --git a/ansible/roles/kolla-openstack/molecule/enable-everything/molecule.yml b/ansible/roles/kolla-openstack/molecule/enable-everything/molecule.yml
index 264ef1cb1..45574e2e9 100644
--- a/ansible/roles/kolla-openstack/molecule/enable-everything/molecule.yml
+++ b/ansible/roles/kolla-openstack/molecule/enable-everything/molecule.yml
@@ -15,7 +15,16 @@ provisioner:
inventory:
group_vars:
all:
- kolla_extra_config_path: ${MOLECULE_TEMP_PATH:-/tmp}/molecule/kolla/config
+ kolla_extra_config_path: ${MOLECULE_TEMP_PATH:-/tmp/molecule}/kolla/config
+ kolla_openstack_custom_config_paths_extra:
+ - "{{ kolla_extra_config_path }}/../.."
+ kolla_openstack_custom_config_rules_extra:
+ - glob: aodh/dummy.yml
+ strategy: merge_yaml
+ priority: 1000
+ - glob: aodh/dummy.ini
+ strategy: merge_configs
+ priority: 1000
kolla_enable_aodh: true
kolla_extra_aodh: |
[extra-aodh.conf]
@@ -44,6 +53,7 @@ provisioner:
kolla_extra_designate: |
[extra-designate.conf]
foo=bar
+ kolla_enable_fluentd: true
kolla_enable_glance: true
kolla_extra_glance: |
[extra-glance.conf]
@@ -72,8 +82,9 @@ provisioner:
kolla_extra_inspector: |
[extra-ironic-inspector.conf]
foo=bar
- kolla_inspector_ipa_kernel_path: ${MOLECULE_TEMP_PATH:-/tmp}/ironic-agent.kernel
- kolla_inspector_ipa_ramdisk_path: ${MOLECULE_TEMP_PATH:-/tmp}/ironic-agent.initramfs
+ kolla_inspector_ipa_kernel_path: ${MOLECULE_TEMP_PATH:-/tmp/molecule}/ironic-agent.kernel
+ kolla_inspector_ipa_ramdisk_path: ${MOLECULE_TEMP_PATH:-/tmp/molecule}/ironic-agent.initramfs
+ kolla_enable_keepalived: true
kolla_enable_keystone: true
kolla_extra_keystone: |
[extra-keystone.conf]
@@ -119,7 +130,7 @@ provisioner:
[extra-nova.conf]
foo=bar
kolla_libvirt_tls: true
- kolla_nova_libvirt_certificates_src: ${MOLECULE_TEMP_PATH:-/tmp}/molecule/nova-libvirt/certificates
+ kolla_nova_libvirt_certificates_src: ${MOLECULE_TEMP_PATH:-/tmp/molecule}/nova-libvirt/certificates
kolla_enable_octavia: true
kolla_extra_octavia: |
[extra-octavia.conf]
diff --git a/ansible/roles/kolla-openstack/molecule/enable-everything/prepare.yml b/ansible/roles/kolla-openstack/molecule/enable-everything/prepare.yml
index 8514e90f3..66be34434 100644
--- a/ansible/roles/kolla-openstack/molecule/enable-everything/prepare.yml
+++ b/ansible/roles/kolla-openstack/molecule/enable-everything/prepare.yml
@@ -26,6 +26,99 @@
- "{{ kolla_inspector_ipa_kernel_path }}"
- "{{ kolla_inspector_ipa_ramdisk_path }}"
+ - name: Ensure parent directories of configuration files exist
+ file:
+ path: "{{ kolla_extra_config_path }}/{{ item }}"
+ state: directory
+ recurse: yes
+ delegate_to: localhost
+ run_once: true
+ with_items:
+ - neutron
+ - aodh
+ # To check that subdirectories are handled correctly
+ - prometheus/prometheus.yml.d
+ # Example of non-ini files that should be templated but not merged
+ - fluentd/input/
+
+ - name: Ensure extra INI configuration files exist
+ copy:
+ content: |
+ [extra-file-{{ item | basename }}]
+ bar=baz
+ dest: "{{ kolla_extra_config_path }}/{{ item }}"
+ run_once: true
+ delegate_to: localhost
+ loop:
+ - aodh.conf
+ - barbican.conf
+ - blazar.conf
+ - ceilometer.conf
+ - cinder.conf
+ - cloudkitty.conf
+ - designate.conf
+ - glance.conf
+ - global.conf
+ - gnocchi.conf
+ - grafana.ini
+ - heat.conf
+ - ironic.conf
+ - ironic-inspector.conf
+ - keystone.conf
+ - magnum.conf
+ - manila.conf
+ - murano.conf
+ - backup.my.cnf
+ - galera.cnf
+ - masakari.conf
+ - neutron.conf
+ - neutron/ml2_conf.ini
+ - nova.conf
+ - octavia.conf
+ - sahara.conf
+ - placement.conf
+
+ - name: Ensure extra YAML configuration files exist
+ copy:
+ content: |
+ dummy_variable: 123
+ dest: "{{ kolla_extra_config_path }}/{{ item }}"
+ run_once: true
+ delegate_to: localhost
+ loop:
+ - aodh/dummy.yml
+ - opensearch.yml
+ - prometheus/prometheus.yml.d/dummy.yml
+
+ - name: Template extra custom config files
+ # These correspond to globs defined in molecule.yml
+ copy:
+ content: "{{ item.content }}"
+ dest: "{{ kolla_extra_config_path }}/{{ item.dest }}"
+ run_once: true
+ delegate_to: localhost
+ with_items:
+ - dest: aodh/dummy.ini
+ content: |
+ [dummy-section]
+ dummy_variable = 123
+ - dest: fluentd/input/01-test.conf
+ content: |
+
+ loop_control:
+ label: "{{ item.dest }}"
+
- name: Ensure nova libvirt certificates directory exists
local_action:
module: file
diff --git a/ansible/roles/kolla-openstack/molecule/enable-everything/tests/test_default.py b/ansible/roles/kolla-openstack/molecule/enable-everything/tests/test_default.py
index aabd19d10..664100501 100644
--- a/ansible/roles/kolla-openstack/molecule/enable-everything/tests/test_default.py
+++ b/ansible/roles/kolla-openstack/molecule/enable-everything/tests/test_default.py
@@ -19,46 +19,12 @@ from kayobe.tests.molecule import utils
import pytest
import testinfra.utils.ansible_runner
+import yaml
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')
-
-@pytest.mark.parametrize(
- 'path',
- ['aodh',
- 'barbican',
- 'cinder',
- 'cloudkitty',
- 'designate',
- 'fluentd/filter',
- 'fluentd/input',
- 'fluentd/output',
- 'glance',
- 'grafana',
- 'heat',
- 'horizon',
- 'ironic',
- 'keystone',
- 'magnum',
- 'manila',
- 'mariadb',
- 'masakari',
- 'murano',
- 'neutron',
- 'nova',
- 'nova/nova-libvirt',
- 'octavia',
- 'placement',
- 'prometheus',
- 'sahara',
- 'swift'])
-def test_service_config_directory(host, path):
- path = os.path.join('/etc/kolla/config', path)
- utils.test_directory(host, path)
-
-
@pytest.mark.parametrize(
'path',
['aodh.conf',
@@ -87,11 +53,44 @@ def test_service_config_directory(host, path):
'backup.my.cnf'])
def test_service_ini_file(host, path):
# TODO(mgoddard): Check more of config file contents.
+ # Tests config added with extra vars e.g kolla_extra_aodh. I.e the
+ # the internal role templates.
path = os.path.join('/etc/kolla/config', path)
extra_section = 'extra-%s' % os.path.basename(path)
expected = {extra_section: {'foo': 'bar'}}
utils.test_ini_file(host, path, expected=expected)
+@pytest.mark.parametrize(
+ 'path',
+ ['aodh.conf',
+ 'barbican.conf',
+ 'cinder.conf',
+ 'cloudkitty.conf',
+ 'designate.conf',
+ 'galera.cnf',
+ 'glance.conf',
+ 'grafana.ini',
+ 'heat.conf',
+ 'ironic.conf',
+ 'ironic-inspector.conf',
+ 'keystone.conf',
+ 'magnum.conf',
+ 'manila.conf',
+ 'masakari.conf',
+ 'murano.conf',
+ 'neutron/ml2_conf.ini',
+ 'neutron.conf',
+ 'nova.conf',
+ 'octavia.conf',
+ 'placement.conf',
+ 'sahara.conf',
+ 'backup.my.cnf'])
+def test_service_ini_file_extra_confs(host, path):
+ # Tests config added via extra config files
+ path = os.path.join('/etc/kolla/config', path)
+ extra_section = 'extra-file-%s' % os.path.basename(path)
+ expected = {extra_section: {'bar': 'baz'}}
+ utils.test_ini_file(host, path, expected=expected)
@pytest.mark.parametrize(
'path',
@@ -104,3 +103,30 @@ def test_service_non_ini_file(host, path):
# TODO(mgoddard): Check config file contents.
path = os.path.join('/etc/kolla/config', path)
utils.test_file(host, path)
+
+@pytest.mark.parametrize(
+ 'path,regex',
+ [('fluentd/input/01-test.conf', 'grepme')])
+def test_service_non_ini_file_regex(host, path, regex):
+ path = os.path.join('/etc/kolla/config', path)
+ utils.test_regex_in_file(host, path, regex=regex)
+
+@pytest.mark.parametrize(
+ 'relative_path',
+ ['aodh/dummy.yml',
+ 'opensearch.yml',
+ 'prometheus/prometheus.yml.d/dummy.yml'])
+def test_service_extra_yml_config(host, relative_path):
+ path = os.path.join('/etc/kolla/config', relative_path)
+ utils.test_file(host, path)
+ content = yaml.safe_load(host.file(path).content_string)
+ assert content["dummy_variable"] == 123
+
+def test_service_extra_ini_config(host):
+ relative_path = "aodh/dummy.ini"
+ path = os.path.join('/etc/kolla/config', relative_path)
+ utils.test_file(host, path)
+ expected = {
+ "dummy-section": {"dummy_variable": "123"}
+ }
+ utils.test_ini_file(host, path, expected=expected)
diff --git a/ansible/roles/kolla-openstack/tasks/config.yml b/ansible/roles/kolla-openstack/tasks/config.yml
index 42f1775ea..ea999ad7b 100644
--- a/ansible/roles/kolla-openstack/tasks/config.yml
+++ b/ansible/roles/kolla-openstack/tasks/config.yml
@@ -1,48 +1,4 @@
---
-- name: Ensure the Kolla OpenStack configuration directories exist
- file:
- path: "{{ item.dest }}"
- state: directory
- mode: 0750
- with_items: "{{ kolla_openstack_custom_config }}"
- when: item.enabled | bool
-
-- name: Ensure the Kolla OpenStack configuration files exist
- template:
- src: "{{ item.src }}"
- dest: "{{ kolla_node_custom_config_path }}/{{ item.dest }}"
- mode: 0640
- with_items:
- - { src: aodh.conf.j2, dest: aodh.conf, enabled: "{{ kolla_enable_aodh }}" }
- - { src: barbican.conf.j2, dest: barbican.conf, enabled: "{{ kolla_enable_barbican }}" }
- - { src: blazar.conf.j2, dest: blazar.conf, enabled: "{{ kolla_enable_blazar }}" }
- - { src: ceilometer.conf.j2, dest: ceilometer.conf, enabled: "{{ kolla_enable_ceilometer }}" }
- - { src: cinder.conf.j2, dest: cinder.conf, enabled: "{{ kolla_enable_cinder }}" }
- - { src: cloudkitty.conf.j2, dest: cloudkitty.conf, enabled: "{{ kolla_enable_cloudkitty }}" }
- - { src: designate.conf.j2, dest: designate.conf, enabled: "{{ kolla_enable_designate }}" }
- - { src: galera.cnf.j2, dest: galera.cnf, enabled: "{{ kolla_enable_mariadb }}" }
- - { src: glance.conf.j2, dest: glance.conf, enabled: "{{ kolla_enable_glance }}" }
- - { src: global.conf.j2, dest: global.conf, enabled: true }
- - { src: gnocchi.conf.j2, dest: gnocchi.conf, enabled: "{{ kolla_enable_gnocchi }}" }
- - { src: grafana.ini.j2, dest: grafana.ini, enabled: "{{ kolla_enable_grafana }}" }
- - { src: heat.conf.j2, dest: heat.conf, enabled: "{{ kolla_enable_heat }}" }
- - { src: ironic.conf.j2, dest: ironic.conf, enabled: "{{ kolla_enable_ironic }}" }
- - { src: ironic-inspector.conf.j2, dest: ironic-inspector.conf, enabled: "{{ kolla_enable_ironic }}" }
- - { src: keystone.conf.j2, dest: keystone.conf, enabled: "{{ kolla_enable_keystone }}" }
- - { src: magnum.conf.j2, dest: magnum.conf, enabled: "{{ kolla_enable_magnum }}" }
- - { src: manila.conf.j2, dest: manila.conf, enabled: "{{ kolla_enable_manila }}" }
- - { src: backup.my.cnf.j2, dest: backup.my.cnf, enabled: "{{ kolla_enable_mariabackup }}" }
- - { src: masakari.conf.j2, dest: masakari.conf, enabled: "{{ kolla_enable_masakari }}" }
- - { src: ml2_conf.ini.j2, dest: neutron/ml2_conf.ini, enabled: "{{ kolla_enable_neutron }}" }
- - { src: multipath.conf.j2, dest: multipath.conf, enabled: "{{ kolla_enable_multipathd }}" }
- - { src: murano.conf.j2, dest: murano.conf, enabled: "{{ kolla_enable_murano }}" }
- - { src: neutron.conf.j2, dest: neutron.conf, enabled: "{{ kolla_enable_neutron }}" }
- - { src: nova.conf.j2, dest: nova.conf, enabled: "{{ kolla_enable_nova }}" }
- - { src: octavia.conf.j2, dest: octavia.conf, enabled: "{{ kolla_enable_octavia }}" }
- - { src: placement.conf.j2, dest: placement.conf, enabled: "{{ kolla_enable_placement }}" }
- - { src: sahara.conf.j2, dest: sahara.conf, enabled: "{{ kolla_enable_sahara }}" }
- when: item.enabled | bool
-
- name: Ensure ironic inspector kernel and ramdisk images are present
vars:
image_download_url: "{{ item.url }}"
@@ -67,84 +23,110 @@
loop_control:
label: "{{ item.dest }}"
+- name: Make destination directory for Nova certificates
+ file:
+ state: directory
+ path: "{{ kolla_node_custom_config_path }}/nova/nova-libvirt/"
+ when: kolla_enable_nova | bool and kolla_libvirt_tls | bool
+
+- name: Copy client TLS certificates for Nova
+ vars:
+ certificates:
+ - clientcert.pem
+ - clientkey.pem
+ - cacert.pem
+ copy:
+ src: "{{ kolla_nova_libvirt_certificates_src }}/{{ item }}"
+ dest: "{{ kolla_node_custom_config_path }}/nova/nova-libvirt/{{ item }}"
+ loop: "{{ certificates if kolla_enable_nova | bool and kolla_libvirt_tls | bool else [] }}"
+
+- name: Copy server TLS certificates for Nova
+ vars:
+ certificates:
+ - servercert.pem
+ - serverkey.pem
+ copy:
+ src: "{{ kolla_nova_libvirt_certificates_src }}/{{ item }}"
+ dest: "{{ kolla_node_custom_config_path }}/nova/nova-libvirt/{{ item }}"
+ loop: "{{ certificates if kolla_enable_nova | bool and kolla_enable_nova_libvirt_container | bool and kolla_libvirt_tls | bool else [] }}"
+
# We support a fairly flexible mechanism of dropping config file templates into
# an 'extra' config directory, and passing these through to kolla-ansible. We
# look for matching files in the source directory to template, and also remove
# any unexpected files from the destination, to support removal of files.
-- name: Find extra configuration files
- find:
- path: "{{ item.src }}"
- patterns: "{{ item.patterns }}"
- recurse: true
- with_items: "{{ kolla_openstack_custom_config }}"
- register: find_src_result
- delegate_to: localhost
+- name: Collect details about custom config
+ kolla_custom_config_info:
+ destination: "{{ kolla_node_custom_config_path }}"
+ ignore_globs: "{{ _kolla_openstack_custom_config_cleanup_ignore_globs }}"
+ include_globs: "{{ kolla_openstack_custom_config_include_globs }}"
+ rules: "{{ kolla_openstack_custom_config_rules }}"
+ search_paths: "{{ kolla_openstack_custom_config_paths | product(['/kolla/config']) | map('join') | list }}"
+ register: kolla_custom_config_info
-- name: Find previously generated extra configuration files
- find:
- path: "{{ item.dest }}"
- patterns: "{{ item.patterns }}"
- with_items: "{{ kolla_openstack_custom_config }}"
- register: find_dest_result
+- name: Print kolla_custom_config_info when using -v
+ debug:
+ msg: "{{ kolla_custom_config_info }}"
+ verbosity: 1
- name: Ensure extra configuration parent directories are present
file:
- path: "{{ item.0.item.dest }}/{{ item.1.path | relpath(item.0.item.src) | dirname }}"
+ path: "{{ item }}"
+ recurse: true
state: directory
- mode: 0750
- with_subelements:
- - "{{ find_src_result.results }}"
- - files
- - skip_missing: true
- when:
- - item.0.item.enabled | bool
- - item.1.path | basename not in item.0.item.ignore | default([])
+ with_items: "{{ kolla_custom_config_info.create_dir }}"
-- name: Ensure templated extra configuration files exist
- template:
- src: "{{ item.1.path }}"
- dest: "{{ item.0.item.dest }}/{{ item.1.path | relpath(item.0.item.src) }}"
- mode: 0640
- with_subelements:
- - "{{ find_src_result.results }}"
- - files
- - skip_missing: true
- when:
- - item.0.item.enabled | bool
- - item.1.path | basename not in item.0.item.ignore | default([])
- - item.1.path | basename not in item.0.item.untemplated | default([])
- - (item.1.path | dirname | relpath(item.0.item.src)).split("/")[0] not in item.0.item.untemplated_dirs | default([])
+- name: "Ensure extra configuration files exist (strategy: template)"
+ vars:
+ params:
+ src: "{{ item.src }}"
+ dest: "{{ item.dest }}"
+ mode: 0640
+ template: "{{ params | combine(item.params) }}"
+ with_items: "{{ kolla_custom_config_info.template }}"
-- name: Ensure untemplated extra configuration files exist
- copy:
- src: "{{ item.1.path }}"
- dest: "{{ item.0.item.dest }}/{{ item.1.path | relpath(item.0.item.src) }}"
- mode: 0640
- with_subelements:
- - "{{ find_src_result.results }}"
- - files
- - skip_missing: true
- when:
- - item.0.item.enabled | bool
- - item.1.path | basename not in item.0.item.ignore | default([])
- - (item.1.path | basename in item.0.item.untemplated | default([])) or
- ((item.1.path | dirname | relpath(item.0.item.src)).split("/")[0] in item.0.item.untemplated_dirs | default([]))
+- name: "Ensure extra configuration files exist (strategy: copy)"
+ vars:
+ params:
+ src: "{{ item.src }}"
+ dest: "{{ item.dest }}"
+ mode: 0640
+ copy: "{{ params | combine(item.params) }}"
+ # NOTE: .copy is ambiguous with copy method
+ with_items: "{{ kolla_custom_config_info['copy'] }}"
+
+- name: "Ensure extra configuration files exist (strategy: merge_configs)"
+ vars:
+ params:
+ sources: "{{ item.sources }}"
+ dest: "{{ item.dest }}"
+ mode: 0640
+ merge_configs: "{{ params | combine(item.params) }}"
+ with_items: "{{ kolla_custom_config_info.merge_configs }}"
+
+- name: "Ensure extra configuration files exist (strategy: merge_yaml)"
+ vars:
+ params:
+ sources: "{{ item.sources }}"
+ dest: "{{ item.dest }}"
+ mode: 0640
+ merge_yaml: "{{ params | combine(item.params) }}"
+ with_items: "{{ kolla_custom_config_info.merge_yaml }}"
+
+- name: "Ensure extra configuration files exist (strategy: concat)"
+ vars:
+ params:
+ content: |
+ {%- for path in item.sources -%}
+ {{ lookup('template', path) }}
+ {%- endfor -%}
+ dest: "{{ item.dest }}"
+ mode: 0640
+ copy: "{{ params | combine(item.params) }}"
+ with_items: "{{ kolla_custom_config_info.concat }}"
- name: Ensure unnecessary extra configuration files are absent
file:
- path: "{{ item.1.path }}"
+ path: "{{ item }}"
state: absent
- with_subelements:
- - "{{ find_dest_result.results }}"
- - files
- - skip_missing: true
- when:
- - not item.0.item.enabled or
- item.1.path | basename not in src_files
- - item.1.path | basename not in item.0.item.ignore | default([])
- vars:
- # Find the source result that corresponds to this one.
- src_result: "{{ (find_src_result.results | selectattr('item', 'equalto', item.0.item) | list)[0] }}"
- # Find the list of files in the source.
- src_files: "{{ src_result.files | map(attribute='path') | map('basename') | list }}"
+ with_items: "{{ kolla_custom_config_info.delete }}"
diff --git a/ansible/roles/kolla-openstack/templates/aodh.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/aodh.conf
similarity index 84%
rename from ansible/roles/kolla-openstack/templates/aodh.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/aodh.conf
index 5d7d4c1e0..50df0b62c 100644
--- a/ansible/roles/kolla-openstack/templates/aodh.conf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/aodh.conf
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
{% if kolla_extra_aodh %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/templates/backup.my.cnf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/backup.my.cnf
similarity index 85%
rename from ansible/roles/kolla-openstack/templates/backup.my.cnf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/backup.my.cnf
index 7213d824d..95d5cd004 100644
--- a/ansible/roles/kolla-openstack/templates/backup.my.cnf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/backup.my.cnf
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
{% if kolla_extra_mariabackup %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/templates/barbican.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/barbican.conf
similarity index 84%
rename from ansible/roles/kolla-openstack/templates/barbican.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/barbican.conf
index 2a33517a8..eb4138b3d 100644
--- a/ansible/roles/kolla-openstack/templates/barbican.conf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/barbican.conf
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
{% if kolla_extra_barbican %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/templates/blazar.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/blazar.conf
similarity index 84%
rename from ansible/roles/kolla-openstack/templates/blazar.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/blazar.conf
index aab01021d..f6c35e852 100644
--- a/ansible/roles/kolla-openstack/templates/blazar.conf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/blazar.conf
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
{% if kolla_extra_blazar %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/templates/ceilometer.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/ceilometer.conf
similarity index 85%
rename from ansible/roles/kolla-openstack/templates/ceilometer.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/ceilometer.conf
index 5a9187e19..474bbc564 100644
--- a/ansible/roles/kolla-openstack/templates/ceilometer.conf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/ceilometer.conf
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
{% if kolla_extra_ceilometer %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/templates/cinder.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/cinder.conf
similarity index 84%
rename from ansible/roles/kolla-openstack/templates/cinder.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/cinder.conf
index 9acf122df..5f0bc7cde 100644
--- a/ansible/roles/kolla-openstack/templates/cinder.conf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/cinder.conf
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
{% if kolla_extra_cinder %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/templates/cloudkitty.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/cloudkitty.conf
similarity index 85%
rename from ansible/roles/kolla-openstack/templates/cloudkitty.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/cloudkitty.conf
index 75929ef15..c2d5a35b8 100644
--- a/ansible/roles/kolla-openstack/templates/cloudkitty.conf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/cloudkitty.conf
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
{% if kolla_extra_cloudkitty %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/templates/designate.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/designate.conf
similarity index 85%
rename from ansible/roles/kolla-openstack/templates/designate.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/designate.conf
index 96386b077..632ecb9ff 100644
--- a/ansible/roles/kolla-openstack/templates/designate.conf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/designate.conf
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
{% if kolla_extra_designate %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/templates/galera.cnf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/galera.cnf
similarity index 84%
rename from ansible/roles/kolla-openstack/templates/galera.cnf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/galera.cnf
index 55122ebb0..49f1df7dc 100644
--- a/ansible/roles/kolla-openstack/templates/galera.cnf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/galera.cnf
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
{% if kolla_extra_mariadb %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/templates/glance.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/glance.conf
similarity index 84%
rename from ansible/roles/kolla-openstack/templates/glance.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/glance.conf
index 34692b6d3..837aef50f 100644
--- a/ansible/roles/kolla-openstack/templates/glance.conf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/glance.conf
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
{% if kolla_extra_glance %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/templates/global.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/global.conf
similarity index 84%
rename from ansible/roles/kolla-openstack/templates/global.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/global.conf
index 5b27f3623..d6be39c4b 100644
--- a/ansible/roles/kolla-openstack/templates/global.conf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/global.conf
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
{% if kolla_extra_global %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/templates/gnocchi.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/gnocchi.conf
similarity index 84%
rename from ansible/roles/kolla-openstack/templates/gnocchi.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/gnocchi.conf
index a9781dfca..a44f667eb 100644
--- a/ansible/roles/kolla-openstack/templates/gnocchi.conf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/gnocchi.conf
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
{% if kolla_extra_gnocchi %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/templates/grafana.ini.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/grafana.ini
similarity index 84%
rename from ansible/roles/kolla-openstack/templates/grafana.ini.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/grafana.ini
index d1c34be6a..efcc475a3 100644
--- a/ansible/roles/kolla-openstack/templates/grafana.ini.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/grafana.ini
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
{% if kolla_extra_grafana %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/templates/heat.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/heat.conf
similarity index 84%
rename from ansible/roles/kolla-openstack/templates/heat.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/heat.conf
index 586fcc32a..70312bf44 100644
--- a/ansible/roles/kolla-openstack/templates/heat.conf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/heat.conf
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
{% if kolla_extra_heat %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/templates/ironic-inspector.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/ironic-inspector.conf
similarity index 100%
rename from ansible/roles/kolla-openstack/templates/ironic-inspector.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/ironic-inspector.conf
diff --git a/ansible/roles/kolla-openstack/templates/ironic.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/ironic.conf
similarity index 98%
rename from ansible/roles/kolla-openstack/templates/ironic.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/ironic.conf
index cdf5e401d..49c5203e8 100644
--- a/ansible/roles/kolla-openstack/templates/ironic.conf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/ironic.conf
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
[DEFAULT]
enabled_hardware_types: {{ kolla_ironic_enabled_hardware_types | join(',') }}
diff --git a/ansible/roles/kolla-openstack/templates/keystone.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/keystone.conf
similarity index 85%
rename from ansible/roles/kolla-openstack/templates/keystone.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/keystone.conf
index 753e98bb8..47c9b31bf 100644
--- a/ansible/roles/kolla-openstack/templates/keystone.conf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/keystone.conf
@@ -1,4 +1,3 @@
-# {{ ansible_managed }}
{% if kolla_extra_keystone %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/templates/magnum.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/magnum.conf
similarity index 84%
rename from ansible/roles/kolla-openstack/templates/magnum.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/magnum.conf
index 03e40fc9e..574afcbb1 100644
--- a/ansible/roles/kolla-openstack/templates/magnum.conf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/magnum.conf
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
{% if kolla_extra_magnum %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/templates/manila.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/manila.conf
similarity index 84%
rename from ansible/roles/kolla-openstack/templates/manila.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/manila.conf
index 63faff851..fa0a7f62c 100644
--- a/ansible/roles/kolla-openstack/templates/manila.conf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/manila.conf
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
{% if kolla_extra_manila %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/templates/masakari.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/masakari.conf
similarity index 84%
rename from ansible/roles/kolla-openstack/templates/masakari.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/masakari.conf
index 5a6848c8f..3a36fc1ac 100644
--- a/ansible/roles/kolla-openstack/templates/masakari.conf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/masakari.conf
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
{% if kolla_extra_masakari %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/templates/multipath.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/multipath.conf
similarity index 100%
rename from ansible/roles/kolla-openstack/templates/multipath.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/multipath.conf
diff --git a/ansible/roles/kolla-openstack/templates/murano.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/murano.conf
similarity index 84%
rename from ansible/roles/kolla-openstack/templates/murano.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/murano.conf
index 5d6af4b97..effbc2fd2 100644
--- a/ansible/roles/kolla-openstack/templates/murano.conf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/murano.conf
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
{% if kolla_extra_murano %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/templates/neutron.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/neutron.conf
similarity index 84%
rename from ansible/roles/kolla-openstack/templates/neutron.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/neutron.conf
index 1cf183d8f..f1af1f710 100644
--- a/ansible/roles/kolla-openstack/templates/neutron.conf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/neutron.conf
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
{% if kolla_extra_neutron %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/templates/ml2_conf.ini.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/neutron/ml2_conf.ini
similarity index 98%
rename from ansible/roles/kolla-openstack/templates/ml2_conf.ini.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/neutron/ml2_conf.ini
index 1e49ae17a..b6674fd1f 100644
--- a/ansible/roles/kolla-openstack/templates/ml2_conf.ini.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/neutron/ml2_conf.ini
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
[ml2]
{% if kolla_neutron_ml2_mechanism_drivers %}
mechanism_drivers = {{ kolla_neutron_ml2_mechanism_drivers | join(',') }}
diff --git a/ansible/roles/kolla-openstack/templates/nova.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/nova.conf
similarity index 84%
rename from ansible/roles/kolla-openstack/templates/nova.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/nova.conf
index 772261a59..b70bbb3ff 100644
--- a/ansible/roles/kolla-openstack/templates/nova.conf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/nova.conf
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
{% if kolla_extra_nova %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/templates/octavia.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/octavia.conf
similarity index 84%
rename from ansible/roles/kolla-openstack/templates/octavia.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/octavia.conf
index 4210d8485..58131fef7 100644
--- a/ansible/roles/kolla-openstack/templates/octavia.conf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/octavia.conf
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
{% if kolla_extra_octavia %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/templates/placement.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/placement.conf
similarity index 85%
rename from ansible/roles/kolla-openstack/templates/placement.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/placement.conf
index 287a13d03..cdbee0070 100644
--- a/ansible/roles/kolla-openstack/templates/placement.conf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/placement.conf
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
{% if kolla_extra_placement %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/templates/sahara.conf.j2 b/ansible/roles/kolla-openstack/templates/kolla/config/sahara.conf
similarity index 84%
rename from ansible/roles/kolla-openstack/templates/sahara.conf.j2
rename to ansible/roles/kolla-openstack/templates/kolla/config/sahara.conf
index 995cfe9bb..d850f95ec 100644
--- a/ansible/roles/kolla-openstack/templates/sahara.conf.j2
+++ b/ansible/roles/kolla-openstack/templates/kolla/config/sahara.conf
@@ -1,5 +1,3 @@
-# {{ ansible_managed }}
-
{% if kolla_extra_sahara %}
#######################
# Extra configuration
diff --git a/ansible/roles/kolla-openstack/vars/main.yml b/ansible/roles/kolla-openstack/vars/main.yml
index a72a7da4b..40b892b01 100644
--- a/ansible/roles/kolla-openstack/vars/main.yml
+++ b/ansible/roles/kolla-openstack/vars/main.yml
@@ -1,222 +1,16 @@
---
-# List of custom configuration directories.
-# Each item is a dict containing the following items:
-# src: Path to directory containing configuration file templates.
-# dest: Path to directory in which generated files will be created.
-# patterns: One or more file name patterns to match.
-# enabled: Whether these files should be templated.
-# ignore: Optional list of files to ignore. These files will not be copied to
-# the destination, and will not be removed from the destination, even
-# if disabled or unexpected.
-kolla_openstack_custom_config:
- # Aodh.
- - src: "{{ kolla_extra_config_path }}/aodh"
- dest: "{{ kolla_node_custom_config_path }}/aodh"
- patterns: "*"
- enabled: "{{ kolla_enable_aodh }}"
- # Barbican.
- - src: "{{ kolla_extra_config_path }}/barbican"
- dest: "{{ kolla_node_custom_config_path }}/barbican"
- patterns: "*"
- enabled: "{{ kolla_enable_barbican }}"
- # Blazar.
- - src: "{{ kolla_extra_config_path }}/blazar"
- dest: "{{ kolla_node_custom_config_path }}/blazar"
- patterns: "*"
- enabled: "{{ kolla_enable_blazar }}"
- # Ceilometer.
- - src: "{{ kolla_extra_config_path }}/ceilometer"
- dest: "{{ kolla_node_custom_config_path }}/ceilometer"
- patterns: "*"
- enabled: "{{ kolla_enable_ceilometer }}"
- # Cinder.
- - src: "{{ kolla_extra_config_path }}/cinder"
- dest: "{{ kolla_node_custom_config_path }}/cinder"
- patterns: "*"
- enabled: "{{ kolla_enable_cinder }}"
- # CloudKitty.
- - src: "{{ kolla_extra_config_path }}/cloudkitty"
- dest: "{{ kolla_node_custom_config_path }}/cloudkitty"
- patterns: "*"
- enabled: "{{ kolla_enable_cloudkitty }}"
- # Designate.
- - src: "{{ kolla_extra_config_path }}/designate"
- dest: "{{ kolla_node_custom_config_path }}/designate"
- patterns: "*"
- enabled: "{{ kolla_enable_designate }}"
- # Fluentd filters.
- - src: "{{ kolla_extra_config_path }}//fluentd/filter"
- dest: "{{ kolla_node_custom_config_path }}/fluentd/filter"
- patterns: "*.conf"
- enabled: true
- # Fluentd inputs.
- - src: "{{ kolla_extra_config_path }}//fluentd/input"
- dest: "{{ kolla_node_custom_config_path }}/fluentd/input"
- patterns: "*.conf"
- enabled: true
- # Fluentd outputs.
- - src: "{{ kolla_extra_config_path }}/fluentd/output"
- dest: "{{ kolla_node_custom_config_path }}/fluentd/output"
- patterns: "*.conf"
- enabled: true
- # Glance.
- - src: "{{ kolla_extra_config_path }}/glance"
- dest: "{{ kolla_node_custom_config_path }}/glance"
- patterns: "*"
- enabled: "{{ kolla_enable_glance }}"
- # Gnocchi.
- - src: "{{ kolla_extra_config_path }}/gnocchi"
- dest: "{{ kolla_node_custom_config_path }}/gnocchi"
- patterns: "*"
- enabled: "{{ kolla_enable_gnocchi }}"
- # Grafana.
- - src: "{{ kolla_extra_config_path }}/grafana"
- dest: "{{ kolla_node_custom_config_path }}/grafana"
- patterns: "*"
- enabled: "{{ kolla_enable_grafana }}"
- # HAProxy.
- - src: "{{ kolla_extra_config_path }}/haproxy"
- dest: "{{ kolla_node_custom_config_path }}/haproxy"
- patterns: "*"
- enabled: "{{ kolla_enable_haproxy }}"
- - src: "{{ kolla_extra_config_path }}/haproxy-config"
- dest: "{{ kolla_node_custom_config_path }}/haproxy-config"
- patterns: "*"
- enabled: "{{ kolla_enable_haproxy }}"
- # Heat.
- - src: "{{ kolla_extra_config_path }}/heat"
- dest: "{{ kolla_node_custom_config_path }}/heat"
- patterns: "*"
- enabled: "{{ kolla_enable_heat }}"
- # Horizon.
- - src: "{{ kolla_extra_config_path }}/horizon"
- dest: "{{ kolla_node_custom_config_path }}/horizon"
- patterns: "*"
- enabled: "{{ kolla_enable_horizon }}"
- untemplated_dirs:
- # Do not attempt to template themes directory.
- - "themes"
- # InfluxDB.
- - src: "{{ kolla_extra_config_path }}/"
- dest: "{{ kolla_node_custom_config_path }}/"
- patterns: "influx*"
- enabled: "{{ kolla_enable_influxdb }}"
- # Ironic.
- - src: "{{ kolla_extra_config_path }}/ironic"
- dest: "{{ kolla_node_custom_config_path }}/ironic"
- patterns: "*"
- enabled: "{{ kolla_enable_ironic }}"
- ignore:
- # These are templated by kayobe, so don't remove them.
- - ironic-agent.initramfs
- - ironic-agent.kernel
- # Keystone.
- - src: "{{ kolla_extra_config_path }}/keystone"
- dest: "{{ kolla_node_custom_config_path }}/keystone"
- patterns: "*"
- enabled: "{{ kolla_enable_keystone }}"
- # Keepalived.
- - src: "{{ kolla_extra_config_path }}/keepalived"
- dest: "{{ kolla_node_custom_config_path }}/keepalived"
- patterns: "*"
- enabled: "{{ kolla_enable_haproxy }}"
- # Magnum.
- - src: "{{ kolla_extra_config_path }}/magnum"
- dest: "{{ kolla_node_custom_config_path }}/magnum"
- patterns: "*"
- enabled: "{{ kolla_enable_magnum }}"
- # Manila.
- - src: "{{ kolla_extra_config_path }}/manila"
- dest: "{{ kolla_node_custom_config_path }}/manila"
- patterns: "*"
- enabled: "{{ kolla_enable_manila }}"
- # MariaDB.
- - src: "{{ kolla_extra_config_path }}/mariadb"
- dest: "{{ kolla_node_custom_config_path }}/mariadb"
- patterns: "*"
- enabled: "{{ kolla_enable_mariadb }}"
- # Masakari.
- - src: "{{ kolla_extra_config_path }}/masakari"
- dest: "{{ kolla_node_custom_config_path }}/masakari"
- patterns: "*"
- enabled: "{{ kolla_enable_masakari }}"
- # Murano.
- - src: "{{ kolla_extra_config_path }}/murano"
- dest: "{{ kolla_node_custom_config_path }}/murano"
- patterns: "*"
- enabled: "{{ kolla_enable_murano }}"
- # Neutron.
- - src: "{{ kolla_extra_config_path }}/neutron"
- dest: "{{ kolla_node_custom_config_path }}/neutron"
- patterns: "*"
- enabled: "{{ kolla_enable_neutron }}"
- ignore:
- # These are templated by kayobe, so don't remove them.
- - ml2_conf.ini
- # Nova.
- - src: "{{ kolla_extra_config_path }}/nova"
- dest: "{{ kolla_node_custom_config_path }}/nova"
- patterns: "*"
- enabled: "{{ kolla_enable_nova }}"
- - src: "{{ kolla_extra_config_path }}/nova_compute"
- dest: "{{ kolla_node_custom_config_path }}/nova_compute"
- patterns: "*"
- enabled: "{{ kolla_enable_nova }}"
- - src: "{{ kolla_nova_libvirt_certificates_src }}"
- dest: "{{ kolla_node_custom_config_path }}/nova/nova-libvirt"
- patterns:
- - clientcert.pem
- - clientkey.pem
- - cacert.pem
- enabled: "{{ kolla_enable_nova | bool and kolla_libvirt_tls | bool }}"
- untemplated:
- - clientcert.pem
- - clientkey.pem
- - cacert.pem
- - src: "{{ kolla_nova_libvirt_certificates_src }}"
- dest: "{{ kolla_node_custom_config_path }}/nova/nova-libvirt"
- patterns:
- - servercert.pem
- - serverkey.pem
+
+# An internal variable used for cleaning files from the generated config
+# directory. Should not be exposed as we may wish to change the cleanup
+# mechanism to something more robust.
+_kolla_openstack_custom_config_cleanup_ignore_globs:
+ - glob: ironic/ironic-agent.initramfs
+ enabled: "{{ kolla_enable_ironic | bool }}"
+ - glob: ironic/ironic-agent.kernel
+ enabled: "{{ kolla_enable_ironic | bool }}"
+ - glob: nova/nova-libvirt/server*.pem
enabled: "{{ kolla_enable_nova | bool and kolla_enable_nova_libvirt_container | bool and kolla_libvirt_tls | bool }}"
- untemplated:
- - servercert.pem
- - serverkey.pem
- # Octavia.
- - src: "{{ kolla_extra_config_path }}/octavia"
- dest: "{{ kolla_node_custom_config_path }}/octavia"
- patterns: "*"
- enabled: "{{ kolla_enable_octavia }}"
- # OpenSearch.
- - src: "{{ kolla_extra_config_path }}/opensearch"
- dest: "{{ kolla_node_custom_config_path }}/opensearch"
- patterns: "*"
- enabled: "{{ kolla_enable_opensearch }}"
- # Placement
- - src: "{{ kolla_extra_config_path }}/placement"
- dest: "{{ kolla_node_custom_config_path }}/placement"
- patterns: "*"
- enabled: "{{ kolla_enable_placement }}"
- # Prometheus config
- - src: "{{ kolla_extra_config_path }}/prometheus"
- dest: "{{ kolla_node_custom_config_path }}/prometheus"
- patterns: "*"
- enabled: "{{ kolla_enable_prometheus }}"
- # Sahara.
- - src: "{{ kolla_extra_config_path }}/sahara"
- dest: "{{ kolla_node_custom_config_path }}/sahara"
- patterns: "*"
- enabled: "{{ kolla_enable_sahara }}"
- # Swift.
- - src: "{{ kolla_extra_config_path }}/swift"
- dest: "{{ kolla_node_custom_config_path }}/swift"
- patterns: "*"
- enabled: "{{ kolla_enable_swift }}"
- untemplated:
- # These are binary files, and should not be templated.
- - account.builder
- - account.ring.gz
- - container.builder
- - container.ring.gz
- - object.builder
- - object.ring.gz
+ - glob: nova/nova-libvirt/client*.pem
+ enabled: "{{ kolla_enable_nova | bool and kolla_libvirt_tls | bool }}"
+ - glob: nova/nova-libvirt/cacert.pem
+ enabled: "{{ kolla_enable_nova | bool and kolla_libvirt_tls | bool }}"
diff --git a/doc/source/multiple-environments.rst b/doc/source/multiple-environments.rst
index bf2097d98..86ba0e328 100644
--- a/doc/source/multiple-environments.rst
+++ b/doc/source/multiple-environments.rst
@@ -177,10 +177,8 @@ Kolla Configuration
-------------------
In the Wallaby release, Kolla configuration was independent in each
-environment.
-
-As of the Xena release, the following files support combining the
-environment-specific and shared configuration file content:
+environment. The Xena release supported combining environment-specific
+and shared configuration file content for the following subset of the files:
* ``kolla/config/bifrost/bifrost.yml``
* ``kolla/config/bifrost/dib.yml``
@@ -189,8 +187,156 @@ environment-specific and shared configuration file content:
* ``kolla/kolla-build.conf``
* ``kolla/repos.yml`` or ``kolla/repos.yaml``
-Options in the environment-specific files take precedence over those in the
-shared files.
+The Antelope release expands upon this list to add support for combining Kolla
+Ansible custom service configuration. This behaviour is configured using two
+variables:
+
+* ``kolla_openstack_custom_config_include_globs``: Specifies which files are
+ considered when templating the Kolla configuration. The Kayobe defaults
+ are set using ``kolla_openstack_custom_config_include_globs_default``.
+ An optional list of additional globs can be set using:
+ ``kolla_openstack_custom_config_include_globs_extra``. These are
+ combined with ``kolla_openstack_custom_config_include_globs_default``
+ to produce ``kolla_openstack_custom_config_include_globs``.
+ Each list entry is a dictionary with the following keys:
+
+ * ``enabled``: Boolean which determines if this rule is used. Set to
+ ``false`` to disable the rule.
+ * ``glob``: String glob matching a relative path in the ``kolla/config``
+ directory
+
+ An example of such a rule:
+
+ .. code-block:: yaml
+
+ enabled: '{{ kolla_enable_aodh | bool }}'
+ glob: aodh/**
+
+* ``kolla_openstack_custom_config_rules``: List of rules that specify the
+ strategy to use when generating a particular file. The Kayobe defaults
+ are set using ``kolla_openstack_custom_config_rules_default``.
+ An optional list of additional rules can be set using:
+ ``kolla_openstack_custom_config_rules_extra``. These are
+ combined with ``kolla_openstack_custom_config_rules_default``
+ to produce ``kolla_openstack_custom_config_rules``.
+ Each list entry is a dictionary with the format:
+
+ * ``glob``: A glob matching files for this rule to match on (relative to the
+ search path)
+ * ``priority``: The rules are processed in increasing priority order with the
+ first rule matching taking effect
+ * ``strategy``: How to process the matched file. One of ``copy``,
+ ``concat``, ``template``, ``merge_configs``, ``merge_yaml``
+ * ``params``: Optional list of additional params to pass to module enacting
+ the strategy
+
+ An example of such a rule:
+
+ .. code-block:: yaml
+
+ glob: a/path/test.yml
+ strategy: merge_yaml
+ priority: 1000
+ params:
+ extend_lists: true
+
+The Kayobe defaults fallback to using the ``template`` strategy, with a
+priority of 65535. To override this behaviour configure a rule with a lower
+priority e.g:
+
+ .. code-block:: yaml
+
+ glob: horizon/themes/**
+ strategy: copy
+ priority: 1000
+
+The default INI merging strategy can be configured using:
+``kolla_openstack_custom_config_ini_merge_strategy_default``. It defaults to ``concat``
+for backwards compatibility. An alternative strategy is ``merge_configs`` which will
+merge the two INI files so that values set in the environment take precedence over values
+set in the shared files. The caveat with the ``merge_configs`` strategy is that files
+must template to valid INI. This is mostly an issue when you use raw Jinja
+tags, for example:
+
+ .. code-block:: ini
+
+ [defaults]
+ {% raw %}
+ {% if inventory_hostname in 'compute' %}
+ foo=bar
+ {% else %}
+ foo=baz
+ {% endif %}
+ {% endraw %}
+
+After the first round of templating by Kayobe the raw tags are stripped. This leaves:
+
+ .. code-block:: ini
+
+ [defaults]
+ {% if inventory_hostname in 'compute' %}
+ foo=bar
+ {% else %}
+ foo=baz
+ {% endif %}
+
+Which isn't valid INI (due to the Jinja if blocks) and cannot be merged. In most cases
+the templating can be refactored:
+
+ .. code-block:: ini
+
+ [defaults]
+ {% raw %}
+ foo={{ 'bar' if inventory_hostname in 'compute' else 'baz' }}
+ {% endraw %}
+
+Alternatively, you can use Kolla host or group variables.
+
+Disabling the default rules
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+There are some convenience variables to disable a subset of the
+rules in ``kolla_openstack_custom_config_rules_default``:
+
+* ``kolla_openstack_custom_config_rules_default_remove``: Allows you remove
+ a rule by matching on the glob:
+
+ .. code-block:: yaml
+
+ kolla_openstack_custom_config_rules_default_remove:
+ - "**/*.ini"
+
+* ``kolla_openstack_custom_config_merge_configs_enabled``: Enables rules for
+ matching INI files. Default is ``true``.
+
+* ``kolla_openstack_custom_config_merge_yaml_enabled``: Enables rules for
+ matching YAML files. Default is ``true``.
+
+These allow you to more easily keep in sync with the upstream defaults. If
+you had an override on ``kolla_openstack_custom_config_rules``, that
+replicated most of ``kolla_openstack_custom_config_rules_default`` you'd have
+to keep this in sync with the upstream kayobe defaults.
+
+Search paths
+^^^^^^^^^^^^
+
+When merging config files the following locations are "searched" to find
+files with an identical relative path:
+
+- ``/kolla/config``
+- ``/kolla/config``
+- ``/templates/kolla/config``
+
+Not all strategies use all of the files when generating the kolla config.
+For instance, the copy strategy will use the first file found when searching
+each of the paths.
+
+There is a feature flag: ``kolla_openstack_custom_config_environment_merging_enabled``,
+that may be set to ``false`` to prevent Kayobe searching the shared files path
+when merging configs. This is to replicate the legacy behaviour where the
+environment Kolla custom service configuration was not merged with the base
+layer. We still merge the files with Kayobe's defaults in the
+``kolla-openstack`` role's internal templates.
Managing Independent Environment Files
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/etc/kayobe/kolla.yml b/etc/kayobe/kolla.yml
index 81e48c55b..19e54c809 100644
--- a/etc/kayobe/kolla.yml
+++ b/etc/kayobe/kolla.yml
@@ -447,6 +447,79 @@
#kolla_enable_watcher:
#kolla_enable_zun:
+###############################################################################
+# Kolla custom config generation.
+
+# Feature flag to add $KAYOBE_CONFIG_PATH to the list of search paths used
+# when searching for Kolla custom service configuration. Only has an effect in
+# a multiple environments setup. This allows you to configure merging between
+# your environment and the base layer. Defaults to true. Set to false to for
+# backwards compatability.
+#kolla_openstack_custom_config_environment_merging_enabled:
+
+# Default value for kolla_openstack_custom_config_include_globs.
+#kolla_openstack_custom_config_include_globs_default:
+
+# Extra items to add to kolla_openstack_custom_config_include_globs_default
+# to produce kolla_openstack_custom_config_include_globs.
+#kolla_openstack_custom_config_include_globs_extra:
+
+# List of dictionaries with the following keys:
+# glob: a glob pattern. Any files matching this pattern will be copied to the
+# the kolla custom config directory
+# enabled: boolean to disable the glob.
+# This determines the list of files to copy to the generated kolla config
+# directory.
+#kolla_openstack_custom_config_include_globs:
+
+# Kolla config generation rules. These operate on the list of files produced by
+# applying kolla_openstack_custom_config_include_globs. Each of the paths in
+# kolla_openstack_custom_config_paths is searched for files matching one of the
+# globs. If a match is found, any files with the same relative path are grouped
+# together. The rules determine what to do with these matching files e.g copy
+# the most specific file without templating, merge the files with
+# merge_configs, etc.
+# List of dictionaries with the following keys:
+# glob: A glob matching files for this rule to match on (relative to the
+# search path)
+# priority: The rules are processed in increasing priority order with the
+# first rule matching taking effect.
+# strategy: How to process the matched file. One of copy, concat, template,
+# merge_configs, merge_yaml
+# params: List of params to pass to module enacting the strategy
+# Strategies:
+# copy: Copy most specific file to kolla config without templating
+# template: Template most specific file to kolla config
+# concat: Concatenate files and copy the result to generated kolla config
+# merge_configs: Use the merge_configs module to merge an ini file, before
+# copying to the generated kolla-config.
+# merge_yaml: Use the merge_yaml module to merge a file, before copying to
+# the generated kolla-config.
+#kolla_openstack_custom_config_rules:
+
+# Whether to enable ini merging rules in
+# kolla_openstack_custom_config_rules_default. Default is true.
+#kolla_openstack_custom_config_merge_configs_enabled:
+
+# Whether to enable yaml merging rules in
+# kolla_openstack_custom_config_rules_default. Default is true.
+#kolla_openstack_custom_config_merge_yaml_enabled:
+
+# Default merge strategy for ini files in
+# kolla_openstack_custom_config_rules_default. Default is concat.
+#kolla_openstack_custom_config_ini_merge_strategy_default:
+
+# Default value for kolla_openstack_custom_config_rules.
+#kolla_openstack_custom_config_rules_default:
+
+# List of globs to filter from kolla_openstack_custom_config_rules_default.
+# Default is an empty list.
+#kolla_openstack_custom_config_rules_default_remove:
+
+# Extra items to add to kolla_openstack_custom_config_rules_default
+# to produce kolla_openstack_custom_config_rules.
+#kolla_openstack_custom_config_rules_extra:
+
###############################################################################
# Passwords and credentials.
diff --git a/kayobe/tests/molecule/utils.py b/kayobe/tests/molecule/utils.py
index 07e311b7f..fa129e93d 100644
--- a/kayobe/tests/molecule/utils.py
+++ b/kayobe/tests/molecule/utils.py
@@ -12,6 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import re
+
import configparser
from io import StringIO
@@ -53,6 +55,21 @@ def test_ini_file(host, path, owner='root', group='root', expected=None):
assert parser.get(exp_section_name, exp_key) == exp_value
+def test_regex_in_file(host, path, owner='root', group='root', regex=None):
+ """Test that a regex exists in file
+
+ Validate that the file exists, has the correct ownership, format and
+ expected contents.
+
+ :param regex to search for in file
+ """
+ test_file(host, path, owner, group)
+
+ matches = re.findall(regex, host.file(path).content_string)
+
+ assert len(matches) > 0
+
+
def test_directory(host, path, owner='root', group='root'):
"""Test an expected directory.
diff --git a/releasenotes/notes/feature-merge-kolla-configs-99773e2f0af2ea4b.yaml b/releasenotes/notes/feature-merge-kolla-configs-99773e2f0af2ea4b.yaml
new file mode 100644
index 000000000..74f5773f0
--- /dev/null
+++ b/releasenotes/notes/feature-merge-kolla-configs-99773e2f0af2ea4b.yaml
@@ -0,0 +1,52 @@
+---
+features:
+ - |
+ Adds new functionality to merge Kolla custom service configuration in a
+ Kayobe environment with Kolla configuration in the base configuration
+ layer.
+upgrade:
+ - |
+ Environment-specific Kolla custom service configuration is now merged with
+ Kolla configuration in the base configuration layer. Config options
+ duplicated in the base layer and the environment will need to be
+ de-deduplicated to avoid the config option showing up multiple times in the
+ generated output (although in general this should not be a problem).
+
+ Set ``kolla_openstack_custom_config_environment_merging_enabled`` to
+ ``false`` to revert back to the previous behavior where only the config in
+ the environment was considered.
+deprecations:
+ - |
+ Deprecates the following variables for removal in the Bobcat release:
+
+ * ``kolla_extra_global``
+ * ``kolla_extra_aodh``
+ * ``kolla_extra_barbican``
+ * ``kolla_extra_blazar``
+ * ``kolla_extra_ceilometer``
+ * ``kolla_extra_cinder``
+ * ``kolla_extra_cloudkitty``
+ * ``kolla_extra_designate``
+ * ``kolla_extra_gnocchi``
+ * ``kolla_extra_grafana``
+ * ``kolla_extra_heat``
+ * ``kolla_extra_ironic``
+ * ``kolla_extra_inspector``
+ * ``kolla_extra_keystone``
+ * ``kolla_extra_magnum``
+ * ``kolla_extra_mariabackup``
+ * ``kolla_extra_mariadb``
+ * ``kolla_extra_manila``
+ * ``kolla_extra_masakari``
+ * ``kolla_extra_murano``
+ * ``kolla_extra_neutron``
+ * ``kolla_extra_neutron_ml2``
+ * ``kolla_extra_nova``
+ * ``kolla_extra_octavia``
+ * ``kolla_extra_placement``
+ * ``kolla_extra_sahara``
+
+ Use of Kolla custom service configuration files in
+ ``etc/kayobe/kolla/config`` and
+ ``etc/kayobe/environments//kolla/config`` should be used
+ instead.
diff --git a/requirements.txt b/requirements.txt
index 752bc6d20..4ab09abd0 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -9,4 +9,5 @@ selinux # MIT
oslo.config>=5.2.0 # Apache-2.0
paramiko # LGPL
jsonschema<5 # MIT
+wcmatch>=8.2,<=9.0 # MIT
hvac>=0.10.1
diff --git a/tools/test-molecule.sh b/tools/test-molecule.sh
index 41b9f8a77..89b4a24c4 100755
--- a/tools/test-molecule.sh
+++ b/tools/test-molecule.sh
@@ -7,6 +7,12 @@ set -e
molecules="$(find ansible/roles/ -name molecule -type d)"
+PARENT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+# FIXME: doesn't get passed through to linter.
+export ANSIBLE_ACTION_PLUGINS="$PARENT/../kayobe/plugins/action:~/.ansible/plugins/action:/usr/share/ansible/plugins/action"
+export ANSIBLE_FORCE_COLOR=True
+
failed=0
ran=0
for molecule in $molecules; do