mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
saltclass: Reference classes with globs
Allow the list of classes in saltclass external pillar/master_tops to include shell-style globs.
This commit is contained in:
parent
5b708dba40
commit
3ddd6539c7
3 changed files with 113 additions and 9 deletions
|
@ -2,6 +2,7 @@
|
|||
# Import Python libs
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
import glob
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
|
@ -43,13 +44,7 @@ def get_class(_class, salt_data):
|
|||
l_files = []
|
||||
saltclass_path = salt_data["path"]
|
||||
|
||||
straight = os.path.join(saltclass_path, "classes", "{0}.yml".format(_class))
|
||||
sub_straight = os.path.join(
|
||||
saltclass_path, "classes", "{0}.yml".format(_class.replace(".", os.sep))
|
||||
)
|
||||
sub_init = os.path.join(
|
||||
saltclass_path, "classes", _class.replace(".", os.sep), "init.yml"
|
||||
)
|
||||
straight, sub_init, sub_straight = get_class_paths(_class, saltclass_path)
|
||||
|
||||
for root, dirs, files in salt.utils.path.os_walk(
|
||||
os.path.join(saltclass_path, "classes"), followlinks=True
|
||||
|
@ -70,6 +65,51 @@ def get_class(_class, salt_data):
|
|||
return {}
|
||||
|
||||
|
||||
def get_class_paths(_class, saltclass_path):
|
||||
"""
|
||||
Converts the dotted notation of a saltclass class to its possible file counterparts.
|
||||
|
||||
:param str _class: Dotted notation of the class
|
||||
:param str saltclass_path: Root to saltclass storage
|
||||
:return: 3-tuple of possible file counterparts
|
||||
:rtype: tuple(str)
|
||||
"""
|
||||
straight = os.path.join(saltclass_path, "classes", "{0}.yml".format(_class))
|
||||
sub_straight = os.path.join(
|
||||
saltclass_path, "classes", "{0}.yml".format(_class.replace(".", os.sep))
|
||||
)
|
||||
sub_init = os.path.join(
|
||||
saltclass_path, "classes", _class.replace(".", os.sep), "init.yml"
|
||||
)
|
||||
return straight, sub_init, sub_straight
|
||||
|
||||
|
||||
def get_class_from_file(_file, saltclass_path):
|
||||
"""
|
||||
Converts the absolute path to a saltclass file back to the dotted notation.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
print(get_class_from_file('/srv/saltclass/classes/services/nginx/init.yml', '/srv/saltclass'))
|
||||
# services.nginx
|
||||
|
||||
:param str _file: Absolute path to file
|
||||
:param str saltclass_path: Root to saltclass storage
|
||||
:return: class name in dotted notation
|
||||
:rtype: str
|
||||
"""
|
||||
# remove classes path prefix
|
||||
_file = _file[len(os.path.join(saltclass_path, "classes")) + len(os.sep) :]
|
||||
# remove .yml extension
|
||||
_file = _file[:-4]
|
||||
# revert to dotted notation
|
||||
_file = _file.replace(os.sep, ".")
|
||||
# remove tailing init
|
||||
if _file.endswith(".init"):
|
||||
_file = _file[:-5]
|
||||
return _file
|
||||
|
||||
|
||||
# Return environment
|
||||
def get_env_from_dict(exp_dict_list):
|
||||
environment = ""
|
||||
|
@ -189,6 +229,61 @@ def expand_variables(a, b, expanded, path=None):
|
|||
return b
|
||||
|
||||
|
||||
def match_class_glob(_class, saltclass_path):
|
||||
"""
|
||||
Takes a class name possibly including `*` or `?` wildcards (or any other wildcards supportet by `glob.glob`) and
|
||||
returns a list of expanded class names without wildcards.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
classes = match_class_glob('services.*', '/srv/saltclass')
|
||||
print(classes)
|
||||
# services.mariadb
|
||||
# services.nginx...
|
||||
|
||||
|
||||
:param str _class: dotted class name, globbing allowed.
|
||||
:param str saltclass_path: path to the saltclass root directory.
|
||||
|
||||
:return: The list of expanded class matches.
|
||||
:rtype: list(str)
|
||||
"""
|
||||
straight, sub_init, sub_straight = get_class_paths(_class, saltclass_path)
|
||||
classes = []
|
||||
matches = []
|
||||
matches.extend(glob.glob(straight))
|
||||
matches.extend(glob.glob(sub_straight))
|
||||
matches.extend(glob.glob(sub_init))
|
||||
if len(matches) == 0:
|
||||
log.warning("%s: Class globbing did not yield any results", _class)
|
||||
for match in matches:
|
||||
classes.append(get_class_from_file(match, saltclass_path))
|
||||
return classes
|
||||
|
||||
|
||||
def expand_classes_glob(classes, salt_data):
|
||||
"""
|
||||
Expand the list of `classes` to no longer include any globbing.
|
||||
|
||||
:param iterable(str) classes: Iterable of classes
|
||||
:param dict salt_data: configuration data
|
||||
:return: Expanded list of classes with resolved globbing
|
||||
:rtype: list(str)
|
||||
"""
|
||||
all_classes = []
|
||||
expanded_classes = []
|
||||
saltclass_path = salt_data["path"]
|
||||
|
||||
for _class in classes:
|
||||
all_classes.extend(match_class_glob(_class, saltclass_path))
|
||||
|
||||
for _class in all_classes:
|
||||
if _class not in expanded_classes:
|
||||
expanded_classes.append(_class)
|
||||
|
||||
return expanded_classes
|
||||
|
||||
|
||||
def expand_classes_in_order(
|
||||
minion_dict, salt_data, seen_classes, expanded_classes, classes_to_expand
|
||||
):
|
||||
|
@ -196,6 +291,8 @@ def expand_classes_in_order(
|
|||
if not classes_to_expand and "classes" in minion_dict:
|
||||
classes_to_expand = minion_dict["classes"]
|
||||
|
||||
classes_to_expand = expand_classes_glob(classes_to_expand, salt_data)
|
||||
|
||||
# Now loop on list to recursively expand them
|
||||
for klass in classes_to_expand:
|
||||
if klass not in seen_classes:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
environment: base
|
||||
|
||||
classes:
|
||||
{% for class in ['default', 'roles.app'] %}
|
||||
{% for class in ['default', 'roles.*', 'empty.*'] %}
|
||||
- {{ class }}
|
||||
{% endfor %}
|
||||
|
|
|
@ -83,5 +83,12 @@ class SaltclassPillarTestCaseListExpansion(TestCase, LoaderModuleMockMixin):
|
|||
self.assertListEqual(parsed_ret, expected_ret)
|
||||
|
||||
def test_succeeds(self):
|
||||
ret = [{"a": "192.168.10.10"}, "192.168.10.20"]
|
||||
ret = [
|
||||
"default.users",
|
||||
"default.motd",
|
||||
"default.empty",
|
||||
"default",
|
||||
"roles.app",
|
||||
"roles.nginx",
|
||||
]
|
||||
self._runner(ret)
|
||||
|
|
Loading…
Add table
Reference in a new issue