mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge pull request #65485 from s0undt3ch/hotfix/merge-forward
[master] Merge 3006.x into master
This commit is contained in:
commit
53f54d08d9
78 changed files with 3692 additions and 2595 deletions
25
CHANGELOG.md
25
CHANGELOG.md
|
@ -7,6 +7,31 @@ Versions are `MAJOR.PATCH`.
|
|||
|
||||
# Changelog
|
||||
|
||||
|
||||
## 3006.4 (2023-10-16)
|
||||
|
||||
### Security
|
||||
|
||||
- Fix CVE-2023-34049 by ensuring we do not use a predictable name for the script and correctly check returncode of scp command.
|
||||
This only impacts salt-ssh users using the pre-flight option. [#cve-2023-34049](https://github.com/saltstack/salt/issues/cve-2023-34049)
|
||||
- Update to `gitpython>=3.1.35` due to https://github.com/advisories/GHSA-wfm5-v35h-vwf4 and https://github.com/advisories/GHSA-cwvm-v4w8-q58c [#65163](https://github.com/saltstack/salt/issues/65163)
|
||||
- Bump to `cryptography==41.0.4` due to https://github.com/advisories/GHSA-v8gr-m533-ghj9 [#65268](https://github.com/saltstack/salt/issues/65268)
|
||||
- Upgrade relenv to 0.13.12 to address CVE-2023-4807 [#65316](https://github.com/saltstack/salt/issues/65316)
|
||||
- Bump to `urllib3==1.26.17` or `urllib3==2.0.6` due to https://github.com/advisories/GHSA-v845-jxx5-vc9f [#65334](https://github.com/saltstack/salt/issues/65334)
|
||||
- Bump to `gitpython==3.1.37` due to https://github.com/advisories/GHSA-cwvm-v4w8-q58c [#65383](https://github.com/saltstack/salt/issues/65383)
|
||||
|
||||
|
||||
## 3005.4 (2023-10-16)
|
||||
|
||||
### Security
|
||||
|
||||
- Fix CVE-2023-34049 by ensuring we do not use a predictable name for the script and correctly check returncode of scp command.
|
||||
This only impacts salt-ssh users using the pre-flight option. (cve-2023-34049)
|
||||
- Bump to `cryptography==41.0.4` due to https://github.com/advisories/GHSA-v8gr-m533-ghj9 (#65267)
|
||||
- Bump to `urllib3==1.26.17` or `urllib3==2.0.6` due to https://github.com/advisories/GHSA-v845-jxx5-vc9f (#65334)
|
||||
- Bump to `gitpython==3.1.37` due to https://github.com/advisories/GHSA-cwvm-v4w8-q58c (#65383)
|
||||
|
||||
|
||||
## Salt v3005.3 (2023-09-14)
|
||||
|
||||
### Fixed
|
||||
|
|
1
changelog/64572.fixed.md
Normal file
1
changelog/64572.fixed.md
Normal file
|
@ -0,0 +1 @@
|
|||
Move salt.ufw to correct location /etc/ufw/applications.d/
|
|
@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SALT-API" "1" "Generated on September 06, 2023 at 04:52:57 PM UTC." "3006.3" "Salt"
|
||||
.TH "SALT-API" "1" "Generated on October 16, 2023 at 05:24:47 PM UTC." "3006.4" "Salt"
|
||||
.SH NAME
|
||||
salt-api \- salt-api Command
|
||||
.sp
|
||||
|
|
|
@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SALT-CALL" "1" "Generated on September 06, 2023 at 04:52:57 PM UTC." "3006.3" "Salt"
|
||||
.TH "SALT-CALL" "1" "Generated on October 16, 2023 at 05:24:47 PM UTC." "3006.4" "Salt"
|
||||
.SH NAME
|
||||
salt-call \- salt-call Documentation
|
||||
.SH SYNOPSIS
|
||||
|
|
|
@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SALT-CLOUD" "1" "Generated on September 06, 2023 at 04:52:57 PM UTC." "3006.3" "Salt"
|
||||
.TH "SALT-CLOUD" "1" "Generated on October 16, 2023 at 05:24:47 PM UTC." "3006.4" "Salt"
|
||||
.SH NAME
|
||||
salt-cloud \- Salt Cloud Command
|
||||
.sp
|
||||
|
|
|
@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SALT-CP" "1" "Generated on September 06, 2023 at 04:52:57 PM UTC." "3006.3" "Salt"
|
||||
.TH "SALT-CP" "1" "Generated on October 16, 2023 at 05:24:47 PM UTC." "3006.4" "Salt"
|
||||
.SH NAME
|
||||
salt-cp \- salt-cp Documentation
|
||||
.sp
|
||||
|
|
|
@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SALT-KEY" "1" "Generated on September 06, 2023 at 04:52:57 PM UTC." "3006.3" "Salt"
|
||||
.TH "SALT-KEY" "1" "Generated on October 16, 2023 at 05:24:47 PM UTC." "3006.4" "Salt"
|
||||
.SH NAME
|
||||
salt-key \- salt-key Documentation
|
||||
.SH SYNOPSIS
|
||||
|
|
|
@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SALT-MASTER" "1" "Generated on September 06, 2023 at 04:52:57 PM UTC." "3006.3" "Salt"
|
||||
.TH "SALT-MASTER" "1" "Generated on October 16, 2023 at 05:24:47 PM UTC." "3006.4" "Salt"
|
||||
.SH NAME
|
||||
salt-master \- salt-master Documentation
|
||||
.sp
|
||||
|
|
|
@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SALT-MINION" "1" "Generated on September 06, 2023 at 04:52:57 PM UTC." "3006.3" "Salt"
|
||||
.TH "SALT-MINION" "1" "Generated on October 16, 2023 at 05:24:47 PM UTC." "3006.4" "Salt"
|
||||
.SH NAME
|
||||
salt-minion \- salt-minion Documentation
|
||||
.sp
|
||||
|
|
|
@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SALT-PROXY" "1" "Generated on September 06, 2023 at 04:52:57 PM UTC." "3006.3" "Salt"
|
||||
.TH "SALT-PROXY" "1" "Generated on October 16, 2023 at 05:24:47 PM UTC." "3006.4" "Salt"
|
||||
.SH NAME
|
||||
salt-proxy \- salt-proxy Documentation
|
||||
.sp
|
||||
|
|
|
@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SALT-RUN" "1" "Generated on September 06, 2023 at 04:52:57 PM UTC." "3006.3" "Salt"
|
||||
.TH "SALT-RUN" "1" "Generated on October 16, 2023 at 05:24:47 PM UTC." "3006.4" "Salt"
|
||||
.SH NAME
|
||||
salt-run \- salt-run Documentation
|
||||
.sp
|
||||
|
|
|
@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SALT-SSH" "1" "Generated on September 06, 2023 at 04:52:57 PM UTC." "3006.3" "Salt"
|
||||
.TH "SALT-SSH" "1" "Generated on October 16, 2023 at 05:24:47 PM UTC." "3006.4" "Salt"
|
||||
.SH NAME
|
||||
salt-ssh \- salt-ssh Documentation
|
||||
.SH SYNOPSIS
|
||||
|
|
|
@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SALT-SYNDIC" "1" "Generated on September 06, 2023 at 04:52:57 PM UTC." "3006.3" "Salt"
|
||||
.TH "SALT-SYNDIC" "1" "Generated on October 16, 2023 at 05:24:47 PM UTC." "3006.4" "Salt"
|
||||
.SH NAME
|
||||
salt-syndic \- salt-syndic Documentation
|
||||
.sp
|
||||
|
|
|
@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SALT" "1" "Generated on September 06, 2023 at 04:52:57 PM UTC." "3006.3" "Salt"
|
||||
.TH "SALT" "1" "Generated on October 16, 2023 at 05:24:47 PM UTC." "3006.4" "Salt"
|
||||
.SH NAME
|
||||
salt \- salt
|
||||
.SH SYNOPSIS
|
||||
|
|
|
@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SALT" "7" "Generated on September 06, 2023 at 04:52:57 PM UTC." "3006.3" "Salt"
|
||||
.TH "SALT" "7" "Generated on October 16, 2023 at 05:24:47 PM UTC." "3006.4" "Salt"
|
||||
.SH NAME
|
||||
salt \- Salt Documentation
|
||||
.SH SALT PROJECT
|
||||
|
@ -194128,7 +194128,7 @@ Passes through all the parameters described in the
|
|||
\fI\%utils.http.query function\fP:
|
||||
.INDENT 7.0
|
||||
.TP
|
||||
.B salt.utils.http.query(url, method=\(aqGET\(aq, params=None, data=None, data_file=None, header_dict=None, header_list=None, header_file=None, username=None, password=None, auth=None, decode=False, decode_type=\(aqauto\(aq, status=False, headers=False, text=False, cookies=None, cookie_jar=None, cookie_format=\(aqlwp\(aq, persist_session=False, session_cookie_jar=None, data_render=False, data_renderer=None, header_render=False, header_renderer=None, template_dict=None, test=False, test_url=None, node=\(aqminion\(aq, port=80, opts=None, backend=None, ca_bundle=None, verify_ssl=None, cert=None, text_out=None, headers_out=None, decode_out=None, stream=False, streaming_callback=None, header_callback=None, handle=False, agent=\(aqSalt/3006.3\(aq, hide_fields=None, raise_error=True, formdata=False, formdata_fieldname=None, formdata_filename=None, decode_body=True, **kwargs)
|
||||
.B salt.utils.http.query(url, method=\(aqGET\(aq, params=None, data=None, data_file=None, header_dict=None, header_list=None, header_file=None, username=None, password=None, auth=None, decode=False, decode_type=\(aqauto\(aq, status=False, headers=False, text=False, cookies=None, cookie_jar=None, cookie_format=\(aqlwp\(aq, persist_session=False, session_cookie_jar=None, data_render=False, data_renderer=None, header_render=False, header_renderer=None, template_dict=None, test=False, test_url=None, node=\(aqminion\(aq, port=80, opts=None, backend=None, ca_bundle=None, verify_ssl=None, cert=None, text_out=None, headers_out=None, decode_out=None, stream=False, streaming_callback=None, header_callback=None, handle=False, agent=\(aqSalt/3006.4\(aq, hide_fields=None, raise_error=True, formdata=False, formdata_fieldname=None, formdata_filename=None, decode_body=True, **kwargs)
|
||||
Query a resource, and decode the return data
|
||||
.UNINDENT
|
||||
.INDENT 7.0
|
||||
|
@ -457626,7 +457626,7 @@ installed2
|
|||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B salt.states.zcbuildout.installed(name, config=\(aqbuildout.cfg\(aq, quiet=False, parts=None, user=None, env=(), buildout_ver=None, test_release=False, distribute=None, new_st=None, offline=False, newest=False, python=\(aq/opt/actions\-runner/_work/salt/salt/.tools\-venvs/py3.10/docs/bin/python\(aq, debug=False, verbose=False, unless=None, onlyif=None, use_vt=False, loglevel=\(aqdebug\(aq, **kwargs)
|
||||
.B salt.states.zcbuildout.installed(name, config=\(aqbuildout.cfg\(aq, quiet=False, parts=None, user=None, env=(), buildout_ver=None, test_release=False, distribute=None, new_st=None, offline=False, newest=False, python=\(aq/opt/actions\-runner/_work/salt\-priv/salt\-priv/.tools\-venvs/py3.10/docs/bin/python\(aq, debug=False, verbose=False, unless=None, onlyif=None, use_vt=False, loglevel=\(aqdebug\(aq, **kwargs)
|
||||
Install buildout in a specific directory
|
||||
.sp
|
||||
It is a thin wrapper to modules.buildout.buildout
|
||||
|
@ -477556,6 +477556,25 @@ Addresses multiple CVEs in Python\(aqs dependencies: \fI\%https://docs.python.or
|
|||
.IP \(bu 2
|
||||
Update to \fBgitpython>=3.1.32\fP due to \fI\%https://github.com/advisories/GHSA\-pr76\-5cm5\-w9cj\fP \fI\%#64988\fP
|
||||
.UNINDENT
|
||||
(release\-3006.4)=
|
||||
.SS Salt 3006.4 release notes
|
||||
.SS Changelog
|
||||
.SS Security
|
||||
.INDENT 0.0
|
||||
.IP \(bu 2
|
||||
Fix CVE\-2023\-34049 by ensuring we do not use a predictable name for the script and correctly check returncode of scp command.
|
||||
This only impacts salt\-ssh users using the pre\-flight option. \fI\%#cve\-2023\-34049\fP
|
||||
.IP \(bu 2
|
||||
Update to \fBgitpython>=3.1.35\fP due to \fI\%https://github.com/advisories/GHSA\-wfm5\-v35h\-vwf4\fP and \fI\%https://github.com/advisories/GHSA\-cwvm\-v4w8\-q58c\fP \fI\%#65163\fP
|
||||
.IP \(bu 2
|
||||
Bump to \fBcryptography==41.0.4\fP due to \fI\%https://github.com/advisories/GHSA\-v8gr\-m533\-ghj9\fP \fI\%#65268\fP
|
||||
.IP \(bu 2
|
||||
Upgrade relenv to 0.13.12 to address CVE\-2023\-4807 \fI\%#65316\fP
|
||||
.IP \(bu 2
|
||||
Bump to \fBurllib3==1.26.17\fP or \fBurllib3==2.0.6\fP due to \fI\%https://github.com/advisories/GHSA\-v845\-jxx5\-vc9f\fP \fI\%#65334\fP
|
||||
.IP \(bu 2
|
||||
Bump to \fBgitpython==3.1.37\fP due to \fI\%https://github.com/advisories/GHSA\-cwvm\-v4w8\-q58c\fP \fI\%#65383\fP
|
||||
.UNINDENT
|
||||
.sp
|
||||
See \fI\%Install a release candidate\fP
|
||||
for more information about installing an RC when one is available.
|
||||
|
|
|
@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "SPM" "1" "Generated on September 06, 2023 at 04:52:57 PM UTC." "3006.3" "Salt"
|
||||
.TH "SPM" "1" "Generated on October 16, 2023 at 05:24:47 PM UTC." "3006.4" "Salt"
|
||||
.SH NAME
|
||||
spm \- Salt Package Manager Command
|
||||
.sp
|
||||
|
|
17
doc/topics/releases/3005.4.rst
Normal file
17
doc/topics/releases/3005.4.rst
Normal file
|
@ -0,0 +1,17 @@
|
|||
.. _release-3005-4:
|
||||
|
||||
=========================
|
||||
Salt 3005.4 Release Notes
|
||||
=========================
|
||||
|
||||
Version 3005.4 is a CVE security fix release for :ref:`3005 <release-3005>`.
|
||||
|
||||
|
||||
Security
|
||||
--------
|
||||
|
||||
- Fix CVE-2023-34049 by ensuring we do not use a predictable name for the script and correctly check returncode of scp command.
|
||||
This only impacts salt-ssh users using the pre-flight option. (cve-2023-34049)
|
||||
- Bump to `cryptography==41.0.4` due to https://github.com/advisories/GHSA-v8gr-m533-ghj9 (#65267)
|
||||
- Bump to `urllib3==1.26.17` or `urllib3==2.0.6` due to https://github.com/advisories/GHSA-v845-jxx5-vc9f (#65334)
|
||||
- Bump to `gitpython==3.1.37` due to https://github.com/advisories/GHSA-cwvm-v4w8-q58c (#65383)
|
29
doc/topics/releases/3006.4.md
Normal file
29
doc/topics/releases/3006.4.md
Normal file
|
@ -0,0 +1,29 @@
|
|||
(release-3006.4)=
|
||||
# Salt 3006.4 release notes
|
||||
|
||||
<!---
|
||||
Do not edit this file. This is auto generated.
|
||||
Edit the templates in doc/topics/releases/templates/
|
||||
for a given release.
|
||||
-->
|
||||
|
||||
|
||||
<!--
|
||||
Add release specific details below
|
||||
-->
|
||||
|
||||
<!--
|
||||
Do not edit the changelog below.
|
||||
This is auto generated.
|
||||
-->
|
||||
## Changelog
|
||||
|
||||
### Security
|
||||
|
||||
- Fix CVE-2023-34049 by ensuring we do not use a predictable name for the script and correctly check returncode of scp command.
|
||||
This only impacts salt-ssh users using the pre-flight option. [#cve-2023-34049](https://github.com/saltstack/salt/issues/cve-2023-34049)
|
||||
- Update to `gitpython>=3.1.35` due to https://github.com/advisories/GHSA-wfm5-v35h-vwf4 and https://github.com/advisories/GHSA-cwvm-v4w8-q58c [#65163](https://github.com/saltstack/salt/issues/65163)
|
||||
- Bump to `cryptography==41.0.4` due to https://github.com/advisories/GHSA-v8gr-m533-ghj9 [#65268](https://github.com/saltstack/salt/issues/65268)
|
||||
- Upgrade relenv to 0.13.12 to address CVE-2023-4807 [#65316](https://github.com/saltstack/salt/issues/65316)
|
||||
- Bump to `urllib3==1.26.17` or `urllib3==2.0.6` due to https://github.com/advisories/GHSA-v845-jxx5-vc9f [#65334](https://github.com/saltstack/salt/issues/65334)
|
||||
- Bump to `gitpython==3.1.37` due to https://github.com/advisories/GHSA-cwvm-v4w8-q58c [#65383](https://github.com/saltstack/salt/issues/65383)
|
14
doc/topics/releases/templates/3006.4.md.template
Normal file
14
doc/topics/releases/templates/3006.4.md.template
Normal file
|
@ -0,0 +1,14 @@
|
|||
(release-3006.4)=
|
||||
# Salt 3006.4 release notes{{ unreleased }}
|
||||
{{ warning }}
|
||||
|
||||
<!--
|
||||
Add release specific details below
|
||||
-->
|
||||
|
||||
<!--
|
||||
Do not edit the changelog below.
|
||||
This is auto generated.
|
||||
-->
|
||||
## Changelog
|
||||
{{ changelog }}
|
|
@ -1,3 +1,19 @@
|
|||
salt (3006.4) stable; urgency=medium
|
||||
|
||||
|
||||
# Security
|
||||
|
||||
* Fix CVE-2023-34049 by ensuring we do not use a predictable name for the script and correctly check returncode of scp command.
|
||||
This only impacts salt*ssh users using the pre-flight option. [#cve-2023-34049](https://github.com/saltstack/salt/issues/cve-2023-34049)
|
||||
* Update to `gitpython>=3.1.35` due to https://github.com/advisories/GHSA-wfm5-v35h-vwf4 and https://github.com/advisories/GHSA-cwvm-v4w8-q58c [#65163](https://github.com/saltstack/salt/issues/65163)
|
||||
* Bump to `cryptography==41.0.4` due to https://github.com/advisories/GHSA-v8gr-m533-ghj9 [#65268](https://github.com/saltstack/salt/issues/65268)
|
||||
* Upgrade relenv to 0.13.12 to address CVE-2023-4807 [#65316](https://github.com/saltstack/salt/issues/65316)
|
||||
* Bump to `urllib3==1.26.17` or `urllib3==2.0.6` due to https://github.com/advisories/GHSA-v845-jxx5-vc9f [#65334](https://github.com/saltstack/salt/issues/65334)
|
||||
* Bump to `gitpython==3.1.37` due to https://github.com/advisories/GHSA-cwvm-v4w8-q58c [#65383](https://github.com/saltstack/salt/issues/65383)
|
||||
|
||||
|
||||
-- Salt Project Packaging <saltproject-packaging@vmware.com> Mon, 16 Oct 2023 17:22:41 +0000
|
||||
|
||||
salt (3006.3) stable; urgency=medium
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/etc/salt/master.d
|
||||
/etc/ufw/applications.d/salt-master
|
||||
/etc/salt/pki/master/minions
|
||||
/etc/salt/pki/master/minions_autosign
|
||||
/etc/salt/pki/master/minions_denied
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
pkg/common/salt-master.service /lib/systemd/system
|
||||
pkg/common/salt.ufw /etc/ufw/applications.d/salt-master
|
||||
pkg/common/salt.ufw /etc/ufw/applications.d
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
%define fish_dir %{_datadir}/fish/vendor_functions.d
|
||||
|
||||
Name: salt
|
||||
Version: 3006.3
|
||||
Version: 3006.4
|
||||
Release: 0
|
||||
Summary: A parallel remote execution system
|
||||
Group: System Environment/Daemons
|
||||
|
@ -563,6 +563,19 @@ fi
|
|||
|
||||
|
||||
%changelog
|
||||
* Mon Oct 16 2023 Salt Project Packaging <saltproject-packaging@vmware.com> - 3006.4
|
||||
|
||||
# Security
|
||||
|
||||
- Fix CVE-2023-34049 by ensuring we do not use a predictable name for the script and correctly check returncode of scp command.
|
||||
This only impacts salt-ssh users using the pre-flight option. [#cve-2023-34049](https://github.com/saltstack/salt/issues/cve-2023-34049)
|
||||
- Update to `gitpython>=3.1.35` due to https://github.com/advisories/GHSA-wfm5-v35h-vwf4 and https://github.com/advisories/GHSA-cwvm-v4w8-q58c [#65163](https://github.com/saltstack/salt/issues/65163)
|
||||
- Bump to `cryptography==41.0.4` due to https://github.com/advisories/GHSA-v8gr-m533-ghj9 [#65268](https://github.com/saltstack/salt/issues/65268)
|
||||
- Upgrade relenv to 0.13.12 to address CVE-2023-4807 [#65316](https://github.com/saltstack/salt/issues/65316)
|
||||
- Bump to `urllib3==1.26.17` or `urllib3==2.0.6` due to https://github.com/advisories/GHSA-v845-jxx5-vc9f [#65334](https://github.com/saltstack/salt/issues/65334)
|
||||
- Bump to `gitpython==3.1.37` due to https://github.com/advisories/GHSA-cwvm-v4w8-q58c [#65383](https://github.com/saltstack/salt/issues/65383)
|
||||
|
||||
|
||||
* Wed Sep 06 2023 Salt Project Packaging <saltproject-packaging@vmware.com> - 3006.3
|
||||
|
||||
# Removed
|
||||
|
|
38
pkg/tests/integration/test_salt_ufw.py
Normal file
38
pkg/tests/integration/test_salt_ufw.py
Normal file
|
@ -0,0 +1,38 @@
|
|||
import pathlib
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.skip_on_windows
|
||||
@pytest.mark.skip_if_binaries_missing("ufw")
|
||||
def test_salt_ufw(salt_master, salt_call_cli, install_salt):
|
||||
"""
|
||||
Test salt.ufw for Debian/Ubuntu salt-master
|
||||
"""
|
||||
if install_salt.distro_id not in ("debian", "ubuntu"):
|
||||
pytest.skip("Only tests Debian / Ubuntu packages")
|
||||
|
||||
# check that the salt_master is running
|
||||
assert salt_master.is_running()
|
||||
|
||||
ufw_master_path = pathlib.Path("/etc/ufw/applications.d/salt.ufw")
|
||||
assert ufw_master_path.exists()
|
||||
assert ufw_master_path.is_file()
|
||||
|
||||
ufw_list_cmd = "/usr/sbin/ufw app list"
|
||||
ret = salt_call_cli.run("--local", "cmd.run", ufw_list_cmd)
|
||||
assert "Available applications" in ret.stdout
|
||||
assert "Salt" in ret.stdout
|
||||
ufw_upd_cmd = "/usr/sbin/ufw app update Salt"
|
||||
ret = salt_call_cli.run("--local", "cmd.run", ufw_upd_cmd)
|
||||
assert ret.returncode == 0
|
||||
expected_info = """Profile: Salt
|
||||
Title: salt
|
||||
Description: fast and powerful configuration management and remote
|
||||
execution
|
||||
|
||||
Ports:
|
||||
4505,4506/tcp"""
|
||||
ufw_info_cmd = "/usr/sbin/ufw app info Salt"
|
||||
ret = salt_call_cli.run("--local", "cmd.run", ufw_info_cmd)
|
||||
assert expected_info in ret.data
|
|
@ -6,7 +6,7 @@ apache-libcloud>=2.4.0
|
|||
cherrypy>=17.4.1
|
||||
gitpython>=3.1.35
|
||||
cryptography>=41.0.3
|
||||
gitpython>=3.1.30
|
||||
gitpython>=3.1.37
|
||||
idna>=2.8
|
||||
linode-python>=1.1.1
|
||||
pyasn1>=0.4.8
|
||||
|
|
|
@ -15,7 +15,7 @@ clustershell
|
|||
croniter>=0.3.0,!=0.3.22"; sys_platform != 'win32'
|
||||
dnspython
|
||||
etcd3-py==0.1.6
|
||||
gitpython>=3.1.35
|
||||
gitpython>=3.1.37
|
||||
jmespath
|
||||
jsonschema
|
||||
junos-eznc; sys_platform != 'win32'
|
||||
|
|
|
@ -67,7 +67,7 @@ smbprotocol==1.10.1
|
|||
# via
|
||||
# -r requirements/static/ci/cloud.in
|
||||
# pypsexec
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -c requirements/static/ci/py3.10/linux.txt
|
||||
# requests
|
||||
|
|
|
@ -140,7 +140,7 @@ gitdb==4.0.10
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/darwin.txt
|
||||
# gitpython
|
||||
gitpython==3.1.35
|
||||
gitpython==3.1.40
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/darwin.txt
|
||||
# -r requirements/darwin.txt
|
||||
|
@ -480,7 +480,7 @@ six==1.16.0
|
|||
# transitions
|
||||
# vcert
|
||||
# websocket-client
|
||||
smmap==3.0.2
|
||||
smmap==5.0.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/darwin.txt
|
||||
# gitdb
|
||||
|
@ -519,14 +519,14 @@ ttp==0.9.5
|
|||
# ttp-templates
|
||||
types-pyyaml==6.0.1
|
||||
# via responses
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/darwin.txt
|
||||
# napalm
|
||||
# pydantic
|
||||
# pytest-shell-utilities
|
||||
# pytest-system-statistics
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/darwin.txt
|
||||
# botocore
|
||||
|
|
|
@ -146,13 +146,13 @@ tempora==5.3.0
|
|||
# via
|
||||
# -c requirements/static/ci/py3.10/linux.txt
|
||||
# portend
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via
|
||||
# -c requirements/static/ci/py3.10/linux.txt
|
||||
# pydantic
|
||||
uc-micro-py==1.0.2
|
||||
# via linkify-it-py
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -c requirements/static/ci/py3.10/linux.txt
|
||||
# requests
|
||||
|
|
|
@ -135,7 +135,7 @@ geomet==0.2.1.post1
|
|||
# via cassandra-driver
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.35
|
||||
gitpython==3.1.40
|
||||
# via -r requirements/static/ci/common.in
|
||||
google-auth==2.19.1
|
||||
# via kubernetes
|
||||
|
@ -509,14 +509,14 @@ ttp==0.9.5
|
|||
# ttp-templates
|
||||
types-pyyaml==6.0.1
|
||||
# via responses
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/freebsd.txt
|
||||
# napalm
|
||||
# pydantic
|
||||
# pytest-shell-utilities
|
||||
# pytest-system-statistics
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/freebsd.txt
|
||||
# botocore
|
||||
|
|
|
@ -151,7 +151,7 @@ geomet==0.2.1.post1
|
|||
# via cassandra-driver
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.35
|
||||
gitpython==3.1.40
|
||||
# via -r requirements/static/ci/common.in
|
||||
google-auth==2.19.1
|
||||
# via kubernetes
|
||||
|
@ -573,14 +573,14 @@ twilio==8.2.2
|
|||
# via -r requirements/static/ci/linux.in
|
||||
types-pyyaml==6.0.1
|
||||
# via responses
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/linux.txt
|
||||
# napalm
|
||||
# pydantic
|
||||
# pytest-shell-utilities
|
||||
# pytest-system-statistics
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/linux.txt
|
||||
# botocore
|
||||
|
|
|
@ -52,9 +52,9 @@ s3transfer==0.6.1
|
|||
# via boto3
|
||||
six==1.16.0
|
||||
# via python-dateutil
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via python-tools-scripts
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# botocore
|
||||
# requests
|
||||
|
|
|
@ -133,7 +133,7 @@ gitdb==4.0.10
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/windows.txt
|
||||
# gitpython
|
||||
gitpython==3.1.35
|
||||
gitpython==3.1.40
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/windows.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
|
@ -434,7 +434,7 @@ six==1.15.0
|
|||
# pyvmomi
|
||||
# pywinrm
|
||||
# websocket-client
|
||||
smmap==4.0.0
|
||||
smmap==5.0.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/windows.txt
|
||||
# gitdb
|
||||
|
@ -460,13 +460,13 @@ tornado==6.3.3
|
|||
# -r requirements/base.txt
|
||||
types-pyyaml==6.0.1
|
||||
# via responses
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/windows.txt
|
||||
# pydantic
|
||||
# pytest-shell-utilities
|
||||
# pytest-system-statistics
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/windows.txt
|
||||
# -r requirements/windows.txt
|
||||
|
|
|
@ -67,7 +67,7 @@ smbprotocol==1.10.1
|
|||
# via
|
||||
# -r requirements/static/ci/cloud.in
|
||||
# pypsexec
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -c requirements/static/ci/py3.11/linux.txt
|
||||
# requests
|
||||
|
|
|
@ -138,7 +138,7 @@ gitdb==4.0.10
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/darwin.txt
|
||||
# gitpython
|
||||
gitpython==3.1.35
|
||||
gitpython==3.1.40
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/darwin.txt
|
||||
# -r requirements/darwin.txt
|
||||
|
@ -476,7 +476,7 @@ six==1.16.0
|
|||
# transitions
|
||||
# vcert
|
||||
# websocket-client
|
||||
smmap==3.0.2
|
||||
smmap==5.0.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/darwin.txt
|
||||
# gitdb
|
||||
|
@ -513,7 +513,7 @@ ttp==0.9.5
|
|||
# ttp-templates
|
||||
types-pyyaml==6.0.1
|
||||
# via responses
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/darwin.txt
|
||||
# napalm
|
||||
|
|
|
@ -146,13 +146,13 @@ tempora==5.3.0
|
|||
# via
|
||||
# -c requirements/static/ci/py3.11/linux.txt
|
||||
# portend
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via
|
||||
# -c requirements/static/ci/py3.11/linux.txt
|
||||
# pydantic
|
||||
uc-micro-py==1.0.2
|
||||
# via linkify-it-py
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -c requirements/static/ci/py3.11/linux.txt
|
||||
# requests
|
||||
|
|
|
@ -133,7 +133,7 @@ geomet==0.2.1.post1
|
|||
# via cassandra-driver
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.35
|
||||
gitpython==3.1.40
|
||||
# via -r requirements/static/ci/common.in
|
||||
google-auth==2.19.1
|
||||
# via kubernetes
|
||||
|
@ -505,14 +505,14 @@ ttp==0.9.5
|
|||
# ttp-templates
|
||||
types-pyyaml==6.0.1
|
||||
# via responses
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/freebsd.txt
|
||||
# napalm
|
||||
# pydantic
|
||||
# pytest-shell-utilities
|
||||
# pytest-system-statistics
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/freebsd.txt
|
||||
# botocore
|
||||
|
|
|
@ -147,7 +147,7 @@ geomet==0.2.1.post1
|
|||
# via cassandra-driver
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.35
|
||||
gitpython==3.1.40
|
||||
# via -r requirements/static/ci/common.in
|
||||
google-auth==2.19.1
|
||||
# via kubernetes
|
||||
|
@ -567,14 +567,14 @@ twilio==8.2.2
|
|||
# via -r requirements/static/ci/linux.in
|
||||
types-pyyaml==6.0.1
|
||||
# via responses
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/linux.txt
|
||||
# napalm
|
||||
# pydantic
|
||||
# pytest-shell-utilities
|
||||
# pytest-system-statistics
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/linux.txt
|
||||
# botocore
|
||||
|
|
|
@ -52,7 +52,7 @@ s3transfer==0.6.1
|
|||
# via boto3
|
||||
six==1.16.0
|
||||
# via python-dateutil
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# botocore
|
||||
# requests
|
||||
|
|
|
@ -131,7 +131,7 @@ gitdb==4.0.10
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/windows.txt
|
||||
# gitpython
|
||||
gitpython==3.1.35
|
||||
gitpython==3.1.40
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/windows.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
|
@ -432,7 +432,7 @@ six==1.15.0
|
|||
# pyvmomi
|
||||
# pywinrm
|
||||
# websocket-client
|
||||
smmap==4.0.0
|
||||
smmap==5.0.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/windows.txt
|
||||
# gitdb
|
||||
|
@ -456,13 +456,13 @@ tornado==6.3.3
|
|||
# -r requirements/base.txt
|
||||
types-pyyaml==6.0.1
|
||||
# via responses
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/windows.txt
|
||||
# pydantic
|
||||
# pytest-shell-utilities
|
||||
# pytest-system-statistics
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/windows.txt
|
||||
# -r requirements/windows.txt
|
||||
|
|
|
@ -67,7 +67,7 @@ smbprotocol==1.10.1
|
|||
# via
|
||||
# -r requirements/static/ci/cloud.in
|
||||
# pypsexec
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -c requirements/static/ci/py3.8/linux.txt
|
||||
# requests
|
||||
|
|
|
@ -155,13 +155,13 @@ tempora==5.3.0
|
|||
# via
|
||||
# -c requirements/static/ci/py3.8/linux.txt
|
||||
# portend
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via
|
||||
# -c requirements/static/ci/py3.8/linux.txt
|
||||
# pydantic
|
||||
uc-micro-py==1.0.2
|
||||
# via linkify-it-py
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -c requirements/static/ci/py3.8/linux.txt
|
||||
# requests
|
||||
|
|
|
@ -135,7 +135,7 @@ geomet==0.2.1.post1
|
|||
# via cassandra-driver
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.35
|
||||
gitpython==3.1.40
|
||||
# via -r requirements/static/ci/common.in
|
||||
google-auth==2.19.1
|
||||
# via kubernetes
|
||||
|
@ -513,14 +513,14 @@ ttp==0.9.5
|
|||
# ttp-templates
|
||||
types-pyyaml==6.0.1
|
||||
# via responses
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/freebsd.txt
|
||||
# napalm
|
||||
# pydantic
|
||||
# pytest-shell-utilities
|
||||
# pytest-system-statistics
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/freebsd.txt
|
||||
# botocore
|
||||
|
|
|
@ -151,7 +151,7 @@ geomet==0.2.1.post1
|
|||
# via cassandra-driver
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.35
|
||||
gitpython==3.1.40
|
||||
# via -r requirements/static/ci/common.in
|
||||
google-auth==2.19.1
|
||||
# via kubernetes
|
||||
|
@ -577,14 +577,14 @@ twilio==8.2.2
|
|||
# via -r requirements/static/ci/linux.in
|
||||
types-pyyaml==6.0.1
|
||||
# via responses
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/linux.txt
|
||||
# napalm
|
||||
# pydantic
|
||||
# pytest-shell-utilities
|
||||
# pytest-system-statistics
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/linux.txt
|
||||
# botocore
|
||||
|
|
|
@ -133,7 +133,7 @@ gitdb==4.0.10
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/windows.txt
|
||||
# gitpython
|
||||
gitpython==3.1.35
|
||||
gitpython==3.1.40
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/windows.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
|
@ -439,7 +439,7 @@ six==1.15.0
|
|||
# pyvmomi
|
||||
# pywinrm
|
||||
# websocket-client
|
||||
smmap==4.0.0
|
||||
smmap==5.0.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/windows.txt
|
||||
# gitdb
|
||||
|
@ -465,13 +465,13 @@ tornado==6.3.3
|
|||
# -r requirements/base.txt
|
||||
types-pyyaml==6.0.1
|
||||
# via responses
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/windows.txt
|
||||
# pydantic
|
||||
# pytest-shell-utilities
|
||||
# pytest-system-statistics
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/windows.txt
|
||||
# -r requirements/windows.txt
|
||||
|
|
|
@ -67,7 +67,7 @@ smbprotocol==1.10.1
|
|||
# via
|
||||
# -r requirements/static/ci/cloud.in
|
||||
# pypsexec
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -c requirements/static/ci/py3.9/linux.txt
|
||||
# requests
|
||||
|
|
|
@ -140,7 +140,7 @@ gitdb==4.0.10
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
|
||||
# gitpython
|
||||
gitpython==3.1.35
|
||||
gitpython==3.1.40
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
|
||||
# -r requirements/darwin.txt
|
||||
|
@ -480,7 +480,7 @@ six==1.16.0
|
|||
# transitions
|
||||
# vcert
|
||||
# websocket-client
|
||||
smmap==3.0.2
|
||||
smmap==5.0.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
|
||||
# gitdb
|
||||
|
@ -519,14 +519,14 @@ ttp==0.9.5
|
|||
# ttp-templates
|
||||
types-pyyaml==6.0.1
|
||||
# via responses
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
|
||||
# napalm
|
||||
# pydantic
|
||||
# pytest-shell-utilities
|
||||
# pytest-system-statistics
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
|
||||
# botocore
|
||||
|
|
|
@ -150,13 +150,13 @@ tempora==5.3.0
|
|||
# via
|
||||
# -c requirements/static/ci/py3.9/linux.txt
|
||||
# portend
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via
|
||||
# -c requirements/static/ci/py3.9/linux.txt
|
||||
# pydantic
|
||||
uc-micro-py==1.0.2
|
||||
# via linkify-it-py
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -c requirements/static/ci/py3.9/linux.txt
|
||||
# requests
|
||||
|
|
|
@ -135,7 +135,7 @@ geomet==0.2.1.post1
|
|||
# via cassandra-driver
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.35
|
||||
gitpython==3.1.40
|
||||
# via -r requirements/static/ci/common.in
|
||||
google-auth==2.19.1
|
||||
# via kubernetes
|
||||
|
@ -509,14 +509,14 @@ ttp==0.9.5
|
|||
# ttp-templates
|
||||
types-pyyaml==6.0.1
|
||||
# via responses
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/freebsd.txt
|
||||
# napalm
|
||||
# pydantic
|
||||
# pytest-shell-utilities
|
||||
# pytest-system-statistics
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/freebsd.txt
|
||||
# botocore
|
||||
|
|
|
@ -151,7 +151,7 @@ geomet==0.2.1.post1
|
|||
# via cassandra-driver
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.35
|
||||
gitpython==3.1.40
|
||||
# via -r requirements/static/ci/common.in
|
||||
google-auth==2.19.1
|
||||
# via kubernetes
|
||||
|
@ -575,14 +575,14 @@ twilio==8.2.2
|
|||
# via -r requirements/static/ci/linux.in
|
||||
types-pyyaml==6.0.1
|
||||
# via responses
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/linux.txt
|
||||
# napalm
|
||||
# pydantic
|
||||
# pytest-shell-utilities
|
||||
# pytest-system-statistics
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/linux.txt
|
||||
# botocore
|
||||
|
|
|
@ -52,9 +52,9 @@ s3transfer==0.6.1
|
|||
# via boto3
|
||||
six==1.16.0
|
||||
# via python-dateutil
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via python-tools-scripts
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# botocore
|
||||
# requests
|
||||
|
|
|
@ -133,7 +133,7 @@ gitdb==4.0.10
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/windows.txt
|
||||
# gitpython
|
||||
gitpython==3.1.35
|
||||
gitpython==3.1.40
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/windows.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
|
@ -435,7 +435,7 @@ six==1.15.0
|
|||
# pyvmomi
|
||||
# pywinrm
|
||||
# websocket-client
|
||||
smmap==4.0.0
|
||||
smmap==5.0.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/windows.txt
|
||||
# gitdb
|
||||
|
@ -461,13 +461,13 @@ tornado==6.3.3
|
|||
# -r requirements/base.txt
|
||||
types-pyyaml==6.0.1
|
||||
# via responses
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/windows.txt
|
||||
# pydantic
|
||||
# pytest-shell-utilities
|
||||
# pytest-system-statistics
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/windows.txt
|
||||
# -r requirements/windows.txt
|
||||
|
|
|
@ -29,7 +29,7 @@ distro==1.8.0
|
|||
# via -r requirements/base.txt
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.35
|
||||
gitpython==3.1.40
|
||||
# via -r requirements/darwin.txt
|
||||
idna==3.4
|
||||
# via
|
||||
|
@ -105,7 +105,7 @@ setproctitle==1.3.2
|
|||
# via -r requirements/darwin.txt
|
||||
six==1.16.0
|
||||
# via python-dateutil
|
||||
smmap==3.0.2
|
||||
smmap==5.0.0
|
||||
# via gitdb
|
||||
tempora==5.3.0
|
||||
# via portend
|
||||
|
@ -113,9 +113,9 @@ timelib==0.3.0
|
|||
# via -r requirements/darwin.txt
|
||||
tornado==6.3.3
|
||||
# via -r requirements/base.txt
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via pydantic
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via requests
|
||||
vultr==1.0.1
|
||||
# via -r requirements/darwin.txt
|
||||
|
|
|
@ -100,9 +100,9 @@ timelib==0.3.0
|
|||
# via -r requirements/static/pkg/freebsd.in
|
||||
tornado==6.3.3
|
||||
# via -r requirements/base.txt
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via pydantic
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via requests
|
||||
zc.lockfile==3.0.post1
|
||||
# via cherrypy
|
||||
|
|
|
@ -100,9 +100,9 @@ timelib==0.3.0
|
|||
# via -r requirements/static/pkg/linux.in
|
||||
tornado==6.3.3
|
||||
# via -r requirements/base.txt
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via pydantic
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via requests
|
||||
zc.lockfile==3.0.post1
|
||||
# via cherrypy
|
||||
|
|
|
@ -34,7 +34,7 @@ distro==1.8.0
|
|||
# via -r requirements/base.txt
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.35
|
||||
gitpython==3.1.40
|
||||
# via -r requirements/windows.txt
|
||||
idna==3.4
|
||||
# via requests
|
||||
|
@ -119,7 +119,7 @@ setproctitle==1.3.2
|
|||
# via -r requirements/windows.txt
|
||||
six==1.15.0
|
||||
# via python-dateutil
|
||||
smmap==4.0.0
|
||||
smmap==5.0.0
|
||||
# via gitdb
|
||||
tempora==5.3.0
|
||||
# via portend
|
||||
|
@ -127,9 +127,9 @@ timelib==0.3.0
|
|||
# via -r requirements/windows.txt
|
||||
tornado==6.3.3
|
||||
# via -r requirements/base.txt
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via pydantic
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -r requirements/windows.txt
|
||||
# requests
|
||||
|
|
|
@ -29,7 +29,7 @@ distro==1.8.0
|
|||
# via -r requirements/base.txt
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.35
|
||||
gitpython==3.1.40
|
||||
# via -r requirements/darwin.txt
|
||||
idna==3.4
|
||||
# via
|
||||
|
@ -105,7 +105,7 @@ setproctitle==1.3.2
|
|||
# via -r requirements/darwin.txt
|
||||
six==1.16.0
|
||||
# via python-dateutil
|
||||
smmap==3.0.2
|
||||
smmap==5.0.0
|
||||
# via gitdb
|
||||
tempora==5.3.0
|
||||
# via portend
|
||||
|
@ -113,7 +113,7 @@ timelib==0.3.0
|
|||
# via -r requirements/darwin.txt
|
||||
tornado==6.3.3
|
||||
# via -r requirements/base.txt
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via pydantic
|
||||
urllib3==1.26.14
|
||||
# via requests
|
||||
|
|
|
@ -100,9 +100,9 @@ timelib==0.3.0
|
|||
# via -r requirements/static/pkg/freebsd.in
|
||||
tornado==6.3.3
|
||||
# via -r requirements/base.txt
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via pydantic
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via requests
|
||||
zc.lockfile==3.0.post1
|
||||
# via cherrypy
|
||||
|
|
|
@ -100,9 +100,9 @@ timelib==0.3.0
|
|||
# via -r requirements/static/pkg/linux.in
|
||||
tornado==6.3.3
|
||||
# via -r requirements/base.txt
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via pydantic
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via requests
|
||||
zc.lockfile==3.0.post1
|
||||
# via cherrypy
|
||||
|
|
|
@ -34,7 +34,7 @@ distro==1.8.0
|
|||
# via -r requirements/base.txt
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.35
|
||||
gitpython==3.1.40
|
||||
# via -r requirements/windows.txt
|
||||
idna==3.4
|
||||
# via requests
|
||||
|
@ -119,7 +119,7 @@ setproctitle==1.3.2
|
|||
# via -r requirements/windows.txt
|
||||
six==1.15.0
|
||||
# via python-dateutil
|
||||
smmap==4.0.0
|
||||
smmap==5.0.0
|
||||
# via gitdb
|
||||
tempora==5.3.0
|
||||
# via portend
|
||||
|
@ -127,9 +127,9 @@ timelib==0.3.0
|
|||
# via -r requirements/windows.txt
|
||||
tornado==6.3.3
|
||||
# via -r requirements/base.txt
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via pydantic
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -r requirements/windows.txt
|
||||
# requests
|
||||
|
|
|
@ -102,9 +102,9 @@ timelib==0.3.0
|
|||
# via -r requirements/static/pkg/freebsd.in
|
||||
tornado==6.3.3
|
||||
# via -r requirements/base.txt
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via pydantic
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via requests
|
||||
zc.lockfile==3.0.post1
|
||||
# via cherrypy
|
||||
|
|
|
@ -102,9 +102,9 @@ timelib==0.3.0
|
|||
# via -r requirements/static/pkg/linux.in
|
||||
tornado==6.3.3
|
||||
# via -r requirements/base.txt
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via pydantic
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via requests
|
||||
zc.lockfile==3.0.post1
|
||||
# via cherrypy
|
||||
|
|
|
@ -34,7 +34,7 @@ distro==1.8.0
|
|||
# via -r requirements/base.txt
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.35
|
||||
gitpython==3.1.40
|
||||
# via -r requirements/windows.txt
|
||||
idna==3.4
|
||||
# via requests
|
||||
|
@ -122,7 +122,7 @@ setproctitle==1.3.2
|
|||
# via -r requirements/windows.txt
|
||||
six==1.15.0
|
||||
# via python-dateutil
|
||||
smmap==4.0.0
|
||||
smmap==5.0.0
|
||||
# via gitdb
|
||||
tempora==5.3.0
|
||||
# via portend
|
||||
|
@ -130,9 +130,9 @@ timelib==0.3.0
|
|||
# via -r requirements/windows.txt
|
||||
tornado==6.3.3
|
||||
# via -r requirements/base.txt
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via pydantic
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -r requirements/windows.txt
|
||||
# requests
|
||||
|
|
|
@ -29,7 +29,7 @@ distro==1.8.0
|
|||
# via -r requirements/base.txt
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.35
|
||||
gitpython==3.1.40
|
||||
# via -r requirements/darwin.txt
|
||||
idna==3.4
|
||||
# via
|
||||
|
@ -105,7 +105,7 @@ setproctitle==1.3.2
|
|||
# via -r requirements/darwin.txt
|
||||
six==1.16.0
|
||||
# via python-dateutil
|
||||
smmap==3.0.2
|
||||
smmap==5.0.0
|
||||
# via gitdb
|
||||
tempora==5.3.0
|
||||
# via portend
|
||||
|
@ -113,9 +113,9 @@ timelib==0.3.0
|
|||
# via -r requirements/darwin.txt
|
||||
tornado==6.3.3
|
||||
# via -r requirements/base.txt
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via pydantic
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via requests
|
||||
vultr==1.0.1
|
||||
# via -r requirements/darwin.txt
|
||||
|
|
|
@ -100,9 +100,9 @@ timelib==0.3.0
|
|||
# via -r requirements/static/pkg/freebsd.in
|
||||
tornado==6.3.3
|
||||
# via -r requirements/base.txt
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via pydantic
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via requests
|
||||
zc.lockfile==3.0.post1
|
||||
# via cherrypy
|
||||
|
|
|
@ -100,9 +100,9 @@ timelib==0.3.0
|
|||
# via -r requirements/static/pkg/linux.in
|
||||
tornado==6.3.3
|
||||
# via -r requirements/base.txt
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via pydantic
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via requests
|
||||
zc.lockfile==3.0.post1
|
||||
# via cherrypy
|
||||
|
|
|
@ -34,7 +34,7 @@ distro==1.8.0
|
|||
# via -r requirements/base.txt
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.35
|
||||
gitpython==3.1.40
|
||||
# via -r requirements/windows.txt
|
||||
idna==3.4
|
||||
# via requests
|
||||
|
@ -120,7 +120,7 @@ setproctitle==1.3.2
|
|||
# via -r requirements/windows.txt
|
||||
six==1.15.0
|
||||
# via python-dateutil
|
||||
smmap==4.0.0
|
||||
smmap==5.0.0
|
||||
# via gitdb
|
||||
tempora==5.3.0
|
||||
# via portend
|
||||
|
@ -128,9 +128,9 @@ timelib==0.3.0
|
|||
# via -r requirements/windows.txt
|
||||
tornado==6.3.3
|
||||
# via -r requirements/base.txt
|
||||
typing-extensions==4.6.3
|
||||
typing-extensions==4.8.0
|
||||
# via pydantic
|
||||
urllib3==1.26.14
|
||||
urllib3==1.26.18
|
||||
# via
|
||||
# -r requirements/windows.txt
|
||||
# requests
|
||||
|
|
|
@ -9,7 +9,7 @@ pythonnet>=3.0.1
|
|||
certifi>=2022.12.07
|
||||
cffi>=1.14.5
|
||||
cherrypy>=18.6.1
|
||||
gitpython>=3.1.35
|
||||
gitpython>=3.1.37
|
||||
cryptography>=41.0.3
|
||||
lxml>=4.6.3
|
||||
pyasn1>=0.4.8
|
||||
|
|
|
@ -11,9 +11,11 @@ import hashlib
|
|||
import logging
|
||||
import multiprocessing
|
||||
import os
|
||||
import pathlib
|
||||
import queue
|
||||
import re
|
||||
import shlex
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tarfile
|
||||
|
@ -467,7 +469,14 @@ class SSH(MultiprocessingStateMixin):
|
|||
if target.get("passwd", False) or self.opts["ssh_passwd"]:
|
||||
self._key_deploy_run(host, target, False)
|
||||
return ret
|
||||
if ret[host].get("stderr", "").count("Permission denied"):
|
||||
stderr = ret[host].get("stderr", "")
|
||||
# -failed to upload file- is detecting scp errors
|
||||
# Errors to ignore when Permission denied is in the stderr. For example
|
||||
# scp can get a permission denied on the target host, but they where
|
||||
# able to accurate authenticate against the box
|
||||
ignore_err = ["failed to upload file"]
|
||||
check_err = [x for x in ignore_err if stderr.count(x)]
|
||||
if "Permission denied" in stderr and not check_err:
|
||||
target = self.targets[host]
|
||||
# permission denied, attempt to auto deploy ssh key
|
||||
print(
|
||||
|
@ -1007,11 +1016,30 @@ class Single:
|
|||
"""
|
||||
Run our pre_flight script before running any ssh commands
|
||||
"""
|
||||
script = os.path.join(tempfile.gettempdir(), self.ssh_pre_file)
|
||||
with tempfile.NamedTemporaryFile() as temp:
|
||||
# ensure we use copyfile to not copy the file attributes
|
||||
# we want to ensure we use the perms set by the secure
|
||||
# NamedTemporaryFile
|
||||
try:
|
||||
shutil.copyfile(self.ssh_pre_flight, temp.name)
|
||||
except OSError as err:
|
||||
return (
|
||||
"",
|
||||
"Could not copy pre flight script to temporary path",
|
||||
1,
|
||||
)
|
||||
target_script = f".{pathlib.Path(temp.name).name}"
|
||||
log.trace("Copying the pre flight script to target")
|
||||
stdout, stderr, retcode = self.shell.send(temp.name, target_script)
|
||||
if retcode != 0:
|
||||
# We could not copy the script to the target
|
||||
log.error("Could not copy the pre flight script to target")
|
||||
return stdout, stderr, retcode
|
||||
|
||||
self.shell.send(self.ssh_pre_flight, script)
|
||||
|
||||
return self.execute_script(script, script_args=self.ssh_pre_flight_args)
|
||||
log.trace("Executing the pre flight script on target")
|
||||
return self.execute_script(
|
||||
target_script, script_args=self.ssh_pre_flight_args
|
||||
)
|
||||
|
||||
def check_thin_dir(self):
|
||||
"""
|
||||
|
@ -1388,18 +1416,20 @@ ARGS = {arguments}\n'''.format(
|
|||
return self.shell.exec_cmd(cmd_str)
|
||||
|
||||
# Write the shim to a temporary file in the default temp directory
|
||||
with tempfile.NamedTemporaryFile(
|
||||
mode="w+b", prefix="shim_", delete=False
|
||||
) as shim_tmp_file:
|
||||
with tempfile.NamedTemporaryFile(mode="w+b", delete=False) as shim_tmp_file:
|
||||
shim_tmp_file.write(salt.utils.stringutils.to_bytes(cmd_str))
|
||||
|
||||
# Copy shim to target system, under $HOME/.<randomized name>
|
||||
target_shim_file = ".{}.{}".format(
|
||||
binascii.hexlify(os.urandom(6)).decode("ascii"), extension
|
||||
)
|
||||
target_shim_file = f".{pathlib.Path(shim_tmp_file.name).name}"
|
||||
|
||||
if self.winrm:
|
||||
target_shim_file = saltwinshell.get_target_shim_file(self, target_shim_file)
|
||||
self.shell.send(shim_tmp_file.name, target_shim_file, makedirs=True)
|
||||
stdout, stderr, retcode = self.shell.send(
|
||||
shim_tmp_file.name, target_shim_file, makedirs=True
|
||||
)
|
||||
if retcode != 0:
|
||||
log.error("Could not copy the shim script to target")
|
||||
return stdout, stderr, retcode
|
||||
|
||||
# Remove our shim file
|
||||
try:
|
||||
|
|
|
@ -1,132 +0,0 @@
|
|||
"""
|
||||
Test for ssh_pre_flight roster option
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
import pytest
|
||||
|
||||
import salt.utils.files
|
||||
from tests.support.case import SSHCase
|
||||
from tests.support.runtests import RUNTIME_VARS
|
||||
|
||||
|
||||
class SSHPreFlightTest(SSHCase):
|
||||
"""
|
||||
Test ssh_pre_flight roster option
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.roster = os.path.join(RUNTIME_VARS.TMP, "pre_flight_roster")
|
||||
self.data = {
|
||||
"ssh_pre_flight": os.path.join(RUNTIME_VARS.TMP, "ssh_pre_flight.sh")
|
||||
}
|
||||
self.test_script = os.path.join(
|
||||
RUNTIME_VARS.TMP, "test-pre-flight-script-worked.txt"
|
||||
)
|
||||
|
||||
def _create_roster(self, pre_flight_script_args=None):
|
||||
data = dict(self.data)
|
||||
if pre_flight_script_args:
|
||||
data["ssh_pre_flight_args"] = pre_flight_script_args
|
||||
|
||||
self.custom_roster(self.roster, data)
|
||||
|
||||
with salt.utils.files.fopen(data["ssh_pre_flight"], "w") as fp_:
|
||||
fp_.write("touch {}".format(self.test_script))
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_ssh_pre_flight(self):
|
||||
"""
|
||||
test ssh when ssh_pre_flight is set
|
||||
ensure the script runs successfully
|
||||
"""
|
||||
self._create_roster()
|
||||
assert self.run_function("test.ping", roster_file=self.roster)
|
||||
|
||||
assert os.path.exists(self.test_script)
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_ssh_run_pre_flight(self):
|
||||
"""
|
||||
test ssh when --pre-flight is passed to salt-ssh
|
||||
to ensure the script runs successfully
|
||||
"""
|
||||
self._create_roster()
|
||||
# make sure we previously ran a command so the thin dir exists
|
||||
self.run_function("test.ping", wipe=False)
|
||||
assert not os.path.exists(self.test_script)
|
||||
|
||||
assert self.run_function(
|
||||
"test.ping", ssh_opts="--pre-flight", roster_file=self.roster, wipe=False
|
||||
)
|
||||
assert os.path.exists(self.test_script)
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_ssh_run_pre_flight_args(self):
|
||||
"""
|
||||
test ssh when --pre-flight is passed to salt-ssh
|
||||
to ensure the script runs successfully passing some args
|
||||
"""
|
||||
self._create_roster(pre_flight_script_args="foobar test")
|
||||
# make sure we previously ran a command so the thin dir exists
|
||||
self.run_function("test.ping", wipe=False)
|
||||
assert not os.path.exists(self.test_script)
|
||||
|
||||
assert self.run_function(
|
||||
"test.ping", ssh_opts="--pre-flight", roster_file=self.roster, wipe=False
|
||||
)
|
||||
assert os.path.exists(self.test_script)
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_ssh_run_pre_flight_args_prevent_injection(self):
|
||||
"""
|
||||
test ssh when --pre-flight is passed to salt-ssh
|
||||
and evil arguments are used in order to produce shell injection
|
||||
"""
|
||||
injected_file = os.path.join(RUNTIME_VARS.TMP, "injection")
|
||||
self._create_roster(
|
||||
pre_flight_script_args="foobar; echo injected > {}".format(injected_file)
|
||||
)
|
||||
# make sure we previously ran a command so the thin dir exists
|
||||
self.run_function("test.ping", wipe=False)
|
||||
assert not os.path.exists(self.test_script)
|
||||
assert not os.path.isfile(injected_file)
|
||||
|
||||
assert self.run_function(
|
||||
"test.ping", ssh_opts="--pre-flight", roster_file=self.roster, wipe=False
|
||||
)
|
||||
|
||||
assert not os.path.isfile(
|
||||
injected_file
|
||||
), "File injection suceeded. This shouldn't happend"
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_ssh_run_pre_flight_failure(self):
|
||||
"""
|
||||
test ssh_pre_flight when there is a failure
|
||||
in the script.
|
||||
"""
|
||||
self._create_roster()
|
||||
with salt.utils.files.fopen(self.data["ssh_pre_flight"], "w") as fp_:
|
||||
fp_.write("exit 2")
|
||||
|
||||
ret = self.run_function(
|
||||
"test.ping", ssh_opts="--pre-flight", roster_file=self.roster, wipe=False
|
||||
)
|
||||
assert ret["retcode"] == 2
|
||||
|
||||
def tearDown(self):
|
||||
"""
|
||||
make sure to clean up any old ssh directories
|
||||
"""
|
||||
files = [
|
||||
self.roster,
|
||||
self.data["ssh_pre_flight"],
|
||||
self.test_script,
|
||||
os.path.join(RUNTIME_VARS.TMP, "injection"),
|
||||
]
|
||||
for fp_ in files:
|
||||
if os.path.exists(fp_):
|
||||
os.remove(fp_)
|
106
tests/pytests/integration/_logging/test_logging.py
Normal file
106
tests/pytests/integration/_logging/test_logging.py
Normal file
|
@ -0,0 +1,106 @@
|
|||
import logging
|
||||
import os
|
||||
|
||||
import pytest
|
||||
|
||||
import salt._logging.impl as log_impl
|
||||
from tests.support.mock import MagicMock, patch
|
||||
|
||||
pytestmark = [
|
||||
pytest.mark.skip_on_windows(reason="Temporarily skipped on the newer golden images")
|
||||
]
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def configure_loader_modules():
|
||||
return {log_impl: {}}
|
||||
|
||||
|
||||
def log_nameToLevel(name):
|
||||
"""
|
||||
Return the numeric representation of textual logging level
|
||||
"""
|
||||
# log level values
|
||||
CRITICAL = 50
|
||||
FATAL = CRITICAL
|
||||
ERROR = 40
|
||||
WARNING = 30
|
||||
WARN = WARNING
|
||||
INFO = 20
|
||||
DEBUG = 10
|
||||
NOTSET = 0
|
||||
|
||||
_nameToLevel = {
|
||||
"CRITICAL": CRITICAL,
|
||||
"FATAL": FATAL,
|
||||
"ERROR": ERROR,
|
||||
"WARN": WARNING,
|
||||
"WARNING": WARNING,
|
||||
"INFO": INFO,
|
||||
"DEBUG": DEBUG,
|
||||
"NOTSET": NOTSET,
|
||||
}
|
||||
return _nameToLevel.get(name, None)
|
||||
|
||||
|
||||
def test_lowest_log_level():
|
||||
ret = log_impl.get_lowest_log_level()
|
||||
assert ret is None
|
||||
|
||||
log_impl.set_lowest_log_level(log_nameToLevel("DEBUG"))
|
||||
ret = log_impl.get_lowest_log_level()
|
||||
assert ret is log_nameToLevel("DEBUG")
|
||||
|
||||
log_impl.set_lowest_log_level(log_nameToLevel("WARNING"))
|
||||
ret = log_impl.get_lowest_log_level()
|
||||
assert ret is log_nameToLevel("WARNING")
|
||||
|
||||
opts = {"log_level": "ERROR", "log_level_logfile": "INFO"}
|
||||
log_impl.set_lowest_log_level_by_opts(opts)
|
||||
ret = log_impl.get_lowest_log_level()
|
||||
assert ret is log_nameToLevel("INFO")
|
||||
|
||||
|
||||
def test_get_logging_level_from_string(caplog):
|
||||
ret = log_impl.get_logging_level_from_string(None)
|
||||
assert ret is log_nameToLevel("WARNING")
|
||||
|
||||
ret = log_impl.get_logging_level_from_string(log_nameToLevel("DEBUG"))
|
||||
assert ret is log_nameToLevel("DEBUG")
|
||||
|
||||
ret = log_impl.get_logging_level_from_string("CRITICAL")
|
||||
assert ret is log_nameToLevel("CRITICAL")
|
||||
|
||||
caplog.clear()
|
||||
with caplog.at_level(logging.WARNING):
|
||||
msg = "Could not translate the logging level string 'BADLEVEL' into an actual logging level integer. Returning 'logging.ERROR'."
|
||||
ret = log_impl.get_logging_level_from_string("BADLEVEL")
|
||||
assert ret is log_nameToLevel("ERROR")
|
||||
assert msg in caplog.text
|
||||
|
||||
|
||||
def test_logfile_handler(caplog):
|
||||
caplog.clear()
|
||||
with caplog.at_level(logging.WARNING):
|
||||
ret = log_impl.is_logfile_handler_configured()
|
||||
assert ret is False
|
||||
|
||||
msg = "log_path setting is set to `None`. Nothing else to do"
|
||||
log_path = None
|
||||
assert log_impl.setup_logfile_handler(log_path) is None
|
||||
assert msg in caplog.text
|
||||
|
||||
|
||||
def test_in_mainprocess():
|
||||
ret = log_impl.in_mainprocess()
|
||||
assert ret is True
|
||||
|
||||
curr_pid = os.getpid()
|
||||
with patch(
|
||||
"os.getpid", MagicMock(side_effect=[AttributeError, curr_pid, curr_pid])
|
||||
):
|
||||
ret = log_impl.in_mainprocess()
|
||||
assert ret is True
|
315
tests/pytests/integration/ssh/test_pre_flight.py
Normal file
315
tests/pytests/integration/ssh/test_pre_flight.py
Normal file
|
@ -0,0 +1,315 @@
|
|||
"""
|
||||
Test for ssh_pre_flight roster option
|
||||
"""
|
||||
|
||||
try:
|
||||
import grp
|
||||
import pwd
|
||||
except ImportError:
|
||||
# windows stacktraces on import of these modules
|
||||
pass
|
||||
import os
|
||||
import pathlib
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
import pytest
|
||||
import yaml
|
||||
from saltfactories.utils import random_string
|
||||
|
||||
import salt.utils.files
|
||||
|
||||
pytestmark = pytest.mark.skip_on_windows(reason="Salt-ssh not available on Windows")
|
||||
|
||||
|
||||
def _custom_roster(roster_file, roster_data):
|
||||
with salt.utils.files.fopen(roster_file, "r") as fp:
|
||||
data = salt.utils.yaml.safe_load(fp)
|
||||
for key, item in roster_data.items():
|
||||
data["localhost"][key] = item
|
||||
with salt.utils.files.fopen(roster_file, "w") as fp:
|
||||
yaml.safe_dump(data, fp)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def _create_roster(salt_ssh_roster_file, tmp_path):
|
||||
ret = {}
|
||||
ret["roster"] = salt_ssh_roster_file
|
||||
ret["data"] = {"ssh_pre_flight": str(tmp_path / "ssh_pre_flight.sh")}
|
||||
ret["test_script"] = str(tmp_path / "test-pre-flight-script-worked.txt")
|
||||
ret["thin_dir"] = tmp_path / "thin_dir"
|
||||
|
||||
with salt.utils.files.fopen(salt_ssh_roster_file, "r") as fp:
|
||||
data = salt.utils.yaml.safe_load(fp)
|
||||
pre_flight_script = ret["data"]["ssh_pre_flight"]
|
||||
data["localhost"]["ssh_pre_flight"] = pre_flight_script
|
||||
data["localhost"]["thin_dir"] = str(ret["thin_dir"])
|
||||
with salt.utils.files.fopen(salt_ssh_roster_file, "w") as fp:
|
||||
yaml.safe_dump(data, fp)
|
||||
|
||||
with salt.utils.files.fopen(pre_flight_script, "w") as fp:
|
||||
fp.write("touch {}".format(ret["test_script"]))
|
||||
|
||||
yield ret
|
||||
if ret["thin_dir"].exists():
|
||||
shutil.rmtree(ret["thin_dir"])
|
||||
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_ssh_pre_flight(salt_ssh_cli, caplog, _create_roster):
|
||||
"""
|
||||
test ssh when ssh_pre_flight is set
|
||||
ensure the script runs successfully
|
||||
"""
|
||||
ret = salt_ssh_cli.run("test.ping")
|
||||
assert ret.returncode == 0
|
||||
|
||||
assert pathlib.Path(_create_roster["test_script"]).exists()
|
||||
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_ssh_run_pre_flight(salt_ssh_cli, _create_roster):
|
||||
"""
|
||||
test ssh when --pre-flight is passed to salt-ssh
|
||||
to ensure the script runs successfully
|
||||
"""
|
||||
# make sure we previously ran a command so the thin dir exists
|
||||
ret = salt_ssh_cli.run("test.ping")
|
||||
assert pathlib.Path(_create_roster["test_script"]).exists()
|
||||
|
||||
# Now remeove the script to ensure pre_flight doesn't run
|
||||
# without --pre-flight
|
||||
pathlib.Path(_create_roster["test_script"]).unlink()
|
||||
|
||||
assert salt_ssh_cli.run("test.ping").returncode == 0
|
||||
assert not pathlib.Path(_create_roster["test_script"]).exists()
|
||||
|
||||
# Now ensure
|
||||
ret = salt_ssh_cli.run(
|
||||
"test.ping",
|
||||
"--pre-flight",
|
||||
)
|
||||
assert ret.returncode == 0
|
||||
assert pathlib.Path(_create_roster["test_script"]).exists()
|
||||
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_ssh_run_pre_flight_args(salt_ssh_cli, _create_roster):
|
||||
"""
|
||||
test ssh when --pre-flight is passed to salt-ssh
|
||||
to ensure the script runs successfully passing some args
|
||||
"""
|
||||
_custom_roster(salt_ssh_cli.roster_file, {"ssh_pre_flight_args": "foobar test"})
|
||||
# Create pre_flight script that accepts args
|
||||
test_script = _create_roster["test_script"]
|
||||
test_script_1 = pathlib.Path(test_script + "-foobar")
|
||||
test_script_2 = pathlib.Path(test_script + "-test")
|
||||
with salt.utils.files.fopen(_create_roster["data"]["ssh_pre_flight"], "w") as fp:
|
||||
fp.write(
|
||||
f"""
|
||||
touch {str(test_script)}-$1
|
||||
touch {str(test_script)}-$2
|
||||
"""
|
||||
)
|
||||
ret = salt_ssh_cli.run("test.ping")
|
||||
assert ret.returncode == 0
|
||||
assert test_script_1.exists()
|
||||
assert test_script_2.exists()
|
||||
pathlib.Path(test_script_1).unlink()
|
||||
pathlib.Path(test_script_2).unlink()
|
||||
|
||||
ret = salt_ssh_cli.run("test.ping")
|
||||
assert ret.returncode == 0
|
||||
assert not test_script_1.exists()
|
||||
assert not test_script_2.exists()
|
||||
|
||||
ret = salt_ssh_cli.run(
|
||||
"test.ping",
|
||||
"--pre-flight",
|
||||
)
|
||||
assert ret.returncode == 0
|
||||
assert test_script_1.exists()
|
||||
assert test_script_2.exists()
|
||||
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_ssh_run_pre_flight_args_prevent_injection(
|
||||
salt_ssh_cli, _create_roster, tmp_path
|
||||
):
|
||||
"""
|
||||
test ssh when --pre-flight is passed to salt-ssh
|
||||
and evil arguments are used in order to produce shell injection
|
||||
"""
|
||||
injected_file = tmp_path / "injection"
|
||||
_custom_roster(
|
||||
salt_ssh_cli.roster_file,
|
||||
{"ssh_pre_flight_args": f"foobar; echo injected > {str(injected_file)}"},
|
||||
)
|
||||
# Create pre_flight script that accepts args
|
||||
test_script = _create_roster["test_script"]
|
||||
test_script_1 = pathlib.Path(test_script + "-echo")
|
||||
test_script_2 = pathlib.Path(test_script + "-foobar;")
|
||||
with salt.utils.files.fopen(_create_roster["data"]["ssh_pre_flight"], "w") as fp:
|
||||
fp.write(
|
||||
f"""
|
||||
touch {str(test_script)}-$1
|
||||
touch {str(test_script)}-$2
|
||||
"""
|
||||
)
|
||||
|
||||
# make sure we previously ran a command so the thin dir exists
|
||||
ret = salt_ssh_cli.run("test.ping")
|
||||
assert ret.returncode == 0
|
||||
assert test_script_1.exists()
|
||||
assert test_script_2.exists()
|
||||
test_script_1.unlink()
|
||||
test_script_2.unlink()
|
||||
assert not injected_file.is_file()
|
||||
|
||||
ret = salt_ssh_cli.run(
|
||||
"test.ping",
|
||||
"--pre-flight",
|
||||
)
|
||||
assert ret.returncode == 0
|
||||
|
||||
assert test_script_1.exists()
|
||||
assert test_script_2.exists()
|
||||
assert not pathlib.Path(
|
||||
injected_file
|
||||
).is_file(), "File injection suceeded. This shouldn't happend"
|
||||
|
||||
|
||||
@pytest.mark.flaky(max_runs=4)
|
||||
@pytest.mark.slow_test
|
||||
def test_ssh_run_pre_flight_failure(salt_ssh_cli, _create_roster):
|
||||
"""
|
||||
test ssh_pre_flight when there is a failure
|
||||
in the script.
|
||||
"""
|
||||
with salt.utils.files.fopen(_create_roster["data"]["ssh_pre_flight"], "w") as fp_:
|
||||
fp_.write("exit 2")
|
||||
|
||||
ret = salt_ssh_cli.run(
|
||||
"test.ping",
|
||||
"--pre-flight",
|
||||
)
|
||||
assert ret.data["retcode"] == 2
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def account():
|
||||
username = random_string("test-account-", uppercase=False)
|
||||
with pytest.helpers.create_account(username=username) as account:
|
||||
yield account
|
||||
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_ssh_pre_flight_script(salt_ssh_cli, caplog, _create_roster, tmp_path, account):
|
||||
"""
|
||||
Test to ensure user cannot create and run a script
|
||||
with the expected pre_flight script path on target.
|
||||
"""
|
||||
try:
|
||||
script = pathlib.Path.home() / "hacked"
|
||||
tmp_preflight = pathlib.Path("/tmp", "ssh_pre_flight.sh")
|
||||
tmp_preflight.write_text(f"touch {script}")
|
||||
os.chown(tmp_preflight, account.info.uid, account.info.gid)
|
||||
ret = salt_ssh_cli.run("test.ping")
|
||||
assert not script.is_file()
|
||||
assert ret.returncode == 0
|
||||
assert ret.stdout == '{\n"localhost": true\n}\n'
|
||||
finally:
|
||||
for _file in [script, tmp_preflight]:
|
||||
if _file.is_file():
|
||||
_file.unlink()
|
||||
|
||||
|
||||
def demote(user_uid, user_gid):
|
||||
def result():
|
||||
# os.setgid does not remove group membership, so we remove them here so they are REALLY non-root
|
||||
os.setgroups([])
|
||||
os.setgid(user_gid)
|
||||
os.setuid(user_uid)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_ssh_pre_flight_perms(salt_ssh_cli, caplog, _create_roster, account):
|
||||
"""
|
||||
Test to ensure standard user cannot run pre flight script
|
||||
on target when user sets wrong permissions (777) on
|
||||
ssh_pre_flight script.
|
||||
"""
|
||||
try:
|
||||
script = pathlib.Path("/tmp", "itworked")
|
||||
preflight = pathlib.Path("/ssh_pre_flight.sh")
|
||||
preflight.write_text(f"touch {str(script)}")
|
||||
tmp_preflight = pathlib.Path("/tmp", preflight.name)
|
||||
|
||||
_custom_roster(salt_ssh_cli.roster_file, {"ssh_pre_flight": str(preflight)})
|
||||
preflight.chmod(0o0777)
|
||||
run_script = pathlib.Path("/run_script")
|
||||
run_script.write_text(
|
||||
f"""
|
||||
x=1
|
||||
while [ $x -le 200000 ]; do
|
||||
SCRIPT=`bash {str(tmp_preflight)} 2> /dev/null; echo $?`
|
||||
if [ ${{SCRIPT}} == 0 ]; then
|
||||
break
|
||||
fi
|
||||
x=$(( $x + 1 ))
|
||||
done
|
||||
"""
|
||||
)
|
||||
run_script.chmod(0o0777)
|
||||
# pylint: disable=W1509
|
||||
ret = subprocess.Popen(
|
||||
["sh", f"{run_script}"],
|
||||
preexec_fn=demote(account.info.uid, account.info.gid),
|
||||
stdout=None,
|
||||
stderr=None,
|
||||
stdin=None,
|
||||
universal_newlines=True,
|
||||
)
|
||||
# pylint: enable=W1509
|
||||
ret = salt_ssh_cli.run("test.ping")
|
||||
assert ret.returncode == 0
|
||||
|
||||
# Lets make sure a different user other than root
|
||||
# Didn't run the script
|
||||
assert os.stat(script).st_uid != account.info.uid
|
||||
assert script.is_file()
|
||||
finally:
|
||||
for _file in [script, preflight, tmp_preflight, run_script]:
|
||||
if _file.is_file():
|
||||
_file.unlink()
|
||||
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_ssh_run_pre_flight_target_file_perms(salt_ssh_cli, _create_roster, tmp_path):
|
||||
"""
|
||||
test ssh_pre_flight to ensure the target pre flight script
|
||||
has the correct perms
|
||||
"""
|
||||
perms_file = tmp_path / "perms"
|
||||
with salt.utils.files.fopen(_create_roster["data"]["ssh_pre_flight"], "w") as fp_:
|
||||
fp_.write(
|
||||
f"""
|
||||
SCRIPT_NAME=$0
|
||||
stat -L -c "%a %G %U" $SCRIPT_NAME > {perms_file}
|
||||
"""
|
||||
)
|
||||
|
||||
ret = salt_ssh_cli.run(
|
||||
"test.ping",
|
||||
"--pre-flight",
|
||||
)
|
||||
assert ret.returncode == 0
|
||||
with salt.utils.files.fopen(perms_file) as fp:
|
||||
data = fp.read()
|
||||
assert data.split()[0] == "600"
|
||||
uid = os.getuid()
|
||||
gid = os.getgid()
|
||||
assert data.split()[1] == grp.getgrgid(gid).gr_name
|
||||
assert data.split()[2] == pwd.getpwuid(uid).pw_name
|
|
@ -1,6 +1,5 @@
|
|||
import os
|
||||
import logging
|
||||
import re
|
||||
import tempfile
|
||||
from textwrap import dedent
|
||||
|
||||
import pytest
|
||||
|
@ -16,6 +15,8 @@ import salt.utils.yaml
|
|||
from salt.client import ssh
|
||||
from tests.support.mock import MagicMock, call, patch
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def opts(tmp_path):
|
||||
|
@ -59,7 +60,7 @@ def test_single_opts(opts, target):
|
|||
fsclient=None,
|
||||
thin=salt.utils.thin.thin_path(opts["cachedir"]),
|
||||
mine=False,
|
||||
**target
|
||||
**target,
|
||||
)
|
||||
|
||||
assert single.shell._ssh_opts() == ""
|
||||
|
@ -87,7 +88,7 @@ def test_run_with_pre_flight(opts, target, tmp_path):
|
|||
fsclient=None,
|
||||
thin=salt.utils.thin.thin_path(opts["cachedir"]),
|
||||
mine=False,
|
||||
**target
|
||||
**target,
|
||||
)
|
||||
|
||||
cmd_ret = ("Success", "", 0)
|
||||
|
@ -122,7 +123,7 @@ def test_run_with_pre_flight_with_args(opts, target, tmp_path):
|
|||
fsclient=None,
|
||||
thin=salt.utils.thin.thin_path(opts["cachedir"]),
|
||||
mine=False,
|
||||
**target
|
||||
**target,
|
||||
)
|
||||
|
||||
cmd_ret = ("Success", "foobar", 0)
|
||||
|
@ -156,7 +157,7 @@ def test_run_with_pre_flight_stderr(opts, target, tmp_path):
|
|||
fsclient=None,
|
||||
thin=salt.utils.thin.thin_path(opts["cachedir"]),
|
||||
mine=False,
|
||||
**target
|
||||
**target,
|
||||
)
|
||||
|
||||
cmd_ret = ("", "Error running script", 1)
|
||||
|
@ -190,7 +191,7 @@ def test_run_with_pre_flight_script_doesnot_exist(opts, target, tmp_path):
|
|||
fsclient=None,
|
||||
thin=salt.utils.thin.thin_path(opts["cachedir"]),
|
||||
mine=False,
|
||||
**target
|
||||
**target,
|
||||
)
|
||||
|
||||
cmd_ret = ("Success", "", 0)
|
||||
|
@ -224,7 +225,7 @@ def test_run_with_pre_flight_thin_dir_exists(opts, target, tmp_path):
|
|||
fsclient=None,
|
||||
thin=salt.utils.thin.thin_path(opts["cachedir"]),
|
||||
mine=False,
|
||||
**target
|
||||
**target,
|
||||
)
|
||||
|
||||
cmd_ret = ("", "", 0)
|
||||
|
@ -242,6 +243,39 @@ def test_run_with_pre_flight_thin_dir_exists(opts, target, tmp_path):
|
|||
assert ret == cmd_ret
|
||||
|
||||
|
||||
def test_run_ssh_pre_flight(opts, target, tmp_path):
|
||||
"""
|
||||
test Single.run_ssh_pre_flight function
|
||||
"""
|
||||
target["ssh_pre_flight"] = str(tmp_path / "script.sh")
|
||||
single = ssh.Single(
|
||||
opts,
|
||||
opts["argv"],
|
||||
"localhost",
|
||||
mods={},
|
||||
fsclient=None,
|
||||
thin=salt.utils.thin.thin_path(opts["cachedir"]),
|
||||
mine=False,
|
||||
**target,
|
||||
)
|
||||
|
||||
cmd_ret = ("Success", "", 0)
|
||||
mock_flight = MagicMock(return_value=cmd_ret)
|
||||
mock_cmd = MagicMock(return_value=cmd_ret)
|
||||
patch_flight = patch("salt.client.ssh.Single.run_ssh_pre_flight", mock_flight)
|
||||
patch_cmd = patch("salt.client.ssh.Single.cmd_block", mock_cmd)
|
||||
patch_exec_cmd = patch(
|
||||
"salt.client.ssh.shell.Shell.exec_cmd", return_value=("", "", 1)
|
||||
)
|
||||
patch_os = patch("os.path.exists", side_effect=[True])
|
||||
|
||||
with patch_os, patch_flight, patch_cmd, patch_exec_cmd:
|
||||
ret = single.run()
|
||||
mock_cmd.assert_called()
|
||||
mock_flight.assert_called()
|
||||
assert ret == cmd_ret
|
||||
|
||||
|
||||
def test_execute_script(opts, target, tmp_path):
|
||||
"""
|
||||
test Single.execute_script()
|
||||
|
@ -255,7 +289,7 @@ def test_execute_script(opts, target, tmp_path):
|
|||
thin=salt.utils.thin.thin_path(opts["cachedir"]),
|
||||
mine=False,
|
||||
winrm=False,
|
||||
**target
|
||||
**target,
|
||||
)
|
||||
|
||||
exp_ret = ("Success", "", 0)
|
||||
|
@ -268,12 +302,12 @@ def test_execute_script(opts, target, tmp_path):
|
|||
assert ret == exp_ret
|
||||
assert mock_cmd.call_count == 2
|
||||
assert [
|
||||
call("/bin/sh '{}'".format(script)),
|
||||
call("rm '{}'".format(script)),
|
||||
call(f"/bin/sh '{script}'"),
|
||||
call(f"rm '{script}'"),
|
||||
] == mock_cmd.call_args_list
|
||||
|
||||
|
||||
def test_shim_cmd(opts, target):
|
||||
def test_shim_cmd(opts, target, tmp_path):
|
||||
"""
|
||||
test Single.shim_cmd()
|
||||
"""
|
||||
|
@ -287,7 +321,7 @@ def test_shim_cmd(opts, target):
|
|||
mine=False,
|
||||
winrm=False,
|
||||
tty=True,
|
||||
**target
|
||||
**target,
|
||||
)
|
||||
|
||||
exp_ret = ("Success", "", 0)
|
||||
|
@ -295,21 +329,24 @@ def test_shim_cmd(opts, target):
|
|||
patch_cmd = patch("salt.client.ssh.shell.Shell.exec_cmd", mock_cmd)
|
||||
patch_send = patch("salt.client.ssh.shell.Shell.send", return_value=("", "", 0))
|
||||
patch_rand = patch("os.urandom", return_value=b"5\xd9l\xca\xc2\xff")
|
||||
tmp_file = tmp_path / "tmp_file"
|
||||
mock_tmp = MagicMock()
|
||||
patch_tmp = patch("tempfile.NamedTemporaryFile", mock_tmp)
|
||||
mock_tmp.return_value.__enter__.return_value.name = tmp_file
|
||||
|
||||
with patch_cmd, patch_rand, patch_send:
|
||||
with patch_cmd, patch_tmp, patch_send:
|
||||
ret = single.shim_cmd(cmd_str="echo test")
|
||||
assert ret == exp_ret
|
||||
assert [
|
||||
call("/bin/sh '.35d96ccac2ff.py'"),
|
||||
call("rm '.35d96ccac2ff.py'"),
|
||||
call(f"/bin/sh '.{tmp_file.name}'"),
|
||||
call(f"rm '.{tmp_file.name}'"),
|
||||
] == mock_cmd.call_args_list
|
||||
|
||||
|
||||
def test_run_ssh_pre_flight(opts, target, tmp_path):
|
||||
def test_shim_cmd_copy_fails(opts, target, caplog):
|
||||
"""
|
||||
test Single.run_ssh_pre_flight
|
||||
test Single.shim_cmd() when copying the file fails
|
||||
"""
|
||||
target["ssh_pre_flight"] = str(tmp_path / "script.sh")
|
||||
single = ssh.Single(
|
||||
opts,
|
||||
opts["argv"],
|
||||
|
@ -320,24 +357,202 @@ def test_run_ssh_pre_flight(opts, target, tmp_path):
|
|||
mine=False,
|
||||
winrm=False,
|
||||
tty=True,
|
||||
**target
|
||||
**target,
|
||||
)
|
||||
|
||||
exp_ret = ("Success", "", 0)
|
||||
mock_cmd = MagicMock(return_value=exp_ret)
|
||||
ret_cmd = ("Success", "", 0)
|
||||
mock_cmd = MagicMock(return_value=ret_cmd)
|
||||
patch_cmd = patch("salt.client.ssh.shell.Shell.exec_cmd", mock_cmd)
|
||||
patch_send = patch("salt.client.ssh.shell.Shell.send", return_value=exp_ret)
|
||||
exp_tmp = os.path.join(
|
||||
tempfile.gettempdir(), os.path.basename(target["ssh_pre_flight"])
|
||||
)
|
||||
ret_send = ("", "General error in file copy", 1)
|
||||
patch_send = patch("salt.client.ssh.shell.Shell.send", return_value=ret_send)
|
||||
patch_rand = patch("os.urandom", return_value=b"5\xd9l\xca\xc2\xff")
|
||||
|
||||
with patch_cmd, patch_send:
|
||||
with patch_cmd, patch_rand, patch_send:
|
||||
ret = single.shim_cmd(cmd_str="echo test")
|
||||
assert ret == ret_send
|
||||
assert "Could not copy the shim script to target" in caplog.text
|
||||
mock_cmd.assert_not_called()
|
||||
|
||||
|
||||
def test_run_ssh_pre_flight_no_connect(opts, target, tmp_path, caplog):
|
||||
"""
|
||||
test Single.run_ssh_pre_flight when you
|
||||
cannot connect to the target
|
||||
"""
|
||||
pre_flight = tmp_path / "script.sh"
|
||||
pre_flight.write_text("")
|
||||
target["ssh_pre_flight"] = str(pre_flight)
|
||||
single = ssh.Single(
|
||||
opts,
|
||||
opts["argv"],
|
||||
"localhost",
|
||||
mods={},
|
||||
fsclient=None,
|
||||
thin=salt.utils.thin.thin_path(opts["cachedir"]),
|
||||
mine=False,
|
||||
winrm=False,
|
||||
tty=True,
|
||||
**target,
|
||||
)
|
||||
mock_exec_cmd = MagicMock(return_value=("", "", 1))
|
||||
patch_exec_cmd = patch("salt.client.ssh.shell.Shell.exec_cmd", mock_exec_cmd)
|
||||
tmp_file = tmp_path / "tmp_file"
|
||||
mock_tmp = MagicMock()
|
||||
patch_tmp = patch("tempfile.NamedTemporaryFile", mock_tmp)
|
||||
mock_tmp.return_value.__enter__.return_value.name = tmp_file
|
||||
ret_send = (
|
||||
"",
|
||||
"ssh: connect to host 192.168.1.186 port 22: No route to host\nscp: Connection closed\n",
|
||||
255,
|
||||
)
|
||||
send_mock = MagicMock(return_value=ret_send)
|
||||
patch_send = patch("salt.client.ssh.shell.Shell.send", send_mock)
|
||||
|
||||
with caplog.at_level(logging.TRACE):
|
||||
with patch_send, patch_exec_cmd, patch_tmp:
|
||||
ret = single.run_ssh_pre_flight()
|
||||
assert "Copying the pre flight script" in caplog.text
|
||||
assert "Could not copy the pre flight script to target" in caplog.text
|
||||
assert ret == ret_send
|
||||
assert send_mock.call_args_list[0][0][0] == tmp_file
|
||||
target_script = send_mock.call_args_list[0][0][1]
|
||||
assert re.search(r".[a-z0-9]+", target_script)
|
||||
mock_exec_cmd.assert_not_called()
|
||||
|
||||
|
||||
def test_run_ssh_pre_flight_permission_denied(opts, target, tmp_path):
|
||||
"""
|
||||
test Single.run_ssh_pre_flight when you
|
||||
cannot copy script to the target due to
|
||||
a permission denied error
|
||||
"""
|
||||
pre_flight = tmp_path / "script.sh"
|
||||
pre_flight.write_text("")
|
||||
target["ssh_pre_flight"] = str(pre_flight)
|
||||
single = ssh.Single(
|
||||
opts,
|
||||
opts["argv"],
|
||||
"localhost",
|
||||
mods={},
|
||||
fsclient=None,
|
||||
thin=salt.utils.thin.thin_path(opts["cachedir"]),
|
||||
mine=False,
|
||||
winrm=False,
|
||||
tty=True,
|
||||
**target,
|
||||
)
|
||||
mock_exec_cmd = MagicMock(return_value=("", "", 1))
|
||||
patch_exec_cmd = patch("salt.client.ssh.shell.Shell.exec_cmd", mock_exec_cmd)
|
||||
tmp_file = tmp_path / "tmp_file"
|
||||
mock_tmp = MagicMock()
|
||||
patch_tmp = patch("tempfile.NamedTemporaryFile", mock_tmp)
|
||||
mock_tmp.return_value.__enter__.return_value.name = tmp_file
|
||||
ret_send = (
|
||||
"",
|
||||
'scp: dest open "/tmp/preflight.sh": Permission denied\nscp: failed to upload file /etc/salt/preflight.sh to /tmp/preflight.sh\n',
|
||||
255,
|
||||
)
|
||||
send_mock = MagicMock(return_value=ret_send)
|
||||
patch_send = patch("salt.client.ssh.shell.Shell.send", send_mock)
|
||||
|
||||
with patch_send, patch_exec_cmd, patch_tmp:
|
||||
ret = single.run_ssh_pre_flight()
|
||||
assert ret == exp_ret
|
||||
assert [
|
||||
call("/bin/sh '{}'".format(exp_tmp)),
|
||||
call("rm '{}'".format(exp_tmp)),
|
||||
] == mock_cmd.call_args_list
|
||||
assert ret == ret_send
|
||||
assert send_mock.call_args_list[0][0][0] == tmp_file
|
||||
target_script = send_mock.call_args_list[0][0][1]
|
||||
assert re.search(r".[a-z0-9]+", target_script)
|
||||
mock_exec_cmd.assert_not_called()
|
||||
|
||||
|
||||
def test_run_ssh_pre_flight_connect(opts, target, tmp_path, caplog):
|
||||
"""
|
||||
test Single.run_ssh_pre_flight when you
|
||||
can connect to the target
|
||||
"""
|
||||
pre_flight = tmp_path / "script.sh"
|
||||
pre_flight.write_text("")
|
||||
target["ssh_pre_flight"] = str(pre_flight)
|
||||
single = ssh.Single(
|
||||
opts,
|
||||
opts["argv"],
|
||||
"localhost",
|
||||
mods={},
|
||||
fsclient=None,
|
||||
thin=salt.utils.thin.thin_path(opts["cachedir"]),
|
||||
mine=False,
|
||||
winrm=False,
|
||||
tty=True,
|
||||
**target,
|
||||
)
|
||||
ret_exec_cmd = ("", "", 1)
|
||||
mock_exec_cmd = MagicMock(return_value=ret_exec_cmd)
|
||||
patch_exec_cmd = patch("salt.client.ssh.shell.Shell.exec_cmd", mock_exec_cmd)
|
||||
tmp_file = tmp_path / "tmp_file"
|
||||
mock_tmp = MagicMock()
|
||||
patch_tmp = patch("tempfile.NamedTemporaryFile", mock_tmp)
|
||||
mock_tmp.return_value.__enter__.return_value.name = tmp_file
|
||||
ret_send = (
|
||||
"",
|
||||
"\rroot@192.168.1.187's password: \n\rpreflight.sh 0% 0 0.0KB/s --:-- ETA\rpreflight.sh 100% 20 2.7KB/s 00:00 \n",
|
||||
0,
|
||||
)
|
||||
send_mock = MagicMock(return_value=ret_send)
|
||||
patch_send = patch("salt.client.ssh.shell.Shell.send", send_mock)
|
||||
|
||||
with caplog.at_level(logging.TRACE):
|
||||
with patch_send, patch_exec_cmd, patch_tmp:
|
||||
ret = single.run_ssh_pre_flight()
|
||||
|
||||
assert "Executing the pre flight script on target" in caplog.text
|
||||
assert ret == ret_exec_cmd
|
||||
assert send_mock.call_args_list[0][0][0] == tmp_file
|
||||
target_script = send_mock.call_args_list[0][0][1]
|
||||
assert re.search(r".[a-z0-9]+", target_script)
|
||||
mock_exec_cmd.assert_called()
|
||||
|
||||
|
||||
def test_run_ssh_pre_flight_shutil_fails(opts, target, tmp_path):
|
||||
"""
|
||||
test Single.run_ssh_pre_flight when cannot
|
||||
copyfile with shutil
|
||||
"""
|
||||
pre_flight = tmp_path / "script.sh"
|
||||
pre_flight.write_text("")
|
||||
target["ssh_pre_flight"] = str(pre_flight)
|
||||
single = ssh.Single(
|
||||
opts,
|
||||
opts["argv"],
|
||||
"localhost",
|
||||
mods={},
|
||||
fsclient=None,
|
||||
thin=salt.utils.thin.thin_path(opts["cachedir"]),
|
||||
mine=False,
|
||||
winrm=False,
|
||||
tty=True,
|
||||
**target,
|
||||
)
|
||||
ret_exec_cmd = ("", "", 1)
|
||||
mock_exec_cmd = MagicMock(return_value=ret_exec_cmd)
|
||||
patch_exec_cmd = patch("salt.client.ssh.shell.Shell.exec_cmd", mock_exec_cmd)
|
||||
tmp_file = tmp_path / "tmp_file"
|
||||
mock_tmp = MagicMock()
|
||||
patch_tmp = patch("tempfile.NamedTemporaryFile", mock_tmp)
|
||||
mock_tmp.return_value.__enter__.return_value.name = tmp_file
|
||||
send_mock = MagicMock()
|
||||
mock_shutil = MagicMock(side_effect=IOError("Permission Denied"))
|
||||
patch_shutil = patch("shutil.copyfile", mock_shutil)
|
||||
patch_send = patch("salt.client.ssh.shell.Shell.send", send_mock)
|
||||
|
||||
with patch_send, patch_exec_cmd, patch_tmp, patch_shutil:
|
||||
ret = single.run_ssh_pre_flight()
|
||||
|
||||
assert ret == (
|
||||
"",
|
||||
"Could not copy pre flight script to temporary path",
|
||||
1,
|
||||
)
|
||||
mock_exec_cmd.assert_not_called()
|
||||
send_mock.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.skip_on_windows(reason="SSH_PY_SHIM not set on windows")
|
||||
|
@ -355,7 +570,7 @@ def test_cmd_run_set_path(opts, target):
|
|||
fsclient=None,
|
||||
thin=salt.utils.thin.thin_path(opts["cachedir"]),
|
||||
mine=False,
|
||||
**target
|
||||
**target,
|
||||
)
|
||||
|
||||
ret = single._cmd_str()
|
||||
|
@ -376,7 +591,7 @@ def test_cmd_run_not_set_path(opts, target):
|
|||
fsclient=None,
|
||||
thin=salt.utils.thin.thin_path(opts["cachedir"]),
|
||||
mine=False,
|
||||
**target
|
||||
**target,
|
||||
)
|
||||
|
||||
ret = single._cmd_str()
|
||||
|
@ -395,7 +610,7 @@ def test_cmd_block_python_version_error(opts, target):
|
|||
thin=salt.utils.thin.thin_path(opts["cachedir"]),
|
||||
mine=False,
|
||||
winrm=False,
|
||||
**target
|
||||
**target,
|
||||
)
|
||||
mock_shim = MagicMock(
|
||||
return_value=(("", "ERROR: Unable to locate appropriate python command\n", 10))
|
||||
|
@ -434,7 +649,9 @@ def test_run_with_pre_flight_args(opts, target, test_opts, tmp_path):
|
|||
and script successfully runs
|
||||
"""
|
||||
opts["ssh_run_pre_flight"] = True
|
||||
target["ssh_pre_flight"] = str(tmp_path / "script.sh")
|
||||
pre_flight_script = tmp_path / "script.sh"
|
||||
pre_flight_script.write_text("")
|
||||
target["ssh_pre_flight"] = str(pre_flight_script)
|
||||
|
||||
if test_opts[0] is not None:
|
||||
target["ssh_pre_flight_args"] = test_opts[0]
|
||||
|
@ -448,7 +665,7 @@ def test_run_with_pre_flight_args(opts, target, test_opts, tmp_path):
|
|||
fsclient=None,
|
||||
thin=salt.utils.thin.thin_path(opts["cachedir"]),
|
||||
mine=False,
|
||||
**target
|
||||
**target,
|
||||
)
|
||||
|
||||
cmd_ret = ("Success", "", 0)
|
||||
|
@ -456,14 +673,15 @@ def test_run_with_pre_flight_args(opts, target, test_opts, tmp_path):
|
|||
mock_exec_cmd = MagicMock(return_value=("", "", 0))
|
||||
patch_cmd = patch("salt.client.ssh.Single.cmd_block", mock_cmd)
|
||||
patch_exec_cmd = patch("salt.client.ssh.shell.Shell.exec_cmd", mock_exec_cmd)
|
||||
patch_shell_send = patch("salt.client.ssh.shell.Shell.send", return_value=None)
|
||||
patch_shell_send = patch(
|
||||
"salt.client.ssh.shell.Shell.send", return_value=("", "", 0)
|
||||
)
|
||||
patch_os = patch("os.path.exists", side_effect=[True])
|
||||
|
||||
with patch_os, patch_cmd, patch_exec_cmd, patch_shell_send:
|
||||
ret = single.run()
|
||||
assert mock_exec_cmd.mock_calls[0].args[
|
||||
0
|
||||
] == "/bin/sh '/tmp/script.sh'{}".format(expected_args)
|
||||
single.run()
|
||||
script_args = mock_exec_cmd.mock_calls[0].args[0]
|
||||
assert re.search(r"\/bin\/sh '.[a-z0-9]+", script_args)
|
||||
|
||||
|
||||
@pytest.mark.slow_test
|
||||
|
|
|
@ -339,3 +339,113 @@ def test_extra_filerefs(tmp_path, opts):
|
|||
with patch("salt.roster.get_roster_file", MagicMock(return_value=roster)):
|
||||
ssh_obj = client._prep_ssh(**ssh_opts)
|
||||
assert ssh_obj.opts.get("extra_filerefs", None) == "salt://foobar"
|
||||
|
||||
|
||||
def test_key_deploy_permission_denied_scp(tmp_path, opts):
|
||||
"""
|
||||
test "key_deploy" function when
|
||||
permission denied authentication error
|
||||
when attempting to use scp to copy file
|
||||
to target
|
||||
"""
|
||||
host = "localhost"
|
||||
passwd = "password"
|
||||
usr = "ssh-usr"
|
||||
opts["ssh_user"] = usr
|
||||
opts["tgt"] = host
|
||||
|
||||
ssh_ret = {
|
||||
host: {
|
||||
"stdout": "\rroot@192.168.1.187's password: \n\rroot@192.168.1.187's password: \n\rroot@192.168.1.187's password: \n",
|
||||
"stderr": "Permission denied, please try again.\nPermission denied, please try again.\nroot@192.168.1.187: Permission denied (publickey,gssapi-keyex,gssapi-with-micimport pudb; pu.dbassword).\nscp: Connection closed\n",
|
||||
"retcode": 255,
|
||||
}
|
||||
}
|
||||
key_run_ret = {
|
||||
"localhost": {
|
||||
"jid": "20230922155652279959",
|
||||
"return": "test",
|
||||
"retcode": 0,
|
||||
"id": "test",
|
||||
"fun": "cmd.run",
|
||||
"fun_args": ["echo test"],
|
||||
}
|
||||
}
|
||||
patch_roster_file = patch("salt.roster.get_roster_file", MagicMock(return_value=""))
|
||||
with patch_roster_file:
|
||||
client = ssh.SSH(opts)
|
||||
patch_input = patch("builtins.input", side_effect=["y"])
|
||||
patch_getpass = patch("getpass.getpass", return_value=["password"])
|
||||
mock_key_run = MagicMock(return_value=key_run_ret)
|
||||
patch_key_run = patch("salt.client.ssh.SSH._key_deploy_run", mock_key_run)
|
||||
with patch_input, patch_getpass, patch_key_run:
|
||||
ret = client.key_deploy(host, ssh_ret)
|
||||
assert mock_key_run.call_args_list[0][0] == (
|
||||
host,
|
||||
{"passwd": [passwd], "host": host, "user": usr},
|
||||
True,
|
||||
)
|
||||
assert ret == key_run_ret
|
||||
assert mock_key_run.call_count == 1
|
||||
|
||||
|
||||
def test_key_deploy_permission_denied_file_scp(tmp_path, opts):
|
||||
"""
|
||||
test "key_deploy" function when permission denied
|
||||
due to not having access to copy the file to the target
|
||||
We do not want to deploy the key, because this is not
|
||||
an authentication to the target error.
|
||||
"""
|
||||
host = "localhost"
|
||||
passwd = "password"
|
||||
usr = "ssh-usr"
|
||||
opts["ssh_user"] = usr
|
||||
opts["tgt"] = host
|
||||
|
||||
mock_key_run = MagicMock(return_value=False)
|
||||
patch_key_run = patch("salt.client.ssh.SSH._key_deploy_run", mock_key_run)
|
||||
|
||||
ssh_ret = {
|
||||
"localhost": {
|
||||
"stdout": "",
|
||||
"stderr": 'scp: dest open "/tmp/preflight.sh": Permission denied\nscp: failed to upload file /etc/salt/preflight.sh to /tmp/preflight.sh\n',
|
||||
"retcode": 1,
|
||||
}
|
||||
}
|
||||
patch_roster_file = patch("salt.roster.get_roster_file", MagicMock(return_value=""))
|
||||
with patch_roster_file:
|
||||
client = ssh.SSH(opts)
|
||||
ret = client.key_deploy(host, ssh_ret)
|
||||
assert ret == ssh_ret
|
||||
assert mock_key_run.call_count == 0
|
||||
|
||||
|
||||
def test_key_deploy_no_permission_denied(tmp_path, opts):
|
||||
"""
|
||||
test "key_deploy" function when no permission denied
|
||||
is returned
|
||||
"""
|
||||
host = "localhost"
|
||||
passwd = "password"
|
||||
usr = "ssh-usr"
|
||||
opts["ssh_user"] = usr
|
||||
opts["tgt"] = host
|
||||
|
||||
mock_key_run = MagicMock(return_value=False)
|
||||
patch_key_run = patch("salt.client.ssh.SSH._key_deploy_run", mock_key_run)
|
||||
ssh_ret = {
|
||||
"localhost": {
|
||||
"jid": "20230922161937998385",
|
||||
"return": "test",
|
||||
"retcode": 0,
|
||||
"id": "test",
|
||||
"fun": "cmd.run",
|
||||
"fun_args": ["echo test"],
|
||||
}
|
||||
}
|
||||
patch_roster_file = patch("salt.roster.get_roster_file", MagicMock(return_value=""))
|
||||
with patch_roster_file:
|
||||
client = ssh.SSH(opts)
|
||||
ret = client.key_deploy(host, ssh_ret)
|
||||
assert ret == ssh_ret
|
||||
assert mock_key_run.call_count == 0
|
||||
|
|
165
tests/pytests/unit/modules/test_deb_postgres.py
Normal file
165
tests/pytests/unit/modules/test_deb_postgres.py
Normal file
|
@ -0,0 +1,165 @@
|
|||
import logging
|
||||
|
||||
import pytest
|
||||
|
||||
import salt.modules.deb_postgres as deb_postgres
|
||||
from tests.support.mock import Mock, patch
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
pytestmark = [
|
||||
pytest.mark.skip_unless_on_linux(reason="Only supported on Linux family"),
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def get_lscuster():
|
||||
return """\
|
||||
8.4 main 5432 online postgres /srv/8.4/main \
|
||||
/var/log/postgresql/postgresql-8.4-main.log
|
||||
9.1 main 5433 online postgres /srv/9.1/main \
|
||||
/var/log/postgresql/postgresql-9.1-main.log
|
||||
"""
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def configure_loader_modules(get_lscuster):
|
||||
return {
|
||||
deb_postgres: {
|
||||
"__salt__": {
|
||||
"config.option": Mock(),
|
||||
"cmd.run_all": Mock(return_value={"stdout": get_lscuster}),
|
||||
"file.chown": Mock(),
|
||||
"file.remove": Mock(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def test_cluster_create():
|
||||
with patch("salt.utils.path.which", Mock(return_value="/usr/bin/pg_createcluster")):
|
||||
expected_cmdstr = (
|
||||
"/usr/bin/pg_createcluster "
|
||||
"--port 5432 --locale fr_FR --encoding UTF-8 "
|
||||
"--datadir /opt/postgresql "
|
||||
"9.3 main"
|
||||
)
|
||||
|
||||
deb_postgres.cluster_create(
|
||||
"9.3",
|
||||
"main",
|
||||
port="5432",
|
||||
locale="fr_FR",
|
||||
encoding="UTF-8",
|
||||
datadir="/opt/postgresql",
|
||||
)
|
||||
assert deb_postgres.__salt__["cmd.run_all"].call_args[0][0] == expected_cmdstr
|
||||
|
||||
|
||||
def test_cluster_create_with_initdb_options():
|
||||
with patch("salt.utils.path.which", Mock(return_value="/usr/bin/pg_createcluster")):
|
||||
expected_cmdstr = (
|
||||
"/usr/bin/pg_createcluster "
|
||||
"--port 5432 --locale fr_FR --encoding UTF-8 "
|
||||
"--datadir /opt/postgresql "
|
||||
"11 main "
|
||||
"-- "
|
||||
"--allow-group-access "
|
||||
"--data-checksums "
|
||||
"--wal-segsize 32"
|
||||
)
|
||||
|
||||
deb_postgres.cluster_create(
|
||||
"11",
|
||||
"main",
|
||||
port="5432",
|
||||
locale="fr_FR",
|
||||
encoding="UTF-8",
|
||||
datadir="/opt/postgresql",
|
||||
allow_group_access=True,
|
||||
data_checksums=True,
|
||||
wal_segsize="32",
|
||||
)
|
||||
assert deb_postgres.__salt__["cmd.run_all"].call_args[0][0] == expected_cmdstr
|
||||
|
||||
|
||||
def test_cluster_create_with_float():
|
||||
with patch("salt.utils.path.which", Mock(return_value="/usr/bin/pg_createcluster")):
|
||||
expected_cmdstr = (
|
||||
"/usr/bin/pg_createcluster "
|
||||
"--port 5432 --locale fr_FR --encoding UTF-8 "
|
||||
"--datadir /opt/postgresql "
|
||||
"9.3 main"
|
||||
)
|
||||
|
||||
deb_postgres.cluster_create(
|
||||
9.3,
|
||||
"main",
|
||||
port="5432",
|
||||
locale="fr_FR",
|
||||
encoding="UTF-8",
|
||||
datadir="/opt/postgresql",
|
||||
)
|
||||
assert deb_postgres.__salt__["cmd.run_all"].call_args[0][0] == expected_cmdstr
|
||||
|
||||
|
||||
def test_parse_pg_lsclusters(get_lscuster):
|
||||
with patch("salt.utils.path.which", Mock(return_value="/usr/bin/pg_lsclusters")):
|
||||
stdout = get_lscuster
|
||||
maxDiff = None
|
||||
expected = {
|
||||
"8.4/main": {
|
||||
"port": 5432,
|
||||
"status": "online",
|
||||
"user": "postgres",
|
||||
"datadir": "/srv/8.4/main",
|
||||
"log": "/var/log/postgresql/postgresql-8.4-main.log",
|
||||
},
|
||||
"9.1/main": {
|
||||
"port": 5433,
|
||||
"status": "online",
|
||||
"user": "postgres",
|
||||
"datadir": "/srv/9.1/main",
|
||||
"log": "/var/log/postgresql/postgresql-9.1-main.log",
|
||||
},
|
||||
}
|
||||
assert deb_postgres._parse_pg_lscluster(stdout) == expected
|
||||
|
||||
|
||||
def test_cluster_list():
|
||||
with patch("salt.utils.path.which", Mock(return_value="/usr/bin/pg_lsclusters")):
|
||||
return_list = deb_postgres.cluster_list()
|
||||
assert (
|
||||
deb_postgres.__salt__["cmd.run_all"].call_args[0][0]
|
||||
== "/usr/bin/pg_lsclusters --no-header"
|
||||
)
|
||||
|
||||
return_dict = deb_postgres.cluster_list(verbose=True)
|
||||
assert isinstance(return_dict, dict)
|
||||
|
||||
|
||||
def test_cluster_exists():
|
||||
assert deb_postgres.cluster_exists("8.4")
|
||||
assert deb_postgres.cluster_exists("8.4", "main")
|
||||
assert not deb_postgres.cluster_exists("3.4", "main")
|
||||
|
||||
|
||||
def test_cluster_delete():
|
||||
with patch("salt.utils.path.which", Mock(return_value="/usr/bin/pg_dropcluster")):
|
||||
deb_postgres.cluster_remove("9.3", "main")
|
||||
assert (
|
||||
deb_postgres.__salt__["cmd.run_all"].call_args[0][0]
|
||||
== "/usr/bin/pg_dropcluster 9.3 main"
|
||||
)
|
||||
|
||||
deb_postgres.cluster_remove("9.3", "main", stop=True)
|
||||
assert (
|
||||
deb_postgres.__salt__["cmd.run_all"].call_args[0][0]
|
||||
== "/usr/bin/pg_dropcluster --stop 9.3 main"
|
||||
)
|
||||
|
||||
deb_postgres.cluster_remove(9.3, "main", stop=True)
|
||||
assert (
|
||||
deb_postgres.__salt__["cmd.run_all"].call_args[0][0]
|
||||
== "/usr/bin/pg_dropcluster --stop 9.3 main"
|
||||
)
|
File diff suppressed because it is too large
Load diff
|
@ -1,184 +0,0 @@
|
|||
import salt.modules.deb_postgres as deb_postgres
|
||||
from tests.support.mixins import LoaderModuleMockMixin
|
||||
from tests.support.mock import Mock, patch
|
||||
from tests.support.unit import TestCase
|
||||
|
||||
LSCLUSTER = """\
|
||||
8.4 main 5432 online postgres /srv/8.4/main \
|
||||
/var/log/postgresql/postgresql-8.4-main.log
|
||||
9.1 main 5433 online postgres /srv/9.1/main \
|
||||
/var/log/postgresql/postgresql-9.1-main.log
|
||||
"""
|
||||
|
||||
|
||||
class PostgresClusterTestCase(TestCase, LoaderModuleMockMixin):
|
||||
def setup_loader_modules(self):
|
||||
self.cmd_run_all_mock = Mock(return_value={"stdout": LSCLUSTER})
|
||||
self.addCleanup(delattr, self, "cmd_run_all_mock")
|
||||
patcher = patch(
|
||||
"salt.utils.path.which", Mock(return_value="/usr/bin/pg_createcluster")
|
||||
)
|
||||
patcher.start()
|
||||
self.addCleanup(patcher.stop)
|
||||
return {
|
||||
deb_postgres: {
|
||||
"__salt__": {
|
||||
"config.option": Mock(),
|
||||
"cmd.run_all": self.cmd_run_all_mock,
|
||||
"file.chown": Mock(),
|
||||
"file.remove": Mock(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def test_cluster_create(self):
|
||||
deb_postgres.cluster_create(
|
||||
"9.3",
|
||||
"main",
|
||||
port="5432",
|
||||
locale="fr_FR",
|
||||
encoding="UTF-8",
|
||||
datadir="/opt/postgresql",
|
||||
)
|
||||
cmdstr = (
|
||||
"/usr/bin/pg_createcluster "
|
||||
"--port 5432 --locale fr_FR --encoding UTF-8 "
|
||||
"--datadir /opt/postgresql "
|
||||
"9.3 main"
|
||||
)
|
||||
self.assertEqual(cmdstr, self.cmd_run_all_mock.call_args[0][0])
|
||||
|
||||
def test_cluster_create_with_initdb_options(self):
|
||||
deb_postgres.cluster_create(
|
||||
"11",
|
||||
"main",
|
||||
port="5432",
|
||||
locale="fr_FR",
|
||||
encoding="UTF-8",
|
||||
datadir="/opt/postgresql",
|
||||
allow_group_access=True,
|
||||
data_checksums=True,
|
||||
wal_segsize="32",
|
||||
)
|
||||
cmdstr = (
|
||||
"/usr/bin/pg_createcluster "
|
||||
"--port 5432 --locale fr_FR --encoding UTF-8 "
|
||||
"--datadir /opt/postgresql "
|
||||
"11 main "
|
||||
"-- "
|
||||
"--allow-group-access "
|
||||
"--data-checksums "
|
||||
"--wal-segsize 32"
|
||||
)
|
||||
self.assertEqual(cmdstr, self.cmd_run_all_mock.call_args[0][0])
|
||||
|
||||
def test_cluster_create_with_float(self):
|
||||
deb_postgres.cluster_create(
|
||||
9.3,
|
||||
"main",
|
||||
port="5432",
|
||||
locale="fr_FR",
|
||||
encoding="UTF-8",
|
||||
datadir="/opt/postgresql",
|
||||
)
|
||||
cmdstr = (
|
||||
"/usr/bin/pg_createcluster "
|
||||
"--port 5432 --locale fr_FR --encoding UTF-8 "
|
||||
"--datadir /opt/postgresql "
|
||||
"9.3 main"
|
||||
)
|
||||
self.assertEqual(cmdstr, self.cmd_run_all_mock.call_args[0][0])
|
||||
|
||||
|
||||
class PostgresLsClusterTestCase(TestCase, LoaderModuleMockMixin):
|
||||
def setup_loader_modules(self):
|
||||
self.cmd_run_all_mock = Mock(return_value={"stdout": LSCLUSTER})
|
||||
self.addCleanup(delattr, self, "cmd_run_all_mock")
|
||||
patcher = patch(
|
||||
"salt.utils.path.which", Mock(return_value="/usr/bin/pg_lsclusters")
|
||||
)
|
||||
patcher.start()
|
||||
self.addCleanup(patcher.stop)
|
||||
return {
|
||||
deb_postgres: {
|
||||
"__salt__": {
|
||||
"config.option": Mock(),
|
||||
"cmd.run_all": self.cmd_run_all_mock,
|
||||
"file.chown": Mock(),
|
||||
"file.remove": Mock(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def test_parse_pg_lsclusters(self):
|
||||
stdout = LSCLUSTER
|
||||
self.maxDiff = None
|
||||
self.assertDictEqual(
|
||||
{
|
||||
"8.4/main": {
|
||||
"port": 5432,
|
||||
"status": "online",
|
||||
"user": "postgres",
|
||||
"datadir": "/srv/8.4/main",
|
||||
"log": "/var/log/postgresql/postgresql-8.4-main.log",
|
||||
},
|
||||
"9.1/main": {
|
||||
"port": 5433,
|
||||
"status": "online",
|
||||
"user": "postgres",
|
||||
"datadir": "/srv/9.1/main",
|
||||
"log": "/var/log/postgresql/postgresql-9.1-main.log",
|
||||
},
|
||||
},
|
||||
deb_postgres._parse_pg_lscluster(stdout),
|
||||
)
|
||||
|
||||
def test_cluster_list(self):
|
||||
return_list = deb_postgres.cluster_list()
|
||||
self.assertEqual(
|
||||
"/usr/bin/pg_lsclusters --no-header", self.cmd_run_all_mock.call_args[0][0]
|
||||
)
|
||||
return_dict = deb_postgres.cluster_list(verbose=True)
|
||||
self.assertIsInstance(return_dict, dict)
|
||||
|
||||
def test_cluster_exists(self):
|
||||
self.assertTrue(deb_postgres.cluster_exists("8.4") is True)
|
||||
self.assertTrue(deb_postgres.cluster_exists("8.4", "main") is True)
|
||||
self.assertFalse(deb_postgres.cluster_exists("3.4", "main"))
|
||||
|
||||
|
||||
class PostgresDeleteClusterTestCase(TestCase, LoaderModuleMockMixin):
|
||||
def setup_loader_modules(self):
|
||||
self.cmd_run_all_mock = Mock(return_value={"stdout": LSCLUSTER})
|
||||
self.addCleanup(delattr, self, "cmd_run_all_mock")
|
||||
patcher = patch(
|
||||
"salt.utils.path.which", Mock(return_value="/usr/bin/pg_dropcluster")
|
||||
)
|
||||
patcher.start()
|
||||
self.addCleanup(patcher.stop)
|
||||
return {
|
||||
deb_postgres: {
|
||||
"__salt__": {
|
||||
"config.option": Mock(),
|
||||
"cmd.run_all": self.cmd_run_all_mock,
|
||||
"file.chown": Mock(),
|
||||
"file.remove": Mock(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def test_cluster_delete(self):
|
||||
deb_postgres.cluster_remove("9.3", "main")
|
||||
self.assertEqual(
|
||||
"/usr/bin/pg_dropcluster 9.3 main", self.cmd_run_all_mock.call_args[0][0]
|
||||
)
|
||||
deb_postgres.cluster_remove("9.3", "main", stop=True)
|
||||
self.assertEqual(
|
||||
"/usr/bin/pg_dropcluster --stop 9.3 main",
|
||||
self.cmd_run_all_mock.call_args[0][0],
|
||||
)
|
||||
deb_postgres.cluster_remove(9.3, "main", stop=True)
|
||||
self.assertEqual(
|
||||
"/usr/bin/pg_dropcluster --stop 9.3 main",
|
||||
self.cmd_run_all_mock.call_args[0][0],
|
||||
)
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue