mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge branch '3006.x' into merge/3007.x/3006.x
This commit is contained in:
commit
1a834761bf
67 changed files with 666 additions and 300 deletions
4
changelog/58969.fixed.md
Normal file
4
changelog/58969.fixed.md
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
Issue 58969: Fixes an issue with `saltclass.expand_classes_in_order`
|
||||||
|
function where it was losing nested classes states during class
|
||||||
|
expansion. The logic now use `salt.utils.odict.OrderedDict` to keep
|
||||||
|
the inclusion ordering.
|
4
changelog/63933.fixed.md
Normal file
4
changelog/63933.fixed.md
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
Issue 63933: Fixes an issue with `saltclass.expanded_dict_from_minion`
|
||||||
|
function where it was passing a reference to minion `dict` which was
|
||||||
|
overridden by nested classes during class expansion. Copy the node
|
||||||
|
definition with `copy.deepcopy` instead of passing a reference.
|
1
changelog/66252.fixed.md
Normal file
1
changelog/66252.fixed.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Applying `selinux.fcontext_policy_present` to a shorter path than an existing entry now works
|
1
changelog/66883.fixed.md
Normal file
1
changelog/66883.fixed.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Added cryptogrpahy back to base.txt requirements as a dependency
|
1
changelog/66891.fixed.md
Normal file
1
changelog/66891.fixed.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Remove "perms" from `linux_acl.list_absent()` documentation
|
2
changelog/66959.fixed.md
Normal file
2
changelog/66959.fixed.md
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Removed the usage of wmic to get the disk and iscsi grains for Windows. The wmic
|
||||||
|
binary is being deprecated.
|
1
changelog/66996.fixed.md
Normal file
1
changelog/66996.fixed.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Ensured global dunders like __env__ are defined in state module that are run in parallel on spawning platforms
|
1
changelog/66999.fixed.md
Normal file
1
changelog/66999.fixed.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Filtered unpicklable objects from the context dict when invoking states in parallel on spawning platforms to avoid a crash
|
|
@ -10,7 +10,8 @@ requests>=2.32.3 ; python_version >= '3.10'
|
||||||
certifi==2023.07.22; python_version < '3.10'
|
certifi==2023.07.22; python_version < '3.10'
|
||||||
certifi>=2024.7.4; python_version >= '3.10'
|
certifi>=2024.7.4; python_version >= '3.10'
|
||||||
distro>=1.0.1
|
distro>=1.0.1
|
||||||
psutil>=5.0.0
|
psutil<6.0.0; python_version <= '3.9'
|
||||||
|
psutil>=5.0.0; python_version >= '3.10'
|
||||||
packaging>=21.3
|
packaging>=21.3
|
||||||
looseversion
|
looseversion
|
||||||
tornado>=6.3.3
|
tornado>=6.3.3
|
||||||
|
|
|
@ -15,3 +15,5 @@ pyfakefs
|
||||||
trustme
|
trustme
|
||||||
pytest-skip-markers >= 1.5.2 ; python_version >= '3.8'
|
pytest-skip-markers >= 1.5.2 ; python_version >= '3.8'
|
||||||
pytest-skip-markers <= 1.5.1 ; python_version < '3.8'
|
pytest-skip-markers <= 1.5.1 ; python_version < '3.8'
|
||||||
|
pytest-shell-utilities <= 1.9.0; python_version <= '3.9'
|
||||||
|
pytest-shell-utilities >= 1.9.7; python_version >= '3.10'
|
||||||
|
|
|
@ -310,7 +310,7 @@ portend==3.1.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.10/darwin.txt
|
# -c requirements/static/ci/../pkg/py3.10/darwin.txt
|
||||||
# cherrypy
|
# cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.10/darwin.txt
|
# -c requirements/static/ci/../pkg/py3.10/darwin.txt
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
@ -373,8 +373,10 @@ pytest-httpserver==1.0.8
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-salt-factories==1.0.1
|
pytest-salt-factories==1.0.1
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-shell-utilities==1.8.0
|
pytest-shell-utilities==1.9.7 ; python_version >= "3.10"
|
||||||
# via pytest-salt-factories
|
# via
|
||||||
|
# -r requirements/pytest.txt
|
||||||
|
# pytest-salt-factories
|
||||||
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
||||||
# via
|
# via
|
||||||
# -r requirements/pytest.txt
|
# -r requirements/pytest.txt
|
||||||
|
@ -534,7 +536,6 @@ typing-extensions==4.8.0
|
||||||
# napalm
|
# napalm
|
||||||
# pydantic
|
# pydantic
|
||||||
# pydantic-core
|
# pydantic-core
|
||||||
# pytest-shell-utilities
|
|
||||||
# pytest-system-statistics
|
# pytest-system-statistics
|
||||||
urllib3==1.26.18
|
urllib3==1.26.18
|
||||||
# via
|
# via
|
||||||
|
|
|
@ -314,7 +314,7 @@ portend==3.1.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.10/freebsd.txt
|
# -c requirements/static/ci/../pkg/py3.10/freebsd.txt
|
||||||
# cherrypy
|
# cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.10/freebsd.txt
|
# -c requirements/static/ci/../pkg/py3.10/freebsd.txt
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
@ -377,8 +377,10 @@ pytest-httpserver==1.0.8
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-salt-factories==1.0.1
|
pytest-salt-factories==1.0.1
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-shell-utilities==1.8.0
|
pytest-shell-utilities==1.9.7 ; python_version >= "3.10"
|
||||||
# via pytest-salt-factories
|
# via
|
||||||
|
# -r requirements/pytest.txt
|
||||||
|
# pytest-salt-factories
|
||||||
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
||||||
# via
|
# via
|
||||||
# -r requirements/pytest.txt
|
# -r requirements/pytest.txt
|
||||||
|
@ -539,7 +541,6 @@ typing-extensions==4.8.0
|
||||||
# napalm
|
# napalm
|
||||||
# pydantic
|
# pydantic
|
||||||
# pydantic-core
|
# pydantic-core
|
||||||
# pytest-shell-utilities
|
|
||||||
# pytest-system-statistics
|
# pytest-system-statistics
|
||||||
urllib3==1.26.18
|
urllib3==1.26.18
|
||||||
# via
|
# via
|
||||||
|
|
|
@ -340,7 +340,7 @@ portend==3.1.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.10/linux.txt
|
# -c requirements/static/ci/../pkg/py3.10/linux.txt
|
||||||
# cherrypy
|
# cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.10/linux.txt
|
# -c requirements/static/ci/../pkg/py3.10/linux.txt
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
@ -411,8 +411,10 @@ pytest-httpserver==1.0.8
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-salt-factories==1.0.1
|
pytest-salt-factories==1.0.1
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-shell-utilities==1.8.0
|
pytest-shell-utilities==1.9.7 ; python_version >= "3.10"
|
||||||
# via pytest-salt-factories
|
# via
|
||||||
|
# -r requirements/pytest.txt
|
||||||
|
# pytest-salt-factories
|
||||||
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
||||||
# via
|
# via
|
||||||
# -r requirements/pytest.txt
|
# -r requirements/pytest.txt
|
||||||
|
@ -603,7 +605,6 @@ typing-extensions==4.8.0
|
||||||
# napalm
|
# napalm
|
||||||
# pydantic
|
# pydantic
|
||||||
# pydantic-core
|
# pydantic-core
|
||||||
# pytest-shell-utilities
|
|
||||||
# pytest-system-statistics
|
# pytest-system-statistics
|
||||||
urllib3==1.26.18
|
urllib3==1.26.18
|
||||||
# via
|
# via
|
||||||
|
|
|
@ -272,7 +272,7 @@ portend==3.1.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.10/windows.txt
|
# -c requirements/static/ci/../pkg/py3.10/windows.txt
|
||||||
# cherrypy
|
# cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.10/windows.txt
|
# -c requirements/static/ci/../pkg/py3.10/windows.txt
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
@ -335,8 +335,10 @@ pytest-httpserver==1.0.8
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-salt-factories==1.0.1
|
pytest-salt-factories==1.0.1
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-shell-utilities==1.8.0
|
pytest-shell-utilities==1.9.7 ; python_version >= "3.10"
|
||||||
# via pytest-salt-factories
|
# via
|
||||||
|
# -r requirements/pytest.txt
|
||||||
|
# pytest-salt-factories
|
||||||
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
||||||
# via
|
# via
|
||||||
# -r requirements/pytest.txt
|
# -r requirements/pytest.txt
|
||||||
|
@ -486,7 +488,6 @@ typing-extensions==4.8.0
|
||||||
# inflect
|
# inflect
|
||||||
# pydantic
|
# pydantic
|
||||||
# pydantic-core
|
# pydantic-core
|
||||||
# pytest-shell-utilities
|
|
||||||
# pytest-system-statistics
|
# pytest-system-statistics
|
||||||
urllib3==1.26.18
|
urllib3==1.26.18
|
||||||
# via
|
# via
|
||||||
|
|
|
@ -303,7 +303,7 @@ portend==3.1.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.11/darwin.txt
|
# -c requirements/static/ci/../pkg/py3.11/darwin.txt
|
||||||
# cherrypy
|
# cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.11/darwin.txt
|
# -c requirements/static/ci/../pkg/py3.11/darwin.txt
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
@ -366,8 +366,10 @@ pytest-httpserver==1.0.8
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-salt-factories==1.0.1
|
pytest-salt-factories==1.0.1
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-shell-utilities==1.8.0
|
pytest-shell-utilities==1.9.7 ; python_version >= "3.10"
|
||||||
# via pytest-salt-factories
|
# via
|
||||||
|
# -r requirements/pytest.txt
|
||||||
|
# pytest-salt-factories
|
||||||
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
||||||
# via
|
# via
|
||||||
# -r requirements/pytest.txt
|
# -r requirements/pytest.txt
|
||||||
|
@ -525,7 +527,6 @@ typing-extensions==4.8.0
|
||||||
# napalm
|
# napalm
|
||||||
# pydantic
|
# pydantic
|
||||||
# pydantic-core
|
# pydantic-core
|
||||||
# pytest-shell-utilities
|
|
||||||
# pytest-system-statistics
|
# pytest-system-statistics
|
||||||
urllib3==1.26.18
|
urllib3==1.26.18
|
||||||
# via
|
# via
|
||||||
|
|
|
@ -307,7 +307,7 @@ portend==3.1.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.11/freebsd.txt
|
# -c requirements/static/ci/../pkg/py3.11/freebsd.txt
|
||||||
# cherrypy
|
# cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.11/freebsd.txt
|
# -c requirements/static/ci/../pkg/py3.11/freebsd.txt
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
@ -370,8 +370,10 @@ pytest-httpserver==1.0.8
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-salt-factories==1.0.1
|
pytest-salt-factories==1.0.1
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-shell-utilities==1.8.0
|
pytest-shell-utilities==1.9.7 ; python_version >= "3.10"
|
||||||
# via pytest-salt-factories
|
# via
|
||||||
|
# -r requirements/pytest.txt
|
||||||
|
# pytest-salt-factories
|
||||||
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
||||||
# via
|
# via
|
||||||
# -r requirements/pytest.txt
|
# -r requirements/pytest.txt
|
||||||
|
@ -531,7 +533,6 @@ typing-extensions==4.8.0
|
||||||
# napalm
|
# napalm
|
||||||
# pydantic
|
# pydantic
|
||||||
# pydantic-core
|
# pydantic-core
|
||||||
# pytest-shell-utilities
|
|
||||||
# pytest-system-statistics
|
# pytest-system-statistics
|
||||||
urllib3==1.26.18
|
urllib3==1.26.18
|
||||||
# via
|
# via
|
||||||
|
|
|
@ -331,7 +331,7 @@ portend==3.1.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.11/linux.txt
|
# -c requirements/static/ci/../pkg/py3.11/linux.txt
|
||||||
# cherrypy
|
# cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.11/linux.txt
|
# -c requirements/static/ci/../pkg/py3.11/linux.txt
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
@ -402,8 +402,10 @@ pytest-httpserver==1.0.8
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-salt-factories==1.0.1
|
pytest-salt-factories==1.0.1
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-shell-utilities==1.8.0
|
pytest-shell-utilities==1.9.7 ; python_version >= "3.10"
|
||||||
# via pytest-salt-factories
|
# via
|
||||||
|
# -r requirements/pytest.txt
|
||||||
|
# pytest-salt-factories
|
||||||
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
||||||
# via
|
# via
|
||||||
# -r requirements/pytest.txt
|
# -r requirements/pytest.txt
|
||||||
|
@ -593,7 +595,6 @@ typing-extensions==4.8.0
|
||||||
# napalm
|
# napalm
|
||||||
# pydantic
|
# pydantic
|
||||||
# pydantic-core
|
# pydantic-core
|
||||||
# pytest-shell-utilities
|
|
||||||
# pytest-system-statistics
|
# pytest-system-statistics
|
||||||
urllib3==1.26.18
|
urllib3==1.26.18
|
||||||
# via
|
# via
|
||||||
|
|
|
@ -265,7 +265,7 @@ portend==3.1.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.11/windows.txt
|
# -c requirements/static/ci/../pkg/py3.11/windows.txt
|
||||||
# cherrypy
|
# cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.11/windows.txt
|
# -c requirements/static/ci/../pkg/py3.11/windows.txt
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
@ -328,8 +328,10 @@ pytest-httpserver==1.0.8
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-salt-factories==1.0.1
|
pytest-salt-factories==1.0.1
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-shell-utilities==1.8.0
|
pytest-shell-utilities==1.9.7 ; python_version >= "3.10"
|
||||||
# via pytest-salt-factories
|
# via
|
||||||
|
# -r requirements/pytest.txt
|
||||||
|
# pytest-salt-factories
|
||||||
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
||||||
# via
|
# via
|
||||||
# -r requirements/pytest.txt
|
# -r requirements/pytest.txt
|
||||||
|
@ -477,7 +479,6 @@ typing-extensions==4.8.0
|
||||||
# inflect
|
# inflect
|
||||||
# pydantic
|
# pydantic
|
||||||
# pydantic-core
|
# pydantic-core
|
||||||
# pytest-shell-utilities
|
|
||||||
# pytest-system-statistics
|
# pytest-system-statistics
|
||||||
urllib3==1.26.18
|
urllib3==1.26.18
|
||||||
# via
|
# via
|
||||||
|
|
|
@ -427,7 +427,7 @@ portend==3.1.0
|
||||||
# cherrypy
|
# cherrypy
|
||||||
profitbricks==4.1.3
|
profitbricks==4.1.3
|
||||||
# via -r requirements/static/ci/cloud.in
|
# via -r requirements/static/ci/cloud.in
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.12/linux.txt
|
# -c requirements/static/ci/../pkg/py3.12/linux.txt
|
||||||
# -c requirements/static/ci/py3.12/linux.txt
|
# -c requirements/static/ci/py3.12/linux.txt
|
||||||
|
@ -525,9 +525,10 @@ pytest-salt-factories==1.0.1
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/py3.12/linux.txt
|
# -c requirements/static/ci/py3.12/linux.txt
|
||||||
# -r requirements/pytest.txt
|
# -r requirements/pytest.txt
|
||||||
pytest-shell-utilities==1.8.0
|
pytest-shell-utilities==1.9.7 ; python_version >= "3.10"
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/py3.12/linux.txt
|
# -c requirements/static/ci/py3.12/linux.txt
|
||||||
|
# -r requirements/pytest.txt
|
||||||
# pytest-salt-factories
|
# pytest-salt-factories
|
||||||
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
||||||
# via
|
# via
|
||||||
|
@ -758,7 +759,6 @@ typing-extensions==4.8.0
|
||||||
# napalm
|
# napalm
|
||||||
# pydantic
|
# pydantic
|
||||||
# pydantic-core
|
# pydantic-core
|
||||||
# pytest-shell-utilities
|
|
||||||
# pytest-system-statistics
|
# pytest-system-statistics
|
||||||
urllib3==1.26.18
|
urllib3==1.26.18
|
||||||
# via
|
# via
|
||||||
|
|
|
@ -303,7 +303,7 @@ portend==3.1.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.12/darwin.txt
|
# -c requirements/static/ci/../pkg/py3.12/darwin.txt
|
||||||
# cherrypy
|
# cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.12/darwin.txt
|
# -c requirements/static/ci/../pkg/py3.12/darwin.txt
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
@ -366,8 +366,10 @@ pytest-httpserver==1.0.8
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-salt-factories==1.0.1
|
pytest-salt-factories==1.0.1
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-shell-utilities==1.8.0
|
pytest-shell-utilities==1.9.7 ; python_version >= "3.10"
|
||||||
# via pytest-salt-factories
|
# via
|
||||||
|
# -r requirements/pytest.txt
|
||||||
|
# pytest-salt-factories
|
||||||
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
||||||
# via
|
# via
|
||||||
# -r requirements/pytest.txt
|
# -r requirements/pytest.txt
|
||||||
|
@ -525,7 +527,6 @@ typing-extensions==4.8.0
|
||||||
# napalm
|
# napalm
|
||||||
# pydantic
|
# pydantic
|
||||||
# pydantic-core
|
# pydantic-core
|
||||||
# pytest-shell-utilities
|
|
||||||
# pytest-system-statistics
|
# pytest-system-statistics
|
||||||
urllib3==1.26.18
|
urllib3==1.26.18
|
||||||
# via
|
# via
|
||||||
|
|
|
@ -168,7 +168,7 @@ portend==3.1.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/py3.12/linux.txt
|
# -c requirements/static/ci/py3.12/linux.txt
|
||||||
# cherrypy
|
# cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/py3.12/linux.txt
|
# -c requirements/static/ci/py3.12/linux.txt
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
|
|
@ -307,7 +307,7 @@ portend==3.1.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.12/freebsd.txt
|
# -c requirements/static/ci/../pkg/py3.12/freebsd.txt
|
||||||
# cherrypy
|
# cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.12/freebsd.txt
|
# -c requirements/static/ci/../pkg/py3.12/freebsd.txt
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
@ -370,8 +370,10 @@ pytest-httpserver==1.0.8
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-salt-factories==1.0.1
|
pytest-salt-factories==1.0.1
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-shell-utilities==1.8.0
|
pytest-shell-utilities==1.9.7 ; python_version >= "3.10"
|
||||||
# via pytest-salt-factories
|
# via
|
||||||
|
# -r requirements/pytest.txt
|
||||||
|
# pytest-salt-factories
|
||||||
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
||||||
# via
|
# via
|
||||||
# -r requirements/pytest.txt
|
# -r requirements/pytest.txt
|
||||||
|
@ -531,7 +533,6 @@ typing-extensions==4.8.0
|
||||||
# napalm
|
# napalm
|
||||||
# pydantic
|
# pydantic
|
||||||
# pydantic-core
|
# pydantic-core
|
||||||
# pytest-shell-utilities
|
|
||||||
# pytest-system-statistics
|
# pytest-system-statistics
|
||||||
urllib3==1.26.18
|
urllib3==1.26.18
|
||||||
# via
|
# via
|
||||||
|
|
|
@ -453,7 +453,7 @@ portend==3.1.0
|
||||||
# -c requirements/static/ci/../pkg/py3.12/linux.txt
|
# -c requirements/static/ci/../pkg/py3.12/linux.txt
|
||||||
# -c requirements/static/ci/py3.12/linux.txt
|
# -c requirements/static/ci/py3.12/linux.txt
|
||||||
# cherrypy
|
# cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.12/linux.txt
|
# -c requirements/static/ci/../pkg/py3.12/linux.txt
|
||||||
# -c requirements/static/ci/py3.12/linux.txt
|
# -c requirements/static/ci/py3.12/linux.txt
|
||||||
|
|
|
@ -331,7 +331,7 @@ portend==3.1.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.12/linux.txt
|
# -c requirements/static/ci/../pkg/py3.12/linux.txt
|
||||||
# cherrypy
|
# cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.12/linux.txt
|
# -c requirements/static/ci/../pkg/py3.12/linux.txt
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
@ -402,8 +402,10 @@ pytest-httpserver==1.0.8
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-salt-factories==1.0.1
|
pytest-salt-factories==1.0.1
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-shell-utilities==1.8.0
|
pytest-shell-utilities==1.9.7 ; python_version >= "3.10"
|
||||||
# via pytest-salt-factories
|
# via
|
||||||
|
# -r requirements/pytest.txt
|
||||||
|
# pytest-salt-factories
|
||||||
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
||||||
# via
|
# via
|
||||||
# -r requirements/pytest.txt
|
# -r requirements/pytest.txt
|
||||||
|
@ -593,7 +595,6 @@ typing-extensions==4.8.0
|
||||||
# napalm
|
# napalm
|
||||||
# pydantic
|
# pydantic
|
||||||
# pydantic-core
|
# pydantic-core
|
||||||
# pytest-shell-utilities
|
|
||||||
# pytest-system-statistics
|
# pytest-system-statistics
|
||||||
urllib3==1.26.18
|
urllib3==1.26.18
|
||||||
# via
|
# via
|
||||||
|
|
|
@ -265,7 +265,7 @@ portend==3.1.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.12/windows.txt
|
# -c requirements/static/ci/../pkg/py3.12/windows.txt
|
||||||
# cherrypy
|
# cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.12/windows.txt
|
# -c requirements/static/ci/../pkg/py3.12/windows.txt
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
@ -328,8 +328,10 @@ pytest-httpserver==1.0.8
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-salt-factories==1.0.1
|
pytest-salt-factories==1.0.1
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-shell-utilities==1.8.0
|
pytest-shell-utilities==1.9.7 ; python_version >= "3.10"
|
||||||
# via pytest-salt-factories
|
# via
|
||||||
|
# -r requirements/pytest.txt
|
||||||
|
# pytest-salt-factories
|
||||||
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
||||||
# via
|
# via
|
||||||
# -r requirements/pytest.txt
|
# -r requirements/pytest.txt
|
||||||
|
@ -477,7 +479,6 @@ typing-extensions==4.8.0
|
||||||
# inflect
|
# inflect
|
||||||
# pydantic
|
# pydantic
|
||||||
# pydantic-core
|
# pydantic-core
|
||||||
# pytest-shell-utilities
|
|
||||||
# pytest-system-statistics
|
# pytest-system-statistics
|
||||||
urllib3==1.26.18
|
urllib3==1.26.18
|
||||||
# via
|
# via
|
||||||
|
|
|
@ -318,7 +318,7 @@ portend==3.1.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.8/freebsd.txt
|
# -c requirements/static/ci/../pkg/py3.8/freebsd.txt
|
||||||
# cherrypy
|
# cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version <= "3.9"
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.8/freebsd.txt
|
# -c requirements/static/ci/../pkg/py3.8/freebsd.txt
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
@ -381,8 +381,10 @@ pytest-httpserver==1.0.8
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-salt-factories==1.0.1
|
pytest-salt-factories==1.0.1
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-shell-utilities==1.8.0
|
pytest-shell-utilities==1.8.0 ; python_version <= "3.9"
|
||||||
# via pytest-salt-factories
|
# via
|
||||||
|
# -r requirements/pytest.txt
|
||||||
|
# pytest-salt-factories
|
||||||
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
||||||
# via
|
# via
|
||||||
# -r requirements/pytest.txt
|
# -r requirements/pytest.txt
|
||||||
|
|
|
@ -337,7 +337,7 @@ portend==3.1.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.8/linux.txt
|
# -c requirements/static/ci/../pkg/py3.8/linux.txt
|
||||||
# cherrypy
|
# cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version <= "3.9"
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.8/linux.txt
|
# -c requirements/static/ci/../pkg/py3.8/linux.txt
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
@ -408,8 +408,10 @@ pytest-httpserver==1.0.8
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-salt-factories==1.0.1
|
pytest-salt-factories==1.0.1
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-shell-utilities==1.8.0
|
pytest-shell-utilities==1.8.0 ; python_version <= "3.9"
|
||||||
# via pytest-salt-factories
|
# via
|
||||||
|
# -r requirements/pytest.txt
|
||||||
|
# pytest-salt-factories
|
||||||
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
||||||
# via
|
# via
|
||||||
# -r requirements/pytest.txt
|
# -r requirements/pytest.txt
|
||||||
|
|
|
@ -276,7 +276,7 @@ portend==3.1.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.8/windows.txt
|
# -c requirements/static/ci/../pkg/py3.8/windows.txt
|
||||||
# cherrypy
|
# cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version <= "3.9"
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.8/windows.txt
|
# -c requirements/static/ci/../pkg/py3.8/windows.txt
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
@ -339,8 +339,10 @@ pytest-httpserver==1.0.8
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-salt-factories==1.0.1
|
pytest-salt-factories==1.0.1
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-shell-utilities==1.8.0
|
pytest-shell-utilities==1.8.0 ; python_version <= "3.9"
|
||||||
# via pytest-salt-factories
|
# via
|
||||||
|
# -r requirements/pytest.txt
|
||||||
|
# pytest-salt-factories
|
||||||
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
||||||
# via
|
# via
|
||||||
# -r requirements/pytest.txt
|
# -r requirements/pytest.txt
|
||||||
|
|
|
@ -310,7 +310,7 @@ portend==3.1.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
|
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
|
||||||
# cherrypy
|
# cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version <= "3.9"
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
|
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
@ -373,8 +373,10 @@ pytest-httpserver==1.0.8
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-salt-factories==1.0.1
|
pytest-salt-factories==1.0.1
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-shell-utilities==1.8.0
|
pytest-shell-utilities==1.8.0 ; python_version <= "3.9"
|
||||||
# via pytest-salt-factories
|
# via
|
||||||
|
# -r requirements/pytest.txt
|
||||||
|
# pytest-salt-factories
|
||||||
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
||||||
# via
|
# via
|
||||||
# -r requirements/pytest.txt
|
# -r requirements/pytest.txt
|
||||||
|
|
|
@ -314,7 +314,7 @@ portend==3.1.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.9/freebsd.txt
|
# -c requirements/static/ci/../pkg/py3.9/freebsd.txt
|
||||||
# cherrypy
|
# cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version <= "3.9"
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.9/freebsd.txt
|
# -c requirements/static/ci/../pkg/py3.9/freebsd.txt
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
@ -377,8 +377,10 @@ pytest-httpserver==1.0.8
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-salt-factories==1.0.1
|
pytest-salt-factories==1.0.1
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-shell-utilities==1.8.0
|
pytest-shell-utilities==1.8.0 ; python_version <= "3.9"
|
||||||
# via pytest-salt-factories
|
# via
|
||||||
|
# -r requirements/pytest.txt
|
||||||
|
# pytest-salt-factories
|
||||||
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
||||||
# via
|
# via
|
||||||
# -r requirements/pytest.txt
|
# -r requirements/pytest.txt
|
||||||
|
|
|
@ -333,7 +333,7 @@ portend==3.1.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.9/linux.txt
|
# -c requirements/static/ci/../pkg/py3.9/linux.txt
|
||||||
# cherrypy
|
# cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version <= "3.9"
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.9/linux.txt
|
# -c requirements/static/ci/../pkg/py3.9/linux.txt
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
@ -404,8 +404,10 @@ pytest-httpserver==1.0.8
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-salt-factories==1.0.1
|
pytest-salt-factories==1.0.1
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-shell-utilities==1.8.0
|
pytest-shell-utilities==1.8.0 ; python_version <= "3.9"
|
||||||
# via pytest-salt-factories
|
# via
|
||||||
|
# -r requirements/pytest.txt
|
||||||
|
# pytest-salt-factories
|
||||||
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
||||||
# via
|
# via
|
||||||
# -r requirements/pytest.txt
|
# -r requirements/pytest.txt
|
||||||
|
|
|
@ -272,7 +272,7 @@ portend==3.1.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.9/windows.txt
|
# -c requirements/static/ci/../pkg/py3.9/windows.txt
|
||||||
# cherrypy
|
# cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version <= "3.9"
|
||||||
# via
|
# via
|
||||||
# -c requirements/static/ci/../pkg/py3.9/windows.txt
|
# -c requirements/static/ci/../pkg/py3.9/windows.txt
|
||||||
# -r requirements/base.txt
|
# -r requirements/base.txt
|
||||||
|
@ -335,8 +335,10 @@ pytest-httpserver==1.0.8
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-salt-factories==1.0.1
|
pytest-salt-factories==1.0.1
|
||||||
# via -r requirements/pytest.txt
|
# via -r requirements/pytest.txt
|
||||||
pytest-shell-utilities==1.8.0
|
pytest-shell-utilities==1.8.0 ; python_version <= "3.9"
|
||||||
# via pytest-salt-factories
|
# via
|
||||||
|
# -r requirements/pytest.txt
|
||||||
|
# pytest-salt-factories
|
||||||
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
pytest-skip-markers==1.5.2 ; python_version >= "3.8"
|
||||||
# via
|
# via
|
||||||
# -r requirements/pytest.txt
|
# -r requirements/pytest.txt
|
||||||
|
|
|
@ -89,7 +89,7 @@ packaging==23.1
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
portend==3.1.0
|
portend==3.1.0
|
||||||
# via cherrypy
|
# via cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
# via cffi
|
# via cffi
|
||||||
|
|
|
@ -89,7 +89,7 @@ packaging==23.1
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
portend==3.1.0
|
portend==3.1.0
|
||||||
# via cherrypy
|
# via cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
# via cffi
|
# via cffi
|
||||||
|
|
|
@ -89,7 +89,7 @@ packaging==23.1
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
portend==3.1.0
|
portend==3.1.0
|
||||||
# via cherrypy
|
# via cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
# via cffi
|
# via cffi
|
||||||
|
|
|
@ -97,7 +97,7 @@ packaging==23.1
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
portend==3.1.0
|
portend==3.1.0
|
||||||
# via cherrypy
|
# via cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
# via cffi
|
# via cffi
|
||||||
|
|
|
@ -87,7 +87,7 @@ packaging==23.1
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
portend==3.1.0
|
portend==3.1.0
|
||||||
# via cherrypy
|
# via cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
# via cffi
|
# via cffi
|
||||||
|
|
|
@ -87,7 +87,7 @@ packaging==23.1
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
portend==3.1.0
|
portend==3.1.0
|
||||||
# via cherrypy
|
# via cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
# via cffi
|
# via cffi
|
||||||
|
|
|
@ -87,7 +87,7 @@ packaging==23.1
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
portend==3.1.0
|
portend==3.1.0
|
||||||
# via cherrypy
|
# via cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
# via cffi
|
# via cffi
|
||||||
|
|
|
@ -95,7 +95,7 @@ packaging==23.1
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
portend==3.1.0
|
portend==3.1.0
|
||||||
# via cherrypy
|
# via cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
# via cffi
|
# via cffi
|
||||||
|
|
|
@ -87,7 +87,7 @@ packaging==23.1
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
portend==3.1.0
|
portend==3.1.0
|
||||||
# via cherrypy
|
# via cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
# via cffi
|
# via cffi
|
||||||
|
|
|
@ -87,7 +87,7 @@ packaging==23.1
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
portend==3.1.0
|
portend==3.1.0
|
||||||
# via cherrypy
|
# via cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
# via cffi
|
# via cffi
|
||||||
|
|
|
@ -87,7 +87,7 @@ packaging==23.1
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
portend==3.1.0
|
portend==3.1.0
|
||||||
# via cherrypy
|
# via cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
# via cffi
|
# via cffi
|
||||||
|
|
|
@ -95,7 +95,7 @@ packaging==23.1
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
portend==3.1.0
|
portend==3.1.0
|
||||||
# via cherrypy
|
# via cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version >= "3.10"
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
# via cffi
|
# via cffi
|
||||||
|
|
|
@ -91,7 +91,7 @@ packaging==23.1
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
portend==3.1.0
|
portend==3.1.0
|
||||||
# via cherrypy
|
# via cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version <= "3.9"
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
# via cffi
|
# via cffi
|
||||||
|
|
|
@ -91,7 +91,7 @@ packaging==23.1
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
portend==3.1.0
|
portend==3.1.0
|
||||||
# via cherrypy
|
# via cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version <= "3.9"
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
# via cffi
|
# via cffi
|
||||||
|
|
|
@ -99,7 +99,7 @@ packaging==23.1
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
portend==3.1.0
|
portend==3.1.0
|
||||||
# via cherrypy
|
# via cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version <= "3.9"
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
# via cffi
|
# via cffi
|
||||||
|
|
|
@ -89,7 +89,7 @@ packaging==23.1
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
portend==3.1.0
|
portend==3.1.0
|
||||||
# via cherrypy
|
# via cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version <= "3.9"
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
# via cffi
|
# via cffi
|
||||||
|
|
|
@ -89,7 +89,7 @@ packaging==23.1
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
portend==3.1.0
|
portend==3.1.0
|
||||||
# via cherrypy
|
# via cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version <= "3.9"
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
# via cffi
|
# via cffi
|
||||||
|
|
|
@ -89,7 +89,7 @@ packaging==23.1
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
portend==3.1.0
|
portend==3.1.0
|
||||||
# via cherrypy
|
# via cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version <= "3.9"
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
# via cffi
|
# via cffi
|
||||||
|
|
|
@ -97,7 +97,7 @@ packaging==23.1
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
portend==3.1.0
|
portend==3.1.0
|
||||||
# via cherrypy
|
# via cherrypy
|
||||||
psutil==5.9.6
|
psutil==5.9.6 ; python_version <= "3.9"
|
||||||
# via -r requirements/base.txt
|
# via -r requirements/base.txt
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
# via cffi
|
# via cffi
|
||||||
|
|
|
@ -16,6 +16,7 @@ import salt.utils.platform
|
||||||
__salt__ = {
|
__salt__ = {
|
||||||
"cmd.run": salt.modules.cmdmod._run_quiet,
|
"cmd.run": salt.modules.cmdmod._run_quiet,
|
||||||
"cmd.run_all": salt.modules.cmdmod._run_all_quiet,
|
"cmd.run_all": salt.modules.cmdmod._run_all_quiet,
|
||||||
|
"cmd.powershell": salt.modules.cmdmod.powershell,
|
||||||
}
|
}
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
@ -153,41 +154,28 @@ def _linux_disks():
|
||||||
|
|
||||||
|
|
||||||
def _windows_disks():
|
def _windows_disks():
|
||||||
wmic = salt.utils.path.which("wmic")
|
|
||||||
|
|
||||||
namespace = r"\\root\microsoft\windows\storage"
|
|
||||||
path = "MSFT_PhysicalDisk"
|
|
||||||
get = "DeviceID,MediaType"
|
|
||||||
|
|
||||||
|
cmd = "Get-PhysicalDisk | Select DeviceID, MediaType"
|
||||||
ret = {"disks": [], "ssds": []}
|
ret = {"disks": [], "ssds": []}
|
||||||
|
|
||||||
cmdret = __salt__["cmd.run_all"](
|
drive_info = __salt__["cmd.powershell"](cmd)
|
||||||
"{} /namespace:{} path {} get {} /format:table".format(
|
|
||||||
wmic, namespace, path, get
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if cmdret["retcode"] != 0:
|
if not drive_info:
|
||||||
log.trace("Disk grain does not support this version of Windows")
|
log.trace("No physical discs found")
|
||||||
else:
|
return ret
|
||||||
for line in cmdret["stdout"].splitlines():
|
|
||||||
info = line.split()
|
# We need a list of dict
|
||||||
if len(info) != 2 or not info[0].isdigit() or not info[1].isdigit():
|
if isinstance(drive_info, dict):
|
||||||
continue
|
drive_info = [drive_info]
|
||||||
device = rf"\\.\PhysicalDrive{info[0]}"
|
|
||||||
mediatype = info[1]
|
for drive in drive_info:
|
||||||
if mediatype == "3":
|
# Make sure we have a valid drive type
|
||||||
log.trace("Device %s reports itself as an HDD", device)
|
if drive["MediaType"].lower() not in ["hdd", "ssd", "scm", "unspecified"]:
|
||||||
ret["disks"].append(device)
|
log.trace(f'Unknown media type: {drive["MediaType"]}')
|
||||||
elif mediatype == "4":
|
continue
|
||||||
log.trace("Device %s reports itself as an SSD", device)
|
device = rf'\\.\PhysicalDrive{drive["DeviceID"]}'
|
||||||
ret["ssds"].append(device)
|
ret["disks"].append(device)
|
||||||
ret["disks"].append(device)
|
if drive["MediaType"].lower() == "ssd":
|
||||||
elif mediatype == "5":
|
ret["ssds"].append(device)
|
||||||
log.trace("Device %s reports itself as an SCM", device)
|
|
||||||
ret["disks"].append(device)
|
|
||||||
else:
|
|
||||||
log.trace("Device %s reports itself as Unspecified", device)
|
|
||||||
ret["disks"].append(device)
|
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
|
@ -85,28 +85,25 @@ def _aix_iqn():
|
||||||
|
|
||||||
def _windows_iqn():
|
def _windows_iqn():
|
||||||
"""
|
"""
|
||||||
Return iSCSI IQN from a Windows host.
|
Return iSCSI nodes from a Windows host.
|
||||||
"""
|
"""
|
||||||
|
cmd = "Get-InitiatorPort | Select NodeAddress"
|
||||||
ret = []
|
ret = []
|
||||||
|
|
||||||
wmic = salt.utils.path.which("wmic")
|
nodes = salt.modules.cmdmod.powershell(cmd)
|
||||||
|
|
||||||
if not wmic:
|
if not nodes:
|
||||||
|
log.trace("No iSCSI nodes found")
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
namespace = r"\\root\WMI"
|
# A single node will return a dictionary with a single entry
|
||||||
path = "MSiSCSIInitiator_MethodClass"
|
# {"NodeAddress": "iqn.1991-05.com.microsoft:johnj99-pc2.contoso.com"}
|
||||||
get = "iSCSINodeName"
|
# Multiple nodes will return a list of single entry dicts
|
||||||
|
# We need a list of dict
|
||||||
|
if isinstance(nodes, dict):
|
||||||
|
nodes = [nodes]
|
||||||
|
|
||||||
cmd_ret = salt.modules.cmdmod.run_all(
|
for node in nodes:
|
||||||
"{} /namespace:{} path {} get {} /format:table".format(
|
ret.append(node["NodeAddress"])
|
||||||
wmic, namespace, path, get
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
for line in cmd_ret["stdout"].splitlines():
|
|
||||||
if line.startswith("iqn."):
|
|
||||||
line = line.rstrip()
|
|
||||||
ret.append(line.rstrip())
|
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
|
@ -266,7 +266,7 @@ def _prep_powershell_cmd(win_shell, cmd, encoded_cmd):
|
||||||
win_shell = salt.utils.path.which(win_shell)
|
win_shell = salt.utils.path.which(win_shell)
|
||||||
|
|
||||||
if not win_shell:
|
if not win_shell:
|
||||||
raise CommandExecutionError("PowerShell binary not found")
|
raise CommandExecutionError(f"PowerShell binary not found: {win_shell}")
|
||||||
|
|
||||||
new_cmd = [win_shell, "-NonInteractive", "-NoProfile", "-ExecutionPolicy", "Bypass"]
|
new_cmd = [win_shell, "-NonInteractive", "-NoProfile", "-ExecutionPolicy", "Bypass"]
|
||||||
|
|
||||||
|
|
|
@ -490,7 +490,7 @@ def fcontext_get_policy(
|
||||||
"[[:alpha:] ]+" if filetype is None else filetype_id_to_string(filetype)
|
"[[:alpha:] ]+" if filetype is None else filetype_id_to_string(filetype)
|
||||||
)
|
)
|
||||||
cmd = (
|
cmd = (
|
||||||
"semanage fcontext -l | egrep "
|
"semanage fcontext -l | grep -E "
|
||||||
+ "'^{filespec}{spacer}{filetype}{spacer}{sel_user}:{sel_role}:{sel_type}:{sel_level}{ospacer}$'".format(
|
+ "'^{filespec}{spacer}{filetype}{spacer}{sel_user}:{sel_role}:{sel_type}:{sel_level}{ospacer}$'".format(
|
||||||
**cmd_kwargs
|
**cmd_kwargs
|
||||||
)
|
)
|
||||||
|
@ -616,7 +616,7 @@ def _fcontext_add_or_delete_policy(
|
||||||
if "add" == action:
|
if "add" == action:
|
||||||
# need to use --modify if context for name file exists, otherwise ValueError
|
# need to use --modify if context for name file exists, otherwise ValueError
|
||||||
filespec = re.escape(name)
|
filespec = re.escape(name)
|
||||||
cmd = f"semanage fcontext -l | egrep '{filespec}'"
|
cmd = f"semanage fcontext -l | grep -E '{filespec} '"
|
||||||
current_entry_text = __salt__["cmd.shell"](cmd, ignore_retcode=True)
|
current_entry_text = __salt__["cmd.shell"](cmd, ignore_retcode=True)
|
||||||
if current_entry_text != "":
|
if current_entry_text != "":
|
||||||
action = "modify"
|
action = "modify"
|
||||||
|
@ -762,7 +762,7 @@ def port_get_policy(name, sel_type=None, protocol=None, port=None):
|
||||||
"port": port,
|
"port": port,
|
||||||
}
|
}
|
||||||
cmd = (
|
cmd = (
|
||||||
"semanage port -l | egrep "
|
"semanage port -l | grep -E "
|
||||||
+ "'^{sel_type}{spacer}{protocol}{spacer}((.*)*)[ ]{port}($|,)'".format(
|
+ "'^{sel_type}{spacer}{protocol}{spacer}((.*)*)[ ]{port}($|,)'".format(
|
||||||
**cmd_kwargs
|
**cmd_kwargs
|
||||||
)
|
)
|
||||||
|
|
|
@ -318,7 +318,8 @@ def _get_options(**kwargs):
|
||||||
ret.append(f"--branch={branch}")
|
ret.append(f"--branch={branch}")
|
||||||
|
|
||||||
for item in setopt:
|
for item in setopt:
|
||||||
ret.extend(["--setopt", str(item)])
|
log.info("Adding configuration option '%s'", item)
|
||||||
|
ret.extend([f"--setopt={item}"])
|
||||||
|
|
||||||
if get_extra_options:
|
if get_extra_options:
|
||||||
# sorting here to make order uniform, makes unit testing more reliable
|
# sorting here to make order uniform, makes unit testing more reliable
|
||||||
|
|
|
@ -18,6 +18,7 @@ import importlib
|
||||||
import inspect
|
import inspect
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import pickle
|
||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
import site
|
import site
|
||||||
|
@ -757,21 +758,21 @@ class State:
|
||||||
loader="states",
|
loader="states",
|
||||||
initial_pillar=None,
|
initial_pillar=None,
|
||||||
file_client=None,
|
file_client=None,
|
||||||
__invocation_id=None,
|
_invocation_id=None,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
When instantiating an object of this class, do not pass
|
When instantiating an object of this class, do not pass
|
||||||
``__invocation_id``. It is an internal field for tracking
|
``_invocation_id``. It is an internal field for tracking
|
||||||
parallel executions where no jid is available (Salt-SSH) and
|
parallel executions where no jid is available (Salt-SSH) and
|
||||||
only exposed as an init argument to work on spawning platforms.
|
only exposed as an init argument to work on spawning platforms.
|
||||||
"""
|
"""
|
||||||
if jid is not None:
|
if jid is not None:
|
||||||
__invocation_id = jid
|
_invocation_id = jid
|
||||||
if __invocation_id is None:
|
if _invocation_id is None:
|
||||||
# For salt-ssh parallel states, we need a unique identifier
|
# For salt-ssh parallel states, we need a unique identifier
|
||||||
# for a single execution. self.jid should not be set there
|
# for a single execution. self.jid should not be set there
|
||||||
# since it's used for other purposes as well.
|
# since it's used for other purposes as well.
|
||||||
__invocation_id = salt.utils.jid.gen_jid(opts)
|
_invocation_id = salt.utils.jid.gen_jid(opts)
|
||||||
self._init_kwargs = {
|
self._init_kwargs = {
|
||||||
"opts": opts,
|
"opts": opts,
|
||||||
"pillar_override": pillar_override,
|
"pillar_override": pillar_override,
|
||||||
|
@ -782,7 +783,7 @@ class State:
|
||||||
"mocked": mocked,
|
"mocked": mocked,
|
||||||
"loader": loader,
|
"loader": loader,
|
||||||
"initial_pillar": initial_pillar,
|
"initial_pillar": initial_pillar,
|
||||||
"__invocation_id": __invocation_id,
|
"_invocation_id": _invocation_id,
|
||||||
}
|
}
|
||||||
self.states_loader = loader
|
self.states_loader = loader
|
||||||
if "grains" not in opts:
|
if "grains" not in opts:
|
||||||
|
@ -829,7 +830,7 @@ class State:
|
||||||
self.pre = {}
|
self.pre = {}
|
||||||
self.__run_num = 0
|
self.__run_num = 0
|
||||||
self.jid = jid
|
self.jid = jid
|
||||||
self.invocation_id = __invocation_id
|
self.invocation_id = _invocation_id
|
||||||
self.instance_id = str(id(self))
|
self.instance_id = str(id(self))
|
||||||
self.inject_globals = {}
|
self.inject_globals = {}
|
||||||
self.mocked = mocked
|
self.mocked = mocked
|
||||||
|
@ -2157,12 +2158,15 @@ class State:
|
||||||
return req_in_high, errors
|
return req_in_high, errors
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _call_parallel_target(cls, instance, init_kwargs, name, cdata, low):
|
def _call_parallel_target(
|
||||||
|
cls, instance, init_kwargs, name, cdata, low, inject_globals
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
The target function to call that will create the parallel thread/process
|
The target function to call that will create the parallel thread/process
|
||||||
"""
|
"""
|
||||||
if instance is None:
|
if instance is None:
|
||||||
instance = cls(**init_kwargs)
|
instance = cls(**init_kwargs)
|
||||||
|
instance.states.inject_globals = inject_globals
|
||||||
# we need to re-record start/end duration here because it is impossible to
|
# we need to re-record start/end duration here because it is impossible to
|
||||||
# correctly calculate further down the chain
|
# correctly calculate further down the chain
|
||||||
utc_start_time = datetime.datetime.utcnow()
|
utc_start_time = datetime.datetime.utcnow()
|
||||||
|
@ -2267,7 +2271,7 @@ class State:
|
||||||
with salt.utils.files.fopen(tfile, "wb+") as fp_:
|
with salt.utils.files.fopen(tfile, "wb+") as fp_:
|
||||||
fp_.write(msgpack_serialize(ret))
|
fp_.write(msgpack_serialize(ret))
|
||||||
|
|
||||||
def call_parallel(self, cdata, low):
|
def call_parallel(self, cdata, low, inject_globals):
|
||||||
"""
|
"""
|
||||||
Call the state defined in the given cdata in parallel
|
Call the state defined in the given cdata in parallel
|
||||||
"""
|
"""
|
||||||
|
@ -2284,13 +2288,37 @@ class State:
|
||||||
instance = None
|
instance = None
|
||||||
else:
|
else:
|
||||||
instance = self
|
instance = self
|
||||||
|
inject_globals = None
|
||||||
|
|
||||||
proc = salt.utils.process.Process(
|
proc = salt.utils.process.Process(
|
||||||
target=self._call_parallel_target,
|
target=self._call_parallel_target,
|
||||||
args=(instance, self._init_kwargs, name, cdata, low),
|
args=(instance, self._init_kwargs, name, cdata, low, inject_globals),
|
||||||
name=f"ParallelState({name})",
|
name=f"ParallelState({name})",
|
||||||
)
|
)
|
||||||
proc.start()
|
try:
|
||||||
|
proc.start()
|
||||||
|
except TypeError as err:
|
||||||
|
# Some modules use the context to cache unpicklable objects like
|
||||||
|
# database connections or loader instances.
|
||||||
|
# Ensure we don't crash because of that on spawning platforms.
|
||||||
|
if "cannot pickle" not in str(err):
|
||||||
|
raise
|
||||||
|
clean_context = {}
|
||||||
|
for var, val in self._init_kwargs["context"].items():
|
||||||
|
try:
|
||||||
|
pickle.dumps(val)
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
clean_context[var] = val
|
||||||
|
init_kwargs = self._init_kwargs.copy()
|
||||||
|
init_kwargs["context"] = clean_context
|
||||||
|
proc = salt.utils.process.Process(
|
||||||
|
target=self._call_parallel_target,
|
||||||
|
args=(instance, init_kwargs, name, cdata, low, inject_globals),
|
||||||
|
name=f"ParallelState({name})",
|
||||||
|
)
|
||||||
|
proc.start()
|
||||||
ret = {
|
ret = {
|
||||||
"name": name,
|
"name": name,
|
||||||
"result": None,
|
"result": None,
|
||||||
|
@ -2434,7 +2462,7 @@ class State:
|
||||||
)
|
)
|
||||||
elif not low.get("__prereq__") and low.get("parallel"):
|
elif not low.get("__prereq__") and low.get("parallel"):
|
||||||
# run the state call in parallel, but only if not in a prereq
|
# run the state call in parallel, but only if not in a prereq
|
||||||
ret = self.call_parallel(cdata, low)
|
ret = self.call_parallel(cdata, low, inject_globals)
|
||||||
else:
|
else:
|
||||||
self.format_slots(cdata)
|
self.format_slots(cdata)
|
||||||
with salt.utils.files.set_umask(low.get("__umask__")):
|
with salt.utils.files.set_umask(low.get("__umask__")):
|
||||||
|
|
|
@ -708,9 +708,6 @@ def list_absent(name, acl_type, acl_names=None, recurse=False):
|
||||||
acl_names
|
acl_names
|
||||||
The list of users or groups
|
The list of users or groups
|
||||||
|
|
||||||
perms
|
|
||||||
Remove the permissions eg.: rwx
|
|
||||||
|
|
||||||
recurse
|
recurse
|
||||||
Set the permissions recursive in the path
|
Set the permissions recursive in the path
|
||||||
|
|
||||||
|
|
|
@ -203,7 +203,7 @@ def which(exe=None):
|
||||||
|
|
||||||
# now to search through our system_path
|
# now to search through our system_path
|
||||||
for path in system_path:
|
for path in system_path:
|
||||||
p = join(path, exe)
|
p = join(os.path.expandvars(path), exe)
|
||||||
|
|
||||||
# iterate through all extensions to see which one is executable
|
# iterate through all extensions to see which one is executable
|
||||||
for ext in pathext:
|
for ext in pathext:
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import copy
|
||||||
import glob
|
import glob
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
@ -5,6 +6,7 @@ import re
|
||||||
|
|
||||||
from jinja2 import Environment, FileSystemLoader
|
from jinja2 import Environment, FileSystemLoader
|
||||||
|
|
||||||
|
import salt.utils.odict
|
||||||
import salt.utils.path
|
import salt.utils.path
|
||||||
import salt.utils.yaml
|
import salt.utils.yaml
|
||||||
|
|
||||||
|
@ -277,9 +279,27 @@ def expand_classes_glob(classes, salt_data):
|
||||||
return expanded_classes
|
return expanded_classes
|
||||||
|
|
||||||
|
|
||||||
def expand_classes_in_order(
|
def expand_classes_in_order(minion_dict, salt_data, seen_classes, classes_to_expand):
|
||||||
minion_dict, salt_data, seen_classes, expanded_classes, classes_to_expand
|
"""
|
||||||
):
|
Expand the list of `classes_to_expand` and return them in the order found
|
||||||
|
|
||||||
|
The return order is `[C, B, A, M, B, L, MINION_ID]` when:
|
||||||
|
|
||||||
|
- minion node include classes `A` and `L`
|
||||||
|
- `A` include class `B`
|
||||||
|
- `B` include class `C`
|
||||||
|
- `L` include class `M` and `B`
|
||||||
|
|
||||||
|
:param dict minion_dict: definition of minion node
|
||||||
|
:param dict salt_data: configuration data
|
||||||
|
:param iterable(str) seen_classes: classes already processed
|
||||||
|
:param iterable(str) classes_to_expand: classes to recursivly expand
|
||||||
|
:return: Expanded classes in proper order
|
||||||
|
:rtype: salt.utils.odict.OrderedDict
|
||||||
|
"""
|
||||||
|
|
||||||
|
expanded_classes = salt.utils.odict.OrderedDict()
|
||||||
|
|
||||||
# Get classes to expand from minion dictionary
|
# Get classes to expand from minion dictionary
|
||||||
if not classes_to_expand and "classes" in minion_dict:
|
if not classes_to_expand and "classes" in minion_dict:
|
||||||
classes_to_expand = minion_dict["classes"]
|
classes_to_expand = minion_dict["classes"]
|
||||||
|
@ -290,71 +310,37 @@ def expand_classes_in_order(
|
||||||
for klass in classes_to_expand:
|
for klass in classes_to_expand:
|
||||||
if klass not in seen_classes:
|
if klass not in seen_classes:
|
||||||
seen_classes.append(klass)
|
seen_classes.append(klass)
|
||||||
expanded_classes[klass] = get_class(klass, salt_data)
|
klass_dict = salt.utils.odict.OrderedDict(
|
||||||
|
{klass: get_class(klass, salt_data)}
|
||||||
|
)
|
||||||
# Fix corner case where class is loaded but doesn't contain anything
|
# Fix corner case where class is loaded but doesn't contain anything
|
||||||
if expanded_classes[klass] is None:
|
if klass_dict[klass] is None:
|
||||||
expanded_classes[klass] = {}
|
klass_dict[klass] = {}
|
||||||
|
|
||||||
# Merge newly found pillars into existing ones
|
# Merge newly found pillars into existing ones
|
||||||
new_pillars = expanded_classes[klass].get("pillars", {})
|
new_pillars = klass_dict[klass].get("pillars", {})
|
||||||
if new_pillars:
|
if new_pillars:
|
||||||
dict_merge(salt_data["__pillar__"], new_pillars)
|
dict_merge(salt_data["__pillar__"], new_pillars)
|
||||||
|
|
||||||
# Now replace class element in classes_to_expand by expansion
|
if "classes" in klass_dict[klass]:
|
||||||
if expanded_classes[klass].get("classes"):
|
nested_classes = expand_classes_in_order(
|
||||||
l_id = classes_to_expand.index(klass)
|
{},
|
||||||
classes_to_expand[l_id:l_id] = expanded_classes[klass]["classes"]
|
|
||||||
expand_classes_in_order(
|
|
||||||
minion_dict,
|
|
||||||
salt_data,
|
salt_data,
|
||||||
seen_classes,
|
seen_classes,
|
||||||
expanded_classes,
|
klass_dict[klass].get("classes", {}),
|
||||||
classes_to_expand,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
expand_classes_in_order(
|
|
||||||
minion_dict,
|
|
||||||
salt_data,
|
|
||||||
seen_classes,
|
|
||||||
expanded_classes,
|
|
||||||
classes_to_expand,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# We may have duplicates here and we want to remove them
|
# Put current class after nested classes
|
||||||
tmp = []
|
klass_dict.update(nested_classes)
|
||||||
for t_element in classes_to_expand:
|
klass_dict.move_to_end(klass)
|
||||||
if t_element not in tmp:
|
|
||||||
tmp.append(t_element)
|
|
||||||
|
|
||||||
classes_to_expand = tmp
|
expanded_classes.update(klass_dict)
|
||||||
|
|
||||||
# Now that we've retrieved every class in order,
|
# Minion dict must be at the end
|
||||||
# let's return an ordered list of dicts
|
if minion_dict:
|
||||||
ord_expanded_classes = []
|
expanded_classes.update({salt_data["minion_id"]: minion_dict})
|
||||||
ord_expanded_states = []
|
|
||||||
for ord_klass in classes_to_expand:
|
|
||||||
ord_expanded_classes.append(expanded_classes[ord_klass])
|
|
||||||
# And be smart and sort out states list
|
|
||||||
# Address the corner case where states is empty in a class definition
|
|
||||||
if (
|
|
||||||
"states" in expanded_classes[ord_klass]
|
|
||||||
and expanded_classes[ord_klass]["states"] is None
|
|
||||||
):
|
|
||||||
expanded_classes[ord_klass]["states"] = {}
|
|
||||||
|
|
||||||
if "states" in expanded_classes[ord_klass]:
|
return expanded_classes
|
||||||
ord_expanded_states.extend(expanded_classes[ord_klass]["states"])
|
|
||||||
|
|
||||||
# Add our minion dict as final element but check if we have states to process
|
|
||||||
if "states" in minion_dict and minion_dict["states"] is None:
|
|
||||||
minion_dict["states"] = []
|
|
||||||
|
|
||||||
if "states" in minion_dict:
|
|
||||||
ord_expanded_states.extend(minion_dict["states"])
|
|
||||||
|
|
||||||
ord_expanded_classes.append(minion_dict)
|
|
||||||
|
|
||||||
return ord_expanded_classes, classes_to_expand, ord_expanded_states
|
|
||||||
|
|
||||||
|
|
||||||
def expanded_dict_from_minion(minion_id, salt_data):
|
def expanded_dict_from_minion(minion_id, salt_data):
|
||||||
|
@ -377,22 +363,35 @@ def expanded_dict_from_minion(minion_id, salt_data):
|
||||||
node_dict[minion_id] = {}
|
node_dict[minion_id] = {}
|
||||||
|
|
||||||
# Merge newly found pillars into existing ones
|
# Merge newly found pillars into existing ones
|
||||||
dict_merge(salt_data["__pillar__"], node_dict[minion_id].get("pillars", {}))
|
dict_merge(
|
||||||
|
salt_data["__pillar__"], copy.deepcopy(node_dict[minion_id]).get("pillars", {})
|
||||||
|
)
|
||||||
|
|
||||||
# Get 2 ordered lists:
|
# Get 2 ordered lists:
|
||||||
# expanded_classes: A list of all the dicts
|
# expanded_classes: A list of all the dicts
|
||||||
# classes_list: List of all the classes
|
# classes_list: List of all the classes
|
||||||
expanded_classes, classes_list, states_list = expand_classes_in_order(
|
expanded_classes = expand_classes_in_order(node_dict[minion_id], salt_data, [], [])
|
||||||
node_dict[minion_id], salt_data, [], {}, []
|
|
||||||
)
|
|
||||||
|
|
||||||
# Here merge the pillars together
|
# Here merge the pillars together
|
||||||
pillars_dict = {}
|
pillars_dict = {}
|
||||||
for exp_dict in expanded_classes:
|
states_list = []
|
||||||
|
classes_list = list(expanded_classes.keys())[:-1]
|
||||||
|
classes_values = list(expanded_classes.values())
|
||||||
|
for exp_dict in classes_values:
|
||||||
if "pillars" in exp_dict:
|
if "pillars" in exp_dict:
|
||||||
dict_merge(pillars_dict, exp_dict)
|
dict_merge(pillars_dict, exp_dict)
|
||||||
|
if "states" in exp_dict:
|
||||||
|
states_list.extend(exp_dict["states"])
|
||||||
|
|
||||||
return expanded_classes, pillars_dict, classes_list, states_list
|
# Avoid duplicates, keep first
|
||||||
|
state_seen = set()
|
||||||
|
states_list = [
|
||||||
|
state
|
||||||
|
for state in states_list
|
||||||
|
if not (state in state_seen or state_seen.add(state))
|
||||||
|
]
|
||||||
|
|
||||||
|
return classes_values, pillars_dict, classes_list, states_list
|
||||||
|
|
||||||
|
|
||||||
def get_pillars(minion_id, salt_data):
|
def get_pillars(minion_id, salt_data):
|
||||||
|
|
|
@ -3,6 +3,7 @@ import os
|
||||||
import textwrap
|
import textwrap
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
from textwrap import dedent
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
@ -1081,3 +1082,97 @@ def test_state_sls_mock_ret(state_tree):
|
||||||
ret["cmd_|-echo1_|-echo 'This is a test!'_|-run"]["comment"]
|
ret["cmd_|-echo1_|-echo 'This is a test!'_|-run"]["comment"]
|
||||||
== "Not called, mocked"
|
== "Not called, mocked"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def _state_requires_env(loaders, state_tree):
|
||||||
|
mod_contents = dedent(
|
||||||
|
r"""
|
||||||
|
def test_it(name):
|
||||||
|
return {
|
||||||
|
"name": name,
|
||||||
|
"result": __env__ == "base",
|
||||||
|
"comment": "",
|
||||||
|
"changes": {},
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
sls = "test_spawning"
|
||||||
|
sls_contents = dedent(
|
||||||
|
"""
|
||||||
|
This should not fail on spawning platforms:
|
||||||
|
requires_env.test_it:
|
||||||
|
- name: foo
|
||||||
|
- parallel: true
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
with pytest.helpers.temp_file(
|
||||||
|
f"{sls}.sls", sls_contents, state_tree
|
||||||
|
), pytest.helpers.temp_file("_states/requires_env.py", mod_contents, state_tree):
|
||||||
|
res = loaders.modules.saltutil.sync_states()
|
||||||
|
assert "states.requires_env" in res
|
||||||
|
yield sls
|
||||||
|
|
||||||
|
|
||||||
|
def test_state_apply_parallel_spawning_with_global_dunders(state, _state_requires_env):
|
||||||
|
"""
|
||||||
|
Ensure state modules called via `parallel: true` have access to injected
|
||||||
|
global dunders like `__env__`.
|
||||||
|
"""
|
||||||
|
ret = state.apply(_state_requires_env)
|
||||||
|
assert (
|
||||||
|
ret[
|
||||||
|
"requires_env_|-This should not fail on spawning platforms_|-foo_|-test_it"
|
||||||
|
]["result"]
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def _state_unpicklable_ctx(loaders, state_tree):
|
||||||
|
mod_contents = dedent(
|
||||||
|
r"""
|
||||||
|
import threading
|
||||||
|
|
||||||
|
class Unpicklable:
|
||||||
|
def __init__(self):
|
||||||
|
self._lock = threading.RLock()
|
||||||
|
|
||||||
|
def test_it():
|
||||||
|
__context__["booh"] = Unpicklable()
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
sls = "test_spawning_unpicklable"
|
||||||
|
sls_contents = dedent(
|
||||||
|
r"""
|
||||||
|
{%- do salt["unpicklable.test_it"]() %}
|
||||||
|
|
||||||
|
This should not fail on spawning platforms:
|
||||||
|
test.nop:
|
||||||
|
- name: foo
|
||||||
|
- parallel: true
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
with pytest.helpers.temp_file(
|
||||||
|
f"{sls}.sls", sls_contents, state_tree
|
||||||
|
), pytest.helpers.temp_file("_modules/unpicklable.py", mod_contents, state_tree):
|
||||||
|
res = loaders.modules.saltutil.sync_modules()
|
||||||
|
assert "modules.unpicklable" in res
|
||||||
|
yield sls
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skip_unless_on_spawning_platform(
|
||||||
|
reason="Pickling is only relevant on spawning platforms"
|
||||||
|
)
|
||||||
|
def test_state_apply_parallel_spawning_with_unpicklable_context(
|
||||||
|
state, _state_unpicklable_ctx
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Ensure that if the __context__ dictionary contains unpicklable objects,
|
||||||
|
they are filtered out instead of causing a crash.
|
||||||
|
"""
|
||||||
|
ret = state.apply(_state_unpicklable_ctx)
|
||||||
|
assert (
|
||||||
|
ret["test_|-This should not fail on spawning platforms_|-foo_|-nop"]["result"]
|
||||||
|
is True
|
||||||
|
)
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
:codeauthor: :email:`Shane Lee <slee@saltstack.com>`
|
:codeauthor: :email:`Shane Lee <slee@saltstack.com>`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import textwrap
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import salt.grains.disks as disks
|
import salt.grains.disks as disks
|
||||||
|
@ -17,63 +15,58 @@ def configure_loader_modules():
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def test__windows_disks():
|
def test__windows_disks_dict():
|
||||||
"""
|
"""
|
||||||
Test grains._windows_disks, normal return
|
Test grains._windows_disks with a single disk returned as a dict
|
||||||
Should return a populated dictionary
|
Should return 1 disk and no ssds
|
||||||
"""
|
"""
|
||||||
mock_which = MagicMock(return_value="C:\\Windows\\System32\\wbem\\WMIC.exe")
|
devices = {"DeviceID": 0, "MediaType": "HDD"}
|
||||||
wmic_result = textwrap.dedent(
|
mock_powershell = MagicMock(return_value=devices)
|
||||||
"""
|
|
||||||
DeviceId MediaType
|
|
||||||
0 4
|
|
||||||
1 0
|
|
||||||
2 3
|
|
||||||
3 5
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
mock_run_all = MagicMock(return_value={"stdout": wmic_result, "retcode": 0})
|
|
||||||
|
|
||||||
with patch("salt.utils.path.which", mock_which), patch.dict(
|
with patch.dict(disks.__salt__, {"cmd.powershell": mock_powershell}):
|
||||||
disks.__salt__, {"cmd.run_all": mock_run_all}
|
result = disks._windows_disks()
|
||||||
):
|
expected = {"disks": ["\\\\.\\PhysicalDrive0"], "ssds": []}
|
||||||
|
assert result == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test__windows_disks_list():
|
||||||
|
"""
|
||||||
|
test grains._windows_disks with multiple disks and types as a list of dicts
|
||||||
|
Should return 4 disks and 1 ssd
|
||||||
|
"""
|
||||||
|
devices = [
|
||||||
|
{"DeviceID": 0, "MediaType": "SSD"},
|
||||||
|
{"DeviceID": 1, "MediaType": "HDD"},
|
||||||
|
{"DeviceID": 2, "MediaType": "HDD"},
|
||||||
|
{"DeviceID": 3, "MediaType": "HDD"},
|
||||||
|
]
|
||||||
|
mock_powershell = MagicMock(return_value=devices)
|
||||||
|
|
||||||
|
with patch.dict(disks.__salt__, {"cmd.powershell": mock_powershell}):
|
||||||
result = disks._windows_disks()
|
result = disks._windows_disks()
|
||||||
expected = {
|
expected = {
|
||||||
"ssds": ["\\\\.\\PhysicalDrive0"],
|
|
||||||
"disks": [
|
"disks": [
|
||||||
"\\\\.\\PhysicalDrive0",
|
"\\\\.\\PhysicalDrive0",
|
||||||
"\\\\.\\PhysicalDrive1",
|
"\\\\.\\PhysicalDrive1",
|
||||||
"\\\\.\\PhysicalDrive2",
|
"\\\\.\\PhysicalDrive2",
|
||||||
"\\\\.\\PhysicalDrive3",
|
"\\\\.\\PhysicalDrive3",
|
||||||
],
|
],
|
||||||
|
"ssds": ["\\\\.\\PhysicalDrive0"],
|
||||||
}
|
}
|
||||||
assert result == expected
|
assert result == expected
|
||||||
cmd = " ".join(
|
|
||||||
[
|
|
||||||
"C:\\Windows\\System32\\wbem\\WMIC.exe",
|
|
||||||
"/namespace:\\\\root\\microsoft\\windows\\storage",
|
|
||||||
"path",
|
|
||||||
"MSFT_PhysicalDisk",
|
|
||||||
"get",
|
|
||||||
"DeviceID,MediaType",
|
|
||||||
"/format:table",
|
|
||||||
]
|
|
||||||
)
|
|
||||||
mock_run_all.assert_called_once_with(cmd)
|
|
||||||
|
|
||||||
|
|
||||||
def test__windows_disks_retcode():
|
def test__windows_disks_empty():
|
||||||
"""
|
"""
|
||||||
Test grains._windows_disks, retcode 1
|
Test grains._windows_disks when nothing is returned
|
||||||
Should return empty lists
|
Should return empty lists
|
||||||
"""
|
"""
|
||||||
mock_which = MagicMock(return_value="C:\\Windows\\System32\\wbem\\WMIC.exe")
|
devices = {}
|
||||||
mock_run_all = MagicMock(return_value={"stdout": "", "retcode": 1})
|
mock_powershell = MagicMock(return_value=devices)
|
||||||
with patch("salt.utils.path.which", mock_which), patch.dict(
|
|
||||||
disks.__salt__, {"cmd.run_all": mock_run_all}
|
with patch.dict(disks.__salt__, {"cmd.powershell": mock_powershell}):
|
||||||
):
|
expected = {"disks": [], "ssds": []}
|
||||||
result = disks._windows_disks()
|
result = disks._windows_disks()
|
||||||
expected = {"ssds": [], "disks": []}
|
|
||||||
assert result == expected
|
assert result == expected
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,16 +9,39 @@ import salt.grains.iscsi as iscsi
|
||||||
from tests.support.mock import MagicMock, mock_open, patch
|
from tests.support.mock import MagicMock, mock_open, patch
|
||||||
|
|
||||||
|
|
||||||
def test_windows_iscsi_iqn_grains():
|
def test_windows_iscsi_iqn_grains_empty():
|
||||||
cmd_run_mock = MagicMock(
|
nodes_dict = {}
|
||||||
return_value={"stdout": "iSCSINodeName\niqn.1991-05.com.microsoft:simon-x1\n"}
|
cmd_powershell_mock = MagicMock(return_value=nodes_dict)
|
||||||
)
|
with patch("salt.modules.cmdmod.powershell", cmd_powershell_mock):
|
||||||
_grains = {}
|
result = iscsi._windows_iqn()
|
||||||
with patch("salt.utils.path.which", MagicMock(return_value=True)):
|
expected = []
|
||||||
with patch("salt.modules.cmdmod.run_all", cmd_run_mock):
|
assert result == expected
|
||||||
_grains["iscsi_iqn"] = iscsi._windows_iqn()
|
|
||||||
|
|
||||||
assert _grains.get("iscsi_iqn") == ["iqn.1991-05.com.microsoft:simon-x1"]
|
|
||||||
|
def test_windows_iscsi_iqn_grains_single():
|
||||||
|
nodes_dict = {"NodeAddress": "iqn.1991-05.com.microsoft:simon-x1"}
|
||||||
|
cmd_powershell_mock = MagicMock(return_value=nodes_dict)
|
||||||
|
with patch("salt.modules.cmdmod.powershell", cmd_powershell_mock):
|
||||||
|
result = iscsi._windows_iqn()
|
||||||
|
expected = ["iqn.1991-05.com.microsoft:simon-x1"]
|
||||||
|
assert result == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_windows_iscsi_iqn_grains_multiple():
|
||||||
|
nodes_list = [
|
||||||
|
{"NodeAddress": "iqn.1991-05.com.microsoft:simon-x1"},
|
||||||
|
{"NodeAddress": "iqn.1991-05.com.microsoft:simon-x2"},
|
||||||
|
{"NodeAddress": "iqn.1991-05.com.microsoft:simon-x3"},
|
||||||
|
]
|
||||||
|
cmd_powershell_mock = MagicMock(return_value=nodes_list)
|
||||||
|
with patch("salt.modules.cmdmod.powershell", cmd_powershell_mock):
|
||||||
|
result = iscsi._windows_iqn()
|
||||||
|
expected = [
|
||||||
|
"iqn.1991-05.com.microsoft:simon-x1",
|
||||||
|
"iqn.1991-05.com.microsoft:simon-x2",
|
||||||
|
"iqn.1991-05.com.microsoft:simon-x3",
|
||||||
|
]
|
||||||
|
assert result == expected
|
||||||
|
|
||||||
|
|
||||||
def test_aix_iscsi_iqn_grains():
|
def test_aix_iscsi_iqn_grains():
|
||||||
|
|
|
@ -6,6 +6,8 @@ import salt.modules.selinux as selinux
|
||||||
from salt.exceptions import SaltInvocationError
|
from salt.exceptions import SaltInvocationError
|
||||||
from tests.support.mock import MagicMock, mock_open, patch
|
from tests.support.mock import MagicMock, mock_open, patch
|
||||||
|
|
||||||
|
pytestmark = [pytest.mark.skip_unless_on_linux]
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def configure_loader_modules():
|
def configure_loader_modules():
|
||||||
|
@ -399,7 +401,39 @@ def test_selinux_add_policy_regex(name, sel_type):
|
||||||
):
|
):
|
||||||
selinux.fcontext_add_policy(name, sel_type=sel_type)
|
selinux.fcontext_add_policy(name, sel_type=sel_type)
|
||||||
filespec = re.escape(name)
|
filespec = re.escape(name)
|
||||||
expected_cmd_shell = f"semanage fcontext -l | egrep '{filespec}'"
|
expected_cmd_shell = f"semanage fcontext -l | grep -E '{filespec} '"
|
||||||
|
mock_cmd_shell.assert_called_once_with(
|
||||||
|
expected_cmd_shell,
|
||||||
|
ignore_retcode=True,
|
||||||
|
)
|
||||||
|
expected_cmd_run_all = (
|
||||||
|
f"semanage fcontext --modify --type {sel_type} {filespec}"
|
||||||
|
)
|
||||||
|
mock_cmd_run_all.assert_called_once_with(
|
||||||
|
expected_cmd_run_all,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"name,sel_type",
|
||||||
|
(
|
||||||
|
("/usr/share/munin/plugins/mysql_queries", "services_munin_plugin_exec_t"),
|
||||||
|
("/usr/share/munin/plugins/mysql_", "unconfined_munin_plugin_exec_t"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def test_selinux_add_policy_shorter_path(name, sel_type):
|
||||||
|
"""
|
||||||
|
Test adding policy with a shorter path than an existing entry
|
||||||
|
"""
|
||||||
|
mock_cmd_shell = MagicMock(return_value={"retcode": 0})
|
||||||
|
mock_cmd_run_all = MagicMock(return_value={"retcode": 0})
|
||||||
|
|
||||||
|
with patch.dict(selinux.__salt__, {"cmd.shell": mock_cmd_shell}), patch.dict(
|
||||||
|
selinux.__salt__, {"cmd.run_all": mock_cmd_run_all}
|
||||||
|
):
|
||||||
|
selinux.fcontext_add_policy(name, sel_type=sel_type)
|
||||||
|
filespec = re.escape(name)
|
||||||
|
expected_cmd_shell = f"semanage fcontext -l | grep -E '{filespec} '"
|
||||||
mock_cmd_shell.assert_called_once_with(
|
mock_cmd_shell.assert_called_once_with(
|
||||||
expected_cmd_shell,
|
expected_cmd_shell,
|
||||||
ignore_retcode=True,
|
ignore_retcode=True,
|
||||||
|
|
|
@ -1428,10 +1428,8 @@ def test_install_with_options():
|
||||||
"--disablerepo=*",
|
"--disablerepo=*",
|
||||||
"--enablerepo=good",
|
"--enablerepo=good",
|
||||||
"--branch=foo",
|
"--branch=foo",
|
||||||
"--setopt",
|
"--setopt=obsoletes=0",
|
||||||
"obsoletes=0",
|
"--setopt=plugins=0",
|
||||||
"--setopt",
|
|
||||||
"plugins=0",
|
|
||||||
"install",
|
"install",
|
||||||
"foo",
|
"foo",
|
||||||
],
|
],
|
||||||
|
@ -1459,10 +1457,8 @@ def test_install_with_options():
|
||||||
"--disablerepo=bad",
|
"--disablerepo=bad",
|
||||||
"--enablerepo=good",
|
"--enablerepo=good",
|
||||||
"--branch=foo",
|
"--branch=foo",
|
||||||
"--setopt",
|
"--setopt=obsoletes=0",
|
||||||
"obsoletes=0",
|
"--setopt=plugins=0",
|
||||||
"--setopt",
|
|
||||||
"plugins=0",
|
|
||||||
"install",
|
"install",
|
||||||
"foo",
|
"foo",
|
||||||
],
|
],
|
||||||
|
@ -1857,10 +1853,8 @@ def test_upgrade_with_options():
|
||||||
"--disablerepo=*",
|
"--disablerepo=*",
|
||||||
"--enablerepo=good",
|
"--enablerepo=good",
|
||||||
"--branch=foo",
|
"--branch=foo",
|
||||||
"--setopt",
|
"--setopt=obsoletes=0",
|
||||||
"obsoletes=0",
|
"--setopt=plugins=0",
|
||||||
"--setopt",
|
|
||||||
"plugins=0",
|
|
||||||
"--exclude=kernel*",
|
"--exclude=kernel*",
|
||||||
"--nogpgcheck",
|
"--nogpgcheck",
|
||||||
"upgrade",
|
"upgrade",
|
||||||
|
@ -1902,10 +1896,8 @@ def test_upgrade_with_options():
|
||||||
"--disablerepo=bad",
|
"--disablerepo=bad",
|
||||||
"--enablerepo=good",
|
"--enablerepo=good",
|
||||||
"--branch=foo",
|
"--branch=foo",
|
||||||
"--setopt",
|
"--setopt=obsoletes=0",
|
||||||
"obsoletes=0",
|
"--setopt=plugins=0",
|
||||||
"--setopt",
|
|
||||||
"plugins=0",
|
|
||||||
"--exclude=kernel*",
|
"--exclude=kernel*",
|
||||||
"upgrade",
|
"upgrade",
|
||||||
],
|
],
|
||||||
|
@ -3051,10 +3043,8 @@ def test_pkg_update_dnf():
|
||||||
"dnf",
|
"dnf",
|
||||||
"--quiet",
|
"--quiet",
|
||||||
"-y",
|
"-y",
|
||||||
"--setopt",
|
"--setopt=plugins=0",
|
||||||
"plugins=0",
|
"--setopt=obsoletes=False",
|
||||||
"--setopt",
|
|
||||||
"obsoletes=False",
|
|
||||||
"upgrade",
|
"upgrade",
|
||||||
"foo",
|
"foo",
|
||||||
],
|
],
|
||||||
|
|
|
@ -23,6 +23,8 @@ def temp_saltclass_tree(tmp_path, minion_id):
|
||||||
nodes_dir.mkdir(parents=True, exist_ok=True)
|
nodes_dir.mkdir(parents=True, exist_ok=True)
|
||||||
default_dir = classes_dir / "default"
|
default_dir = classes_dir / "default"
|
||||||
default_dir.mkdir(parents=True, exist_ok=True)
|
default_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
users_dir = default_dir / "users"
|
||||||
|
users_dir.mkdir(parents=True, exist_ok=True)
|
||||||
roles_dir = classes_dir / "roles"
|
roles_dir = classes_dir / "roles"
|
||||||
roles_dir.mkdir(parents=True, exist_ok=True)
|
roles_dir.mkdir(parents=True, exist_ok=True)
|
||||||
nginx_subdir = roles_dir / "nginx"
|
nginx_subdir = roles_dir / "nginx"
|
||||||
|
@ -35,6 +37,9 @@ def temp_saltclass_tree(tmp_path, minion_id):
|
||||||
- default.motd
|
- default.motd
|
||||||
- default.empty
|
- default.empty
|
||||||
|
|
||||||
|
states:
|
||||||
|
- default
|
||||||
|
|
||||||
pillars:
|
pillars:
|
||||||
default:
|
default:
|
||||||
network:
|
network:
|
||||||
|
@ -50,6 +55,13 @@ def temp_saltclass_tree(tmp_path, minion_id):
|
||||||
test_list:
|
test_list:
|
||||||
- a: ${default:network:ntp:srv1}
|
- a: ${default:network:ntp:srv1}
|
||||||
- ${default:network:ntp:srv2}
|
- ${default:network:ntp:srv2}
|
||||||
|
|
||||||
|
global_scalar: from default
|
||||||
|
test_dict:
|
||||||
|
a_scalar: from default
|
||||||
|
a_list:
|
||||||
|
- element1
|
||||||
|
- element2
|
||||||
"""
|
"""
|
||||||
default_init.write_text(test_list)
|
default_init.write_text(test_list)
|
||||||
|
|
||||||
|
@ -57,24 +69,91 @@ def temp_saltclass_tree(tmp_path, minion_id):
|
||||||
nodes_text = """
|
nodes_text = """
|
||||||
environment: base
|
environment: base
|
||||||
|
|
||||||
|
states:
|
||||||
|
- minion_node
|
||||||
|
|
||||||
classes:
|
classes:
|
||||||
{% for class in ['default', 'roles.*', 'empty.*'] %}
|
{% for class in ['default', 'roles.*', 'empty.*'] %}
|
||||||
- {{ class }}
|
- {{ class }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
pillars:
|
||||||
|
global_scalar: from minion_node
|
||||||
|
test_dict:
|
||||||
|
a_scalar: from minion_node
|
||||||
"""
|
"""
|
||||||
minion_node_file.write_text(nodes_text)
|
minion_node_file.write_text(nodes_text)
|
||||||
|
|
||||||
(default_dir / "users.yml").write_text("test: this is a test")
|
(users_dir / "init.yml").write_text(
|
||||||
|
"""
|
||||||
|
classes:
|
||||||
|
- default.users.foo
|
||||||
|
|
||||||
|
states:
|
||||||
|
- users
|
||||||
|
|
||||||
|
pillars:
|
||||||
|
default:
|
||||||
|
ntp:
|
||||||
|
srv1: 192.168.20.10
|
||||||
|
|
||||||
|
global_scalar: from users
|
||||||
|
test_dict:
|
||||||
|
a_scalar: from users
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
(users_dir / "foo.yml").write_text(
|
||||||
|
"""
|
||||||
|
states:
|
||||||
|
- users.foo
|
||||||
|
|
||||||
|
global_scalar: from users.foo
|
||||||
|
users_foo_scalar: from users.foo
|
||||||
|
test_dict:
|
||||||
|
a_scalar: from users.foo
|
||||||
|
"""
|
||||||
|
)
|
||||||
(default_dir / "empty.yml").write_text("test: this is a test")
|
(default_dir / "empty.yml").write_text("test: this is a test")
|
||||||
(default_dir / "motd.yml").write_text("test: this is a test")
|
(default_dir / "motd.yml").write_text(
|
||||||
(roles_dir / "app.yml").write_text("test: this is a test")
|
"""
|
||||||
(nginx_subdir / "init.yml").write_text("test: this is a test")
|
states:
|
||||||
|
- motd
|
||||||
|
|
||||||
|
pillars:
|
||||||
|
global_scalar: from motd
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
(roles_dir / "app.yml").write_text(
|
||||||
|
"""
|
||||||
|
states:
|
||||||
|
- app
|
||||||
|
|
||||||
|
pillars:
|
||||||
|
global_scalar: from app
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
(nginx_subdir / "init.yml").write_text(
|
||||||
|
"""
|
||||||
|
states:
|
||||||
|
- nginx
|
||||||
|
|
||||||
|
pillars:
|
||||||
|
global_scalar: from nginx
|
||||||
|
nginx_scalar: from nginx
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
return dirname
|
return dirname
|
||||||
|
|
||||||
|
|
||||||
def test_succeeds(temp_saltclass_tree):
|
def test_classes_order(temp_saltclass_tree):
|
||||||
|
"""
|
||||||
|
Classes must be correctly ordered.
|
||||||
|
|
||||||
|
See: https://github.com/saltstack/salt/issues/58969
|
||||||
|
"""
|
||||||
expected_ret = [
|
expected_ret = [
|
||||||
|
"default.users.foo",
|
||||||
"default.users",
|
"default.users",
|
||||||
"default.motd",
|
"default.motd",
|
||||||
"default.empty",
|
"default.empty",
|
||||||
|
@ -110,3 +189,102 @@ def test_list_expansion_succeeds(temp_saltclass_tree):
|
||||||
pytest.fail(err)
|
pytest.fail(err)
|
||||||
# Else give the parsed content result
|
# Else give the parsed content result
|
||||||
assert expected_ret == parsed_ret
|
assert expected_ret == parsed_ret
|
||||||
|
|
||||||
|
|
||||||
|
def test_node_override_classes_scalars(temp_saltclass_tree):
|
||||||
|
"""
|
||||||
|
Scalars pillars defined in a node definition must override the
|
||||||
|
definition from classes.
|
||||||
|
"""
|
||||||
|
expected_ret = "from minion_node"
|
||||||
|
fake_args = {"path": str(temp_saltclass_tree)}
|
||||||
|
fake_pillar = {}
|
||||||
|
fake_minion_id = "fake_id"
|
||||||
|
try:
|
||||||
|
full_ret = saltclass.ext_pillar(fake_minion_id, fake_pillar, fake_args)
|
||||||
|
parsed_ret = full_ret["global_scalar"]
|
||||||
|
# Fail the test if we hit our NoneType error
|
||||||
|
except TypeError as err:
|
||||||
|
pytest.fail(err)
|
||||||
|
# Else give the parsed content result
|
||||||
|
assert expected_ret == parsed_ret
|
||||||
|
|
||||||
|
|
||||||
|
def test_node_override_classes_scalar_in_dict(temp_saltclass_tree):
|
||||||
|
"""
|
||||||
|
Scalars defined in `dict` pillars defined in a node definition must override the
|
||||||
|
same dict definition from classes.
|
||||||
|
|
||||||
|
See: https://github.com/saltstack/salt/issues/63933
|
||||||
|
"""
|
||||||
|
expected_ret = "from minion_node"
|
||||||
|
fake_args = {"path": str(temp_saltclass_tree)}
|
||||||
|
fake_pillar = {}
|
||||||
|
fake_minion_id = "fake_id"
|
||||||
|
try:
|
||||||
|
full_ret = saltclass.ext_pillar(fake_minion_id, fake_pillar, fake_args)
|
||||||
|
parsed_ret = full_ret["test_dict"]["a_scalar"]
|
||||||
|
# Fail the test if we hit our NoneType error
|
||||||
|
except TypeError as err:
|
||||||
|
pytest.fail(err)
|
||||||
|
# Else give the parsed content result
|
||||||
|
assert expected_ret == parsed_ret
|
||||||
|
|
||||||
|
|
||||||
|
def test_node_override_classes_list_in_dict(temp_saltclass_tree):
|
||||||
|
"""
|
||||||
|
`list` under a `dict` defined in a node definition must override the
|
||||||
|
same definition from classes.
|
||||||
|
|
||||||
|
See: https://github.com/saltstack/salt/issues/63933
|
||||||
|
"""
|
||||||
|
expected_ret = {"srv1": "192.168.10.10", "srv2": "192.168.10.20"}
|
||||||
|
fake_args = {"path": str(temp_saltclass_tree)}
|
||||||
|
fake_pillar = {}
|
||||||
|
fake_minion_id = "fake_id"
|
||||||
|
try:
|
||||||
|
full_ret = saltclass.ext_pillar(fake_minion_id, fake_pillar, fake_args)
|
||||||
|
parsed_ret = full_ret["default"]["network"]["ntp"]
|
||||||
|
# Fail the test if we hit our NoneType error
|
||||||
|
except TypeError as err:
|
||||||
|
pytest.fail(err)
|
||||||
|
# Else give the parsed content result
|
||||||
|
assert expected_ret == parsed_ret
|
||||||
|
|
||||||
|
|
||||||
|
def test_list_in_dict_no_duplication(temp_saltclass_tree):
|
||||||
|
"""
|
||||||
|
`list` under a `dict` in pillar must not be duplicated.
|
||||||
|
|
||||||
|
See:
|
||||||
|
"""
|
||||||
|
expected_ret = ["element1", "element2"]
|
||||||
|
fake_args = {"path": str(temp_saltclass_tree)}
|
||||||
|
fake_pillar = {}
|
||||||
|
fake_minion_id = "fake_id"
|
||||||
|
try:
|
||||||
|
full_ret = saltclass.ext_pillar(fake_minion_id, fake_pillar, fake_args)
|
||||||
|
parsed_ret = full_ret["test_dict"]["a_list"]
|
||||||
|
# Fail the test if we hit our NoneType error
|
||||||
|
except TypeError as err:
|
||||||
|
pytest.fail(err)
|
||||||
|
# Else give the parsed content result
|
||||||
|
assert expected_ret == parsed_ret
|
||||||
|
|
||||||
|
|
||||||
|
def test_nested_classes_has_pillars(temp_saltclass_tree):
|
||||||
|
"""
|
||||||
|
pillars defined in nested classes are present
|
||||||
|
"""
|
||||||
|
expected_ret = "from nginx"
|
||||||
|
fake_args = {"path": str(temp_saltclass_tree)}
|
||||||
|
fake_pillar = {}
|
||||||
|
fake_minion_id = "fake_id"
|
||||||
|
try:
|
||||||
|
full_ret = saltclass.ext_pillar(fake_minion_id, fake_pillar, fake_args)
|
||||||
|
parsed_ret = full_ret["nginx_scalar"]
|
||||||
|
# Fail the test if we hit our NoneType error
|
||||||
|
except TypeError as err:
|
||||||
|
pytest.fail(err)
|
||||||
|
# Else give the parsed content result
|
||||||
|
assert expected_ret == parsed_ret
|
||||||
|
|
|
@ -345,7 +345,6 @@ MISSING_DOCSTRINGS = {
|
||||||
"get_pillars",
|
"get_pillars",
|
||||||
"expand_variables",
|
"expand_variables",
|
||||||
"render_jinja",
|
"render_jinja",
|
||||||
"expand_classes_in_order",
|
|
||||||
"dict_search_and_replace",
|
"dict_search_and_replace",
|
||||||
"expanded_dict_from_minion",
|
"expanded_dict_from_minion",
|
||||||
"find_value_to_expand",
|
"find_value_to_expand",
|
||||||
|
|
Loading…
Add table
Reference in a new issue