mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Don't use Salt's custom YAML loader to load static grains file
This commit is contained in:
parent
e7f1eba0fc
commit
ea6b6854d3
4 changed files with 67 additions and 4 deletions
|
@ -2,12 +2,13 @@ import glob
|
|||
import logging
|
||||
import os
|
||||
|
||||
import yaml
|
||||
|
||||
import salt.utils
|
||||
import salt.utils.data
|
||||
import salt.utils.files
|
||||
import salt.utils.path
|
||||
import salt.utils.platform
|
||||
import salt.utils.yaml
|
||||
|
||||
__proxyenabled__ = ["*"]
|
||||
log = logging.getLogger(__name__)
|
||||
|
@ -56,7 +57,7 @@ def config():
|
|||
log.debug("Loading static grains from %s", gfn)
|
||||
with salt.utils.files.fopen(gfn, "rb") as fp_:
|
||||
try:
|
||||
return salt.utils.data.decode(salt.utils.yaml.safe_load(fp_))
|
||||
return salt.utils.data.decode(yaml.safe_load(fp_))
|
||||
except Exception: # pylint: disable=broad-except
|
||||
log.warning("Bad syntax in grains file! Skipping.")
|
||||
return {}
|
||||
|
|
|
@ -17,6 +17,8 @@ import os
|
|||
from collections.abc import Mapping
|
||||
from functools import reduce # pylint: disable=redefined-builtin
|
||||
|
||||
import yaml
|
||||
|
||||
import salt.utils.compat
|
||||
import salt.utils.data
|
||||
import salt.utils.files
|
||||
|
@ -262,8 +264,9 @@ def setvals(grains, destructive=False, refresh_pillar=True):
|
|||
if os.path.isfile(gfn):
|
||||
with salt.utils.files.fopen(gfn, "rb") as fp_:
|
||||
try:
|
||||
grains = salt.utils.yaml.safe_load(fp_)
|
||||
except salt.utils.yaml.YAMLError as exc:
|
||||
# DO NOT USE salt.utils.yaml.safe_load HERE
|
||||
grains = yaml.safe_load(fp_)
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
return f"Unable to read existing grains file: {exc}"
|
||||
if not isinstance(grains, dict):
|
||||
grains = {}
|
||||
|
|
30
tests/pytests/unit/grains/test_extra.py
Normal file
30
tests/pytests/unit/grains/test_extra.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
"""
|
||||
tests.pytests.unit.grains.test_extra
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
import salt.grains.extra as extra
|
||||
import salt.utils.platform
|
||||
from tests.support.mock import MagicMock, patch
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def configure_loader_modules():
|
||||
return {extra: {}}
|
||||
|
||||
|
||||
def test_static_grains_file_conflicting_keys(tmp_path):
|
||||
"""
|
||||
Test that static grains files with conflicting keys don't result in failure
|
||||
to load all grains from that file.
|
||||
"""
|
||||
with (tmp_path / "grains").open("w") as fh:
|
||||
fh.write('foo: bar\nfoo: baz\nno_conflict_here: "yay"\n')
|
||||
|
||||
with patch.object(
|
||||
salt.utils.platform, "is_proxy", MagicMock(return_value=False)
|
||||
), patch("salt.grains.extra.__opts__", {"conf_file": str(tmp_path / "minion")}):
|
||||
static_grains = extra.config()
|
||||
assert "no_conflict_here" in static_grains
|
|
@ -2,6 +2,7 @@ import copy
|
|||
import os
|
||||
|
||||
import pytest
|
||||
import yaml
|
||||
|
||||
import salt.modules.grains as grainsmod
|
||||
import salt.utils.dictupdate as dictupdate
|
||||
|
@ -689,6 +690,34 @@ def test_setval_unicode():
|
|||
assert ret[key] == value
|
||||
|
||||
|
||||
def test_setvals_conflicting_ids(tmp_path):
|
||||
"""
|
||||
Test that conflicting top-level keys in static grains file does not break
|
||||
managing static grains
|
||||
"""
|
||||
static_grains = tmp_path / "grains"
|
||||
with static_grains.open("w") as fh:
|
||||
fh.write('foo: bar\nfoo: baz\nno_conflict_here: "yay"\n')
|
||||
|
||||
key = "hello"
|
||||
value = "world"
|
||||
|
||||
with patch.dict(grainsmod.__opts__, {"conf_file": str(tmp_path / "minion")}):
|
||||
# Update the grains file in the temp dir
|
||||
grainsmod.setvals({key: value})
|
||||
|
||||
# Load the contents of the file as text for the below asserts
|
||||
updated_grains = static_grains.read_text()
|
||||
|
||||
top_level_keys = [
|
||||
line.split()[0].rstrip(":") for line in updated_grains.splitlines()
|
||||
]
|
||||
# Confirm that the conflicting IDs were collapsed into a single value
|
||||
assert top_level_keys.count("foo") == 1
|
||||
# Confirm that the new static grain made it into the file
|
||||
assert yaml.safe_load(updated_grains)[key] == value
|
||||
|
||||
|
||||
def test_delval_single():
|
||||
with patch.dict(
|
||||
grainsmod.__grains__, {"a": "aval", "b": {"nested": "val"}, "c": 8}
|
||||
|
|
Loading…
Add table
Reference in a new issue