mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge pull request #64931 from s0undt3ch/hotfix/merge-forward
[master] Merge 3006.x into master
This commit is contained in:
commit
c2d2522f1f
88 changed files with 1591 additions and 998 deletions
1
changelog/63824.fixed.md
Normal file
1
changelog/63824.fixed.md
Normal file
|
@ -0,0 +1 @@
|
|||
Allow long running pillar and file client requests to finish using request_channel_timeout and request_channel_tries minion config.
|
1
changelog/64372.changed.md
Normal file
1
changelog/64372.changed.md
Normal file
|
@ -0,0 +1 @@
|
|||
Replace libnacl with PyNaCl
|
|
@ -1,3 +1,10 @@
|
|||
Upgrade to `cryptography==41.0.1`(and therefor `pyopenssl==23.2.0` due to https://github.com/advisories/GHSA-5cpq-8wj7-hf2v
|
||||
Upgrade to `cryptography==41.0.3`(and therefor `pyopenssl==23.2.0` due to https://github.com/advisories/GHSA-jm77-qphf-c4w8)
|
||||
|
||||
This only really impacts pip installs of Salt and the windows onedir since the linux and macos onedir build every package dependency from source, not from pre-existing wheels.
|
||||
|
||||
Also resolves the following cryptography advisories:
|
||||
|
||||
Due to:
|
||||
* https://github.com/advisories/GHSA-5cpq-8wj7-hf2v
|
||||
* https://github.com/advisories/GHSA-x4qr-2fvf-3mr5
|
||||
* https://github.com/advisories/GHSA-w7pp-m8wf-vj6r
|
||||
|
|
|
@ -1 +1 @@
|
|||
Added support for Chocolatey 2.0.0+
|
||||
Added support for Chocolatey 2.0.0+ while maintaining support for older versions
|
||||
|
|
1
changelog/64651.fixed.md
Normal file
1
changelog/64651.fixed.md
Normal file
|
@ -0,0 +1 @@
|
|||
Show user friendly message when pillars timeout
|
1
changelog/64653.fixed.md
Normal file
1
changelog/64653.fixed.md
Normal file
|
@ -0,0 +1 @@
|
|||
File client timeouts durring jobs show user friendly errors instead of tracbacks
|
1
changelog/64729.fixed.md
Normal file
1
changelog/64729.fixed.md
Normal file
|
@ -0,0 +1 @@
|
|||
SaltClientError does not log a traceback on minions, we expect these to happen so a user friendly log is shown.
|
|
@ -1305,6 +1305,36 @@ restart.
|
|||
|
||||
auth_safemode: False
|
||||
|
||||
.. conf_minion:: request_channel_timeout
|
||||
|
||||
``request_channel_timeout``
|
||||
---------------------------
|
||||
|
||||
.. versionadded:: 3006.2
|
||||
|
||||
Default: ``30``
|
||||
|
||||
The default timeout timeout for request channel requests. This setting can be used to tune minions to better handle long running pillar and file client requests.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
request_channel_timeout: 30
|
||||
|
||||
``request_channel_tries``
|
||||
-------------------------
|
||||
|
||||
.. versionadded:: 3006.2
|
||||
|
||||
Default: ``3``
|
||||
|
||||
The default number of times the minion will try request channel requests. This
|
||||
setting can be used to tune minions to better handle long running pillar and
|
||||
file client requests by retrying them after a timeout happens.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
request_channel_tries: 3
|
||||
|
||||
.. conf_minion:: ping_interval
|
||||
|
||||
``ping_interval``
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
pycryptodomex>=3.9.8
|
||||
cryptography>=40.0.2
|
||||
cryptography>=40.0.3
|
||||
|
|
|
@ -6,7 +6,7 @@ apache-libcloud>=2.4.0
|
|||
backports.ssl_match_hostname>=3.7.0.1; python_version < '3.7'
|
||||
cherrypy>=17.4.1
|
||||
gitpython>=3.1.30
|
||||
cryptography>=41.0.2
|
||||
cryptography>=41.0.3
|
||||
idna>=2.8
|
||||
linode-python>=1.1.1
|
||||
pyasn1>=0.4.8
|
||||
|
|
|
@ -9,7 +9,7 @@ boto3>=1.21.46
|
|||
boto>=2.46.0
|
||||
cassandra-driver>=2.0
|
||||
certifi>=2022.12.07
|
||||
cffi>=1.12.2
|
||||
cffi>=1.14.6
|
||||
cherrypy>=17.4.1
|
||||
clustershell
|
||||
croniter>=0.3.0,!=0.3.22"; sys_platform != 'win32'
|
||||
|
@ -32,6 +32,7 @@ paramiko>=2.10.1; sys_platform != 'win32' and sys_platform != 'darwin'
|
|||
# since that will break using the compiled static requirements files as contraints file
|
||||
bcrypt
|
||||
passlib>=1.7.4
|
||||
pynacl>=1.5.0
|
||||
pyinotify>=0.9.6; sys_platform != 'win32' and sys_platform != 'darwin' and platform_system != "openbsd"
|
||||
python-etcd>0.4.2
|
||||
pyvmomi
|
||||
|
|
|
@ -2,5 +2,5 @@
|
|||
--constraint=./py{py_version}/{platform}.txt
|
||||
|
||||
pylint==2.4.4
|
||||
SaltPyLint>=v2020.9.28
|
||||
SaltPyLint>=2023.3.8
|
||||
toml
|
||||
|
|
|
@ -16,11 +16,11 @@ cffi==1.15.1
|
|||
# via
|
||||
# -c requirements/static/ci/py3.10/linux.txt
|
||||
# cryptography
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via
|
||||
# -c requirements/static/ci/py3.10/linux.txt
|
||||
# requests
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -c requirements/static/ci/py3.10/linux.txt
|
||||
# pyspnego
|
||||
|
|
|
@ -67,7 +67,7 @@ cffi==1.15.1
|
|||
# napalm
|
||||
# pygit2
|
||||
# pynacl
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/darwin.txt
|
||||
# aiohttp
|
||||
|
@ -93,7 +93,7 @@ contextvars==2.4
|
|||
# -r requirements/base.txt
|
||||
croniter==1.3.15 ; sys_platform != "win32"
|
||||
# via -r requirements/static/ci/common.in
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/darwin.txt
|
||||
# -r requirements/crypto.txt
|
||||
|
@ -335,7 +335,9 @@ pyeapi==1.0.0
|
|||
pygit2==1.12.1
|
||||
# via -r requirements/static/ci/darwin.in
|
||||
pynacl==1.5.0
|
||||
# via paramiko
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# paramiko
|
||||
pyopenssl==23.2.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/darwin.txt
|
||||
|
|
|
@ -16,7 +16,7 @@ certifi==2023.07.22
|
|||
# via
|
||||
# -c requirements/static/ci/py3.10/linux.txt
|
||||
# requests
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via
|
||||
# -c requirements/static/ci/py3.10/linux.txt
|
||||
# requests
|
||||
|
|
|
@ -63,7 +63,7 @@ cffi==1.15.1
|
|||
# cryptography
|
||||
# napalm
|
||||
# pynacl
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/freebsd.txt
|
||||
# aiohttp
|
||||
|
@ -89,10 +89,11 @@ contextvars==2.4
|
|||
# -r requirements/base.txt
|
||||
croniter==1.3.15 ; sys_platform != "win32"
|
||||
# via -r requirements/static/ci/common.in
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/freebsd.txt
|
||||
# -r requirements/crypto.txt
|
||||
# -r requirements/static/pkg/freebsd.in
|
||||
# etcd3-py
|
||||
# moto
|
||||
# paramiko
|
||||
|
@ -329,7 +330,9 @@ pyeapi==1.0.0
|
|||
pyinotify==0.9.6 ; sys_platform != "win32" and sys_platform != "darwin" and platform_system != "openbsd"
|
||||
# via -r requirements/static/ci/common.in
|
||||
pynacl==1.5.0
|
||||
# via paramiko
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# paramiko
|
||||
pyopenssl==23.2.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/freebsd.txt
|
||||
|
|
|
@ -20,7 +20,7 @@ pylint==2.4.4
|
|||
# via
|
||||
# -r requirements/static/ci/lint.in
|
||||
# saltpylint
|
||||
saltpylint==2020.9.28
|
||||
saltpylint==2023.8.3
|
||||
# via -r requirements/static/ci/lint.in
|
||||
six==1.16.0
|
||||
# via
|
||||
|
|
|
@ -77,7 +77,7 @@ cffi==1.15.1
|
|||
# napalm
|
||||
# pygit2
|
||||
# pynacl
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/linux.txt
|
||||
# aiohttp
|
||||
|
@ -103,7 +103,7 @@ contextvars==2.4
|
|||
# -r requirements/base.txt
|
||||
croniter==1.3.15 ; sys_platform != "win32"
|
||||
# via -r requirements/static/ci/common.in
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/linux.txt
|
||||
# -r requirements/crypto.txt
|
||||
|
@ -363,7 +363,9 @@ pyjwt==2.7.0
|
|||
pymysql==1.0.3
|
||||
# via -r requirements/static/ci/linux.in
|
||||
pynacl==1.5.0
|
||||
# via paramiko
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# paramiko
|
||||
pyopenssl==23.2.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/linux.txt
|
||||
|
|
|
@ -30,7 +30,7 @@ colorama==0.4.6
|
|||
# via pytest
|
||||
contextvars==2.4
|
||||
# via -r requirements/base.txt
|
||||
cryptography==41.0.1
|
||||
cryptography==41.0.3
|
||||
# via -r requirements/crypto.txt
|
||||
distlib==0.3.6
|
||||
# via virtualenv
|
||||
|
|
|
@ -24,7 +24,7 @@ cherrypy==18.8.0
|
|||
# via -r requirements/static/ci/pkgtests.in
|
||||
contextvars==2.4
|
||||
# via -r requirements/base.txt
|
||||
cryptography==41.0.1
|
||||
cryptography==41.0.3
|
||||
# via -r requirements/crypto.txt
|
||||
distlib==0.3.6
|
||||
# via virtualenv
|
||||
|
|
|
@ -55,7 +55,8 @@ cffi==1.14.6
|
|||
# clr-loader
|
||||
# cryptography
|
||||
# pygit2
|
||||
charset-normalizer==2.1.1
|
||||
# pynacl
|
||||
charset-normalizer==3.1.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/windows.txt
|
||||
# aiohttp
|
||||
|
@ -87,7 +88,7 @@ contextvars==2.4
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/windows.txt
|
||||
# -r requirements/base.txt
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/windows.txt
|
||||
# -r requirements/crypto.txt
|
||||
|
@ -294,6 +295,8 @@ pymysql==1.0.2
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/windows.txt
|
||||
# -r requirements/windows.txt
|
||||
pynacl==1.5.0
|
||||
# via -r requirements/static/ci/common.in
|
||||
pyopenssl==23.2.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/windows.txt
|
||||
|
|
|
@ -16,11 +16,11 @@ cffi==1.15.1
|
|||
# via
|
||||
# -c requirements/static/ci/py3.11/linux.txt
|
||||
# cryptography
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via
|
||||
# -c requirements/static/ci/py3.11/linux.txt
|
||||
# requests
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -c requirements/static/ci/py3.11/linux.txt
|
||||
# pyspnego
|
||||
|
|
|
@ -67,7 +67,7 @@ cffi==1.15.1
|
|||
# napalm
|
||||
# pygit2
|
||||
# pynacl
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/darwin.txt
|
||||
# aiohttp
|
||||
|
@ -93,7 +93,7 @@ contextvars==2.4
|
|||
# -r requirements/base.txt
|
||||
croniter==1.3.15 ; sys_platform != "win32"
|
||||
# via -r requirements/static/ci/common.in
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/darwin.txt
|
||||
# -r requirements/crypto.txt
|
||||
|
@ -333,7 +333,9 @@ pyeapi==1.0.0
|
|||
pygit2==1.12.1
|
||||
# via -r requirements/static/ci/darwin.in
|
||||
pynacl==1.5.0
|
||||
# via paramiko
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# paramiko
|
||||
pyopenssl==23.2.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/darwin.txt
|
||||
|
|
|
@ -16,7 +16,7 @@ certifi==2023.07.22
|
|||
# via
|
||||
# -c requirements/static/ci/py3.11/linux.txt
|
||||
# requests
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via
|
||||
# -c requirements/static/ci/py3.11/linux.txt
|
||||
# requests
|
||||
|
|
|
@ -63,7 +63,7 @@ cffi==1.15.1
|
|||
# cryptography
|
||||
# napalm
|
||||
# pynacl
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/freebsd.txt
|
||||
# aiohttp
|
||||
|
@ -89,10 +89,11 @@ contextvars==2.4
|
|||
# -r requirements/base.txt
|
||||
croniter==1.3.15 ; sys_platform != "win32"
|
||||
# via -r requirements/static/ci/common.in
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/freebsd.txt
|
||||
# -r requirements/crypto.txt
|
||||
# -r requirements/static/pkg/freebsd.in
|
||||
# etcd3-py
|
||||
# moto
|
||||
# paramiko
|
||||
|
@ -327,7 +328,9 @@ pyeapi==1.0.0
|
|||
pyinotify==0.9.6 ; sys_platform != "win32" and sys_platform != "darwin" and platform_system != "openbsd"
|
||||
# via -r requirements/static/ci/common.in
|
||||
pynacl==1.5.0
|
||||
# via paramiko
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# paramiko
|
||||
pyopenssl==23.2.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/freebsd.txt
|
||||
|
|
|
@ -20,7 +20,7 @@ pylint==2.4.4
|
|||
# via
|
||||
# -r requirements/static/ci/lint.in
|
||||
# saltpylint
|
||||
saltpylint==2020.9.28
|
||||
saltpylint==2023.8.3
|
||||
# via -r requirements/static/ci/lint.in
|
||||
six==1.16.0
|
||||
# via
|
||||
|
|
|
@ -77,7 +77,7 @@ cffi==1.15.1
|
|||
# napalm
|
||||
# pygit2
|
||||
# pynacl
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/linux.txt
|
||||
# aiohttp
|
||||
|
@ -103,7 +103,7 @@ contextvars==2.4
|
|||
# -r requirements/base.txt
|
||||
croniter==1.3.15 ; sys_platform != "win32"
|
||||
# via -r requirements/static/ci/common.in
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/linux.txt
|
||||
# -r requirements/crypto.txt
|
||||
|
@ -359,7 +359,9 @@ pyjwt==2.7.0
|
|||
pymysql==1.0.3
|
||||
# via -r requirements/static/ci/linux.in
|
||||
pynacl==1.5.0
|
||||
# via paramiko
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# paramiko
|
||||
pyopenssl==23.2.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/linux.txt
|
||||
|
|
|
@ -18,7 +18,7 @@ cffi==1.15.1
|
|||
# via
|
||||
# clr-loader
|
||||
# cryptography
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via requests
|
||||
cheroot==10.0.0
|
||||
# via cherrypy
|
||||
|
@ -30,7 +30,7 @@ colorama==0.4.6
|
|||
# via pytest
|
||||
contextvars==2.4
|
||||
# via -r requirements/base.txt
|
||||
cryptography==40.0.2
|
||||
cryptography==41.0.3
|
||||
# via -r requirements/crypto.txt
|
||||
distlib==0.3.6
|
||||
# via virtualenv
|
||||
|
|
|
@ -16,7 +16,7 @@ certifi==2023.07.22
|
|||
# via requests
|
||||
cffi==1.15.1
|
||||
# via cryptography
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via requests
|
||||
cheroot==10.0.0
|
||||
# via cherrypy
|
||||
|
@ -24,7 +24,7 @@ cherrypy==18.8.0
|
|||
# via -r requirements/static/ci/pkgtests.in
|
||||
contextvars==2.4
|
||||
# via -r requirements/base.txt
|
||||
cryptography==40.0.2
|
||||
cryptography==41.0.3
|
||||
# via -r requirements/crypto.txt
|
||||
distlib==0.3.6
|
||||
# via virtualenv
|
||||
|
|
|
@ -55,7 +55,8 @@ cffi==1.14.6
|
|||
# clr-loader
|
||||
# cryptography
|
||||
# pygit2
|
||||
charset-normalizer==2.1.1
|
||||
# pynacl
|
||||
charset-normalizer==3.1.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/windows.txt
|
||||
# aiohttp
|
||||
|
@ -87,7 +88,7 @@ contextvars==2.4
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/windows.txt
|
||||
# -r requirements/base.txt
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/windows.txt
|
||||
# -r requirements/crypto.txt
|
||||
|
@ -292,6 +293,8 @@ pymysql==1.0.2
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/windows.txt
|
||||
# -r requirements/windows.txt
|
||||
pynacl==1.5.0
|
||||
# via -r requirements/static/ci/common.in
|
||||
pyopenssl==23.2.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/windows.txt
|
||||
|
|
|
@ -16,11 +16,11 @@ cffi==1.15.1
|
|||
# via
|
||||
# -c requirements/static/ci/py3.8/linux.txt
|
||||
# cryptography
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via
|
||||
# -c requirements/static/ci/py3.8/linux.txt
|
||||
# requests
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -c requirements/static/ci/py3.8/linux.txt
|
||||
# pyspnego
|
||||
|
|
|
@ -16,7 +16,7 @@ certifi==2023.07.22
|
|||
# via
|
||||
# -c requirements/static/ci/py3.8/linux.txt
|
||||
# requests
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via
|
||||
# -c requirements/static/ci/py3.8/linux.txt
|
||||
# requests
|
||||
|
|
|
@ -63,7 +63,7 @@ cffi==1.15.1
|
|||
# cryptography
|
||||
# napalm
|
||||
# pynacl
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/freebsd.txt
|
||||
# aiohttp
|
||||
|
@ -89,10 +89,11 @@ contextvars==2.4
|
|||
# -r requirements/base.txt
|
||||
croniter==1.3.15 ; sys_platform != "win32"
|
||||
# via -r requirements/static/ci/common.in
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/freebsd.txt
|
||||
# -r requirements/crypto.txt
|
||||
# -r requirements/static/pkg/freebsd.in
|
||||
# etcd3-py
|
||||
# moto
|
||||
# paramiko
|
||||
|
@ -332,7 +333,9 @@ pyeapi==1.0.0
|
|||
pyinotify==0.9.6 ; sys_platform != "win32" and sys_platform != "darwin" and platform_system != "openbsd"
|
||||
# via -r requirements/static/ci/common.in
|
||||
pynacl==1.5.0
|
||||
# via paramiko
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# paramiko
|
||||
pyopenssl==23.2.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/freebsd.txt
|
||||
|
|
|
@ -20,7 +20,7 @@ pylint==2.4.4
|
|||
# via
|
||||
# -r requirements/static/ci/lint.in
|
||||
# saltpylint
|
||||
saltpylint==2020.9.28
|
||||
saltpylint==2023.8.3
|
||||
# via -r requirements/static/ci/lint.in
|
||||
six==1.16.0
|
||||
# via
|
||||
|
|
|
@ -77,7 +77,7 @@ cffi==1.15.1
|
|||
# napalm
|
||||
# pygit2
|
||||
# pynacl
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/linux.txt
|
||||
# aiohttp
|
||||
|
@ -103,7 +103,7 @@ contextvars==2.4
|
|||
# -r requirements/base.txt
|
||||
croniter==1.3.15 ; sys_platform != "win32"
|
||||
# via -r requirements/static/ci/common.in
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/linux.txt
|
||||
# -r requirements/crypto.txt
|
||||
|
@ -367,7 +367,9 @@ pyjwt==2.7.0
|
|||
pymysql==1.0.3
|
||||
# via -r requirements/static/ci/linux.in
|
||||
pynacl==1.5.0
|
||||
# via paramiko
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# paramiko
|
||||
pyopenssl==23.2.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/linux.txt
|
||||
|
|
|
@ -55,7 +55,8 @@ cffi==1.14.6
|
|||
# clr-loader
|
||||
# cryptography
|
||||
# pygit2
|
||||
charset-normalizer==2.1.1
|
||||
# pynacl
|
||||
charset-normalizer==3.1.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/windows.txt
|
||||
# aiohttp
|
||||
|
@ -87,7 +88,7 @@ contextvars==2.4
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/windows.txt
|
||||
# -r requirements/base.txt
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/windows.txt
|
||||
# -r requirements/crypto.txt
|
||||
|
@ -298,6 +299,8 @@ pymysql==1.0.2
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/windows.txt
|
||||
# -r requirements/windows.txt
|
||||
pynacl==1.5.0
|
||||
# via -r requirements/static/ci/common.in
|
||||
pyopenssl==23.2.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/windows.txt
|
||||
|
|
|
@ -16,11 +16,11 @@ cffi==1.15.1
|
|||
# via
|
||||
# -c requirements/static/ci/py3.9/linux.txt
|
||||
# cryptography
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via
|
||||
# -c requirements/static/ci/py3.9/linux.txt
|
||||
# requests
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -c requirements/static/ci/py3.9/linux.txt
|
||||
# pyspnego
|
||||
|
|
|
@ -67,7 +67,7 @@ cffi==1.15.1
|
|||
# napalm
|
||||
# pygit2
|
||||
# pynacl
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
|
||||
# aiohttp
|
||||
|
@ -93,7 +93,7 @@ contextvars==2.4
|
|||
# -r requirements/base.txt
|
||||
croniter==1.3.15 ; sys_platform != "win32"
|
||||
# via -r requirements/static/ci/common.in
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
|
||||
# -r requirements/crypto.txt
|
||||
|
@ -335,7 +335,9 @@ pyeapi==1.0.0
|
|||
pygit2==1.12.1
|
||||
# via -r requirements/static/ci/darwin.in
|
||||
pynacl==1.5.0
|
||||
# via paramiko
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# paramiko
|
||||
pyopenssl==23.2.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
|
||||
|
|
|
@ -16,7 +16,7 @@ certifi==2023.07.22
|
|||
# via
|
||||
# -c requirements/static/ci/py3.9/linux.txt
|
||||
# requests
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via
|
||||
# -c requirements/static/ci/py3.9/linux.txt
|
||||
# requests
|
||||
|
|
|
@ -63,7 +63,7 @@ cffi==1.15.1
|
|||
# cryptography
|
||||
# napalm
|
||||
# pynacl
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/freebsd.txt
|
||||
# aiohttp
|
||||
|
@ -89,10 +89,11 @@ contextvars==2.4
|
|||
# -r requirements/base.txt
|
||||
croniter==1.3.15 ; sys_platform != "win32"
|
||||
# via -r requirements/static/ci/common.in
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/freebsd.txt
|
||||
# -r requirements/crypto.txt
|
||||
# -r requirements/static/pkg/freebsd.in
|
||||
# etcd3-py
|
||||
# moto
|
||||
# paramiko
|
||||
|
@ -329,7 +330,9 @@ pyeapi==1.0.0
|
|||
pyinotify==0.9.6 ; sys_platform != "win32" and sys_platform != "darwin" and platform_system != "openbsd"
|
||||
# via -r requirements/static/ci/common.in
|
||||
pynacl==1.5.0
|
||||
# via paramiko
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# paramiko
|
||||
pyopenssl==23.2.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/freebsd.txt
|
||||
|
|
|
@ -20,7 +20,7 @@ pylint==2.4.4
|
|||
# via
|
||||
# -r requirements/static/ci/lint.in
|
||||
# saltpylint
|
||||
saltpylint==2020.9.28
|
||||
saltpylint==2023.8.3
|
||||
# via -r requirements/static/ci/lint.in
|
||||
six==1.16.0
|
||||
# via
|
||||
|
|
|
@ -77,7 +77,7 @@ cffi==1.15.1
|
|||
# napalm
|
||||
# pygit2
|
||||
# pynacl
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/linux.txt
|
||||
# aiohttp
|
||||
|
@ -103,7 +103,7 @@ contextvars==2.4
|
|||
# -r requirements/base.txt
|
||||
croniter==1.3.15 ; sys_platform != "win32"
|
||||
# via -r requirements/static/ci/common.in
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/linux.txt
|
||||
# -r requirements/crypto.txt
|
||||
|
@ -365,7 +365,9 @@ pyjwt==2.7.0
|
|||
pymysql==1.0.3
|
||||
# via -r requirements/static/ci/linux.in
|
||||
pynacl==1.5.0
|
||||
# via paramiko
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# paramiko
|
||||
pyopenssl==23.2.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/linux.txt
|
||||
|
|
|
@ -55,7 +55,8 @@ cffi==1.14.6
|
|||
# clr-loader
|
||||
# cryptography
|
||||
# pygit2
|
||||
charset-normalizer==2.1.1
|
||||
# pynacl
|
||||
charset-normalizer==3.1.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/windows.txt
|
||||
# aiohttp
|
||||
|
@ -87,7 +88,7 @@ contextvars==2.4
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/windows.txt
|
||||
# -r requirements/base.txt
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/windows.txt
|
||||
# -r requirements/crypto.txt
|
||||
|
@ -294,6 +295,8 @@ pymysql==1.0.2
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/windows.txt
|
||||
# -r requirements/windows.txt
|
||||
pynacl==1.5.0
|
||||
# via -r requirements/static/ci/common.in
|
||||
pyopenssl==23.2.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/windows.txt
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
# This file only exists to trigger the right static compiled requirements destination
|
||||
# Any non hard dependencies of Salt for FreeBSD can go here
|
||||
cherrypy
|
||||
cryptography>=41.0.3
|
||||
backports.ssl_match_hostname>=3.7.0.1; python_version < '3.7'
|
||||
pycparser>=2.21; python_version >= '3.9'
|
||||
pyopenssl>=19.0.0
|
||||
pyopenssl>=23.2.0
|
||||
python-dateutil>=2.8.0
|
||||
python-gnupg>=0.4.4
|
||||
setproctitle>=1.2.3
|
||||
|
|
|
@ -9,4 +9,4 @@ rpm-vercmp
|
|||
setproctitle>=1.2.3
|
||||
timelib>=0.2.5
|
||||
importlib-metadata>=3.3.0
|
||||
cryptography>=41.0.2
|
||||
cryptography>=41.0.3
|
||||
|
|
|
@ -12,7 +12,7 @@ certifi==2023.07.22
|
|||
# via requests
|
||||
cffi==1.15.1
|
||||
# via cryptography
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via requests
|
||||
cheroot==10.0.0
|
||||
# via cherrypy
|
||||
|
@ -20,7 +20,7 @@ cherrypy==18.8.0
|
|||
# via -r requirements/darwin.txt
|
||||
contextvars==2.4
|
||||
# via -r requirements/base.txt
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -r requirements/crypto.txt
|
||||
# -r requirements/darwin.txt
|
||||
|
|
|
@ -10,7 +10,7 @@ certifi==2023.07.22
|
|||
# via requests
|
||||
cffi==1.15.1
|
||||
# via cryptography
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via requests
|
||||
cheroot==10.0.0
|
||||
# via cherrypy
|
||||
|
@ -18,9 +18,10 @@ cherrypy==18.8.0
|
|||
# via -r requirements/static/pkg/freebsd.in
|
||||
contextvars==2.4
|
||||
# via -r requirements/base.txt
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -r requirements/crypto.txt
|
||||
# -r requirements/static/pkg/freebsd.in
|
||||
# pyopenssl
|
||||
distro==1.8.0
|
||||
# via
|
||||
|
|
|
@ -10,7 +10,7 @@ certifi==2023.07.22
|
|||
# via requests
|
||||
cffi==1.15.1
|
||||
# via cryptography
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via requests
|
||||
cheroot==10.0.0
|
||||
# via cherrypy
|
||||
|
@ -18,7 +18,7 @@ cherrypy==18.8.0
|
|||
# via -r requirements/static/pkg/linux.in
|
||||
contextvars==2.4
|
||||
# via -r requirements/base.txt
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -r requirements/crypto.txt
|
||||
# -r requirements/static/pkg/linux.in
|
||||
|
|
|
@ -15,7 +15,7 @@ cffi==1.14.6
|
|||
# -r requirements/windows.txt
|
||||
# clr-loader
|
||||
# cryptography
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via requests
|
||||
cheroot==10.0.0
|
||||
# via cherrypy
|
||||
|
@ -25,7 +25,7 @@ clr-loader==0.2.4
|
|||
# via pythonnet
|
||||
contextvars==2.4
|
||||
# via -r requirements/base.txt
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -r requirements/crypto.txt
|
||||
# -r requirements/windows.txt
|
||||
|
|
|
@ -12,7 +12,7 @@ certifi==2023.07.22
|
|||
# via requests
|
||||
cffi==1.15.1
|
||||
# via cryptography
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via requests
|
||||
cheroot==10.0.0
|
||||
# via cherrypy
|
||||
|
@ -20,7 +20,7 @@ cherrypy==18.8.0
|
|||
# via -r requirements/darwin.txt
|
||||
contextvars==2.4
|
||||
# via -r requirements/base.txt
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -r requirements/crypto.txt
|
||||
# -r requirements/darwin.txt
|
||||
|
|
|
@ -10,7 +10,7 @@ certifi==2023.07.22
|
|||
# via requests
|
||||
cffi==1.15.1
|
||||
# via cryptography
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via requests
|
||||
cheroot==10.0.0
|
||||
# via cherrypy
|
||||
|
@ -18,9 +18,10 @@ cherrypy==18.8.0
|
|||
# via -r requirements/static/pkg/freebsd.in
|
||||
contextvars==2.4
|
||||
# via -r requirements/base.txt
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -r requirements/crypto.txt
|
||||
# -r requirements/static/pkg/freebsd.in
|
||||
# pyopenssl
|
||||
distro==1.8.0
|
||||
# via
|
||||
|
|
|
@ -10,7 +10,7 @@ certifi==2023.07.22
|
|||
# via requests
|
||||
cffi==1.15.1
|
||||
# via cryptography
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via requests
|
||||
cheroot==10.0.0
|
||||
# via cherrypy
|
||||
|
@ -18,7 +18,7 @@ cherrypy==18.8.0
|
|||
# via -r requirements/static/pkg/linux.in
|
||||
contextvars==2.4
|
||||
# via -r requirements/base.txt
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -r requirements/crypto.txt
|
||||
# -r requirements/static/pkg/linux.in
|
||||
|
|
|
@ -15,7 +15,7 @@ cffi==1.14.6
|
|||
# -r requirements/windows.txt
|
||||
# clr-loader
|
||||
# cryptography
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via requests
|
||||
cheroot==10.0.0
|
||||
# via cherrypy
|
||||
|
@ -25,7 +25,7 @@ clr-loader==0.2.4
|
|||
# via pythonnet
|
||||
contextvars==2.4
|
||||
# via -r requirements/base.txt
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -r requirements/crypto.txt
|
||||
# -r requirements/windows.txt
|
||||
|
|
|
@ -10,7 +10,7 @@ certifi==2023.07.22
|
|||
# via requests
|
||||
cffi==1.15.1
|
||||
# via cryptography
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via requests
|
||||
cheroot==10.0.0
|
||||
# via cherrypy
|
||||
|
@ -18,9 +18,10 @@ cherrypy==18.8.0
|
|||
# via -r requirements/static/pkg/freebsd.in
|
||||
contextvars==2.4
|
||||
# via -r requirements/base.txt
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -r requirements/crypto.txt
|
||||
# -r requirements/static/pkg/freebsd.in
|
||||
# pyopenssl
|
||||
distro==1.8.0
|
||||
# via
|
||||
|
|
|
@ -10,7 +10,7 @@ certifi==2023.07.22
|
|||
# via requests
|
||||
cffi==1.15.1
|
||||
# via cryptography
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via requests
|
||||
cheroot==10.0.0
|
||||
# via cherrypy
|
||||
|
@ -18,7 +18,7 @@ cherrypy==18.8.0
|
|||
# via -r requirements/static/pkg/linux.in
|
||||
contextvars==2.4
|
||||
# via -r requirements/base.txt
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -r requirements/crypto.txt
|
||||
# -r requirements/static/pkg/linux.in
|
||||
|
|
|
@ -15,7 +15,7 @@ cffi==1.14.6
|
|||
# -r requirements/windows.txt
|
||||
# clr-loader
|
||||
# cryptography
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via requests
|
||||
cheroot==10.0.0
|
||||
# via cherrypy
|
||||
|
@ -25,7 +25,7 @@ clr-loader==0.2.4
|
|||
# via pythonnet
|
||||
contextvars==2.4
|
||||
# via -r requirements/base.txt
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -r requirements/crypto.txt
|
||||
# -r requirements/windows.txt
|
||||
|
|
|
@ -12,7 +12,7 @@ certifi==2023.07.22
|
|||
# via requests
|
||||
cffi==1.15.1
|
||||
# via cryptography
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via requests
|
||||
cheroot==10.0.0
|
||||
# via cherrypy
|
||||
|
@ -20,7 +20,7 @@ cherrypy==18.8.0
|
|||
# via -r requirements/darwin.txt
|
||||
contextvars==2.4
|
||||
# via -r requirements/base.txt
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -r requirements/crypto.txt
|
||||
# -r requirements/darwin.txt
|
||||
|
|
|
@ -10,7 +10,7 @@ certifi==2023.07.22
|
|||
# via requests
|
||||
cffi==1.15.1
|
||||
# via cryptography
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via requests
|
||||
cheroot==10.0.0
|
||||
# via cherrypy
|
||||
|
@ -18,9 +18,10 @@ cherrypy==18.8.0
|
|||
# via -r requirements/static/pkg/freebsd.in
|
||||
contextvars==2.4
|
||||
# via -r requirements/base.txt
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -r requirements/crypto.txt
|
||||
# -r requirements/static/pkg/freebsd.in
|
||||
# pyopenssl
|
||||
distro==1.8.0
|
||||
# via
|
||||
|
|
|
@ -10,7 +10,7 @@ certifi==2023.07.22
|
|||
# via requests
|
||||
cffi==1.15.1
|
||||
# via cryptography
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via requests
|
||||
cheroot==10.0.0
|
||||
# via cherrypy
|
||||
|
@ -18,7 +18,7 @@ cherrypy==18.8.0
|
|||
# via -r requirements/static/pkg/linux.in
|
||||
contextvars==2.4
|
||||
# via -r requirements/base.txt
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -r requirements/crypto.txt
|
||||
# -r requirements/static/pkg/linux.in
|
||||
|
|
|
@ -15,7 +15,7 @@ cffi==1.14.6
|
|||
# -r requirements/windows.txt
|
||||
# clr-loader
|
||||
# cryptography
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.1.0
|
||||
# via requests
|
||||
cheroot==10.0.0
|
||||
# via cherrypy
|
||||
|
@ -25,7 +25,7 @@ clr-loader==0.2.4
|
|||
# via pythonnet
|
||||
contextvars==2.4
|
||||
# via -r requirements/base.txt
|
||||
cryptography==41.0.2
|
||||
cryptography==41.0.3
|
||||
# via
|
||||
# -r requirements/crypto.txt
|
||||
# -r requirements/windows.txt
|
||||
|
|
|
@ -11,7 +11,7 @@ certifi>=2022.12.07
|
|||
cffi>=1.14.5
|
||||
cherrypy>=18.6.1
|
||||
gitpython>=3.1.30
|
||||
cryptography>=41.0.2
|
||||
cryptography>=41.0.3
|
||||
lxml>=4.6.3
|
||||
pyasn1>=0.4.8
|
||||
pymssql>=2.2.1
|
||||
|
|
|
@ -3,6 +3,7 @@ Salt package
|
|||
"""
|
||||
|
||||
import importlib
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
|
@ -12,6 +13,53 @@ if sys.version_info < (3,):
|
|||
)
|
||||
sys.stderr.flush()
|
||||
|
||||
|
||||
class NaclImporter:
|
||||
"""
|
||||
Import hook to force PyNaCl to perform dlopen on libsodium with the
|
||||
RTLD_DEEPBIND flag. This is to work around an issue where pyzmq does a dlopen
|
||||
with RTLD_GLOBAL which then causes calls to libsodium to resolve to
|
||||
tweetnacl when it's been bundled with pyzmq.
|
||||
|
||||
See: https://github.com/zeromq/pyzmq/issues/1878
|
||||
"""
|
||||
|
||||
loading = False
|
||||
|
||||
def find_module(self, module_name, package_path=None):
|
||||
if not NaclImporter.loading and module_name.startswith("nacl"):
|
||||
NaclImporter.loading = True
|
||||
return self
|
||||
return None
|
||||
|
||||
def create_module(self, spec):
|
||||
dlopen = hasattr(sys, "getdlopenflags")
|
||||
if dlopen:
|
||||
dlflags = sys.getdlopenflags()
|
||||
# Use RTDL_DEEPBIND in case pyzmq was compiled with ZMQ_USE_TWEETNACL. This is
|
||||
# needed because pyzmq imports libzmq with RTLD_GLOBAL.
|
||||
if hasattr(os, "RTLD_DEEPBIND"):
|
||||
flags = os.RTLD_DEEPBIND | dlflags
|
||||
else:
|
||||
flags = dlflags
|
||||
sys.setdlopenflags(flags)
|
||||
try:
|
||||
mod = importlib.import_module(spec.name)
|
||||
finally:
|
||||
if dlopen:
|
||||
sys.setdlopenflags(dlflags)
|
||||
NaclImporter.loading = False
|
||||
sys.modules[spec.name] = mod
|
||||
return mod
|
||||
|
||||
def exec_module(self, module):
|
||||
return None
|
||||
|
||||
|
||||
# Try our importer first
|
||||
sys.meta_path = [NaclImporter()] + sys.meta_path
|
||||
|
||||
|
||||
# All salt related deprecation warnings should be shown once each!
|
||||
warnings.filterwarnings(
|
||||
"once", # Show once
|
||||
|
|
|
@ -41,6 +41,9 @@ except ImportError:
|
|||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
REQUEST_CHANNEL_TIMEOUT = 60
|
||||
REQUEST_CHANNEL_TRIES = 3
|
||||
|
||||
|
||||
class ReqChannel:
|
||||
"""
|
||||
|
@ -122,6 +125,9 @@ class AsyncReqChannel:
|
|||
if io_loop is None:
|
||||
io_loop = tornado.ioloop.IOLoop.current()
|
||||
|
||||
timeout = opts.get("request_channel_timeout", REQUEST_CHANNEL_TIMEOUT)
|
||||
tries = opts.get("request_channel_tries", REQUEST_CHANNEL_TRIES)
|
||||
|
||||
crypt = kwargs.get("crypt", "aes")
|
||||
if crypt != "clear":
|
||||
# we don't need to worry about auth as a kwarg, since its a singleton
|
||||
|
@ -130,9 +136,17 @@ class AsyncReqChannel:
|
|||
auth = None
|
||||
|
||||
transport = salt.transport.request_client(opts, io_loop=io_loop)
|
||||
return cls(opts, transport, auth)
|
||||
return cls(opts, transport, auth, tries=tries, timeout=timeout)
|
||||
|
||||
def __init__(self, opts, transport, auth, **kwargs):
|
||||
def __init__(
|
||||
self,
|
||||
opts,
|
||||
transport,
|
||||
auth,
|
||||
timeout=REQUEST_CHANNEL_TIMEOUT,
|
||||
tries=REQUEST_CHANNEL_TRIES,
|
||||
**kwargs,
|
||||
):
|
||||
self.opts = dict(opts)
|
||||
self.transport = transport
|
||||
self.auth = auth
|
||||
|
@ -140,6 +154,8 @@ class AsyncReqChannel:
|
|||
if self.auth:
|
||||
self.master_pubkey_path = os.path.join(self.opts["pki_dir"], self.auth.mpub)
|
||||
self._closing = False
|
||||
self.timeout = timeout
|
||||
self.tries = tries
|
||||
|
||||
@property
|
||||
def crypt(self):
|
||||
|
@ -158,28 +174,54 @@ class AsyncReqChannel:
|
|||
"version": 2,
|
||||
}
|
||||
|
||||
@tornado.gen.coroutine
|
||||
def _send_with_retry(self, load, tries, timeout):
|
||||
_try = 1
|
||||
while True:
|
||||
try:
|
||||
ret = yield self.transport.send(
|
||||
load,
|
||||
timeout=timeout,
|
||||
)
|
||||
break
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
log.trace("Failed to send msg %r", exc)
|
||||
if _try >= tries:
|
||||
raise
|
||||
else:
|
||||
_try += 1
|
||||
continue
|
||||
raise tornado.gen.Return(ret)
|
||||
|
||||
@tornado.gen.coroutine
|
||||
def crypted_transfer_decode_dictentry(
|
||||
self,
|
||||
load,
|
||||
dictkey=None,
|
||||
timeout=60,
|
||||
timeout=None,
|
||||
tries=None,
|
||||
):
|
||||
if timeout is None:
|
||||
timeout = self.timeout
|
||||
if tries is None:
|
||||
tries = self.tries
|
||||
nonce = uuid.uuid4().hex
|
||||
load["nonce"] = nonce
|
||||
if not self.auth.authenticated:
|
||||
yield self.auth.authenticate()
|
||||
ret = yield self.transport.send(
|
||||
ret = yield self._send_with_retry(
|
||||
self._package_load(self.auth.crypticle.dumps(load)),
|
||||
timeout=timeout,
|
||||
tries,
|
||||
timeout,
|
||||
)
|
||||
key = self.auth.get_keys()
|
||||
if "key" not in ret:
|
||||
# Reauth in the case our key is deleted on the master side.
|
||||
yield self.auth.authenticate()
|
||||
ret = yield self.transport.send(
|
||||
ret = yield self._send_with_retry(
|
||||
self._package_load(self.auth.crypticle.dumps(load)),
|
||||
timeout=timeout,
|
||||
tries,
|
||||
timeout,
|
||||
)
|
||||
if HAS_M2:
|
||||
aes = key.private_decrypt(ret["key"], RSA.pkcs1_oaep_padding)
|
||||
|
@ -211,7 +253,7 @@ class AsyncReqChannel:
|
|||
return salt.crypt.verify_signature(self.master_pubkey_path, data, sig)
|
||||
|
||||
@tornado.gen.coroutine
|
||||
def _crypted_transfer(self, load, timeout=60, raw=False):
|
||||
def _crypted_transfer(self, load, timeout, raw=False):
|
||||
"""
|
||||
Send a load across the wire, with encryption
|
||||
|
||||
|
@ -258,7 +300,7 @@ class AsyncReqChannel:
|
|||
raise tornado.gen.Return(ret)
|
||||
|
||||
@tornado.gen.coroutine
|
||||
def _uncrypted_transfer(self, load, timeout=60):
|
||||
def _uncrypted_transfer(self, load, timeout):
|
||||
"""
|
||||
Send a load across the wire in cleartext
|
||||
|
||||
|
@ -277,7 +319,7 @@ class AsyncReqChannel:
|
|||
yield self.transport.connect()
|
||||
|
||||
@tornado.gen.coroutine
|
||||
def send(self, load, tries=3, timeout=60, raw=False):
|
||||
def send(self, load, tries=None, timeout=None, raw=False):
|
||||
"""
|
||||
Send a request, return a future which will complete when we send the message
|
||||
|
||||
|
@ -285,6 +327,10 @@ class AsyncReqChannel:
|
|||
:param int tries: The number of times to make before failure
|
||||
:param int timeout: The number of seconds on a response before failing
|
||||
"""
|
||||
if timeout is None:
|
||||
timeout = self.timeout
|
||||
if tries is None:
|
||||
tries = self.tries
|
||||
_try = 1
|
||||
while True:
|
||||
try:
|
||||
|
@ -402,7 +448,7 @@ class AsyncPubChannel:
|
|||
except Exception as exc: # pylint: disable=broad-except
|
||||
if "-|RETRY|-" not in str(exc):
|
||||
raise salt.exceptions.SaltClientError(
|
||||
"Unable to sign_in to master: {}".format(exc)
|
||||
f"Unable to sign_in to master: {exc}"
|
||||
) # TODO: better error message
|
||||
|
||||
def close(self):
|
||||
|
|
|
@ -990,6 +990,8 @@ VALID_OPTS = immutabletypes.freeze(
|
|||
"maintenance_interval": int,
|
||||
# Fileserver process restart interval
|
||||
"fileserver_interval": int,
|
||||
"request_channel_timeout": int,
|
||||
"request_channel_tries": int,
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -1051,6 +1053,8 @@ DEFAULT_MINION_OPTS = immutabletypes.freeze(
|
|||
"pillar_cache": False,
|
||||
"pillar_cache_ttl": 3600,
|
||||
"pillar_cache_backend": "disk",
|
||||
"request_channel_timeout": 30,
|
||||
"request_channel_tries": 3,
|
||||
"gpg_cache": False,
|
||||
"gpg_cache_ttl": 86400,
|
||||
"gpg_cache_backend": "disk",
|
||||
|
|
|
@ -9,6 +9,7 @@ import logging
|
|||
import os
|
||||
import shutil
|
||||
import string
|
||||
import time
|
||||
import urllib.error
|
||||
import urllib.parse
|
||||
|
||||
|
@ -33,7 +34,7 @@ import salt.utils.templates
|
|||
import salt.utils.url
|
||||
import salt.utils.verify
|
||||
import salt.utils.versions
|
||||
from salt.exceptions import CommandExecutionError, MinionError
|
||||
from salt.exceptions import CommandExecutionError, MinionError, SaltClientError
|
||||
from salt.utils.openstack.swift import SaltSwift
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
@ -100,7 +101,7 @@ class Client:
|
|||
Make sure that this path is intended for the salt master and trim it
|
||||
"""
|
||||
if not path.startswith("salt://"):
|
||||
raise MinionError("Unsupported path: {}".format(path))
|
||||
raise MinionError(f"Unsupported path: {path}")
|
||||
file_path, saltenv = salt.utils.url.parse(path)
|
||||
return file_path
|
||||
|
||||
|
@ -266,7 +267,7 @@ class Client:
|
|||
for fn_ in self.file_list_emptydirs(saltenv):
|
||||
fn_ = salt.utils.data.decode(fn_)
|
||||
if fn_.startswith(path):
|
||||
minion_dir = "{}/{}".format(dest, fn_)
|
||||
minion_dir = f"{dest}/{fn_}"
|
||||
if not os.path.isdir(minion_dir):
|
||||
os.makedirs(minion_dir)
|
||||
ret.append(minion_dir)
|
||||
|
@ -431,7 +432,7 @@ class Client:
|
|||
ret.append(
|
||||
self.get_file(
|
||||
salt.utils.url.create(fn_),
|
||||
"{}/{}".format(dest, minion_relpath),
|
||||
f"{dest}/{minion_relpath}",
|
||||
True,
|
||||
saltenv,
|
||||
gzip,
|
||||
|
@ -450,7 +451,7 @@ class Client:
|
|||
# Remove the leading directories from path to derive
|
||||
# the relative path on the minion.
|
||||
minion_relpath = fn_[len(prefix) :].lstrip("/")
|
||||
minion_mkdir = "{}/{}".format(dest, minion_relpath)
|
||||
minion_mkdir = f"{dest}/{minion_relpath}"
|
||||
if not os.path.isdir(minion_mkdir):
|
||||
os.makedirs(minion_mkdir)
|
||||
ret.append(minion_mkdir)
|
||||
|
@ -501,9 +502,7 @@ class Client:
|
|||
if url_scheme in ("file", ""):
|
||||
# Local filesystem
|
||||
if not os.path.isabs(url_path):
|
||||
raise CommandExecutionError(
|
||||
"Path '{}' is not absolute".format(url_path)
|
||||
)
|
||||
raise CommandExecutionError(f"Path '{url_path}' is not absolute")
|
||||
if dest is None:
|
||||
with salt.utils.files.fopen(url_path, "rb") as fp_:
|
||||
data = fp_.read()
|
||||
|
@ -577,9 +576,7 @@ class Client:
|
|||
)
|
||||
return dest
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
raise MinionError(
|
||||
"Could not fetch from {}. Exception: {}".format(url, exc)
|
||||
)
|
||||
raise MinionError(f"Could not fetch from {url}. Exception: {exc}")
|
||||
if url_data.scheme == "ftp":
|
||||
try:
|
||||
ftp = ftplib.FTP() # nosec
|
||||
|
@ -590,7 +587,7 @@ class Client:
|
|||
ftp.login(url_data.username, url_data.password)
|
||||
remote_file_path = url_data.path.lstrip("/")
|
||||
with salt.utils.files.fopen(dest, "wb") as fp_:
|
||||
ftp.retrbinary("RETR {}".format(remote_file_path), fp_.write)
|
||||
ftp.retrbinary(f"RETR {remote_file_path}", fp_.write)
|
||||
ftp.quit()
|
||||
return dest
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
|
@ -624,7 +621,7 @@ class Client:
|
|||
swift_conn.get_object(url_data.netloc, url_data.path[1:], dest)
|
||||
return dest
|
||||
except Exception: # pylint: disable=broad-except
|
||||
raise MinionError("Could not fetch from {}".format(url))
|
||||
raise MinionError(f"Could not fetch from {url}")
|
||||
|
||||
get_kwargs = {}
|
||||
if url_data.username is not None and url_data.scheme in ("http", "https"):
|
||||
|
@ -647,7 +644,7 @@ class Client:
|
|||
fixed_url = url
|
||||
|
||||
destfp = None
|
||||
dest_etag = "{}.etag".format(dest)
|
||||
dest_etag = f"{dest}.etag"
|
||||
try:
|
||||
# Tornado calls streaming_callback on redirect response bodies.
|
||||
# But we need streaming to support fetching large files (> RAM
|
||||
|
@ -761,7 +758,7 @@ class Client:
|
|||
result.append(chunk)
|
||||
|
||||
else:
|
||||
dest_tmp = "{}.part".format(dest)
|
||||
dest_tmp = f"{dest}.part"
|
||||
# We need an open filehandle to use in the on_chunk callback,
|
||||
# that's why we're not using a with clause here.
|
||||
# pylint: disable=resource-leakage
|
||||
|
@ -790,7 +787,7 @@ class Client:
|
|||
opts=self.opts,
|
||||
verify_ssl=verify_ssl,
|
||||
header_dict=header_dict,
|
||||
**get_kwargs
|
||||
**get_kwargs,
|
||||
)
|
||||
|
||||
# 304 Not Modified is returned when If-None-Match header
|
||||
|
@ -819,11 +816,11 @@ class Client:
|
|||
"HTTP error {0} reading {1}: {3}".format(
|
||||
exc.code,
|
||||
url,
|
||||
*http.server.BaseHTTPRequestHandler.responses[exc.code]
|
||||
*http.server.BaseHTTPRequestHandler.responses[exc.code],
|
||||
)
|
||||
)
|
||||
except urllib.error.URLError as exc:
|
||||
raise MinionError("Error reading {}: {}".format(url, exc.reason))
|
||||
raise MinionError(f"Error reading {url}: {exc.reason}")
|
||||
finally:
|
||||
if destfp is not None:
|
||||
destfp.close()
|
||||
|
@ -836,7 +833,7 @@ class Client:
|
|||
makedirs=False,
|
||||
saltenv="base",
|
||||
cachedir=None,
|
||||
**kwargs
|
||||
**kwargs,
|
||||
):
|
||||
"""
|
||||
Cache a file then process it as a template
|
||||
|
@ -1133,6 +1130,18 @@ class RemoteClient(Client):
|
|||
self.channel = salt.channel.client.ReqChannel.factory(self.opts)
|
||||
return self.channel
|
||||
|
||||
def _channel_send(self, load, raw=False):
|
||||
start = time.monotonic()
|
||||
try:
|
||||
return self.channel.send(
|
||||
load,
|
||||
raw=raw,
|
||||
)
|
||||
except salt.exceptions.SaltReqTimeoutError:
|
||||
raise SaltClientError(
|
||||
f"File client timed out after {int(time.time() - start)}"
|
||||
)
|
||||
|
||||
def destroy(self):
|
||||
if self._closing:
|
||||
return
|
||||
|
@ -1247,7 +1256,10 @@ class RemoteClient(Client):
|
|||
load["loc"] = 0
|
||||
else:
|
||||
load["loc"] = fn_.tell()
|
||||
data = self.channel.send(load, raw=True)
|
||||
data = self._channel_send(
|
||||
load,
|
||||
raw=True,
|
||||
)
|
||||
# Sometimes the source is local (eg when using
|
||||
# 'salt.fileserver.FSChan'), in which case the keys are
|
||||
# already strings. Sometimes the source is remote, in which
|
||||
|
@ -1340,28 +1352,36 @@ class RemoteClient(Client):
|
|||
List the files on the master
|
||||
"""
|
||||
load = {"saltenv": saltenv, "prefix": prefix, "cmd": "_file_list"}
|
||||
return self.channel.send(load)
|
||||
return self._channel_send(
|
||||
load,
|
||||
)
|
||||
|
||||
def file_list_emptydirs(self, saltenv="base", prefix=""):
|
||||
"""
|
||||
List the empty dirs on the master
|
||||
"""
|
||||
load = {"saltenv": saltenv, "prefix": prefix, "cmd": "_file_list_emptydirs"}
|
||||
return self.channel.send(load)
|
||||
return self._channel_send(
|
||||
load,
|
||||
)
|
||||
|
||||
def dir_list(self, saltenv="base", prefix=""):
|
||||
"""
|
||||
List the dirs on the master
|
||||
"""
|
||||
load = {"saltenv": saltenv, "prefix": prefix, "cmd": "_dir_list"}
|
||||
return self.channel.send(load)
|
||||
return self._channel_send(
|
||||
load,
|
||||
)
|
||||
|
||||
def symlink_list(self, saltenv="base", prefix=""):
|
||||
"""
|
||||
List symlinked files and dirs on the master
|
||||
"""
|
||||
load = {"saltenv": saltenv, "prefix": prefix, "cmd": "_symlink_list"}
|
||||
return self.channel.send(load)
|
||||
return self._channel_send(
|
||||
load,
|
||||
)
|
||||
|
||||
def __hash_and_stat_file(self, path, saltenv="base"):
|
||||
"""
|
||||
|
@ -1382,7 +1402,9 @@ class RemoteClient(Client):
|
|||
ret["hash_type"] = hash_type
|
||||
return ret
|
||||
load = {"path": path, "saltenv": saltenv, "cmd": "_file_hash"}
|
||||
return self.channel.send(load)
|
||||
return self._channel_send(
|
||||
load,
|
||||
)
|
||||
|
||||
def hash_file(self, path, saltenv="base"):
|
||||
"""
|
||||
|
@ -1409,7 +1431,9 @@ class RemoteClient(Client):
|
|||
except Exception: # pylint: disable=broad-except
|
||||
return hash_result, None
|
||||
load = {"path": path, "saltenv": saltenv, "cmd": "_file_find"}
|
||||
fnd = self.channel.send(load)
|
||||
fnd = self._channel_send(
|
||||
load,
|
||||
)
|
||||
try:
|
||||
stat_result = fnd.get("stat")
|
||||
except AttributeError:
|
||||
|
@ -1421,21 +1445,27 @@ class RemoteClient(Client):
|
|||
Return a list of the files in the file server's specified environment
|
||||
"""
|
||||
load = {"saltenv": saltenv, "cmd": "_file_list"}
|
||||
return self.channel.send(load)
|
||||
return self._channel_send(
|
||||
load,
|
||||
)
|
||||
|
||||
def envs(self):
|
||||
"""
|
||||
Return a list of available environments
|
||||
"""
|
||||
load = {"cmd": "_file_envs"}
|
||||
return self.channel.send(load)
|
||||
return self._channel_send(
|
||||
load,
|
||||
)
|
||||
|
||||
def master_opts(self):
|
||||
"""
|
||||
Return the master opts data
|
||||
"""
|
||||
load = {"cmd": "_master_opts"}
|
||||
return self.channel.send(load)
|
||||
return self._channel_send(
|
||||
load,
|
||||
)
|
||||
|
||||
def master_tops(self):
|
||||
"""
|
||||
|
@ -1444,7 +1474,9 @@ class RemoteClient(Client):
|
|||
load = {"cmd": "_master_tops", "id": self.opts["id"], "opts": self.opts}
|
||||
if self.auth:
|
||||
load["tok"] = self.auth.gen_token(b"salt")
|
||||
return self.channel.send(load)
|
||||
return self._channel_send(
|
||||
load,
|
||||
)
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
are made to assure backwards compatibility.
|
||||
"""
|
||||
|
||||
# pylint: disable = no-name-in-module
|
||||
|
||||
# Import several classes/functions from salt.log.setup for backwards compatibility
|
||||
from salt._logging import LOG_LEVELS, SORTED_LEVEL_NAMES
|
||||
from salt.log.setup import (
|
||||
|
|
|
@ -339,7 +339,7 @@ def load_args_and_kwargs(func, args, data=None, ignore_invalid=False):
|
|||
# **kwargs not in argspec and parsed argument name not in
|
||||
# list of positional arguments. This keyword argument is
|
||||
# invalid.
|
||||
invalid_kwargs.append("{}={}".format(key, val))
|
||||
invalid_kwargs.append(f"{key}={val}")
|
||||
continue
|
||||
|
||||
else:
|
||||
|
@ -356,7 +356,7 @@ def load_args_and_kwargs(func, args, data=None, ignore_invalid=False):
|
|||
# list of positional arguments. This keyword argument is
|
||||
# invalid.
|
||||
for key, val in string_kwarg.items():
|
||||
invalid_kwargs.append("{}={}".format(key, val))
|
||||
invalid_kwargs.append(f"{key}={val}")
|
||||
else:
|
||||
_args.append(arg)
|
||||
|
||||
|
@ -366,7 +366,7 @@ def load_args_and_kwargs(func, args, data=None, ignore_invalid=False):
|
|||
if argspec.keywords and isinstance(data, dict):
|
||||
# this function accepts **kwargs, pack in the publish data
|
||||
for key, val in data.items():
|
||||
_kwargs["__pub_{}".format(key)] = val
|
||||
_kwargs[f"__pub_{key}"] = val
|
||||
|
||||
return _args, _kwargs
|
||||
|
||||
|
@ -411,7 +411,7 @@ def master_event(type, master=None):
|
|||
}
|
||||
|
||||
if type == "alive" and master is not None:
|
||||
return "{}_{}".format(event_map.get(type), master)
|
||||
return f"{event_map.get(type)}_{master}"
|
||||
|
||||
return event_map.get(type, None)
|
||||
|
||||
|
@ -1886,9 +1886,9 @@ class Minion(MinionBase):
|
|||
log.trace("Executors list %s", executors) # pylint: disable=no-member
|
||||
|
||||
for name in executors:
|
||||
fname = "{}.execute".format(name)
|
||||
fname = f"{name}.execute"
|
||||
if fname not in self.executors:
|
||||
raise SaltInvocationError("Executor '{}' is not available".format(name))
|
||||
raise SaltInvocationError(f"Executor '{name}' is not available")
|
||||
return_data = self.executors[fname](opts, data, func, args, kwargs)
|
||||
if return_data is not None:
|
||||
return return_data
|
||||
|
@ -1907,7 +1907,7 @@ class Minion(MinionBase):
|
|||
minion_instance.gen_modules()
|
||||
fn_ = os.path.join(minion_instance.proc_dir, data["jid"])
|
||||
|
||||
salt.utils.process.appendproctitle("{}._thread_return".format(cls.__name__))
|
||||
salt.utils.process.appendproctitle(f"{cls.__name__}._thread_return")
|
||||
|
||||
sdata = {"pid": os.getpid()}
|
||||
sdata.update(data)
|
||||
|
@ -1924,11 +1924,11 @@ class Minion(MinionBase):
|
|||
)
|
||||
allow_missing_funcs = any(
|
||||
[
|
||||
minion_instance.executors["{}.allow_missing_func".format(executor)](
|
||||
minion_instance.executors[f"{executor}.allow_missing_func"](
|
||||
function_name
|
||||
)
|
||||
for executor in executors
|
||||
if "{}.allow_missing_func".format(executor) in minion_instance.executors
|
||||
if f"{executor}.allow_missing_func" in minion_instance.executors
|
||||
]
|
||||
)
|
||||
if function_name in minion_instance.functions or allow_missing_funcs is True:
|
||||
|
@ -1974,9 +1974,9 @@ class Minion(MinionBase):
|
|||
ret["retcode"] = retcode
|
||||
ret["success"] = retcode == salt.defaults.exitcodes.EX_OK
|
||||
except CommandNotFoundError as exc:
|
||||
msg = "Command required for '{}' not found".format(function_name)
|
||||
msg = f"Command required for '{function_name}' not found"
|
||||
log.debug(msg, exc_info=True)
|
||||
ret["return"] = "{}: {}".format(msg, exc)
|
||||
ret["return"] = f"{msg}: {exc}"
|
||||
ret["out"] = "nested"
|
||||
ret["retcode"] = salt.defaults.exitcodes.EX_GENERIC
|
||||
except CommandExecutionError as exc:
|
||||
|
@ -1986,7 +1986,7 @@ class Minion(MinionBase):
|
|||
exc,
|
||||
exc_info_on_loglevel=logging.DEBUG,
|
||||
)
|
||||
ret["return"] = "ERROR: {}".format(exc)
|
||||
ret["return"] = f"ERROR: {exc}"
|
||||
ret["out"] = "nested"
|
||||
ret["retcode"] = salt.defaults.exitcodes.EX_GENERIC
|
||||
except SaltInvocationError as exc:
|
||||
|
@ -1996,10 +1996,23 @@ class Minion(MinionBase):
|
|||
exc,
|
||||
exc_info_on_loglevel=logging.DEBUG,
|
||||
)
|
||||
ret["return"] = "ERROR executing '{}': {}".format(function_name, exc)
|
||||
ret["return"] = f"ERROR executing '{function_name}': {exc}"
|
||||
ret["out"] = "nested"
|
||||
ret["retcode"] = salt.defaults.exitcodes.EX_GENERIC
|
||||
except SaltClientError as exc:
|
||||
log.error(
|
||||
"Problem executing '%s': %s",
|
||||
function_name,
|
||||
exc,
|
||||
)
|
||||
ret["return"] = f"ERROR executing '{function_name}': {exc}"
|
||||
ret["out"] = "nested"
|
||||
ret["retcode"] = salt.defaults.exitcodes.EX_GENERIC
|
||||
except TypeError as exc:
|
||||
# XXX: This can ba extreemly missleading when something outside of a
|
||||
# execution module call raises a TypeError. Make this it's own
|
||||
# type of exception when we start validating state and
|
||||
# execution argument module inputs.
|
||||
msg = "Passed invalid arguments to {}: {}\n{}".format(
|
||||
function_name,
|
||||
exc,
|
||||
|
@ -2015,11 +2028,11 @@ class Minion(MinionBase):
|
|||
salt.utils.error.fire_exception(
|
||||
salt.exceptions.MinionError(msg), opts, job=data
|
||||
)
|
||||
ret["return"] = "{}: {}".format(msg, traceback.format_exc())
|
||||
ret["return"] = f"{msg}: {traceback.format_exc()}"
|
||||
ret["out"] = "nested"
|
||||
ret["retcode"] = salt.defaults.exitcodes.EX_GENERIC
|
||||
else:
|
||||
docs = minion_instance.functions["sys.doc"]("{}*".format(function_name))
|
||||
docs = minion_instance.functions["sys.doc"](f"{function_name}*")
|
||||
if docs:
|
||||
docs[function_name] = minion_instance.functions.missing_fun_string(
|
||||
function_name
|
||||
|
@ -2069,7 +2082,7 @@ class Minion(MinionBase):
|
|||
ret["id"] = opts["id"]
|
||||
for returner in set(data["ret"].split(",")):
|
||||
try:
|
||||
returner_str = "{}.returner".format(returner)
|
||||
returner_str = f"{returner}.returner"
|
||||
if returner_str in minion_instance.returners:
|
||||
minion_instance.returners[returner_str](ret)
|
||||
else:
|
||||
|
@ -2096,9 +2109,7 @@ class Minion(MinionBase):
|
|||
minion_instance.gen_modules()
|
||||
fn_ = os.path.join(minion_instance.proc_dir, data["jid"])
|
||||
|
||||
salt.utils.process.appendproctitle(
|
||||
"{}._thread_multi_return".format(cls.__name__)
|
||||
)
|
||||
salt.utils.process.appendproctitle(f"{cls.__name__}._thread_multi_return")
|
||||
|
||||
sdata = {"pid": os.getpid()}
|
||||
sdata.update(data)
|
||||
|
@ -2175,7 +2186,7 @@ class Minion(MinionBase):
|
|||
for returner in set(data["ret"].split(",")):
|
||||
ret["id"] = opts["id"]
|
||||
try:
|
||||
minion_instance.returners["{}.returner".format(returner)](ret)
|
||||
minion_instance.returners[f"{returner}.returner"](ret)
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
log.error("The return failed for job %s: %s", data["jid"], exc)
|
||||
|
||||
|
@ -2700,11 +2711,14 @@ class Minion(MinionBase):
|
|||
notify=data.get("notify", False),
|
||||
)
|
||||
elif tag.startswith("__master_req_channel_payload"):
|
||||
yield _minion.req_channel.send(
|
||||
data,
|
||||
timeout=_minion._return_retry_timer(),
|
||||
tries=_minion.opts["return_retry_tries"],
|
||||
)
|
||||
try:
|
||||
yield _minion.req_channel.send(
|
||||
data,
|
||||
timeout=_minion._return_retry_timer(),
|
||||
tries=_minion.opts["return_retry_tries"],
|
||||
)
|
||||
except salt.exceptions.SaltReqTimeoutError:
|
||||
log.error("Timeout encountered while sending %r request", data)
|
||||
elif tag.startswith("pillar_refresh"):
|
||||
yield _minion.pillar_refresh(
|
||||
force_refresh=data.get("force_refresh", False),
|
||||
|
@ -3307,7 +3321,7 @@ class Syndic(Minion):
|
|||
data["to"],
|
||||
io_loop=self.io_loop,
|
||||
callback=lambda _: None,
|
||||
**kwargs
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
def _send_req_sync(self, load, timeout):
|
||||
|
@ -3964,8 +3978,8 @@ class SProxyMinion(SMinion):
|
|||
self.proxy.reload_modules()
|
||||
|
||||
if (
|
||||
"{}.init".format(fq_proxyname) not in self.proxy
|
||||
or "{}.shutdown".format(fq_proxyname) not in self.proxy
|
||||
f"{fq_proxyname}.init" not in self.proxy
|
||||
or f"{fq_proxyname}.shutdown" not in self.proxy
|
||||
):
|
||||
errmsg = (
|
||||
"Proxymodule {} is missing an init() or a shutdown() or both. ".format(
|
||||
|
@ -3978,7 +3992,7 @@ class SProxyMinion(SMinion):
|
|||
raise SaltSystemExit(code=salt.defaults.exitcodes.EX_GENERIC, msg=errmsg)
|
||||
|
||||
self.module_executors = self.proxy.get(
|
||||
"{}.module_executors".format(fq_proxyname), lambda: []
|
||||
f"{fq_proxyname}.module_executors", lambda: []
|
||||
)()
|
||||
proxy_init_fn = self.proxy[fq_proxyname + ".init"]
|
||||
proxy_init_fn(self.opts)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
"""
|
||||
A dead simple module wrapping calls to the Chocolatey package manager
|
||||
A module that wraps calls to the Chocolatey package manager
|
||||
(http://chocolatey.org)
|
||||
|
||||
.. versionadded:: 2014.1.0
|
||||
|
@ -40,13 +40,10 @@ def __virtual__():
|
|||
salt-minion running as SYSTEM.
|
||||
"""
|
||||
if not salt.utils.platform.is_windows():
|
||||
return (False, "Cannot load module chocolatey: Chocolatey requires Windows")
|
||||
return False, "Chocolatey: Requires Windows"
|
||||
|
||||
if __grains__["osrelease"] in ("XP", "2003Server"):
|
||||
return (
|
||||
False,
|
||||
"Cannot load module chocolatey: Chocolatey requires Windows Vista or later",
|
||||
)
|
||||
return False, "Chocolatey: Requires Windows Vista or later"
|
||||
|
||||
return __virtualname__
|
||||
|
||||
|
@ -355,12 +352,12 @@ def unbootstrap():
|
|||
"""
|
||||
Uninstall chocolatey from the system by doing the following:
|
||||
|
||||
.. versionadded:: 3001
|
||||
|
||||
- Delete the Chocolatey Directory
|
||||
- Remove Chocolatey from the path
|
||||
- Remove Chocolatey environment variables
|
||||
|
||||
.. versionadded:: 3001
|
||||
|
||||
Returns:
|
||||
list: A list of items that were removed, otherwise an empty list
|
||||
|
||||
|
@ -441,10 +438,10 @@ def list_(
|
|||
None is passed. Default is None.
|
||||
|
||||
local_only (bool):
|
||||
Display packages only installed locally. Default is False.
|
||||
Only display packages that are installed locally. Default is False.
|
||||
|
||||
exact (bool):
|
||||
Display only packages that match ``narrow`` exactly. Default is
|
||||
Only display packages that match ``narrow`` exactly. Default is
|
||||
False.
|
||||
|
||||
.. versionadded:: 2017.7.0
|
||||
|
@ -463,8 +460,14 @@ def list_(
|
|||
# https://docs.chocolatey.org/en-us/guides/upgrading-to-chocolatey-v2-v6
|
||||
if Version(chocolatey_version()) < Version("2.0.0"):
|
||||
cmd = [choc_path, "list"]
|
||||
if local_only:
|
||||
cmd.append("--local-only")
|
||||
else:
|
||||
cmd = [choc_path, "search"]
|
||||
if local_only:
|
||||
# Starting with 2.0.0, list only returns local packages
|
||||
cmd = [choc_path, "list"]
|
||||
else:
|
||||
cmd = [choc_path, "search"]
|
||||
if narrow:
|
||||
cmd.append(narrow)
|
||||
if salt.utils.data.is_true(all_versions):
|
||||
|
@ -473,8 +476,6 @@ def list_(
|
|||
cmd.append("--prerelease")
|
||||
if source:
|
||||
cmd.extend(["--source", source])
|
||||
if local_only:
|
||||
cmd.append("--local-only")
|
||||
if exact:
|
||||
cmd.append("--exact")
|
||||
|
||||
|
@ -589,12 +590,12 @@ def install(
|
|||
|
||||
version (str):
|
||||
Install a specific version of the package. Defaults to latest
|
||||
version. Default is None.
|
||||
version. Default is ``None``.
|
||||
|
||||
source (str):
|
||||
Chocolatey repository (directory, share or remote URL feed) the
|
||||
package comes from. Defaults to the official Chocolatey feed.
|
||||
Default is None.
|
||||
Default is ``None``.
|
||||
|
||||
Alternate Sources:
|
||||
|
||||
|
@ -606,36 +607,38 @@ def install(
|
|||
|
||||
force (bool):
|
||||
Reinstall the current version of an existing package. Do not use
|
||||
with ``allow_multiple``. Default is False.
|
||||
with ``allow_multiple``. Default is ``False``.
|
||||
|
||||
pre_versions (bool):
|
||||
Include pre-release packages. Default is False.
|
||||
Include pre-release packages. Default is ``False``.
|
||||
|
||||
install_args (str):
|
||||
A list of install arguments you want to pass to the installation
|
||||
process i.e product key or feature list. Default is None.
|
||||
process, i.e. product key or feature list. Default is ``None``.
|
||||
|
||||
override_args (bool):
|
||||
Set to true if you want to override the original install arguments
|
||||
(for the native installer) in the package and use your own. When
|
||||
this is set to False install_args will be appended to the end of the
|
||||
default arguments. Default is None.
|
||||
this is set to ``False`` install_args will be appended to the end of
|
||||
the default arguments. Default is ``None``.
|
||||
|
||||
force_x86 (bool):
|
||||
Force x86 (32bit) installation on 64 bit systems. Default is False.
|
||||
Force x86 (32bit) installation on 64bit systems. Default is
|
||||
``False``.
|
||||
|
||||
package_args (str):
|
||||
Arguments you want to pass to the package. Default is None.
|
||||
Arguments you want to pass to the package. Default is ``None``.
|
||||
|
||||
allow_multiple (bool):
|
||||
Allow multiple versions of the package to be installed. Do not use
|
||||
with ``force``. Does not work with all packages. Default is False.
|
||||
with ``force``. Does not work with all packages. Default is
|
||||
``False``.
|
||||
|
||||
.. versionadded:: 2017.7.0
|
||||
|
||||
execution_timeout (str):
|
||||
Chocolatey execution timeout value you want to pass to the
|
||||
installation process. Default is None.
|
||||
installation process. Default is ``None``.
|
||||
|
||||
.. versionadded:: 2018.3.0
|
||||
|
||||
|
@ -700,18 +703,21 @@ def install_cygwin(name, install_args=None, override_args=False):
|
|||
"""
|
||||
Instructs Chocolatey to install a package via Cygwin.
|
||||
|
||||
name
|
||||
The name of the package to be installed. Only accepts a single argument.
|
||||
Args:
|
||||
|
||||
install_args
|
||||
A list of install arguments you want to pass to the installation process
|
||||
i.e product key or feature list
|
||||
name (str):
|
||||
The name of the package to be installed. Only accepts a single
|
||||
argument.
|
||||
|
||||
override_args
|
||||
Set to true if you want to override the original install arguments (for
|
||||
the native installer) in the package and use your own. When this is set
|
||||
to False install_args will be appended to the end of the default
|
||||
arguments
|
||||
install_args (str):
|
||||
A list of install arguments you want to pass to the installation
|
||||
process, i.e. product key or feature list
|
||||
|
||||
override_args (bool):
|
||||
Set to ``True`` if you want to override the original install
|
||||
arguments (for the native installer) in the package and use your
|
||||
own. When this is set to ``False`` install_args will be appended to
|
||||
the end of the default arguments
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -729,22 +735,25 @@ def install_gem(name, version=None, install_args=None, override_args=False):
|
|||
"""
|
||||
Instructs Chocolatey to install a package via Ruby's Gems.
|
||||
|
||||
name
|
||||
The name of the package to be installed. Only accepts a single argument.
|
||||
Args:
|
||||
|
||||
version
|
||||
Install a specific version of the package. Defaults to latest version
|
||||
available.
|
||||
name (str):
|
||||
The name of the package to be installed. Only accepts a single
|
||||
argument.
|
||||
|
||||
install_args
|
||||
A list of install arguments you want to pass to the installation process
|
||||
i.e product key or feature list
|
||||
version (str):
|
||||
Install a specific version of the package. Defaults to the latest
|
||||
version available.
|
||||
|
||||
override_args
|
||||
Set to true if you want to override the original install arguments (for
|
||||
the native installer) in the package and use your own. When this is set
|
||||
to False install_args will be appended to the end of the default
|
||||
arguments
|
||||
install_args (str):
|
||||
A list of install arguments you want to pass to the installation
|
||||
process, i.e. product key or feature list
|
||||
|
||||
override_args (bool):
|
||||
Set to ``True`` if you want to override the original install
|
||||
arguments (for the native installer) in the package and use your
|
||||
own. When this is set to ``False`` install_args will be appended to
|
||||
the end of the default arguments
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -773,16 +782,19 @@ def install_missing(name, version=None, source=None):
|
|||
``installmissing`` is deprecated as of that version and will be removed
|
||||
in Chocolatey 1.0.
|
||||
|
||||
name
|
||||
The name of the package to be installed. Only accepts a single argument.
|
||||
Args:
|
||||
|
||||
version
|
||||
Install a specific version of the package. Defaults to latest version
|
||||
available.
|
||||
name (str):
|
||||
The name of the package to be installed. Only accepts a single
|
||||
argument.
|
||||
|
||||
source
|
||||
Chocolatey repository (directory, share or remote URL feed) the package
|
||||
comes from. Defaults to the official Chocolatey feed.
|
||||
version (str):
|
||||
Install a specific version of the package. Defaults to the latest
|
||||
version available.
|
||||
|
||||
source (str):
|
||||
Chocolatey repository (directory, share or remote URL feed) the
|
||||
package comes from. Defaults to the official Chocolatey feed.
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -816,22 +828,25 @@ def install_python(name, version=None, install_args=None, override_args=False):
|
|||
"""
|
||||
Instructs Chocolatey to install a package via Python's easy_install.
|
||||
|
||||
name
|
||||
The name of the package to be installed. Only accepts a single argument.
|
||||
Args:
|
||||
|
||||
version
|
||||
Install a specific version of the package. Defaults to latest version
|
||||
available.
|
||||
name (str):
|
||||
The name of the package to be installed. Only accepts a single
|
||||
argument.
|
||||
|
||||
install_args
|
||||
A list of install arguments you want to pass to the installation process
|
||||
i.e product key or feature list
|
||||
version (str):
|
||||
Install a specific version of the package. Defaults to the latest
|
||||
version available.
|
||||
|
||||
override_args
|
||||
Set to true if you want to override the original install arguments (for
|
||||
the native installer) in the package and use your own. When this is set
|
||||
to False install_args will be appended to the end of the default
|
||||
arguments
|
||||
install_args (str):
|
||||
A list of install arguments you want to pass to the installation
|
||||
process, i.e. product key or feature list.
|
||||
|
||||
override_args (bool):
|
||||
Set to ``True`` if you want to override the original install
|
||||
arguments (for the native installer) in the package and use your
|
||||
own. When this is set to ``False`` install_args will be appended to
|
||||
the end of the default arguments.
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -855,8 +870,11 @@ def install_windowsfeatures(name):
|
|||
Instructs Chocolatey to install a Windows Feature via the Deployment Image
|
||||
Servicing and Management tool.
|
||||
|
||||
name
|
||||
The name of the feature to be installed. Only accepts a single argument.
|
||||
Args:
|
||||
|
||||
name (str):
|
||||
The name of the feature to be installed. Only accepts a single
|
||||
argument.
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -871,18 +889,21 @@ def install_webpi(name, install_args=None, override_args=False):
|
|||
"""
|
||||
Instructs Chocolatey to install a package via the Microsoft Web PI service.
|
||||
|
||||
name
|
||||
The name of the package to be installed. Only accepts a single argument.
|
||||
Args:
|
||||
|
||||
install_args
|
||||
A list of install arguments you want to pass to the installation process
|
||||
i.e product key or feature list
|
||||
name (str):
|
||||
The name of the package to be installed. Only accepts a single
|
||||
argument.
|
||||
|
||||
override_args
|
||||
Set to true if you want to override the original install arguments (for
|
||||
the native installer) in the package and use your own. When this is set
|
||||
to False install_args will be appended to the end of the default
|
||||
arguments
|
||||
install_args (str):
|
||||
A list of install arguments you want to pass to the installation
|
||||
process, i.e. product key or feature list.
|
||||
|
||||
override_args (bool):
|
||||
Set to ``True`` if you want to override the original install
|
||||
arguments (for the native installer) in the package and use your
|
||||
own. When this is set to ``False`` install_args will be appended to
|
||||
the end of the default arguments.
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -896,27 +917,35 @@ def install_webpi(name, install_args=None, override_args=False):
|
|||
)
|
||||
|
||||
|
||||
def uninstall(name, version=None, uninstall_args=None, override_args=False):
|
||||
def uninstall(
|
||||
name,
|
||||
version=None,
|
||||
uninstall_args=None,
|
||||
override_args=False,
|
||||
force=False,
|
||||
):
|
||||
"""
|
||||
Instructs Chocolatey to uninstall a package.
|
||||
|
||||
name
|
||||
The name of the package to be uninstalled. Only accepts a single
|
||||
argument.
|
||||
Args:
|
||||
|
||||
version
|
||||
Uninstalls a specific version of the package. Defaults to latest version
|
||||
installed.
|
||||
name (str):
|
||||
The name of the package to be uninstalled. Only accepts a single
|
||||
argument.
|
||||
|
||||
uninstall_args
|
||||
A list of uninstall arguments you want to pass to the uninstallation
|
||||
process i.e product key or feature list
|
||||
version (str):
|
||||
Uninstalls a specific version of the package. Defaults to the latest
|
||||
version installed.
|
||||
|
||||
override_args
|
||||
Set to true if you want to override the original uninstall arguments
|
||||
(for the native uninstaller) in the package and use your own. When this
|
||||
is set to False uninstall_args will be appended to the end of the
|
||||
default arguments
|
||||
uninstall_args (str):
|
||||
A list of uninstall arguments you want to pass to the uninstallation
|
||||
process, i.e. product key or feature list.
|
||||
|
||||
override_args
|
||||
Set to ``True`` if you want to override the original uninstall
|
||||
arguments (for the native uninstaller) in the package and use your
|
||||
own. When this is set to ``False`` uninstall_args will be appended
|
||||
to the end of the default arguments.
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -933,11 +962,13 @@ def uninstall(name, version=None, uninstall_args=None, override_args=False):
|
|||
if uninstall_args:
|
||||
cmd.extend(["--uninstallarguments", uninstall_args])
|
||||
if override_args:
|
||||
cmd.extend(["--overridearguments"])
|
||||
cmd.append("--overridearguments")
|
||||
if force:
|
||||
cmd.append("--force")
|
||||
cmd.extend(_yes())
|
||||
result = __salt__["cmd.run_all"](cmd, python_shell=False)
|
||||
|
||||
if result["retcode"] not in [0, 1605, 1614, 1641]:
|
||||
if result["retcode"] not in [0, 1, 1605, 1614, 1641]:
|
||||
err = "Running chocolatey failed: {}".format(result["stdout"])
|
||||
raise CommandExecutionError(err)
|
||||
|
||||
|
@ -976,26 +1007,27 @@ def upgrade(
|
|||
package comes from. Defaults to the official Chocolatey feed.
|
||||
|
||||
force (bool):
|
||||
Reinstall the **same** version already installed
|
||||
Reinstall the **same** version already installed.
|
||||
|
||||
pre_versions (bool):
|
||||
Include pre-release packages in comparison. Defaults to False.
|
||||
Include pre-release packages in comparison. Defaults to ``False``.
|
||||
|
||||
install_args (str):
|
||||
A list of install arguments you want to pass to the installation
|
||||
process i.e product key or feature list
|
||||
process, i.e. product key or feature list.
|
||||
|
||||
override_args (str):
|
||||
Set to true if you want to override the original install arguments
|
||||
(for the native installer) in the package and use your own. When
|
||||
this is set to False install_args will be appended to the end of the
|
||||
default arguments
|
||||
override_args (bool):
|
||||
Set to ``True`` if you want to override the original install
|
||||
arguments (for the native installer) in the package and use your
|
||||
own. When this is set to ``False`` install_args will be appended to
|
||||
the end of the default arguments.
|
||||
|
||||
force_x86
|
||||
Force x86 (32bit) installation on 64 bit systems. Defaults to false.
|
||||
force_x86 (bool):
|
||||
Force x86 (32bit) installation on 64bit systems. Defaults to
|
||||
``False``.
|
||||
|
||||
package_args
|
||||
A list of arguments you want to pass to the package
|
||||
package_args (str):
|
||||
A list of arguments you want to pass to the package.
|
||||
|
||||
Returns:
|
||||
str: Results of the ``chocolatey`` command
|
||||
|
@ -1043,16 +1075,18 @@ def update(name, source=None, pre_versions=False):
|
|||
"""
|
||||
Instructs Chocolatey to update packages on the system.
|
||||
|
||||
name
|
||||
The name of the package to update, or "all" to update everything
|
||||
installed on the system.
|
||||
Args:
|
||||
|
||||
source
|
||||
Chocolatey repository (directory, share or remote URL feed) the package
|
||||
comes from. Defaults to the official Chocolatey feed.
|
||||
name (str):
|
||||
The name of the package to update, or "all" to update everything
|
||||
installed on the system.
|
||||
|
||||
pre_versions
|
||||
Include pre-release packages in comparison. Defaults to False.
|
||||
source (str):
|
||||
Chocolatey repository (directory, share or remote URL feed) the
|
||||
package comes from. Defaults to the official Chocolatey feed.
|
||||
|
||||
pre_versions (bool):
|
||||
Include pre-release packages in comparison. Defaults to ``False``.
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -1096,15 +1130,15 @@ def version(name, check_remote=False, source=None, pre_versions=False):
|
|||
|
||||
check_remote (bool):
|
||||
Get the version number of the latest package from the remote feed.
|
||||
Default is False.
|
||||
Default is ``False``.
|
||||
|
||||
source (str):
|
||||
Chocolatey repository (directory, share or remote URL feed) the
|
||||
package comes from. Defaults to the official Chocolatey feed.
|
||||
Default is None.
|
||||
Default is ``None``.
|
||||
|
||||
pre_versions (bool):
|
||||
Include pre-release packages in comparison. Default is False.
|
||||
Include pre-release packages in comparison. Default is ``False``.
|
||||
|
||||
Returns:
|
||||
dict: A dictionary of currently installed software and versions
|
||||
|
@ -1120,21 +1154,23 @@ def version(name, check_remote=False, source=None, pre_versions=False):
|
|||
|
||||
packages = {}
|
||||
lower_name = name.lower()
|
||||
for pkg in installed:
|
||||
if lower_name in pkg.lower():
|
||||
packages[pkg] = installed[pkg]
|
||||
if installed:
|
||||
for pkg in installed:
|
||||
if lower_name == pkg.lower():
|
||||
packages.setdefault(pkg, {})
|
||||
packages[pkg]["installed"] = installed[pkg]
|
||||
|
||||
if check_remote:
|
||||
available = list_(narrow=name, pre_versions=pre_versions, source=source)
|
||||
|
||||
for pkg in packages:
|
||||
# Grab the current version from the package that was installed
|
||||
packages[pkg] = {"installed": installed[pkg]}
|
||||
|
||||
# If there's a remote package available, then also include that
|
||||
# in the dictionary that we return.
|
||||
if pkg in available:
|
||||
packages[pkg]["available"] = available[pkg]
|
||||
# If there's a remote package available, then also include that
|
||||
# in the dictionary that we return.
|
||||
available = list_(
|
||||
narrow=name, local_only=False, pre_versions=pre_versions, source=source
|
||||
)
|
||||
if available:
|
||||
for pkg in available:
|
||||
if lower_name == pkg.lower():
|
||||
packages.setdefault(pkg, {})
|
||||
packages[pkg]["available"] = available[pkg]
|
||||
|
||||
return packages
|
||||
|
||||
|
@ -1143,25 +1179,27 @@ def add_source(name, source_location, username=None, password=None, priority=Non
|
|||
"""
|
||||
Instructs Chocolatey to add a source.
|
||||
|
||||
name
|
||||
The name of the source to be added as a chocolatey repository.
|
||||
Args:
|
||||
|
||||
source
|
||||
Location of the source you want to work with.
|
||||
name (str):
|
||||
The name of the source to be added as a chocolatey repository.
|
||||
|
||||
username
|
||||
Provide username for chocolatey sources that need authentication
|
||||
credentials.
|
||||
source (str):
|
||||
Location of the source you want to work with.
|
||||
|
||||
password
|
||||
Provide password for chocolatey sources that need authentication
|
||||
credentials.
|
||||
username (str):
|
||||
Provide username for chocolatey sources that need authentication
|
||||
credentials.
|
||||
|
||||
priority
|
||||
The priority order of this source as compared to other sources,
|
||||
lower is better. Defaults to 0 (no priority). All priorities
|
||||
above 0 will be evaluated first, then zero-based values will be
|
||||
evaluated in config file order.
|
||||
password (str):
|
||||
Provide password for chocolatey sources that need authentication
|
||||
credentials.
|
||||
|
||||
priority (int):
|
||||
The priority order of this source as compared to other sources,
|
||||
lower is better. Defaults to 0 (no priority). All priorities
|
||||
above 0 will be evaluated first, then zero-based values will be
|
||||
evaluated in config file order.
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -1200,12 +1238,13 @@ def _change_source_state(name, state):
|
|||
"""
|
||||
Instructs Chocolatey to change the state of a source.
|
||||
|
||||
name
|
||||
Name of the repository to affect.
|
||||
Args:
|
||||
|
||||
state
|
||||
State in which you want the chocolatey repository.
|
||||
name (str):
|
||||
Name of the repository to affect.
|
||||
|
||||
state (str):
|
||||
State in which you want the chocolatey repository.
|
||||
"""
|
||||
cmd = [_find_chocolatey(), "source", state, "--name", name]
|
||||
result = __salt__["cmd.run_all"](cmd, python_shell=False)
|
||||
|
@ -1221,8 +1260,10 @@ def enable_source(name):
|
|||
"""
|
||||
Instructs Chocolatey to enable a source.
|
||||
|
||||
name
|
||||
Name of the source repository to enable.
|
||||
Args:
|
||||
|
||||
name (str):
|
||||
Name of the source repository to enable.
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -1238,8 +1279,10 @@ def disable_source(name):
|
|||
"""
|
||||
Instructs Chocolatey to disable a source.
|
||||
|
||||
name
|
||||
Name of the source repository to disable.
|
||||
Args:
|
||||
|
||||
name (str):
|
||||
Name of the source repository to disable.
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
"""
|
||||
This module helps include encrypted passwords in pillars, grains and salt state files.
|
||||
|
||||
:depends: libnacl, https://github.com/saltstack/libnacl
|
||||
:depends: PyNaCl, https://github.com/pyca/pynacl
|
||||
|
||||
This is often useful if you wish to store your pillars in source control or
|
||||
share your pillar data with others that you trust. I don't advise making your pillars public
|
||||
|
@ -137,9 +137,9 @@ Optional small program to encrypt data without needing salt modules.
|
|||
.. code-block:: python
|
||||
|
||||
#!/bin/python3
|
||||
import sys, base64, libnacl.sealed
|
||||
import sys, base64, nacl.public
|
||||
pk = base64.b64decode('YOURPUBKEY')
|
||||
b = libnacl.sealed.SealedBox(pk)
|
||||
b = nacl.public.SealedBox(pk)
|
||||
data = sys.stdin.buffer.read()
|
||||
print(base64.b64encode(b.encrypt(data)).decode())
|
||||
|
||||
|
@ -163,7 +163,7 @@ def __virtual__():
|
|||
|
||||
def keygen(sk_file=None, pk_file=None, **kwargs):
|
||||
"""
|
||||
Use libnacl to generate a keypair.
|
||||
Use PyNaCl to generate a keypair.
|
||||
|
||||
If no `sk_file` is defined return a keypair.
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import fnmatch
|
|||
import logging
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
|
||||
import tornado.gen
|
||||
|
@ -260,6 +261,7 @@ class AsyncRemotePillar(RemotePillarMixin):
|
|||
if self.ext:
|
||||
load["ext"] = self.ext
|
||||
try:
|
||||
start = time.monotonic()
|
||||
ret_pillar = yield self.channel.crypted_transfer_decode_dictentry(
|
||||
load,
|
||||
dictkey="pillar",
|
||||
|
@ -267,6 +269,10 @@ class AsyncRemotePillar(RemotePillarMixin):
|
|||
except salt.crypt.AuthenticationError as exc:
|
||||
log.error(exc.message)
|
||||
raise SaltClientError("Exception getting pillar.")
|
||||
except salt.exceptions.SaltReqTimeoutError:
|
||||
raise SaltClientError(
|
||||
f"Pillar timed out after {int(time.monotonic() - start)} seconds"
|
||||
)
|
||||
except Exception: # pylint: disable=broad-except
|
||||
log.exception("Exception getting pillar:")
|
||||
raise SaltClientError("Exception getting pillar.")
|
||||
|
@ -351,10 +357,23 @@ class RemotePillar(RemotePillarMixin):
|
|||
}
|
||||
if self.ext:
|
||||
load["ext"] = self.ext
|
||||
ret_pillar = self.channel.crypted_transfer_decode_dictentry(
|
||||
load,
|
||||
dictkey="pillar",
|
||||
)
|
||||
|
||||
try:
|
||||
start = time.monotonic()
|
||||
ret_pillar = self.channel.crypted_transfer_decode_dictentry(
|
||||
load,
|
||||
dictkey="pillar",
|
||||
)
|
||||
except salt.crypt.AuthenticationError as exc:
|
||||
log.error(exc.message)
|
||||
raise SaltClientError("Exception getting pillar.")
|
||||
except salt.exceptions.SaltReqTimeoutError:
|
||||
raise SaltClientError(
|
||||
f"Pillar timed out after {int(time.monotonic() - start)} seconds"
|
||||
)
|
||||
except Exception: # pylint: disable=broad-except
|
||||
log.exception("Exception getting pillar:")
|
||||
raise SaltClientError("Exception getting pillar.")
|
||||
|
||||
if not isinstance(ret_pillar, dict):
|
||||
log.error(
|
||||
|
@ -722,9 +741,7 @@ class Pillar:
|
|||
)
|
||||
)
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
errors.append(
|
||||
"Rendering Primary Top file failed, render error:\n{}".format(exc)
|
||||
)
|
||||
errors.append(f"Rendering Primary Top file failed, render error:\n{exc}")
|
||||
log.exception("Pillar rendering failed for minion %s", self.minion_id)
|
||||
|
||||
# Search initial top files for includes
|
||||
|
@ -926,10 +943,10 @@ class Pillar:
|
|||
saltenv,
|
||||
sls,
|
||||
_pillar_rend=True,
|
||||
**defaults
|
||||
**defaults,
|
||||
)
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
msg = "Rendering SLS '{}' failed, render error:\n{}".format(sls, exc)
|
||||
msg = f"Rendering SLS '{sls}' failed, render error:\n{exc}"
|
||||
log.critical(msg, exc_info=True)
|
||||
if self.opts.get("pillar_safe_render_error", True):
|
||||
errors.append(
|
||||
|
@ -942,7 +959,7 @@ class Pillar:
|
|||
nstate = None
|
||||
if state:
|
||||
if not isinstance(state, dict):
|
||||
msg = "SLS '{}' does not render to a dictionary".format(sls)
|
||||
msg = f"SLS '{sls}' does not render to a dictionary"
|
||||
log.error(msg)
|
||||
errors.append(msg)
|
||||
else:
|
||||
|
@ -1079,7 +1096,7 @@ class Pillar:
|
|||
"a sign of a malformed pillar sls file. Returned "
|
||||
"errors: %s",
|
||||
sls,
|
||||
", ".join(["'{}'".format(e) for e in errors]),
|
||||
", ".join([f"'{e}'" for e in errors]),
|
||||
)
|
||||
continue
|
||||
pillar = merge(
|
||||
|
@ -1105,7 +1122,7 @@ class Pillar:
|
|||
self.minion_id,
|
||||
pillar,
|
||||
extra_minion_data=self.extra_minion_data,
|
||||
**val
|
||||
**val,
|
||||
)
|
||||
else:
|
||||
ext = self.ext_pillars[key](self.minion_id, pillar, **val)
|
||||
|
@ -1115,7 +1132,7 @@ class Pillar:
|
|||
self.minion_id,
|
||||
pillar,
|
||||
*val,
|
||||
extra_minion_data=self.extra_minion_data
|
||||
extra_minion_data=self.extra_minion_data,
|
||||
)
|
||||
else:
|
||||
ext = self.ext_pillars[key](self.minion_id, pillar, *val)
|
||||
|
@ -1329,7 +1346,7 @@ class Pillar:
|
|||
if ptr is not None:
|
||||
ptr[child] = ret
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
msg = "Failed to decrypt pillar key '{}': {}".format(key, exc)
|
||||
msg = f"Failed to decrypt pillar key '{key}': {exc}"
|
||||
errors.append(msg)
|
||||
log.error(msg, exc_info=True)
|
||||
return errors
|
||||
|
|
|
@ -10,8 +10,7 @@ The typical use-case would be to use ciphers in your pillar data, and keep a
|
|||
secret key on your master. You can put the public key in source control so that
|
||||
developers can add new secrets quickly and easily.
|
||||
|
||||
This renderer requires the libsodium library binary and libnacl >= 1.5.1
|
||||
python package (support for sealed boxes came in 1.5.1 version).
|
||||
This renderer requires the libsodium library binary and PyNacl >= 1.0
|
||||
|
||||
|
||||
Setup
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
"""
|
||||
This module helps include encrypted passwords in pillars, grains and salt state files.
|
||||
|
||||
:depends: libnacl, https://github.com/saltstack/libnacl
|
||||
:depends: PyNaCl, https://github.com/pyca/pynacl
|
||||
|
||||
This is often useful if you wish to store your pillars in source control or
|
||||
share your pillar data with others that you trust. I don't advise making your pillars public
|
||||
|
@ -125,7 +125,7 @@ def __virtual__():
|
|||
|
||||
def keygen(sk_file=None, pk_file=None, **kwargs):
|
||||
"""
|
||||
Use libnacl to generate a keypair.
|
||||
Use PyNaCL to generate a keypair.
|
||||
|
||||
If no `sk_file` is defined return a keypair.
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
"""
|
||||
Manage Chocolatey package installs
|
||||
Manage Windows Packages using Chocolatey
|
||||
.. versionadded:: 2016.3.0
|
||||
|
||||
.. note::
|
||||
|
@ -20,7 +20,7 @@ def __virtual__():
|
|||
"""
|
||||
if "chocolatey.install" in __salt__:
|
||||
return "chocolatey"
|
||||
return (False, "chocolatey module could not be loaded")
|
||||
return False, "chocolatey module could not be loaded"
|
||||
|
||||
|
||||
def installed(
|
||||
|
@ -45,50 +45,55 @@ def installed(
|
|||
The name of the package to be installed. Required.
|
||||
|
||||
version (str):
|
||||
Install a specific version of the package. Defaults to latest
|
||||
version. If the version is different to the one installed then the
|
||||
specified version will be installed. Default is None.
|
||||
Install a specific version of the package. Defaults to the latest
|
||||
version. If the version is different to the one installed, then the
|
||||
specified version will be installed. Default is ``None``.
|
||||
|
||||
source (str):
|
||||
Chocolatey repository (directory, share or remote URL, feed).
|
||||
Defaults to the official Chocolatey feed. Default is None.
|
||||
``None`` defaults to the official Chocolatey feed. Default is
|
||||
``None``.
|
||||
|
||||
force (bool):
|
||||
Reinstall the current version of an existing package. Do not use
|
||||
with ``allow_multiple``. Default is False.
|
||||
with ``allow_multiple``. Default is ``False``.
|
||||
|
||||
pre_versions (bool):
|
||||
Include pre-release packages. Default is False.
|
||||
Include pre-release packages. Default is ``False``.
|
||||
|
||||
install_args (str):
|
||||
Install arguments you want to pass to the installation process, i.e
|
||||
product key or feature list. Default is None.
|
||||
Install arguments you want to pass to the installation process, i.e.
|
||||
product key or feature list. Default is ``None``.
|
||||
|
||||
override_args (bool):
|
||||
Set to True if you want to override the original install arguments
|
||||
(for the native installer) in the package and use your own. When
|
||||
this is set to False install_args will be appended to the end of the
|
||||
default arguments. Default is False.
|
||||
Set to ``True`` to override the original install arguments (for the
|
||||
native installer) in the package and use your own. When this is set
|
||||
to ``False``, install_args will be appended to the end of the
|
||||
default arguments. Default is ``False``.
|
||||
|
||||
force_x86 (bool):
|
||||
Force x86 (32bit) installation on 64 bit systems. Default is False.
|
||||
Force x86 (32bit) installation on 64bit systems. Default is
|
||||
``False``.
|
||||
|
||||
package_args (str):
|
||||
Arguments you want to pass to the package. Default is None.
|
||||
Arguments you want to pass to the package. Default is ``None``.
|
||||
|
||||
allow_multiple (bool):
|
||||
Allow mulitiple versions of the package to be installed. Do not use
|
||||
with ``force``. Does not work with all packages. Default is False.
|
||||
Allow multiple versions of the package to be installed. Do not use
|
||||
with ``force``. Does not work with all packages. Default is
|
||||
``False``.
|
||||
|
||||
.. versionadded:: 2017.7.0
|
||||
|
||||
execution_timeout (str):
|
||||
Chocolatey execution timeout value you want to pass to the
|
||||
installation process. Default is None.
|
||||
installation process. Default is ``None``.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
Installsomepackage:
|
||||
install_some_package:
|
||||
chocolatey.installed:
|
||||
- name: packagename
|
||||
- version: '12.04'
|
||||
|
@ -109,9 +114,9 @@ def installed(
|
|||
# Package not installed
|
||||
if name.lower() not in [package.lower() for package in pre_install.keys()]:
|
||||
if version:
|
||||
ret["changes"] = {name: "Version {} will be installed".format(version)}
|
||||
ret["comment"] = f"{name} {version} will be installed"
|
||||
else:
|
||||
ret["changes"] = {name: "Latest version will be installed"}
|
||||
ret["comment"] = f"Latest version of {name} will be installed"
|
||||
|
||||
# Package installed
|
||||
else:
|
||||
|
@ -124,59 +129,36 @@ def installed(
|
|||
if name.lower() == pkg.lower():
|
||||
full_name = pkg
|
||||
|
||||
installed_version = version_info[full_name]["installed"][0]
|
||||
installed_version = version_info[full_name].get("installed")[0]
|
||||
|
||||
if version:
|
||||
if salt.utils.versions.compare(
|
||||
ver1=installed_version, oper="==", ver2=version
|
||||
):
|
||||
if force:
|
||||
ret["changes"] = {
|
||||
name: "Version {} will be reinstalled".format(version)
|
||||
}
|
||||
ret["comment"] = "Reinstall {} {}".format(full_name, version)
|
||||
ret["comment"] = f"{name} {version} will be reinstalled"
|
||||
else:
|
||||
ret["comment"] = "{} {} is already installed".format(name, version)
|
||||
if __opts__["test"]:
|
||||
ret["result"] = None
|
||||
return ret
|
||||
ret["comment"] = f"{name} {version} is already installed"
|
||||
else:
|
||||
if allow_multiple:
|
||||
ret["changes"] = {
|
||||
name: (
|
||||
"Version {} will be installed side by side with "
|
||||
"Version {} if supported".format(version, installed_version)
|
||||
)
|
||||
}
|
||||
ret["comment"] = "Install {0} {1} side-by-side with {0} {2}".format(
|
||||
full_name, version, installed_version
|
||||
)
|
||||
ret[
|
||||
"comment"
|
||||
] = f"{name} {version} will be installed side by side with {name} {installed_version} if supported"
|
||||
else:
|
||||
ret["changes"] = {
|
||||
name: "Version {} will be installed over Version {}".format(
|
||||
version, installed_version
|
||||
)
|
||||
}
|
||||
ret["comment"] = "Install {0} {1} over {0} {2}".format(
|
||||
full_name, version, installed_version
|
||||
)
|
||||
ret[
|
||||
"comment"
|
||||
] = f"{name} {version} will be installed over {name} {installed_version}"
|
||||
force = True
|
||||
else:
|
||||
version = installed_version
|
||||
if force:
|
||||
ret["changes"] = {
|
||||
name: "Version {} will be reinstalled".format(version)
|
||||
}
|
||||
ret["comment"] = "Reinstall {} {}".format(full_name, version)
|
||||
ret["comment"] = f"{name} {version} will be reinstalled"
|
||||
else:
|
||||
ret["comment"] = "{} {} is already installed".format(name, version)
|
||||
if __opts__["test"]:
|
||||
ret["result"] = None
|
||||
ret["comment"] = f"{name} {version} is already installed"
|
||||
return ret
|
||||
|
||||
if __opts__["test"]:
|
||||
ret["result"] = None
|
||||
ret["comment"] = "The installation was tested"
|
||||
return ret
|
||||
|
||||
# Install the package
|
||||
|
@ -195,13 +177,12 @@ def installed(
|
|||
)
|
||||
|
||||
if "Running chocolatey failed" not in result:
|
||||
ret["comment"] = f"{name} installed successfully"
|
||||
ret["result"] = True
|
||||
else:
|
||||
ret["comment"] = f"Failed to install {name}"
|
||||
ret["result"] = False
|
||||
|
||||
if not ret["result"]:
|
||||
ret["comment"] = "Failed to install the package {}".format(name)
|
||||
|
||||
# Get list of installed packages after 'chocolatey.install'
|
||||
post_install = __salt__["chocolatey.list"](local_only=True)
|
||||
|
||||
|
@ -212,32 +193,35 @@ def installed(
|
|||
|
||||
def uninstalled(name, version=None, uninstall_args=None, override_args=False):
|
||||
"""
|
||||
Uninstalls a package
|
||||
Uninstalls a chocolatey package
|
||||
|
||||
name
|
||||
The name of the package to be uninstalled
|
||||
Args:
|
||||
|
||||
version
|
||||
Uninstalls a specific version of the package. Defaults to latest
|
||||
version installed.
|
||||
name (str):
|
||||
The name of the package to be uninstalled. Required.
|
||||
|
||||
uninstall_args
|
||||
A list of uninstall arguments you want to pass to the uninstallation
|
||||
process i.e product key or feature list
|
||||
version (str):
|
||||
Uninstalls a specific version of the package. Defaults to the latest
|
||||
version installed.
|
||||
|
||||
override_args
|
||||
Set to true if you want to override the original uninstall arguments (
|
||||
for the native uninstaller)in the package and use your own.
|
||||
When this is set to False uninstall_args will be appended to the end of
|
||||
the default arguments
|
||||
uninstall_args (str):
|
||||
A list of uninstall arguments you want to pass to the uninstallation
|
||||
process, i.e. product key or feature list
|
||||
|
||||
override_args (str):
|
||||
Set to ``True`` if you want to override the original uninstall
|
||||
arguments (for the native uninstaller) in the package and use your
|
||||
own. When this is set to ``False``, uninstall_args will be appended
|
||||
to the end of the default arguments
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
Removemypackage:
|
||||
remove_my_package:
|
||||
chocolatey.uninstalled:
|
||||
- name: mypackage
|
||||
- version: '21.5'
|
||||
|
||||
"""
|
||||
|
||||
ret = {"name": name, "result": True, "changes": {}, "comment": ""}
|
||||
|
@ -248,20 +232,15 @@ def uninstalled(name, version=None, uninstall_args=None, override_args=False):
|
|||
# Determine if package is installed
|
||||
if name.lower() in [package.lower() for package in pre_uninstall.keys()]:
|
||||
try:
|
||||
ret["changes"] = {
|
||||
name: "{} version {} will be removed".format(
|
||||
name, pre_uninstall[name][0]
|
||||
)
|
||||
}
|
||||
ret["comment"] = f"{name} {pre_uninstall[name][0]} will be removed"
|
||||
except KeyError:
|
||||
ret["changes"] = {name: "{} will be removed".format(name)}
|
||||
ret["comment"] = f"{name} will be removed"
|
||||
else:
|
||||
ret["comment"] = "The package {} is not installed".format(name)
|
||||
ret["comment"] = f"The package {name} is not installed"
|
||||
return ret
|
||||
|
||||
if __opts__["test"]:
|
||||
ret["result"] = None
|
||||
ret["comment"] = "The uninstall was tested"
|
||||
return ret
|
||||
|
||||
# Uninstall the package
|
||||
|
@ -270,13 +249,12 @@ def uninstalled(name, version=None, uninstall_args=None, override_args=False):
|
|||
)
|
||||
|
||||
if "Running chocolatey failed" not in result:
|
||||
ret["comment"] = f"{name} uninstalled successfully"
|
||||
ret["result"] = True
|
||||
else:
|
||||
ret["comment"] = f"Failed to uninstall {name}"
|
||||
ret["result"] = False
|
||||
|
||||
if not ret["result"]:
|
||||
ret["comment"] = "Failed to uninstall the package {}".format(name)
|
||||
|
||||
# Get list of installed packages after 'chocolatey.uninstall'
|
||||
post_uninstall = __salt__["chocolatey.list"](local_only=True)
|
||||
|
||||
|
@ -297,7 +275,7 @@ def upgraded(
|
|||
package_args=None,
|
||||
):
|
||||
"""
|
||||
Upgrades a package. Will install the package if not installed.
|
||||
Upgrades a chocolatey package. Will install the package if not installed.
|
||||
|
||||
.. versionadded:: 2018.3.0
|
||||
|
||||
|
@ -320,7 +298,7 @@ def upgraded(
|
|||
Default is ``False``.
|
||||
|
||||
pre_versions (bool):
|
||||
``True`` will nclude pre-release packages. Default is ``False``.
|
||||
``True`` will include pre-release packages. Default is ``False``.
|
||||
|
||||
install_args (str):
|
||||
Install arguments you want to pass to the installation process, i.e
|
||||
|
@ -333,12 +311,14 @@ def upgraded(
|
|||
the default arguments. Default is ``False``.
|
||||
|
||||
force_x86 (bool):
|
||||
``True`` forces 32bit installation on 64 bit systems. Default is
|
||||
``True`` forces 32bit installation on 64bit systems. Default is
|
||||
``False``.
|
||||
|
||||
package_args (str):
|
||||
Arguments you want to pass to the package. Default is ``None``.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
upgrade_some_package:
|
||||
|
@ -356,15 +336,15 @@ def upgraded(
|
|||
# Package not installed
|
||||
if name.lower() not in [package.lower() for package in pre_install.keys()]:
|
||||
if version:
|
||||
ret["changes"][name] = "Version {} will be installed".format(version)
|
||||
ret["comment"] = "Install version {}".format(version)
|
||||
ret["comment"] = f"{name} {version} will be installed"
|
||||
else:
|
||||
ret["changes"][name] = "Latest version will be installed"
|
||||
ret["comment"] = "Install latest version"
|
||||
ret["comment"] = f"Latest version of {name} will be installed"
|
||||
|
||||
# Package installed
|
||||
else:
|
||||
version_info = __salt__["chocolatey.version"](name, check_remote=True)
|
||||
version_info = __salt__["chocolatey.version"](
|
||||
name=name, check_remote=True, source=source
|
||||
)
|
||||
|
||||
# Get the actual full name out of version_info
|
||||
full_name = name
|
||||
|
@ -385,40 +365,29 @@ def upgraded(
|
|||
ver1=installed_version, oper="==", ver2=version
|
||||
):
|
||||
if force:
|
||||
ret["changes"][name] = "Version {} will be reinstalled".format(
|
||||
version
|
||||
)
|
||||
ret["comment"] = "Reinstall {} {}".format(full_name, version)
|
||||
ret["comment"] = f"{name} {version} will be reinstalled"
|
||||
else:
|
||||
ret["comment"] = "{} {} is already installed".format(
|
||||
name, installed_version
|
||||
)
|
||||
ret["comment"] = f"{name} {version} is already installed"
|
||||
return ret
|
||||
else:
|
||||
# If installed version is older than new version
|
||||
if salt.utils.versions.compare(
|
||||
ver1=installed_version, oper="<", ver2=version
|
||||
):
|
||||
ret["changes"][
|
||||
name
|
||||
] = "Version {} will be upgraded to Version {}".format(
|
||||
installed_version, version
|
||||
)
|
||||
ret["comment"] = "Upgrade {} {} to {}".format(
|
||||
full_name, installed_version, version
|
||||
)
|
||||
ret[
|
||||
"comment"
|
||||
] = f"{name} {installed_version} will be upgraded to version {version}"
|
||||
# If installed version is newer than new version
|
||||
else:
|
||||
ret["comment"] = "{} {} (newer) is already installed".format(
|
||||
name, installed_version
|
||||
)
|
||||
ret[
|
||||
"comment"
|
||||
] = f"{name} {installed_version} (newer) is already installed"
|
||||
return ret
|
||||
# Catch all for a condition where version is not passed and there is no
|
||||
# available version
|
||||
else:
|
||||
ret["comment"] = "No version found to install"
|
||||
|
||||
# Return if there are no changes to be made
|
||||
if not ret["changes"]:
|
||||
return ret
|
||||
return ret
|
||||
|
||||
# Return if running in test mode
|
||||
if __opts__["test"]:
|
||||
|
@ -439,10 +408,10 @@ def upgraded(
|
|||
)
|
||||
|
||||
if "Running chocolatey failed" not in result:
|
||||
ret["comment"] = "Package {} upgraded successfully".format(name)
|
||||
ret["comment"] = f"{name} upgraded successfully"
|
||||
ret["result"] = True
|
||||
else:
|
||||
ret["comment"] = "Failed to upgrade the package {}".format(name)
|
||||
ret["comment"] = f"Failed to upgrade {name}"
|
||||
ret["result"] = False
|
||||
|
||||
# Get list of installed packages after 'chocolatey.install'
|
||||
|
@ -460,33 +429,35 @@ def source_present(
|
|||
name, source_location, username=None, password=None, force=False, priority=None
|
||||
):
|
||||
"""
|
||||
Instructs Chocolatey to add a source if not already present.
|
||||
Adds a Chocolatey source if not already present.
|
||||
|
||||
name
|
||||
The name of the source to be added as a chocolatey repository.
|
||||
Args:
|
||||
|
||||
source
|
||||
Location of the source you want to work with.
|
||||
name (str):
|
||||
The name of the source to be added as a chocolatey repository.
|
||||
|
||||
username
|
||||
Provide username for chocolatey sources that need authentication
|
||||
credentials.
|
||||
source (str):
|
||||
Location of the source you want to work with.
|
||||
|
||||
password
|
||||
Provide password for chocolatey sources that need authentication
|
||||
credentials.
|
||||
username (str):
|
||||
The username for a chocolatey source that needs authentication
|
||||
credentials.
|
||||
|
||||
force
|
||||
Salt will not modify a existing repository with the same name. Set this
|
||||
option to true to update an existing repository.
|
||||
password (str):
|
||||
The password for a chocolatey source that needx authentication
|
||||
credentials.
|
||||
|
||||
priority
|
||||
The priority order of this source as compared to other sources,
|
||||
lower is better. Defaults to 0 (no priority). All priorities
|
||||
above 0 will be evaluated first, then zero-based values will be
|
||||
evaluated in config file order.
|
||||
force (bool):
|
||||
Salt will not modify an existing repository with the same name. Set
|
||||
this option to ``True`` to update an existing repository.
|
||||
|
||||
CLI Example:
|
||||
priority (int):
|
||||
The priority order of this source as compared to other sources.
|
||||
Lower is better. Defaults to 0 (no priority). All priorities
|
||||
above 0 will be evaluated first, then zero-based values will be
|
||||
evaluated in config file order.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
|
@ -506,21 +477,18 @@ def source_present(
|
|||
# Determine action
|
||||
# Source with same name not present
|
||||
if name.lower() not in [present.lower() for present in pre_install.keys()]:
|
||||
ret["comment"] = "Add the source {}".format(name)
|
||||
ret["comment"] = f"{name} will be added"
|
||||
|
||||
# Source with same name already present
|
||||
else:
|
||||
if force:
|
||||
ret["comment"] = "Update the source {}".format(name)
|
||||
ret["comment"] = f"{name} will be updated"
|
||||
else:
|
||||
ret["comment"] = "A source with the name {} is already present".format(name)
|
||||
if __opts__["test"]:
|
||||
ret["result"] = None
|
||||
ret["comment"] = f"{name} is already present"
|
||||
return ret
|
||||
|
||||
if __opts__["test"]:
|
||||
ret["result"] = None
|
||||
ret["comment"] = "The installation was tested"
|
||||
return ret
|
||||
|
||||
# Add the source
|
||||
|
@ -534,10 +502,10 @@ def source_present(
|
|||
|
||||
if "Running chocolatey failed" not in result:
|
||||
ret["result"] = True
|
||||
ret["comment"] = "Source {} added successfully".format(name)
|
||||
ret["comment"] = f"Source {name} added successfully"
|
||||
else:
|
||||
ret["result"] = False
|
||||
ret["comment"] = "Failed to add the source {}".format(name)
|
||||
ret["comment"] = f"Failed to add the source {name}"
|
||||
|
||||
# Get list of present sources after 'chocolatey.add_source'
|
||||
post_install = __salt__["chocolatey.list_sources"]()
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
Common code shared between the nacl module and runner.
|
||||
"""
|
||||
|
||||
|
||||
import base64
|
||||
import logging
|
||||
import os
|
||||
|
||||
import salt.syspaths
|
||||
|
@ -15,15 +13,13 @@ import salt.utils.versions
|
|||
import salt.utils.win_dacl
|
||||
import salt.utils.win_functions
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
REQ_ERROR = None
|
||||
try:
|
||||
import libnacl.sealed
|
||||
import libnacl.secret
|
||||
import nacl.public
|
||||
import nacl.secret
|
||||
except (ImportError, OSError) as e:
|
||||
REQ_ERROR = (
|
||||
"libnacl import error, perhaps missing python libnacl package or should update."
|
||||
"PyNaCl import error, perhaps missing python PyNaCl package or should update."
|
||||
)
|
||||
|
||||
__virtualname__ = "nacl"
|
||||
|
@ -62,7 +58,7 @@ def _get_config(**kwargs):
|
|||
"pk_file": pk_file,
|
||||
}
|
||||
|
||||
config_key = "{}.config".format(__virtualname__)
|
||||
config_key = f"{__virtualname__}.config"
|
||||
try:
|
||||
config.update(__salt__["config.get"](config_key, {}))
|
||||
except (NameError, KeyError) as e:
|
||||
|
@ -113,7 +109,7 @@ def _get_pk(**kwargs):
|
|||
|
||||
def keygen(sk_file=None, pk_file=None, **kwargs):
|
||||
"""
|
||||
Use libnacl to generate a keypair.
|
||||
Use PyNaCl to generate a keypair.
|
||||
|
||||
If no `sk_file` is defined return a keypair.
|
||||
|
||||
|
@ -143,17 +139,20 @@ def keygen(sk_file=None, pk_file=None, **kwargs):
|
|||
sk_file = kwargs["keyfile"]
|
||||
|
||||
if sk_file is None:
|
||||
kp = libnacl.public.SecretKey()
|
||||
return {"sk": base64.b64encode(kp.sk), "pk": base64.b64encode(kp.pk)}
|
||||
kp = nacl.public.PrivateKey.generate()
|
||||
return {
|
||||
"sk": base64.b64encode(kp.encode()),
|
||||
"pk": base64.b64encode(kp.public_key.encode()),
|
||||
}
|
||||
|
||||
if pk_file is None:
|
||||
pk_file = "{}.pub".format(sk_file)
|
||||
pk_file = f"{sk_file}.pub"
|
||||
|
||||
if sk_file and pk_file is None:
|
||||
if not os.path.isfile(sk_file):
|
||||
kp = libnacl.public.SecretKey()
|
||||
kp = nacl.public.PrivateKey.generate()
|
||||
with salt.utils.files.fopen(sk_file, "wb") as keyf:
|
||||
keyf.write(base64.b64encode(kp.sk))
|
||||
keyf.write(base64.b64encode(kp.encode()))
|
||||
if salt.utils.platform.is_windows():
|
||||
cur_user = salt.utils.win_functions.get_current_user()
|
||||
salt.utils.win_dacl.set_owner(sk_file, cur_user)
|
||||
|
@ -168,31 +167,29 @@ def keygen(sk_file=None, pk_file=None, **kwargs):
|
|||
else:
|
||||
# chmod 0600 file
|
||||
os.chmod(sk_file, 1536)
|
||||
return "saved sk_file: {}".format(sk_file)
|
||||
return f"saved sk_file: {sk_file}"
|
||||
else:
|
||||
raise Exception("sk_file:{} already exist.".format(sk_file))
|
||||
raise Exception(f"sk_file:{sk_file} already exist.")
|
||||
|
||||
if sk_file is None and pk_file:
|
||||
raise Exception("sk_file: Must be set inorder to generate a public key.")
|
||||
|
||||
if os.path.isfile(sk_file) and os.path.isfile(pk_file):
|
||||
raise Exception(
|
||||
"sk_file:{} and pk_file:{} already exist.".format(sk_file, pk_file)
|
||||
)
|
||||
raise Exception(f"sk_file:{sk_file} and pk_file:{pk_file} already exist.")
|
||||
|
||||
if os.path.isfile(sk_file) and not os.path.isfile(pk_file):
|
||||
# generate pk using the sk
|
||||
with salt.utils.files.fopen(sk_file, "rb") as keyf:
|
||||
sk = salt.utils.stringutils.to_unicode(keyf.read()).rstrip("\n")
|
||||
sk = base64.b64decode(sk)
|
||||
kp = libnacl.public.SecretKey(sk)
|
||||
kp = nacl.public.PublicKey(sk)
|
||||
with salt.utils.files.fopen(pk_file, "wb") as keyf:
|
||||
keyf.write(base64.b64encode(kp.pk))
|
||||
return "saved pk_file: {}".format(pk_file)
|
||||
keyf.write(base64.b64encode(kp.encode()))
|
||||
return f"saved pk_file: {pk_file}"
|
||||
|
||||
kp = libnacl.public.SecretKey()
|
||||
kp = nacl.public.PublicKey.generate()
|
||||
with salt.utils.files.fopen(sk_file, "wb") as keyf:
|
||||
keyf.write(base64.b64encode(kp.sk))
|
||||
keyf.write(base64.b64encode(kp.encode()))
|
||||
if salt.utils.platform.is_windows():
|
||||
cur_user = salt.utils.win_functions.get_current_user()
|
||||
salt.utils.win_dacl.set_owner(sk_file, cur_user)
|
||||
|
@ -203,8 +200,8 @@ def keygen(sk_file=None, pk_file=None, **kwargs):
|
|||
# chmod 0600 file
|
||||
os.chmod(sk_file, 1536)
|
||||
with salt.utils.files.fopen(pk_file, "wb") as keyf:
|
||||
keyf.write(base64.b64encode(kp.pk))
|
||||
return "saved sk_file:{} pk_file: {}".format(sk_file, pk_file)
|
||||
keyf.write(base64.b64encode(kp.encode()))
|
||||
return f"saved sk_file:{sk_file} pk_file: {pk_file}"
|
||||
|
||||
|
||||
def enc(data, **kwargs):
|
||||
|
@ -271,10 +268,10 @@ def enc_file(name, out=None, **kwargs):
|
|||
d = enc(data, **kwargs)
|
||||
if out:
|
||||
if os.path.isfile(out):
|
||||
raise Exception("file:{} already exist.".format(out))
|
||||
raise Exception(f"file:{out} already exist.")
|
||||
with salt.utils.files.fopen(out, "wb") as f:
|
||||
f.write(salt.utils.stringutils.to_bytes(d))
|
||||
return "Wrote: {}".format(out)
|
||||
return f"Wrote: {out}"
|
||||
return d
|
||||
|
||||
|
||||
|
@ -313,6 +310,7 @@ def dec(data, **kwargs):
|
|||
box_type = _get_config(**kwargs)["box_type"]
|
||||
if box_type == "secretbox":
|
||||
return secretbox_decrypt(data, **kwargs)
|
||||
|
||||
return sealedbox_decrypt(data, **kwargs)
|
||||
|
||||
|
||||
|
@ -342,10 +340,10 @@ def dec_file(name, out=None, **kwargs):
|
|||
d = dec(data, **kwargs)
|
||||
if out:
|
||||
if os.path.isfile(out):
|
||||
raise Exception("file:{} already exist.".format(out))
|
||||
raise Exception(f"file:{out} already exist.")
|
||||
with salt.utils.files.fopen(out, "wb") as f:
|
||||
f.write(salt.utils.stringutils.to_bytes(d))
|
||||
return "Wrote: {}".format(out)
|
||||
return f"Wrote: {out}"
|
||||
return d
|
||||
|
||||
|
||||
|
@ -366,7 +364,8 @@ def sealedbox_encrypt(data, **kwargs):
|
|||
data = salt.utils.stringutils.to_bytes(data)
|
||||
|
||||
pk = _get_pk(**kwargs)
|
||||
b = libnacl.sealed.SealedBox(pk)
|
||||
keypair = nacl.public.PublicKey(pk)
|
||||
b = nacl.public.SealedBox(keypair)
|
||||
return base64.b64encode(b.encrypt(data))
|
||||
|
||||
|
||||
|
@ -389,8 +388,8 @@ def sealedbox_decrypt(data, **kwargs):
|
|||
data = salt.utils.stringutils.to_bytes(data)
|
||||
|
||||
sk = _get_sk(**kwargs)
|
||||
keypair = libnacl.public.SecretKey(sk)
|
||||
b = libnacl.sealed.SealedBox(keypair)
|
||||
keypair = nacl.public.PrivateKey(sk)
|
||||
b = nacl.public.SealedBox(keypair)
|
||||
return b.decrypt(base64.b64decode(data))
|
||||
|
||||
|
||||
|
@ -411,7 +410,7 @@ def secretbox_encrypt(data, **kwargs):
|
|||
data = salt.utils.stringutils.to_bytes(data)
|
||||
|
||||
sk = _get_sk(**kwargs)
|
||||
b = libnacl.secret.SecretBox(sk)
|
||||
b = nacl.secret.SecretBox(sk)
|
||||
return base64.b64encode(b.encrypt(data))
|
||||
|
||||
|
||||
|
@ -435,6 +434,5 @@ def secretbox_decrypt(data, **kwargs):
|
|||
data = salt.utils.stringutils.to_bytes(data)
|
||||
|
||||
key = _get_sk(**kwargs)
|
||||
b = libnacl.secret.SecretBox(key=key)
|
||||
|
||||
b = nacl.secret.SecretBox(key=key)
|
||||
return b.decrypt(base64.b64decode(data))
|
||||
|
|
|
@ -1,200 +0,0 @@
|
|||
"""
|
||||
Tests for the salt-run command
|
||||
"""
|
||||
|
||||
import logging
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
from tests.support.case import ShellCase
|
||||
|
||||
try:
|
||||
import libnacl.sealed # pylint: disable=unused-import
|
||||
import libnacl.secret # pylint: disable=unused-import
|
||||
|
||||
HAS_LIBNACL = True
|
||||
except (ImportError, OSError, AttributeError):
|
||||
HAS_LIBNACL = False
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
not HAS_LIBNACL, reason="skipping test_nacl, reason=libnacl is unavailable"
|
||||
)
|
||||
@pytest.mark.skipif(sys.version_info >= (3, 10), reason="Segfaults with python 3")
|
||||
@pytest.mark.windows_whitelisted
|
||||
class NaclTest(ShellCase):
|
||||
"""
|
||||
Test the nacl runner
|
||||
"""
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_keygen(self):
|
||||
"""
|
||||
Test keygen
|
||||
"""
|
||||
# Store the data
|
||||
ret = self.run_run_plus(
|
||||
"nacl.keygen",
|
||||
)
|
||||
self.assertIn("pk", ret["return"])
|
||||
self.assertIn("sk", ret["return"])
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_enc(self):
|
||||
"""
|
||||
Test keygen
|
||||
"""
|
||||
# Store the data
|
||||
ret = self.run_run_plus(
|
||||
"nacl.keygen",
|
||||
)
|
||||
self.assertIn("pk", ret["return"])
|
||||
self.assertIn("sk", ret["return"])
|
||||
pk = ret["return"]["pk"]
|
||||
sk = ret["return"]["sk"]
|
||||
|
||||
unencrypted_data = "hello"
|
||||
|
||||
# Encrypt with pk
|
||||
ret = self.run_run_plus(
|
||||
"nacl.enc",
|
||||
data=unencrypted_data,
|
||||
pk=pk,
|
||||
)
|
||||
self.assertIn("return", ret)
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_enc_dec(self):
|
||||
"""
|
||||
Store, list, fetch, then flush data
|
||||
"""
|
||||
# Store the data
|
||||
ret = self.run_run_plus(
|
||||
"nacl.keygen",
|
||||
)
|
||||
self.assertIn("pk", ret["return"])
|
||||
self.assertIn("sk", ret["return"])
|
||||
pk = ret["return"]["pk"]
|
||||
sk = ret["return"]["sk"]
|
||||
|
||||
unencrypted_data = b"hello"
|
||||
|
||||
# Encrypt with pk
|
||||
ret = self.run_run_plus(
|
||||
"nacl.enc",
|
||||
data=unencrypted_data,
|
||||
pk=pk,
|
||||
)
|
||||
self.assertIn("return", ret)
|
||||
encrypted_data = ret["return"]
|
||||
|
||||
# Decrypt with sk
|
||||
ret = self.run_run_plus(
|
||||
"nacl.dec",
|
||||
data=encrypted_data,
|
||||
sk=sk,
|
||||
)
|
||||
self.assertIn("return", ret)
|
||||
self.assertEqual(unencrypted_data, ret["return"])
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_sealedbox_enc_dec(self):
|
||||
"""
|
||||
Generate keys, encrypt, then decrypt.
|
||||
"""
|
||||
# Store the data
|
||||
ret = self.run_run_plus(
|
||||
"nacl.keygen",
|
||||
)
|
||||
self.assertIn("pk", ret["return"])
|
||||
self.assertIn("sk", ret["return"])
|
||||
pk = ret["return"]["pk"]
|
||||
sk = ret["return"]["sk"]
|
||||
|
||||
unencrypted_data = b"hello"
|
||||
|
||||
# Encrypt with pk
|
||||
ret = self.run_run_plus(
|
||||
"nacl.sealedbox_encrypt",
|
||||
data=unencrypted_data,
|
||||
pk=pk,
|
||||
)
|
||||
encrypted_data = ret["return"]
|
||||
|
||||
# Decrypt with sk
|
||||
ret = self.run_run_plus(
|
||||
"nacl.sealedbox_decrypt",
|
||||
data=encrypted_data,
|
||||
sk=sk,
|
||||
)
|
||||
self.assertEqual(unencrypted_data, ret["return"])
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_secretbox_enc_dec(self):
|
||||
"""
|
||||
Generate keys, encrypt, then decrypt.
|
||||
"""
|
||||
# Store the data
|
||||
ret = self.run_run_plus(
|
||||
"nacl.keygen",
|
||||
)
|
||||
self.assertIn("pk", ret["return"])
|
||||
self.assertIn("sk", ret["return"])
|
||||
pk = ret["return"]["pk"]
|
||||
sk = ret["return"]["sk"]
|
||||
|
||||
unencrypted_data = b"hello"
|
||||
|
||||
# Encrypt with pk
|
||||
ret = self.run_run_plus(
|
||||
"nacl.secretbox_encrypt",
|
||||
data=unencrypted_data,
|
||||
sk=sk,
|
||||
)
|
||||
encrypted_data = ret["return"]
|
||||
|
||||
# Decrypt with sk
|
||||
ret = self.run_run_plus(
|
||||
"nacl.secretbox_decrypt",
|
||||
data=encrypted_data,
|
||||
sk=sk,
|
||||
)
|
||||
self.assertEqual(unencrypted_data, ret["return"])
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_enc_dec_no_pk_no_sk(self):
|
||||
"""
|
||||
Store, list, fetch, then flush data
|
||||
"""
|
||||
# Store the data
|
||||
ret = self.run_run_plus(
|
||||
"nacl.keygen",
|
||||
)
|
||||
self.assertIn("pk", ret["return"])
|
||||
self.assertIn("sk", ret["return"])
|
||||
pk = ret["return"]["pk"]
|
||||
sk = ret["return"]["sk"]
|
||||
|
||||
unencrypted_data = b"hello"
|
||||
|
||||
# Encrypt with pk
|
||||
ret = self.run_run_plus(
|
||||
"nacl.enc",
|
||||
data=unencrypted_data,
|
||||
pk=None,
|
||||
)
|
||||
self.assertIn("Exception: no pubkey or pk_file found", ret["return"])
|
||||
|
||||
self.assertIn("return", ret)
|
||||
encrypted_data = ret["return"]
|
||||
|
||||
# Decrypt with sk
|
||||
ret = self.run_run_plus(
|
||||
"nacl.dec",
|
||||
data=encrypted_data,
|
||||
sk=None,
|
||||
)
|
||||
self.assertIn("Exception: no key or sk_file found", ret["return"])
|
128
tests/pytests/functional/states/test_chocolatey_1_2_1.py
Normal file
128
tests/pytests/functional/states/test_chocolatey_1_2_1.py
Normal file
|
@ -0,0 +1,128 @@
|
|||
"""
|
||||
Functional tests for chocolatey state
|
||||
"""
|
||||
import os
|
||||
import pathlib
|
||||
|
||||
import pytest
|
||||
|
||||
import salt.utils.path
|
||||
|
||||
pytestmark = [
|
||||
pytest.mark.windows_whitelisted,
|
||||
pytest.mark.skip_unless_on_windows,
|
||||
pytest.mark.slow_test,
|
||||
pytest.mark.destructive_test,
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def chocolatey(states):
|
||||
yield states.chocolatey
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def chocolatey_mod(modules):
|
||||
|
||||
url = "https://packages.chocolatey.org/chocolatey.1.2.1.nupkg"
|
||||
with pytest.helpers.temp_file(name="choco.nupkg") as nupkg:
|
||||
choco_pkg = pathlib.Path(str(nupkg))
|
||||
choco_dir = choco_pkg.parent / "choco_dir"
|
||||
choco_script = choco_dir / "tools" / "chocolateyInstall.ps1"
|
||||
|
||||
def install():
|
||||
# Install Chocolatey 1.2.1
|
||||
|
||||
# Download Package
|
||||
modules.cp.get_url(path=url, dest=str(choco_pkg))
|
||||
|
||||
# Unzip Package
|
||||
modules.archive.unzip(
|
||||
zip_file=str(choco_pkg),
|
||||
dest=str(choco_dir),
|
||||
extract_perms=False,
|
||||
)
|
||||
|
||||
# Run installer script
|
||||
assert choco_script.exists()
|
||||
result = modules.cmd.script(
|
||||
source=str(choco_script),
|
||||
cwd=str(choco_script.parent),
|
||||
shell="powershell",
|
||||
python_shell=True,
|
||||
)
|
||||
assert result["retcode"] == 0
|
||||
|
||||
def uninstall():
|
||||
choco_dir = os.environ.get("ChocolateyInstall", False)
|
||||
if choco_dir:
|
||||
# Remove Chocolatey Directory
|
||||
modules.file.remove(path=choco_dir, force=True)
|
||||
# Remove Chocolatey Environment Variables
|
||||
for env_var in modules.environ.items():
|
||||
if env_var.lower().startswith("chocolatey"):
|
||||
modules.environ.setval(
|
||||
key=env_var, val=False, false_unsets=True, permanent="HKLM"
|
||||
)
|
||||
modules.environ.setval(
|
||||
key=env_var, val=False, false_unsets=True, permanent="HKCU"
|
||||
)
|
||||
# Remove Chocolatey from the Path
|
||||
for path in modules.win_path.get_path():
|
||||
if "chocolatey" in path.lower():
|
||||
modules.win_path.remove(path=path, rehash=True)
|
||||
|
||||
# Remove unknown version
|
||||
if salt.utils.path.which("choco.exe"):
|
||||
uninstall()
|
||||
|
||||
# Install known version
|
||||
install()
|
||||
|
||||
yield modules.chocolatey
|
||||
|
||||
# Remove
|
||||
uninstall()
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def clean(chocolatey_mod):
|
||||
chocolatey_mod.uninstall(name="vim", force=True)
|
||||
yield
|
||||
chocolatey_mod.uninstall(name="vim", force=True)
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def vim(chocolatey_mod):
|
||||
chocolatey_mod.install(name="vim", version="9.0.1672")
|
||||
yield
|
||||
chocolatey_mod.uninstall(name="vim", force=True)
|
||||
|
||||
|
||||
def test_installed_latest(clean, chocolatey, chocolatey_mod):
|
||||
chocolatey.installed(name="vim")
|
||||
result = chocolatey_mod.version(name="vim")
|
||||
assert "vim" in result
|
||||
|
||||
|
||||
def test_installed_version(clean, chocolatey, chocolatey_mod):
|
||||
chocolatey.installed(name="vim", version="9.0.1672")
|
||||
result = chocolatey_mod.version(name="vim")
|
||||
assert "vim" in result
|
||||
assert result["vim"]["installed"][0] == "9.0.1672"
|
||||
|
||||
|
||||
def test_uninstalled(vim, chocolatey, chocolatey_mod):
|
||||
chocolatey.uninstalled(name="vim")
|
||||
result = chocolatey_mod.version(name="vim")
|
||||
assert "vim" not in result
|
||||
|
||||
|
||||
def test_upgraded(vim, chocolatey, chocolatey_mod):
|
||||
result = chocolatey_mod.version(name="vim")
|
||||
assert "vim" in result
|
||||
assert result["vim"]["installed"][0] == "9.0.1672"
|
||||
chocolatey.upgraded(name="vim", version="9.0.1677")
|
||||
result = chocolatey_mod.version(name="vim")
|
||||
assert "vim" in result
|
||||
assert result["vim"]["installed"][0] == "9.0.1677"
|
128
tests/pytests/functional/states/test_chocolatey_latest.py
Normal file
128
tests/pytests/functional/states/test_chocolatey_latest.py
Normal file
|
@ -0,0 +1,128 @@
|
|||
"""
|
||||
Functional tests for chocolatey state
|
||||
"""
|
||||
import os
|
||||
import pathlib
|
||||
|
||||
import pytest
|
||||
|
||||
import salt.utils.path
|
||||
|
||||
pytestmark = [
|
||||
pytest.mark.windows_whitelisted,
|
||||
pytest.mark.skip_unless_on_windows,
|
||||
pytest.mark.slow_test,
|
||||
pytest.mark.destructive_test,
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def chocolatey(states):
|
||||
yield states.chocolatey
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def chocolatey_mod(modules):
|
||||
|
||||
url = "https://community.chocolatey.org/api/v2/package/chocolatey/"
|
||||
with pytest.helpers.temp_file(name="choco.nupkg") as nupkg:
|
||||
choco_pkg = pathlib.Path(str(nupkg))
|
||||
choco_dir = choco_pkg.parent / "choco_dir"
|
||||
choco_script = choco_dir / "tools" / "chocolateyInstall.ps1"
|
||||
|
||||
def install():
|
||||
# Install Chocolatey 1.2.1
|
||||
|
||||
# Download Package
|
||||
modules.cp.get_url(path=url, dest=str(choco_pkg))
|
||||
|
||||
# Unzip Package
|
||||
modules.archive.unzip(
|
||||
zip_file=str(choco_pkg),
|
||||
dest=str(choco_dir),
|
||||
extract_perms=False,
|
||||
)
|
||||
|
||||
# Run installer script
|
||||
assert choco_script.exists()
|
||||
result = modules.cmd.script(
|
||||
source=str(choco_script),
|
||||
cwd=str(choco_script.parent),
|
||||
shell="powershell",
|
||||
python_shell=True,
|
||||
)
|
||||
assert result["retcode"] == 0
|
||||
|
||||
def uninstall():
|
||||
choco_dir = os.environ.get("ChocolateyInstall", False)
|
||||
if choco_dir:
|
||||
# Remove Chocolatey Directory
|
||||
modules.file.remove(path=choco_dir, force=True)
|
||||
# Remove Chocolatey Environment Variables
|
||||
for env_var in modules.environ.items():
|
||||
if env_var.lower().startswith("chocolatey"):
|
||||
modules.environ.setval(
|
||||
key=env_var, val=False, false_unsets=True, permanent="HKLM"
|
||||
)
|
||||
modules.environ.setval(
|
||||
key=env_var, val=False, false_unsets=True, permanent="HKCU"
|
||||
)
|
||||
# Remove Chocolatey from the Path
|
||||
for path in modules.win_path.get_path():
|
||||
if "chocolatey" in path.lower():
|
||||
modules.win_path.remove(path=path, rehash=True)
|
||||
|
||||
# Remove unknown version
|
||||
if salt.utils.path.which("choco.exe"):
|
||||
uninstall()
|
||||
|
||||
# Install known version
|
||||
install()
|
||||
|
||||
yield modules.chocolatey
|
||||
|
||||
# Remove
|
||||
uninstall()
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def clean(chocolatey_mod):
|
||||
chocolatey_mod.uninstall(name="vim", force=True)
|
||||
yield
|
||||
chocolatey_mod.uninstall(name="vim", force=True)
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def vim(chocolatey_mod):
|
||||
chocolatey_mod.install(name="vim", version="9.0.1672")
|
||||
yield
|
||||
chocolatey_mod.uninstall(name="vim", force=True)
|
||||
|
||||
|
||||
def test_installed_latest(clean, chocolatey, chocolatey_mod):
|
||||
chocolatey.installed(name="vim")
|
||||
result = chocolatey_mod.version(name="vim")
|
||||
assert "vim" in result
|
||||
|
||||
|
||||
def test_installed_version(clean, chocolatey, chocolatey_mod):
|
||||
chocolatey.installed(name="vim", version="9.0.1672")
|
||||
result = chocolatey_mod.version(name="vim")
|
||||
assert "vim" in result
|
||||
assert result["vim"]["installed"][0] == "9.0.1672"
|
||||
|
||||
|
||||
def test_uninstalled(vim, chocolatey, chocolatey_mod):
|
||||
chocolatey.uninstalled(name="vim")
|
||||
result = chocolatey_mod.version(name="vim")
|
||||
assert "vim" not in result
|
||||
|
||||
|
||||
def test_upgraded(vim, chocolatey, chocolatey_mod):
|
||||
result = chocolatey_mod.version(name="vim")
|
||||
assert "vim" in result
|
||||
assert result["vim"]["installed"][0] == "9.0.1672"
|
||||
chocolatey.upgraded(name="vim", version="9.0.1677")
|
||||
result = chocolatey_mod.version(name="vim")
|
||||
assert "vim" in result
|
||||
assert result["vim"]["installed"][0] == "9.0.1677"
|
|
@ -50,3 +50,66 @@ def test_publish_retry(salt_master, salt_minion_retry, salt_cli, salt_run_cli):
|
|||
|
||||
assert salt_minion_retry.id in data
|
||||
assert data[salt_minion_retry.id] is True
|
||||
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_pillar_timeout(salt_master_factory):
|
||||
cmd = """
|
||||
python -c "import time; time.sleep(2.5); print('{\\"foo\\": \\"bar\\"}');\"
|
||||
""".strip()
|
||||
master_overrides = {
|
||||
"ext_pillar": [
|
||||
{"cmd_json": cmd},
|
||||
],
|
||||
"auto_accept": True,
|
||||
"worker_threads": 3,
|
||||
"peer": True,
|
||||
}
|
||||
minion_overrides = {
|
||||
"auth_timeout": 20,
|
||||
"request_channel_timeout": 5,
|
||||
"request_channel_tries": 1,
|
||||
}
|
||||
sls_name = "issue-50221"
|
||||
sls_contents = """
|
||||
custom_test_state:
|
||||
test.configurable_test_state:
|
||||
- name: example
|
||||
- changes: True
|
||||
- result: True
|
||||
- comment: "Nothing has acutally been changed"
|
||||
"""
|
||||
master = salt_master_factory.salt_master_daemon(
|
||||
"pillar-timeout-master",
|
||||
overrides=master_overrides,
|
||||
)
|
||||
minion1 = master.salt_minion_daemon(
|
||||
random_string("pillar-timeout-1-"),
|
||||
overrides=minion_overrides,
|
||||
)
|
||||
minion2 = master.salt_minion_daemon(
|
||||
random_string("pillar-timeout-2-"),
|
||||
overrides=minion_overrides,
|
||||
)
|
||||
minion3 = master.salt_minion_daemon(
|
||||
random_string("pillar-timeout-3-"),
|
||||
overrides=minion_overrides,
|
||||
)
|
||||
minion4 = master.salt_minion_daemon(
|
||||
random_string("pillar-timeout-4-"),
|
||||
overrides=minion_overrides,
|
||||
)
|
||||
cli = master.salt_cli()
|
||||
sls_tempfile = master.state_tree.base.temp_file(f"{sls_name}.sls", sls_contents)
|
||||
with master.started(), minion1.started(), minion2.started(), minion3.started(), minion4.started(), sls_tempfile:
|
||||
proc = cli.run("state.sls", sls_name, minion_tgt="*")
|
||||
# At least one minion should have a Pillar timeout
|
||||
assert proc.returncode == 1
|
||||
minion_timed_out = False
|
||||
# Find the minion that has a Pillar timeout
|
||||
for key in proc.data:
|
||||
if isinstance(proc.data[key], str):
|
||||
if "Pillar timed out" in proc.data[key]:
|
||||
minion_timed_out = True
|
||||
break
|
||||
assert minion_timed_out is True
|
||||
|
|
165
tests/pytests/integration/runners/test_nacl.py
Normal file
165
tests/pytests/integration/runners/test_nacl.py
Normal file
|
@ -0,0 +1,165 @@
|
|||
"""
|
||||
Tests for the nacl runner
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
import salt.config
|
||||
import salt.utils.stringutils
|
||||
from tests.support.mock import patch
|
||||
|
||||
pytest.importorskip("nacl.public")
|
||||
pytest.importorskip("nacl.secret")
|
||||
|
||||
import salt.runners.nacl as nacl
|
||||
|
||||
pytestmark = [
|
||||
pytest.mark.windows_whitelisted,
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def minion_opts():
|
||||
return salt.config.minion_config(None)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_data():
|
||||
unencrypted_data = salt.utils.stringutils.to_bytes("hello")
|
||||
return unencrypted_data
|
||||
|
||||
|
||||
def test_keygen(minion_opts):
|
||||
"""
|
||||
Test keygen
|
||||
"""
|
||||
# Store the data
|
||||
with patch("salt.runners.nacl.__opts__", minion_opts, create=True):
|
||||
ret = nacl.keygen()
|
||||
assert "pk" in ret
|
||||
assert "sk" in ret
|
||||
|
||||
|
||||
def test_enc(test_data, minion_opts):
|
||||
"""
|
||||
Test keygen
|
||||
"""
|
||||
# Store the data
|
||||
with patch("salt.runners.nacl.__opts__", minion_opts, create=True):
|
||||
ret = nacl.keygen()
|
||||
assert "pk" in ret
|
||||
assert "sk" in ret
|
||||
pk = ret["pk"]
|
||||
sk = ret["sk"]
|
||||
|
||||
# Encrypt with pk
|
||||
ret = nacl.enc(
|
||||
data=test_data,
|
||||
pk=pk,
|
||||
)
|
||||
|
||||
|
||||
def test_enc_dec(test_data, minion_opts):
|
||||
"""
|
||||
Store, list, fetch, then flush data
|
||||
"""
|
||||
# Store the data
|
||||
with patch("salt.runners.nacl.__opts__", minion_opts, create=True):
|
||||
ret = nacl.keygen()
|
||||
assert "pk" in ret
|
||||
assert "sk" in ret
|
||||
pk = ret["pk"]
|
||||
sk = ret["sk"]
|
||||
|
||||
# Encrypt with pk
|
||||
encrypted_data = nacl.enc(
|
||||
data=test_data,
|
||||
pk=pk,
|
||||
)
|
||||
|
||||
# Decrypt with sk
|
||||
ret = nacl.dec(
|
||||
data=encrypted_data,
|
||||
sk=sk,
|
||||
)
|
||||
assert test_data == ret
|
||||
|
||||
|
||||
def test_sealedbox_enc_dec(test_data, minion_opts):
|
||||
"""
|
||||
Generate keys, encrypt, then decrypt.
|
||||
"""
|
||||
# Store the data
|
||||
with patch("salt.runners.nacl.__opts__", minion_opts, create=True):
|
||||
ret = nacl.keygen()
|
||||
assert "pk" in ret
|
||||
assert "sk" in ret
|
||||
pk = ret["pk"]
|
||||
sk = ret["sk"]
|
||||
|
||||
# Encrypt with pk
|
||||
encrypted_data = nacl.sealedbox_encrypt(
|
||||
data=test_data,
|
||||
pk=pk,
|
||||
)
|
||||
|
||||
# Decrypt with sk
|
||||
ret = nacl.sealedbox_decrypt(
|
||||
data=encrypted_data,
|
||||
sk=sk,
|
||||
)
|
||||
assert test_data == ret
|
||||
|
||||
|
||||
def test_secretbox_enc_dec(test_data, minion_opts):
|
||||
"""
|
||||
Generate keys, encrypt, then decrypt.
|
||||
"""
|
||||
# Store the data
|
||||
with patch("salt.runners.nacl.__opts__", minion_opts, create=True):
|
||||
ret = nacl.keygen()
|
||||
assert "pk" in ret
|
||||
assert "sk" in ret
|
||||
pk = ret["pk"]
|
||||
sk = ret["sk"]
|
||||
|
||||
# Encrypt with pk
|
||||
encrypted_data = nacl.secretbox_encrypt(
|
||||
data=test_data,
|
||||
sk=sk,
|
||||
)
|
||||
|
||||
# Decrypt with sk
|
||||
ret = nacl.secretbox_decrypt(
|
||||
data=encrypted_data,
|
||||
sk=sk,
|
||||
)
|
||||
assert test_data == ret
|
||||
|
||||
|
||||
def test_enc_dec_no_pk_no_sk(test_data, minion_opts):
|
||||
"""
|
||||
Store, list, fetch, then flush data
|
||||
"""
|
||||
# Store the data
|
||||
with patch("salt.runners.nacl.__opts__", minion_opts, create=True):
|
||||
ret = nacl.keygen()
|
||||
assert "pk" in ret
|
||||
assert "sk" in ret
|
||||
pk = ret["pk"]
|
||||
sk = ret["sk"]
|
||||
|
||||
# Encrypt with pk
|
||||
with pytest.raises(Exception, match="no pubkey or pk_file found"):
|
||||
ret = nacl.enc(
|
||||
data=test_data,
|
||||
pk=None,
|
||||
)
|
||||
|
||||
encrypted_data = test_data # dummy data, should get exception
|
||||
# Decrypt with sk
|
||||
with pytest.raises(Exception, match="no key or sk_file found"):
|
||||
ret = nacl.dec(
|
||||
data=encrypted_data,
|
||||
sk=None,
|
||||
)
|
|
@ -1,8 +1,6 @@
|
|||
"""
|
||||
Test for the chocolatey module
|
||||
"""
|
||||
|
||||
|
||||
import os
|
||||
|
||||
import pytest
|
||||
|
@ -190,7 +188,7 @@ def test_version_check_remote_false():
|
|||
"""
|
||||
list_return_value = {"ack": ["3.1.1"]}
|
||||
with patch.object(chocolatey, "list_", return_value=list_return_value):
|
||||
expected = {"ack": ["3.1.1"]}
|
||||
expected = {"ack": {"installed": ["3.1.1"]}}
|
||||
result = chocolatey.version("ack", check_remote=False)
|
||||
assert result == expected
|
||||
|
||||
|
|
|
@ -1,10 +1,44 @@
|
|||
"""
|
||||
Unit tests for the salt.modules.nacl module
|
||||
"""
|
||||
import pytest
|
||||
|
||||
import salt.modules.nacl
|
||||
import salt.utils.stringutils
|
||||
from tests.support.mock import patch
|
||||
|
||||
pytest.importorskip("nacl.public")
|
||||
pytest.importorskip("nacl.secret")
|
||||
|
||||
import salt.modules.nacl as nacl
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def configure_loader_modules(minion_opts):
|
||||
utils = salt.loader.utils(minion_opts)
|
||||
funcs = salt.loader.minion_mods(minion_opts, utils=utils)
|
||||
return {
|
||||
nacl: {
|
||||
"__opts__": minion_opts,
|
||||
"__utils__": utils,
|
||||
"__salt__": funcs,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_keys():
|
||||
# Generate the keys
|
||||
ret = nacl.keygen()
|
||||
assert "pk" in ret
|
||||
assert "sk" in ret
|
||||
return ret["pk"], ret["sk"]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_data():
|
||||
unencrypted_data = salt.utils.stringutils.to_bytes("hello")
|
||||
return unencrypted_data
|
||||
|
||||
|
||||
def test_fips_mode():
|
||||
"""
|
||||
|
@ -14,3 +48,53 @@ def test_fips_mode():
|
|||
with patch("salt.modules.nacl.__opts__", opts, create=True):
|
||||
ret = salt.modules.nacl.__virtual__()
|
||||
assert ret == (False, "nacl module not available in FIPS mode")
|
||||
|
||||
|
||||
def test_keygen(test_keys):
|
||||
"""
|
||||
Test keygen
|
||||
"""
|
||||
test_pk, test_sk = test_keys
|
||||
assert len(test_pk) == 44
|
||||
assert len(test_sk) == 44
|
||||
|
||||
|
||||
def test_enc_dec(test_data, test_keys):
|
||||
"""
|
||||
Generate keys, encrypt, then decrypt.
|
||||
"""
|
||||
# Encrypt with pk
|
||||
test_pk, test_sk = test_keys
|
||||
encrypted_data = nacl.enc(data=test_data, pk=test_pk)
|
||||
|
||||
# Decrypt with sk
|
||||
decrypted_data = nacl.dec(data=encrypted_data, sk=test_sk)
|
||||
assert test_data == decrypted_data
|
||||
|
||||
|
||||
def test_sealedbox_enc_dec(test_data, test_keys):
|
||||
"""
|
||||
Generate keys, encrypt, then decrypt.
|
||||
"""
|
||||
# Encrypt with pk
|
||||
test_pk, test_sk = test_keys
|
||||
encrypted_data = nacl.sealedbox_encrypt(data=test_data, pk=test_pk)
|
||||
|
||||
# Decrypt with sk
|
||||
decrypted_data = nacl.sealedbox_decrypt(data=encrypted_data, sk=test_sk)
|
||||
|
||||
assert test_data == decrypted_data
|
||||
|
||||
|
||||
def test_secretbox_enc_dec(test_data, test_keys):
|
||||
"""
|
||||
Generate keys, encrypt, then decrypt.
|
||||
"""
|
||||
# Encrypt with sk
|
||||
test_pk, test_sk = test_keys
|
||||
encrypted_data = nacl.secretbox_encrypt(data=test_data, sk=test_sk)
|
||||
|
||||
# Decrypt with sk
|
||||
decrypted_data = nacl.secretbox_decrypt(data=encrypted_data, sk=test_sk)
|
||||
|
||||
assert test_data == decrypted_data
|
||||
|
|
|
@ -7,6 +7,7 @@ import salt.loader
|
|||
import salt.pillar
|
||||
import salt.utils.cache
|
||||
from salt.utils.odict import OrderedDict
|
||||
from tests.support.mock import MagicMock
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
@ -157,3 +158,20 @@ def test_pillar_get_cache_disk(temp_salt_minion, caplog):
|
|||
in caplog.messages
|
||||
)
|
||||
assert fresh_pillar == {}
|
||||
|
||||
|
||||
def test_remote_pillar_timeout(temp_salt_minion, tmp_path):
|
||||
opts = temp_salt_minion.config.copy()
|
||||
opts["master_uri"] = "tcp://127.0.0.1:12323"
|
||||
grains = salt.loader.grains(opts)
|
||||
pillar = salt.pillar.RemotePillar(
|
||||
opts,
|
||||
grains,
|
||||
temp_salt_minion.id,
|
||||
"base",
|
||||
)
|
||||
mock = MagicMock()
|
||||
mock.side_effect = salt.exceptions.SaltReqTimeoutError()
|
||||
pillar.channel.crypted_transfer_decode_dictentry = mock
|
||||
with pytest.raises(salt.exceptions.SaltClientError):
|
||||
pillar.compile_pillar()
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
"""
|
||||
Unit tests for chocolatey state
|
||||
"""
|
||||
import logging
|
||||
|
||||
import pytest
|
||||
|
@ -74,6 +77,7 @@ def test_source_present(list_sources):
|
|||
chocolatey.__salt__,
|
||||
{
|
||||
"chocolatey.list_sources": list_sources_sideeffect,
|
||||
"chocolatey.add_source": chocolatey_mod.add_source,
|
||||
},
|
||||
):
|
||||
|
||||
|
@ -84,11 +88,6 @@ def test_source_present(list_sources):
|
|||
cmd_run_all_mock = MagicMock(return_value={"retcode": 0, "stdout": stdout_ret})
|
||||
cmd_run_which_mock = MagicMock(return_value=choco_path)
|
||||
with patch.dict(
|
||||
chocolatey.__salt__,
|
||||
{
|
||||
"chocolatey.add_source": chocolatey_mod.add_source,
|
||||
},
|
||||
), patch.dict(
|
||||
chocolatey_mod.__salt__,
|
||||
{
|
||||
"cmd.which": cmd_run_which_mock,
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import pytest
|
||||
|
||||
import salt.fileclient
|
||||
from tests.support.mock import patch
|
||||
from tests.support.mock import Mock, patch
|
||||
|
||||
|
||||
class MockReqChannel:
|
||||
|
@ -13,36 +15,74 @@ class MockReqChannel:
|
|||
return self
|
||||
|
||||
|
||||
def test_fileclient_context_manager_closes(temp_salt_minion, temp_salt_master):
|
||||
def test_fileclient_context_manager_closes(minion_opts, master_opts):
|
||||
"""
|
||||
ensure fileclient channel closes
|
||||
when used with a context manager
|
||||
"""
|
||||
opts = temp_salt_minion.config.copy()
|
||||
opts.update(
|
||||
minion_opts.update(
|
||||
{
|
||||
"id": "root",
|
||||
"transport": "zeromq",
|
||||
"auth_tries": 1,
|
||||
"auth_timeout": 5,
|
||||
"master_ip": "127.0.0.1",
|
||||
"master_port": temp_salt_master.config["ret_port"],
|
||||
"master_uri": "tcp://127.0.0.1:{}".format(
|
||||
temp_salt_master.config["ret_port"]
|
||||
),
|
||||
"master_port": master_opts["ret_port"],
|
||||
"master_uri": "tcp://127.0.0.1:{}".format(master_opts["ret_port"]),
|
||||
"request_channel_timeout": 1,
|
||||
"request_channel_tries": 1,
|
||||
}
|
||||
)
|
||||
master_uri = "tcp://{master_ip}:{master_port}".format(
|
||||
master_ip="localhost", master_port=opts["master_port"]
|
||||
master_ip="localhost", master_port=minion_opts["master_port"]
|
||||
)
|
||||
mock_reqchannel = MockReqChannel()
|
||||
patch_reqchannel = patch.object(
|
||||
salt.channel.client, "ReqChannel", return_value=mock_reqchannel
|
||||
)
|
||||
with patch_reqchannel:
|
||||
with salt.fileclient.get_file_client(opts) as client:
|
||||
with salt.fileclient.get_file_client(minion_opts) as client:
|
||||
client.master_opts()
|
||||
assert not client._closing
|
||||
|
||||
assert client._closing
|
||||
assert client.channel.close.called
|
||||
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_fileclient_timeout(minion_opts, master_opts):
|
||||
"""
|
||||
ensure fileclient channel closes
|
||||
when used with a context manager
|
||||
"""
|
||||
minion_opts.update(
|
||||
{
|
||||
"id": "root",
|
||||
"transport": "zeromq",
|
||||
"auth_tries": 1,
|
||||
"auth_timeout": 5,
|
||||
"master_ip": "127.0.0.1",
|
||||
"master_port": master_opts["ret_port"],
|
||||
"master_uri": "tcp://127.0.0.1:{}".format(master_opts["ret_port"]),
|
||||
"request_channel_timeout": 1,
|
||||
"request_channel_tries": 1,
|
||||
}
|
||||
)
|
||||
master_uri = "tcp://{master_ip}:{master_port}".format(
|
||||
master_ip="localhost", master_port=minion_opts["master_port"]
|
||||
)
|
||||
|
||||
async def mock_auth():
|
||||
return True
|
||||
|
||||
def mock_dumps(*args):
|
||||
return b"meh"
|
||||
|
||||
with salt.fileclient.get_file_client(minion_opts) as client:
|
||||
# Authenticate must return true
|
||||
client.auth.authenticate = mock_auth
|
||||
# Crypticla must return bytes to pass to transport.RequestClient.send
|
||||
client.auth._crypticle = Mock()
|
||||
client.auth._crypticle.dumps = mock_dumps
|
||||
with pytest.raises(salt.exceptions.SaltClientError):
|
||||
client.file_list()
|
||||
|
|
|
@ -1,10 +1,40 @@
|
|||
"""
|
||||
Unit tests for the salt.utils.nacl module
|
||||
"""
|
||||
import os
|
||||
|
||||
import salt.utils.nacl
|
||||
import pytest
|
||||
|
||||
import salt.modules.config as config
|
||||
import salt.utils.files
|
||||
from tests.support.mock import patch
|
||||
|
||||
pytest.importorskip("nacl.public")
|
||||
pytest.importorskip("nacl.secret")
|
||||
|
||||
import salt.utils.nacl as nacl
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def configure_loader_modules():
|
||||
return {
|
||||
nacl: {"__salt__": {"config.get": config.get}},
|
||||
config: {"__opts__": {}},
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def test_keygen():
|
||||
"""
|
||||
test nacl.keygen function
|
||||
|
||||
Note: nacl.keygen returns base64 encoded values
|
||||
"""
|
||||
ret = nacl.keygen()
|
||||
assert "sk" in ret
|
||||
assert "pk" in ret
|
||||
return ret
|
||||
|
||||
|
||||
def test_fips_mode():
|
||||
"""
|
||||
|
@ -14,3 +44,122 @@ def test_fips_mode():
|
|||
with patch("salt.utils.nacl.__opts__", opts, create=True):
|
||||
ret = salt.utils.nacl.__virtual__()
|
||||
assert ret == (False, "nacl utils not available in FIPS mode")
|
||||
|
||||
|
||||
def test_keygen_sk_file(test_keygen):
|
||||
"""
|
||||
test nacl.keygen function
|
||||
with sk_file set
|
||||
"""
|
||||
with pytest.helpers.temp_file("test_keygen_sk_file") as fpath:
|
||||
with salt.utils.files.fopen(fpath, "wb") as wfh:
|
||||
wfh.write(test_keygen["sk"])
|
||||
|
||||
# test sk_file
|
||||
ret = nacl.keygen(sk_file=fpath)
|
||||
assert f"saved pk_file: {fpath}.pub" == ret
|
||||
salt.utils.files.remove(str(fpath) + ".pub")
|
||||
|
||||
|
||||
def test_keygen_keyfile(test_keygen):
|
||||
"""
|
||||
test nacl.keygen function
|
||||
with keyfile set
|
||||
"""
|
||||
with pytest.helpers.temp_file("test_keygen_keyfile") as fpath:
|
||||
with salt.utils.files.fopen(fpath, "wb") as wfh:
|
||||
wfh.write(test_keygen["sk"])
|
||||
|
||||
ret = nacl.keygen(keyfile=fpath)
|
||||
assert f"saved pk_file: {fpath}.pub" == ret
|
||||
salt.utils.files.remove(str(fpath) + ".pub")
|
||||
|
||||
|
||||
def test_enc_keyfile(test_keygen):
|
||||
"""
|
||||
test nacl.enc function
|
||||
with keyfile and pk_file set
|
||||
"""
|
||||
with pytest.helpers.temp_file("test_enc_keyfile") as fpath:
|
||||
with salt.utils.files.fopen(fpath, "wb") as wfh:
|
||||
wfh.write(test_keygen["sk"])
|
||||
with salt.utils.files.fopen(str(fpath) + ".pub", "wb") as wfhpub:
|
||||
wfhpub.write(test_keygen["pk"])
|
||||
|
||||
kwargs = {
|
||||
"opts": {"pki_dir": os.path.dirname(fpath)},
|
||||
"keyfile": str(fpath),
|
||||
"pk_file": str(fpath) + ".pub",
|
||||
}
|
||||
ret = nacl.enc("blah", **kwargs)
|
||||
assert isinstance(ret, bytes)
|
||||
salt.utils.files.remove(str(fpath) + ".pub")
|
||||
|
||||
|
||||
def test_enc_sk_file(test_keygen):
|
||||
"""
|
||||
test nacl.enc function
|
||||
with sk_file and pk_file set
|
||||
"""
|
||||
with pytest.helpers.temp_file("test_enc_sk_file") as fpath:
|
||||
with salt.utils.files.fopen(fpath, "wb") as wfh:
|
||||
wfh.write(test_keygen["sk"])
|
||||
with salt.utils.files.fopen(str(fpath) + ".pub", "wb") as wfhpub:
|
||||
wfhpub.write(test_keygen["pk"])
|
||||
|
||||
kwargs = {
|
||||
"opts": {"pki_dir": os.path.dirname(fpath)},
|
||||
"sk_file": str(fpath),
|
||||
"pk_file": str(fpath) + ".pub",
|
||||
}
|
||||
ret = nacl.enc("blah", **kwargs)
|
||||
assert isinstance(ret, bytes)
|
||||
salt.utils.files.remove(str(fpath) + ".pub")
|
||||
|
||||
|
||||
def test_dec_keyfile(test_keygen):
|
||||
"""
|
||||
test nacl.dec function
|
||||
with keyfile and pk_file set
|
||||
"""
|
||||
with pytest.helpers.temp_file("test_dec_keyfile") as fpath:
|
||||
with salt.utils.files.fopen(fpath, "wb") as wfh:
|
||||
wfh.write(test_keygen["sk"])
|
||||
with salt.utils.files.fopen(str(fpath) + ".pub", "wb") as wfhpub:
|
||||
wfhpub.write(test_keygen["pk"])
|
||||
|
||||
kwargs = {
|
||||
"opts": {"pki_dir": os.path.dirname(fpath)},
|
||||
"keyfile": str(fpath),
|
||||
"pk_file": str(fpath) + ".pub",
|
||||
}
|
||||
|
||||
enc_data = nacl.enc("blah", **kwargs)
|
||||
ret = nacl.dec(enc_data, **kwargs)
|
||||
assert isinstance(ret, bytes)
|
||||
assert ret == b"blah"
|
||||
salt.utils.files.remove(str(fpath) + ".pub")
|
||||
|
||||
|
||||
def test_dec_sk_file(test_keygen):
|
||||
"""
|
||||
test nacl.dec function
|
||||
with sk_file and pk_file set
|
||||
"""
|
||||
with pytest.helpers.temp_file("test_dec_sk_file") as fpath:
|
||||
with salt.utils.files.fopen(fpath, "wb") as wfh:
|
||||
wfh.write(test_keygen["sk"])
|
||||
with salt.utils.files.fopen(str(fpath) + ".pub", "wb") as wfhpub:
|
||||
wfhpub.write(test_keygen["pk"])
|
||||
|
||||
kwargs = {
|
||||
"opts": {"pki_dir": os.path.dirname(fpath)},
|
||||
"sk_file": str(fpath),
|
||||
"pk_file": str(fpath) + ".pub",
|
||||
}
|
||||
|
||||
enc_data = nacl.enc("blah", **kwargs)
|
||||
ret = nacl.dec(enc_data, **kwargs)
|
||||
assert isinstance(ret, bytes)
|
||||
assert ret == b"blah"
|
||||
salt.utils.files.remove(str(fpath) + ".pub")
|
||||
|
|
|
@ -1,91 +0,0 @@
|
|||
"""
|
||||
Tests for the nacl execution module
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
import salt.utils.stringutils
|
||||
from tests.support.mixins import LoaderModuleMockMixin
|
||||
from tests.support.unit import TestCase
|
||||
|
||||
try:
|
||||
import libnacl.sealed # pylint: disable=unused-import
|
||||
import libnacl.secret # pylint: disable=unused-import
|
||||
|
||||
import salt.modules.nacl as nacl
|
||||
|
||||
HAS_LIBNACL = True
|
||||
except (ImportError, OSError, AttributeError):
|
||||
HAS_LIBNACL = False
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info >= (3, 10), reason="Segfaults with python 3.10")
|
||||
@pytest.mark.skipif(
|
||||
not HAS_LIBNACL, reason="skipping test_nacl, reason=libnacl is unavailable"
|
||||
)
|
||||
class NaclTest(TestCase, LoaderModuleMockMixin):
|
||||
"""
|
||||
Test the nacl runner
|
||||
"""
|
||||
|
||||
def setup_loader_modules(self):
|
||||
self.unencrypted_data = salt.utils.stringutils.to_bytes("hello")
|
||||
self.opts = salt.config.DEFAULT_MINION_OPTS.copy()
|
||||
utils = salt.loader.utils(self.opts)
|
||||
funcs = salt.loader.minion_mods(self.opts, utils=utils, whitelist=["nacl"])
|
||||
|
||||
return {
|
||||
nacl: {"__opts__": self.opts, "__utils__": utils, "__salt__": funcs},
|
||||
}
|
||||
|
||||
def setUp(self):
|
||||
# Generate the keys
|
||||
ret = nacl.keygen()
|
||||
self.assertIn("pk", ret)
|
||||
self.assertIn("sk", ret)
|
||||
self.pk = ret["pk"]
|
||||
self.sk = ret["sk"]
|
||||
|
||||
def test_keygen(self):
|
||||
"""
|
||||
Test keygen
|
||||
"""
|
||||
self.assertEqual(len(self.pk), 44)
|
||||
self.assertEqual(len(self.sk), 44)
|
||||
|
||||
def test_enc_dec(self):
|
||||
"""
|
||||
Generate keys, encrypt, then decrypt.
|
||||
"""
|
||||
# Encrypt with pk
|
||||
encrypted_data = nacl.enc(data=self.unencrypted_data, pk=self.pk)
|
||||
|
||||
# Decrypt with sk
|
||||
decrypted_data = nacl.dec(data=encrypted_data, sk=self.sk)
|
||||
self.assertEqual(self.unencrypted_data, decrypted_data)
|
||||
|
||||
def test_sealedbox_enc_dec(self):
|
||||
"""
|
||||
Generate keys, encrypt, then decrypt.
|
||||
"""
|
||||
# Encrypt with pk
|
||||
encrypted_data = nacl.sealedbox_encrypt(data=self.unencrypted_data, pk=self.pk)
|
||||
|
||||
# Decrypt with sk
|
||||
decrypted_data = nacl.sealedbox_decrypt(data=encrypted_data, sk=self.sk)
|
||||
|
||||
self.assertEqual(self.unencrypted_data, decrypted_data)
|
||||
|
||||
def test_secretbox_enc_dec(self):
|
||||
"""
|
||||
Generate keys, encrypt, then decrypt.
|
||||
"""
|
||||
# Encrypt with sk
|
||||
encrypted_data = nacl.secretbox_encrypt(data=self.unencrypted_data, sk=self.sk)
|
||||
|
||||
# Decrypt with sk
|
||||
decrypted_data = nacl.secretbox_decrypt(data=encrypted_data, sk=self.sk)
|
||||
|
||||
self.assertEqual(self.unencrypted_data, decrypted_data)
|
|
@ -1,149 +0,0 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
import salt.modules.config as config
|
||||
import salt.utils.files
|
||||
from tests.support.helpers import with_tempfile
|
||||
from tests.support.mixins import LoaderModuleMockMixin
|
||||
from tests.support.unit import TestCase
|
||||
|
||||
try:
|
||||
import libnacl.sealed # pylint: disable=unused-import
|
||||
import libnacl.secret # pylint: disable=unused-import
|
||||
|
||||
import salt.utils.nacl as nacl
|
||||
|
||||
HAS_LIBNACL = True
|
||||
except (ImportError, OSError, AttributeError):
|
||||
HAS_LIBNACL = False
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info >= (3, 10), reason="Segfaults with python 3.10")
|
||||
@pytest.mark.skipif(
|
||||
not HAS_LIBNACL, reason="skipping test_nacl, reason=libnacl is unavailable"
|
||||
)
|
||||
class NaclUtilsTests(TestCase, LoaderModuleMockMixin):
|
||||
def setup_loader_modules(self):
|
||||
return {
|
||||
nacl: {"__salt__": {"config.get": config.get}},
|
||||
config: {"__opts__": {}},
|
||||
}
|
||||
|
||||
def setUp(self):
|
||||
self.key = "C16NxgBhw8cqbhvPCDAn2pirwW1A1WEVLUexCsoUD2Y="
|
||||
self.pub = "+XWFfZXnfItS++a4gQf8Adu1aUlTgHWyTfsglbTdXyg="
|
||||
|
||||
def test_keygen(self):
|
||||
"""
|
||||
test nacl.keygen function
|
||||
"""
|
||||
ret = nacl.keygen()
|
||||
assert all(key in ret for key in ret.keys())
|
||||
|
||||
@with_tempfile()
|
||||
def test_keygen_sk_file(self, fpath):
|
||||
"""
|
||||
test nacl.keygen function
|
||||
with sk_file set
|
||||
"""
|
||||
with salt.utils.files.fopen(fpath, "w") as wfh:
|
||||
wfh.write(self.key)
|
||||
# test sk_file
|
||||
ret = nacl.keygen(sk_file=fpath)
|
||||
assert "saved pk_file: {}.pub".format(fpath) == ret
|
||||
|
||||
@with_tempfile()
|
||||
def test_keygen_keyfile(self, fpath):
|
||||
"""
|
||||
test nacl.keygen function
|
||||
with keyfile set
|
||||
"""
|
||||
with salt.utils.files.fopen(fpath, "w") as wfh:
|
||||
wfh.write(self.key)
|
||||
|
||||
ret = nacl.keygen(keyfile=fpath)
|
||||
assert "saved pk_file: {}.pub".format(fpath) == ret
|
||||
|
||||
@with_tempfile()
|
||||
def test_enc_keyfile(self, fpath):
|
||||
"""
|
||||
test nacl.enc function
|
||||
with keyfile and pk_file set
|
||||
"""
|
||||
with salt.utils.files.fopen(fpath, "w") as wfh:
|
||||
wfh.write(self.key)
|
||||
with salt.utils.files.fopen(fpath + ".pub", "w") as wfh:
|
||||
wfh.write(self.pub)
|
||||
|
||||
kwargs = {
|
||||
"opts": {"pki_dir": os.path.dirname(fpath)},
|
||||
"keyfile": fpath,
|
||||
"pk_file": fpath + ".pub",
|
||||
}
|
||||
ret = nacl.enc("blah", **kwargs)
|
||||
assert isinstance(ret, bytes)
|
||||
|
||||
@with_tempfile()
|
||||
def test_enc_sk_file(self, fpath):
|
||||
"""
|
||||
test nacl.enc function
|
||||
with sk_file and pk_file set
|
||||
"""
|
||||
with salt.utils.files.fopen(fpath, "w") as wfh:
|
||||
wfh.write(self.key)
|
||||
with salt.utils.files.fopen(fpath + ".pub", "w") as wfh:
|
||||
wfh.write(self.pub)
|
||||
|
||||
kwargs = {
|
||||
"opts": {"pki_dir": os.path.dirname(fpath)},
|
||||
"sk_file": fpath,
|
||||
"pk_file": fpath + ".pub",
|
||||
}
|
||||
ret = nacl.enc("blah", **kwargs)
|
||||
assert isinstance(ret, bytes)
|
||||
|
||||
@with_tempfile()
|
||||
def test_dec_keyfile(self, fpath):
|
||||
"""
|
||||
test nacl.dec function
|
||||
with keyfile and pk_file set
|
||||
"""
|
||||
with salt.utils.files.fopen(fpath, "w") as wfh:
|
||||
wfh.write(self.key)
|
||||
with salt.utils.files.fopen(fpath + ".pub", "w") as wfh:
|
||||
wfh.write(self.pub)
|
||||
|
||||
kwargs = {
|
||||
"opts": {"pki_dir": os.path.dirname(fpath)},
|
||||
"keyfile": fpath,
|
||||
"pk_file": fpath + ".pub",
|
||||
}
|
||||
|
||||
enc_data = nacl.enc("blah", **kwargs)
|
||||
ret = nacl.dec(enc_data, **kwargs)
|
||||
assert isinstance(ret, bytes)
|
||||
assert ret == b"blah"
|
||||
|
||||
@with_tempfile()
|
||||
def test_dec_sk_file(self, fpath):
|
||||
"""
|
||||
test nacl.dec function
|
||||
with sk_file and pk_file set
|
||||
"""
|
||||
with salt.utils.files.fopen(fpath, "w") as wfh:
|
||||
wfh.write(self.key)
|
||||
with salt.utils.files.fopen(fpath + ".pub", "w") as wfh:
|
||||
wfh.write(self.pub)
|
||||
|
||||
kwargs = {
|
||||
"opts": {"pki_dir": os.path.dirname(fpath)},
|
||||
"sk_file": fpath,
|
||||
"pk_file": fpath + ".pub",
|
||||
}
|
||||
|
||||
enc_data = nacl.enc("blah", **kwargs)
|
||||
ret = nacl.dec(enc_data, **kwargs)
|
||||
assert isinstance(ret, bytes)
|
||||
assert ret == b"blah"
|
16
tools/vm.py
16
tools/vm.py
|
@ -78,7 +78,7 @@ vm.add_argument("--region", help="The AWS region.", default=AWS_REGION)
|
|||
"choices": list(AMIS),
|
||||
},
|
||||
"key_name": {
|
||||
"help": "The SSH key name.",
|
||||
"help": "The SSH key name. Will default to TOOLS_KEY_NAME in environment",
|
||||
},
|
||||
"instance_type": {
|
||||
"help": "The instance type to use.",
|
||||
|
@ -110,7 +110,7 @@ vm.add_argument("--region", help="The AWS region.", default=AWS_REGION)
|
|||
def create(
|
||||
ctx: Context,
|
||||
name: str,
|
||||
key_name: str = os.environ.get("RUNNER_NAME"), # type: ignore[assignment]
|
||||
key_name: str = os.environ.get("RUNNER_NAME") or os.environ.get("TOOLS_KEY_NAME"), # type: ignore[assignment]
|
||||
instance_type: str = None,
|
||||
no_delete: bool = False,
|
||||
no_destroy_on_failure: bool = False,
|
||||
|
@ -566,7 +566,9 @@ def download_artifacts(ctx: Context, name: str):
|
|||
@vm.command(
|
||||
name="sync-cache",
|
||||
arguments={
|
||||
"key_name": {"help": "The SSH key name."},
|
||||
"key_name": {
|
||||
"help": "The SSH key name. Will default to TOOLS_KEY_NAME in environment"
|
||||
},
|
||||
"delete": {
|
||||
"help": "Delete the entries in the cache that don't align with ec2",
|
||||
"action": "store_true",
|
||||
|
@ -575,7 +577,7 @@ def download_artifacts(ctx: Context, name: str):
|
|||
)
|
||||
def sync_cache(
|
||||
ctx: Context,
|
||||
key_name: str = os.environ.get("RUNNER_NAME"), # type: ignore[assignment]
|
||||
key_name: str = os.environ.get("RUNNER_NAME") or os.environ.get("TOOLS_KEY_NAME"), # type: ignore[assignment]
|
||||
delete: bool = False,
|
||||
):
|
||||
"""
|
||||
|
@ -626,7 +628,9 @@ def sync_cache(
|
|||
@vm.command(
|
||||
name="list",
|
||||
arguments={
|
||||
"key_name": {"help": "The SSH key name."},
|
||||
"key_name": {
|
||||
"help": "The SSH key name. Will default to TOOLS_KEY_NAME in environment"
|
||||
},
|
||||
"states": {
|
||||
"help": "The instance state to filter by.",
|
||||
"flags": ["-s", "-state"],
|
||||
|
@ -636,7 +640,7 @@ def sync_cache(
|
|||
)
|
||||
def list_vms(
|
||||
ctx: Context,
|
||||
key_name: str = os.environ.get("RUNNER_NAME"), # type: ignore[assignment]
|
||||
key_name: str = os.environ.get("RUNNER_NAME") or os.environ.get("TOOLS_KEY_NAME"), # type: ignore[assignment]
|
||||
states: set[str] = None,
|
||||
):
|
||||
"""
|
||||
|
|
Loading…
Add table
Reference in a new issue