mirror of
https://github.com/saltstack/salt.git
synced 2025-04-16 17:50:20 +00:00
Merge tag 'v3005.1' into merge-forward/3005.1
Version 3005.1
This commit is contained in:
commit
58ec510d26
92 changed files with 1940 additions and 710 deletions
10
.github/workflows/release.yml
vendored
10
.github/workflows/release.yml
vendored
|
@ -10,6 +10,10 @@ on:
|
|||
description: "Build Man Pages"
|
||||
default: true
|
||||
required: false
|
||||
branch:
|
||||
description: "Branch to build/push PR"
|
||||
default: "master"
|
||||
required: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
@ -36,6 +40,7 @@ jobs:
|
|||
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.inputs.branch }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Nox
|
||||
|
@ -101,6 +106,9 @@ jobs:
|
|||
apt-get install -y git/buster-backports
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.inputs.branch }}
|
||||
|
||||
|
||||
- id: changed-files
|
||||
if: github.event.inputs.manPages == 'true'
|
||||
|
@ -163,6 +171,7 @@ jobs:
|
|||
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.inputs.branch }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Download salt-man-pages
|
||||
|
@ -196,3 +205,4 @@ jobs:
|
|||
This PR is auto-generated by
|
||||
[create-pull-request](https://github.com/peter-evans/create-pull-request).
|
||||
branch: docs_${{ github.event.inputs.saltVersion }}
|
||||
base: ${{ github.event.inputs.branch }}
|
||||
|
|
25
CHANGELOG.md
25
CHANGELOG.md
|
@ -7,6 +7,31 @@ Versions are `MAJOR.PATCH`.
|
|||
|
||||
# Changelog
|
||||
|
||||
Salt 3005.1 (2022-09-26)
|
||||
========================
|
||||
|
||||
Fixed
|
||||
-----
|
||||
|
||||
- Fix arch parsing issue in apt source files (#62247)
|
||||
- Fixed parsing CDROM apt sources (#62474)
|
||||
- Use str() method instead of repo_line for when python3-apt is installed or not in aptpkg.py. (#62546)
|
||||
- Remove the connection_timeout from netmiko_connection_args before netmiko_connection_args is added to __context__["netmiko_device"]["args"] which is passed along to the Netmiko library. (#62547)
|
||||
- fixes #62553 by checking for disabled master_type before starting master connection and skipping it if set. (#62553)
|
||||
- Fix runas with cmd module when using the onedir bundled packages (#62565)
|
||||
- Fix the Pyinstaller hooks to preserve the environment if None is passed. (#62567, #62628)
|
||||
- pkgrepo.managed sets wrong permissions on keys installed to /etc/apt/keyring (#62569)
|
||||
- pkgrepo.managed creates zero byte gpg files when dearmoring contents to the same filename (#62570)
|
||||
- Ensure default values for IPC Buffers are correct type (#62591)
|
||||
- Fix a hang on salt-ssh when using sudo. (#62603)
|
||||
- Renderers now have access to the correct set of salt functions. (#62610, #62620)
|
||||
- Fix including Jinja template from absolute path (#62611)
|
||||
- include jmespath in package requirements (#62613)
|
||||
- Fix pkgrepo.managed signed-by in test=true mode (#62662)
|
||||
- Ensure the status of the service is captured when the beacon function is called, even when the event is not being emitted. (#62675)
|
||||
- The sub proxies controlled by Deltaproxy need to have their own req_channel otherwise there are timeout exceptions when the __master_req_channel_payload is fired and reacted on. (#62708)
|
||||
|
||||
|
||||
Salt 3005 (2022-08-22)
|
||||
======================
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-API" "1" "Jun 30, 2022" "3005" "Salt"
|
||||
.TH "SALT-API" "1" "Sep 26, 2022" "3005.1" "Salt"
|
||||
.SH NAME
|
||||
salt-api \- salt-api Command
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-CALL" "1" "Jun 30, 2022" "3005" "Salt"
|
||||
.TH "SALT-CALL" "1" "Sep 26, 2022" "3005.1" "Salt"
|
||||
.SH NAME
|
||||
salt-call \- salt-call Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-CLOUD" "1" "Jun 30, 2022" "3005" "Salt"
|
||||
.TH "SALT-CLOUD" "1" "Sep 26, 2022" "3005.1" "Salt"
|
||||
.SH NAME
|
||||
salt-cloud \- Salt Cloud Command
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-CP" "1" "Jun 30, 2022" "3005" "Salt"
|
||||
.TH "SALT-CP" "1" "Sep 26, 2022" "3005.1" "Salt"
|
||||
.SH NAME
|
||||
salt-cp \- salt-cp Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-KEY" "1" "Jun 30, 2022" "3005" "Salt"
|
||||
.TH "SALT-KEY" "1" "Sep 26, 2022" "3005.1" "Salt"
|
||||
.SH NAME
|
||||
salt-key \- salt-key Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-MASTER" "1" "Jun 30, 2022" "3005" "Salt"
|
||||
.TH "SALT-MASTER" "1" "Sep 26, 2022" "3005.1" "Salt"
|
||||
.SH NAME
|
||||
salt-master \- salt-master Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-MINION" "1" "Jun 30, 2022" "3005" "Salt"
|
||||
.TH "SALT-MINION" "1" "Sep 26, 2022" "3005.1" "Salt"
|
||||
.SH NAME
|
||||
salt-minion \- salt-minion Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-PROXY" "1" "Jun 30, 2022" "3005" "Salt"
|
||||
.TH "SALT-PROXY" "1" "Sep 26, 2022" "3005.1" "Salt"
|
||||
.SH NAME
|
||||
salt-proxy \- salt-proxy Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-RUN" "1" "Jun 30, 2022" "3005" "Salt"
|
||||
.TH "SALT-RUN" "1" "Sep 26, 2022" "3005.1" "Salt"
|
||||
.SH NAME
|
||||
salt-run \- salt-run Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-SSH" "1" "Jun 30, 2022" "3005" "Salt"
|
||||
.TH "SALT-SSH" "1" "Sep 26, 2022" "3005.1" "Salt"
|
||||
.SH NAME
|
||||
salt-ssh \- salt-ssh Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-SYNDIC" "1" "Jun 30, 2022" "3005" "Salt"
|
||||
.TH "SALT-SYNDIC" "1" "Sep 26, 2022" "3005.1" "Salt"
|
||||
.SH NAME
|
||||
salt-syndic \- salt-syndic Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT" "1" "Jun 30, 2022" "3005" "Salt"
|
||||
.TH "SALT" "1" "Sep 26, 2022" "3005.1" "Salt"
|
||||
.SH NAME
|
||||
salt \- salt
|
||||
.
|
||||
|
|
1803
doc/man/salt.7
1803
doc/man/salt.7
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SPM" "1" "Jun 30, 2022" "3005" "Salt"
|
||||
.TH "SPM" "1" "Sep 26, 2022" "3005.1" "Salt"
|
||||
.SH NAME
|
||||
spm \- Salt Package Manager Command
|
||||
.
|
||||
|
|
30
doc/topics/releases/3005.1.rst
Normal file
30
doc/topics/releases/3005.1.rst
Normal file
|
@ -0,0 +1,30 @@
|
|||
.. _release-3005-1:
|
||||
|
||||
=========================
|
||||
Salt 3005.1 Release Notes
|
||||
=========================
|
||||
|
||||
Version 3005.1 is a bug fix release for :ref:`3005 <release-3005>`.
|
||||
|
||||
|
||||
Fixed
|
||||
-----
|
||||
|
||||
- Fix arch parsing issue in apt source files (#62247)
|
||||
- Fixed parsing CDROM apt sources (#62474)
|
||||
- Use str() method instead of repo_line for when python3-apt is installed or not in aptpkg.py. (#62546)
|
||||
- Remove the connection_timeout from netmiko_connection_args before netmiko_connection_args is added to __context__["netmiko_device"]["args"] which is passed along to the Netmiko library. (#62547)
|
||||
- fixes #62553 by checking for disabled master_type before starting master connection and skipping it if set. (#62553)
|
||||
- Fix runas with cmd module when using the onedir bundled packages (#62565)
|
||||
- Fix the Pyinstaller hooks to preserve the environment if None is passed. (#62567, #62628)
|
||||
- pkgrepo.managed sets wrong permissions on keys installed to /etc/apt/keyring (#62569)
|
||||
- pkgrepo.managed creates zero byte gpg files when dearmoring contents to the same filename (#62570)
|
||||
- Ensure default values for IPC Buffers are correct type (#62591)
|
||||
- Fix a hang on salt-ssh when using sudo. (#62603)
|
||||
- Renderers now have access to the correct set of salt functions. (#62610, #62620)
|
||||
- Fix including Jinja template from absolute path (#62611)
|
||||
- include jmespath in package requirements (#62613)
|
||||
- Fix pkgrepo.managed signed-by in test=true mode (#62662)
|
||||
- Ensure the status of the service is captured when the beacon function is called, even when the event is not being emitted. (#62675)
|
||||
- The sub proxies controlled by Deltaproxy need to have their own req_channel otherwise there are timeout exceptions when the __master_req_channel_payload is fired and reacted on. (#62708)
|
||||
|
|
@ -21,6 +21,15 @@ node and the local ``salt-master`` daemon. This gives the Master node control
|
|||
over the Minion nodes attached to the ``salt-master`` daemon running on the
|
||||
Syndic node.
|
||||
|
||||
.. warning::
|
||||
|
||||
Salt does not officially support Syndic and :ref:`external auth or
|
||||
publisher_acl<acl-eauth>`. It's possible that it might work under certain
|
||||
circumstances, but comprehensive support is lacking. See `issue #62618 on
|
||||
GitHub <https://github.com/saltstack/salt/issues/62618>`_ for more
|
||||
information. Currently Syndic is only expected to work when running Salt as
|
||||
root, though work is scheduled to fix this in Salt 3006 (Sulfur).
|
||||
|
||||
Configuring the Syndic
|
||||
======================
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
Jinja2
|
||||
jmespath
|
||||
msgpack>=0.5,!=0.5.5
|
||||
PyYAML
|
||||
MarkupSafe
|
||||
|
|
|
@ -463,6 +463,7 @@ jinja2==3.0.3
|
|||
# moto
|
||||
jmespath==0.10.0
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -466,6 +466,7 @@ jinja2==3.1.0
|
|||
# moto
|
||||
jmespath==0.9.4
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -472,6 +472,7 @@ jinja2==3.0.3
|
|||
# sphinx
|
||||
jmespath==0.10.0
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -461,6 +461,7 @@ jinja2==3.1.0
|
|||
# moto
|
||||
jmespath==0.9.4
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -464,6 +464,7 @@ jinja2==3.0.3
|
|||
# moto
|
||||
jmespath==0.10.0
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -478,6 +478,7 @@ jinja2==3.1.0
|
|||
# moto
|
||||
jmespath==0.9.4
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -495,6 +495,7 @@ jinja2==2.11.3
|
|||
# moto
|
||||
jmespath==0.9.4
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -486,6 +486,7 @@ jinja2==3.0.3
|
|||
# moto
|
||||
jmespath==0.10.0
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -495,6 +495,7 @@ jinja2==3.0.3
|
|||
# sphinx
|
||||
jmespath==0.10.0
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -489,6 +489,7 @@ jinja2==3.0.3
|
|||
# moto
|
||||
jmespath==0.10.0
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -501,6 +501,7 @@ jinja2==3.0.3
|
|||
# moto
|
||||
jmespath==0.9.4
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -485,6 +485,7 @@ jinja2==3.0.3
|
|||
# napalm
|
||||
jmespath==0.10.0
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -492,6 +492,7 @@ jinja2==3.0.3
|
|||
# sphinx
|
||||
jmespath==0.10.0
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -484,6 +484,7 @@ jinja2==3.1.0
|
|||
# napalm
|
||||
jmespath==0.9.4
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -486,6 +486,7 @@ jinja2==3.0.3
|
|||
# napalm
|
||||
jmespath==0.10.0
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -499,6 +499,7 @@ jinja2==3.1.0
|
|||
# napalm
|
||||
jmespath==0.9.4
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -159,6 +159,7 @@ jinja2==3.1.0
|
|||
# moto
|
||||
jmespath==0.9.4
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -474,6 +474,7 @@ jinja2==3.0.3
|
|||
# napalm
|
||||
jmespath==0.10.0
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -483,6 +483,7 @@ jinja2==3.0.3
|
|||
# sphinx
|
||||
jmespath==0.10.0
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -474,6 +474,7 @@ jinja2==3.1.0
|
|||
# napalm
|
||||
jmespath==0.9.4
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -477,6 +477,7 @@ jinja2==3.0.3
|
|||
# napalm
|
||||
jmespath==0.10.0
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -489,6 +489,7 @@ jinja2==3.1.0
|
|||
# napalm
|
||||
jmespath==0.9.4
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -147,6 +147,7 @@ jinja2==3.1.0
|
|||
# moto
|
||||
jmespath==0.9.4
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -474,6 +474,7 @@ jinja2==3.0.3
|
|||
# napalm
|
||||
jmespath==0.10.0
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -479,6 +479,7 @@ jinja2==3.1.0
|
|||
# napalm
|
||||
jmespath==0.9.4
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -481,6 +481,7 @@ jinja2==3.0.3
|
|||
# sphinx
|
||||
jmespath==0.10.0
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -474,6 +474,7 @@ jinja2==3.1.0
|
|||
# napalm
|
||||
jmespath==0.9.4
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -475,6 +475,7 @@ jinja2==3.0.3
|
|||
# napalm
|
||||
jmespath==0.10.0
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -491,6 +491,7 @@ jinja2==3.1.0
|
|||
# napalm
|
||||
jmespath==0.9.4
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -147,6 +147,7 @@ jinja2==3.1.0
|
|||
# moto
|
||||
jmespath==0.9.4
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# boto3
|
||||
# botocore
|
||||
|
|
|
@ -47,6 +47,8 @@ jaraco.text==3.5.1
|
|||
# via jaraco.collections
|
||||
jinja2==3.1.0
|
||||
# via -r requirements/base.txt
|
||||
jmespath==1.0.1
|
||||
# via -r requirements/base.txt
|
||||
linode-python==1.1.1
|
||||
# via -r requirements/darwin.txt
|
||||
mako==1.2.2
|
||||
|
|
|
@ -39,6 +39,8 @@ jaraco.text==3.5.1
|
|||
# via jaraco.collections
|
||||
jinja2==3.1.0
|
||||
# via -r requirements/base.txt
|
||||
jmespath==1.0.1
|
||||
# via -r requirements/base.txt
|
||||
markupsafe==2.0.1
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
|
|
|
@ -39,6 +39,8 @@ jaraco.text==3.5.1
|
|||
# via jaraco.collections
|
||||
jinja2==3.1.0
|
||||
# via -r requirements/base.txt
|
||||
jmespath==1.0.1
|
||||
# via -r requirements/base.txt
|
||||
markupsafe==2.0.1
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
|
|
|
@ -41,6 +41,8 @@ jaraco.text==3.2.0
|
|||
# via jaraco.collections
|
||||
jinja2==2.11.3
|
||||
# via -r requirements/base.txt
|
||||
jmespath==0.10.0
|
||||
# via -r requirements/base.txt
|
||||
markupsafe==1.1.1
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
|
|
|
@ -43,6 +43,8 @@ jaraco.text==3.5.1
|
|||
# via jaraco.collections
|
||||
jinja2==3.0.3
|
||||
# via -r requirements/base.txt
|
||||
jmespath==0.10.0
|
||||
# via -r requirements/base.txt
|
||||
markupsafe==2.0.1
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
|
|
|
@ -41,6 +41,8 @@ jaraco.text==3.5.1
|
|||
# via jaraco.collections
|
||||
jinja2==3.1.0
|
||||
# via -r requirements/base.txt
|
||||
jmespath==1.0.1
|
||||
# via -r requirements/base.txt
|
||||
markupsafe==2.0.1
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
|
|
|
@ -39,6 +39,8 @@ jaraco.text==3.5.1
|
|||
# via jaraco.collections
|
||||
jinja2==3.1.0
|
||||
# via -r requirements/base.txt
|
||||
jmespath==1.0.1
|
||||
# via -r requirements/base.txt
|
||||
markupsafe==2.0.1
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
|
|
|
@ -53,6 +53,8 @@ jaraco.text==3.5.0
|
|||
# via jaraco.collections
|
||||
jinja2==3.1.0
|
||||
# via -r requirements/base.txt
|
||||
jmespath==1.0.1
|
||||
# via -r requirements/base.txt
|
||||
libnacl==1.8.0
|
||||
# via -r requirements/windows.txt
|
||||
lxml==4.9.1
|
||||
|
|
|
@ -41,6 +41,8 @@ jaraco.text==3.5.1
|
|||
# via jaraco.collections
|
||||
jinja2==3.1.0
|
||||
# via -r requirements/base.txt
|
||||
jmespath==1.0.1
|
||||
# via -r requirements/base.txt
|
||||
markupsafe==2.0.1
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
|
|
|
@ -39,6 +39,8 @@ jaraco.text==3.5.1
|
|||
# via jaraco.collections
|
||||
jinja2==3.1.0
|
||||
# via -r requirements/base.txt
|
||||
jmespath==1.0.1
|
||||
# via -r requirements/base.txt
|
||||
markupsafe==2.0.1
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
|
|
|
@ -51,6 +51,8 @@ jaraco.text==3.5.0
|
|||
# via jaraco.collections
|
||||
jinja2==3.1.0
|
||||
# via -r requirements/base.txt
|
||||
jmespath==1.0.1
|
||||
# via -r requirements/base.txt
|
||||
libnacl==1.8.0
|
||||
# via -r requirements/windows.txt
|
||||
lxml==4.9.1
|
||||
|
|
|
@ -49,6 +49,8 @@ jaraco.text==3.5.1
|
|||
# via jaraco.collections
|
||||
jinja2==3.1.0
|
||||
# via -r requirements/base.txt
|
||||
jmespath==1.0.1
|
||||
# via -r requirements/base.txt
|
||||
linode-python==1.1.1
|
||||
# via -r requirements/darwin.txt
|
||||
mako==1.2.2
|
||||
|
|
|
@ -41,6 +41,8 @@ jaraco.text==3.5.1
|
|||
# via jaraco.collections
|
||||
jinja2==3.1.0
|
||||
# via -r requirements/base.txt
|
||||
jmespath==1.0.1
|
||||
# via -r requirements/base.txt
|
||||
markupsafe==2.0.1
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
|
|
|
@ -39,6 +39,8 @@ jaraco.text==3.5.1
|
|||
# via jaraco.collections
|
||||
jinja2==3.1.0
|
||||
# via -r requirements/base.txt
|
||||
jmespath==1.0.1
|
||||
# via -r requirements/base.txt
|
||||
markupsafe==2.0.1
|
||||
# via
|
||||
# -r requirements/base.txt
|
||||
|
|
|
@ -51,6 +51,8 @@ jaraco.text==3.5.0
|
|||
# via jaraco.collections
|
||||
jinja2==3.1.0
|
||||
# via -r requirements/base.txt
|
||||
jmespath==1.0.1
|
||||
# via -r requirements/base.txt
|
||||
libnacl==1.8.0
|
||||
# via -r requirements/windows.txt
|
||||
lxml==4.9.1
|
||||
|
|
|
@ -142,9 +142,9 @@ def beacon(config):
|
|||
)
|
||||
if "onchangeonly" in service_config and service_config["onchangeonly"] is True:
|
||||
if service not in LAST_STATUS:
|
||||
LAST_STATUS[service] = ret_dict[service]
|
||||
if not service_config["emitatstartup"]:
|
||||
continue
|
||||
LAST_STATUS[service] = ret_dict[service]
|
||||
if service_config["delay"] > 0:
|
||||
LAST_STATUS[service]["time"] = currtime
|
||||
else:
|
||||
|
|
|
@ -23,8 +23,11 @@ SSH_PRIVATE_KEY_PASSWORD_PROMPT_RE = re.compile(r"Enter passphrase for key", re.
|
|||
|
||||
# sudo prompt is used to recognize sudo prompting for a password and should
|
||||
# therefore be fairly recognizable and unique
|
||||
SUDO_PROMPT = r"[salt:sudo:d11bd4221135c33324a6bdc09674146fbfdf519989847491e34a689369bbce23]passwd:"
|
||||
SUDO_PROMPT_RE = re.compile(SUDO_PROMPT, re.M)
|
||||
SUDO_PROMPT = "[salt:sudo:d11bd4221135c33324a6bdc09674146fbfdf519989847491e34a689369bbce23]passwd:"
|
||||
SUDO_PROMPT_RE = re.compile(
|
||||
r"\[salt:sudo:d11bd4221135c33324a6bdc09674146fbfdf519989847491e34a689369bbce23\]passwd:",
|
||||
re.M,
|
||||
)
|
||||
|
||||
# Keep these in sync with ./__init__.py
|
||||
RSTR = "_edbc7885e4f9aac9b83b35999b68d015148caf467b78fa39c05f669c0ff89878"
|
||||
|
@ -379,12 +382,16 @@ class Shell:
|
|||
if not cmd:
|
||||
return "", "No command or passphrase", 245
|
||||
|
||||
log_sanitize = None
|
||||
if self.passwd:
|
||||
log_sanitize = self.passwd
|
||||
term = salt.utils.vt.Terminal(
|
||||
self._split_cmd(cmd),
|
||||
log_stdout=True,
|
||||
log_stdout_level="trace",
|
||||
log_stderr=True,
|
||||
log_stderr_level="trace",
|
||||
log_sanitize=log_sanitize,
|
||||
stream_stdout=False,
|
||||
stream_stderr=False,
|
||||
)
|
||||
|
@ -398,11 +405,15 @@ class Shell:
|
|||
while term.has_unread_data:
|
||||
stdout, stderr = term.recv()
|
||||
if stdout:
|
||||
if self.passwd:
|
||||
stdout = stdout.replace(self.passwd, ("*" * 6))
|
||||
ret_stdout += stdout
|
||||
buff = old_stdout + stdout
|
||||
else:
|
||||
buff = stdout
|
||||
if stderr:
|
||||
if self.passwd:
|
||||
stderr = stderr.replace(self.passwd, ("*" * 6))
|
||||
ret_stderr += stderr
|
||||
if buff and RSTR_RE.search(buff):
|
||||
# We're getting results back, don't try to send passwords
|
||||
|
|
|
@ -40,7 +40,7 @@ class SSHState(salt.state.State):
|
|||
"""
|
||||
Load up the modules for remote compilation via ssh
|
||||
"""
|
||||
self.functions = salt.loader.ssh_wrapper(self.opts, None, context=self.context)
|
||||
self.functions = self.wrapper
|
||||
self.utils = salt.loader.utils(self.opts)
|
||||
self.serializers = salt.loader.serializers(self.opts)
|
||||
locals_ = salt.loader.minion_mods(self.opts, utils=self.utils)
|
||||
|
|
|
@ -97,9 +97,9 @@ def _gather_buffer_space():
|
|||
|
||||
# For the time being this will be a fixed calculation
|
||||
# TODO: Allow user configuration
|
||||
_DFLT_IPC_WBUFFER = _gather_buffer_space() * 0.5
|
||||
_DFLT_IPC_WBUFFER = int(_gather_buffer_space() * 0.5)
|
||||
# TODO: Reserved for future use
|
||||
_DFLT_IPC_RBUFFER = _gather_buffer_space() * 0.5
|
||||
_DFLT_IPC_RBUFFER = int(_gather_buffer_space() * 0.5)
|
||||
|
||||
VALID_OPTS = immutabletypes.freeze(
|
||||
{
|
||||
|
|
|
@ -372,6 +372,11 @@ def post_master_init(self, master):
|
|||
)
|
||||
_proxy_minion.subprocess_list = self.subprocess_list
|
||||
|
||||
# a long-running req channel
|
||||
_proxy_minion.req_channel = salt.transport.client.AsyncReqChannel.factory(
|
||||
proxyopts, io_loop=self.io_loop
|
||||
)
|
||||
|
||||
# And load the modules
|
||||
(
|
||||
_proxy_minion.functions,
|
||||
|
|
|
@ -1131,7 +1131,8 @@ class MinionManager(MinionBase):
|
|||
minion.setup_beacons(before_connect=True)
|
||||
if minion.opts.get("scheduler_before_connect", False):
|
||||
minion.setup_scheduler(before_connect=True)
|
||||
yield minion.connect_master(failed=failed)
|
||||
if minion.opts.get("master_type", "str") != "disable":
|
||||
yield minion.connect_master(failed=failed)
|
||||
minion.tune_in(start=False)
|
||||
self.minions.append(minion)
|
||||
break
|
||||
|
@ -2693,10 +2694,10 @@ class Minion(MinionBase):
|
|||
notify=data.get("notify", False),
|
||||
)
|
||||
elif tag.startswith("__master_req_channel_payload"):
|
||||
yield self.req_channel.send(
|
||||
yield _minion.req_channel.send(
|
||||
data,
|
||||
timeout=self._return_retry_timer(),
|
||||
tries=self.opts["return_retry_tries"],
|
||||
timeout=_minion._return_retry_timer(),
|
||||
tries=_minion.opts["return_retry_tries"],
|
||||
)
|
||||
elif tag.startswith("pillar_refresh"):
|
||||
yield _minion.pillar_refresh(
|
||||
|
|
|
@ -146,7 +146,15 @@ def _invalid(line):
|
|||
comment = line[idx + 1 :]
|
||||
line = line[:idx]
|
||||
|
||||
repo_line = line.strip().split()
|
||||
cdrom_match = re.match(r"(.*)(cdrom:.*/)(.*)", line.strip())
|
||||
if cdrom_match:
|
||||
repo_line = (
|
||||
[p.strip() for p in cdrom_match.group(1).split()]
|
||||
+ [cdrom_match.group(2).strip()]
|
||||
+ [p.strip() for p in cdrom_match.group(3).split()]
|
||||
)
|
||||
else:
|
||||
repo_line = line.strip().split()
|
||||
if (
|
||||
not repo_line
|
||||
or repo_line[0] not in ["deb", "deb-src", "rpm", "rpm-src"]
|
||||
|
@ -267,7 +275,7 @@ if not HAS_APT:
|
|||
opts_count = []
|
||||
opts_line = ""
|
||||
if architectures:
|
||||
architectures = "arch={}".format(" ".join(architectures))
|
||||
architectures = "arch={}".format(",".join(architectures))
|
||||
opts_count.append(architectures)
|
||||
if signedby:
|
||||
signedby = "signed-by={}".format(signedby)
|
||||
|
@ -1719,7 +1727,7 @@ def _get_opts(line):
|
|||
"""
|
||||
Return all opts in [] for a repo line
|
||||
"""
|
||||
get_opts = re.search(r"\[.*\]", line)
|
||||
get_opts = re.search(r"\[(.*=.*)\]", line)
|
||||
ret = {
|
||||
"arch": {"full": "", "value": "", "index": 0},
|
||||
"signedby": {"full": "", "value": "", "index": 0},
|
||||
|
@ -1851,7 +1859,6 @@ def list_repo_pkgs(*args, **kwargs): # pylint: disable=unused-import
|
|||
|
||||
ret = {}
|
||||
pkg_name = None
|
||||
skip_pkg = False
|
||||
new_pkg = re.compile("^Package: (.+)")
|
||||
for line in salt.utils.itertools.split(out["stdout"], "\n"):
|
||||
if not line.strip():
|
||||
|
@ -2287,13 +2294,11 @@ def _decrypt_key(key):
|
|||
key,
|
||||
)
|
||||
return False
|
||||
encrypted_key = key
|
||||
if not pathlib.Path(key).suffix:
|
||||
encrypted_key = key + ".gpg"
|
||||
cmd = ["gpg", "--yes", "--output", encrypted_key, "--dearmor", key]
|
||||
decrypted_key = str(key) + ".decrypted"
|
||||
cmd = ["gpg", "--yes", "--output", decrypted_key, "--dearmor", key]
|
||||
if not __salt__["cmd.run_all"](cmd)["retcode"] == 0:
|
||||
log.error("Failed to decrypt the key %s", key)
|
||||
return encrypted_key
|
||||
return decrypted_key
|
||||
except UnicodeDecodeError:
|
||||
log.debug("Key is not ASCII Armored. Do not need to decrypt")
|
||||
return key
|
||||
|
@ -2363,7 +2368,13 @@ def add_repo_key(
|
|||
cmd = ["apt-key"]
|
||||
kwargs = {}
|
||||
|
||||
current_repo_keys = get_repo_keys(aptkey=aptkey, keydir=keydir)
|
||||
# If the keyid is provided or determined, check it against the existing
|
||||
# repo key ids to determine whether it needs to be imported.
|
||||
if keyid:
|
||||
for current_keyid in get_repo_keys(aptkey=aptkey, keydir=keydir):
|
||||
if current_keyid[-(len(keyid)) :] == keyid:
|
||||
log.debug("The keyid '%s' already present: %s", keyid, current_keyid)
|
||||
return True
|
||||
|
||||
if path:
|
||||
cached_source_path = __salt__["cp.cache_file"](path, saltenv)
|
||||
|
@ -2376,7 +2387,13 @@ def add_repo_key(
|
|||
key = _decrypt_key(cached_source_path)
|
||||
if not key:
|
||||
return False
|
||||
cmd = ["cp", key, str(keydir)]
|
||||
key = pathlib.Path(str(key))
|
||||
if not keyfile:
|
||||
keyfile = key.name
|
||||
if keyfile.endswith(".decrypted"):
|
||||
keyfile = keyfile[:-10]
|
||||
shutil.copyfile(str(key), str(keydir / keyfile))
|
||||
return True
|
||||
else:
|
||||
cmd.extend(["add", cached_source_path])
|
||||
elif text:
|
||||
|
@ -2417,14 +2434,6 @@ def add_repo_key(
|
|||
"{}() takes at least 1 argument (0 given)".format(add_repo_key.__name__)
|
||||
)
|
||||
|
||||
# If the keyid is provided or determined, check it against the existing
|
||||
# repo key ids to determine whether it needs to be imported.
|
||||
if keyid:
|
||||
for current_keyid in current_repo_keys:
|
||||
if current_keyid[-(len(keyid)) :] == keyid:
|
||||
log.debug("The keyid '%s' already present: %s", keyid, current_keyid)
|
||||
return True
|
||||
|
||||
cmd_ret = _call_apt(cmd, **kwargs)
|
||||
|
||||
if cmd_ret["retcode"] == 0:
|
||||
|
@ -3091,14 +3100,21 @@ def expand_repo_def(**kwargs):
|
|||
if signedby not in sanitized["line"]:
|
||||
line = sanitized["line"].split()
|
||||
repo_opts = _get_opts(repo)
|
||||
opts_order = [x for x in repo_opts.keys()]
|
||||
opts_order = [
|
||||
opt_type
|
||||
for opt_type, opt_def in repo_opts.items()
|
||||
if opt_def["full"] != ""
|
||||
]
|
||||
for opt in repo_opts:
|
||||
if "index" in repo_opts[opt]:
|
||||
idx = repo_opts[opt]["index"]
|
||||
opts_order[idx] = repo_opts[opt]["full"]
|
||||
|
||||
opts = "[" + " ".join(opts_order) + "]"
|
||||
line[1] = opts
|
||||
if line[1].startswith("["):
|
||||
line[1] = opts
|
||||
else:
|
||||
line.insert(1, opts)
|
||||
sanitized["line"] = " ".join(line)
|
||||
|
||||
return sanitized
|
||||
|
|
|
@ -254,7 +254,8 @@ def show(commands, raw_text=True, **kwargs):
|
|||
Execute one or more show (non-configuration) commands.
|
||||
|
||||
commands
|
||||
The commands to be executed.
|
||||
The commands to be executed. Multiple commands should
|
||||
be specified as a list.
|
||||
|
||||
raw_text: ``True``
|
||||
Whether to return raw text or structured data.
|
||||
|
@ -290,7 +291,7 @@ def show(commands, raw_text=True, **kwargs):
|
|||
.. code-block:: bash
|
||||
|
||||
salt-call --local nxos_api.show 'show version'
|
||||
salt '*' nxos_api.show 'show bgp sessions' 'show processes' raw_text=False
|
||||
salt '*' nxos_api.show "['show bgp sessions','show processes']" raw_text=False
|
||||
salt 'regular-minion' nxos_api.show 'show interfaces' host=sw01.example.com username=test password=test
|
||||
"""
|
||||
ret = []
|
||||
|
|
|
@ -197,7 +197,7 @@ class SaltCacheLoader(BaseLoader):
|
|||
}
|
||||
environment.globals.update(tpldata)
|
||||
|
||||
if _template in self.cached:
|
||||
if _template in self.cached or os.path.exists(_template):
|
||||
# pylint: disable=cell-var-from-loop
|
||||
for spath in self.searchpath:
|
||||
filepath = os.path.join(spath, _template)
|
||||
|
|
|
@ -17,7 +17,7 @@ def clean_pyinstaller_vars(environ):
|
|||
Restore or cleanup PyInstaller specific environent variable behavior.
|
||||
"""
|
||||
if environ is None:
|
||||
environ = {}
|
||||
environ = dict(os.environ)
|
||||
# When Salt is bundled with tiamat, it MUST NOT contain LD_LIBRARY_PATH
|
||||
# when shelling out, or, at least the value of LD_LIBRARY_PATH set by
|
||||
# pyinstaller.
|
||||
|
|
|
@ -118,6 +118,7 @@ class Terminal:
|
|||
log_stdout_level="debug",
|
||||
log_stderr=None,
|
||||
log_stderr_level="debug",
|
||||
log_sanitize=None,
|
||||
# sys.stdXYZ streaming options
|
||||
stream_stdout=None,
|
||||
stream_stderr=None,
|
||||
|
@ -222,7 +223,16 @@ class Terminal:
|
|||
self.child_fd,
|
||||
self.child_fde,
|
||||
)
|
||||
if log_sanitize:
|
||||
if not isinstance(log_sanitize, str):
|
||||
raise RuntimeError("'log_sanitize' needs to be a str type")
|
||||
self.log_sanitize = log_sanitize
|
||||
else:
|
||||
self.log_sanitize = None
|
||||
|
||||
terminal_command = " ".join(self.args)
|
||||
if self.log_sanitize:
|
||||
terminal_command = terminal_command.replace(self.log_sanitize, ("*" * 6))
|
||||
if (
|
||||
'decode("base64")' in terminal_command
|
||||
or "base64.b64decode(" in terminal_command
|
||||
|
@ -580,6 +590,10 @@ class Terminal:
|
|||
|
||||
if self.stderr_logger:
|
||||
stripped = stderr.rstrip()
|
||||
if self.log_sanitize:
|
||||
stripped = stripped.replace(
|
||||
self.log_sanitize, ("*" * 6)
|
||||
)
|
||||
if stripped.startswith(os.linesep):
|
||||
stripped = stripped[len(os.linesep) :]
|
||||
if stripped:
|
||||
|
@ -613,6 +627,10 @@ class Terminal:
|
|||
|
||||
if self.stdout_logger:
|
||||
stripped = stdout.rstrip()
|
||||
if self.log_sanitize:
|
||||
stripped = stripped.replace(
|
||||
self.log_sanitize, ("*" * 6)
|
||||
)
|
||||
if stripped.startswith(os.linesep):
|
||||
stripped = stripped[len(os.linesep) :]
|
||||
if stripped:
|
||||
|
|
|
@ -606,6 +606,8 @@ def delta_proxy_minion_ids():
|
|||
return [
|
||||
"dummy_proxy_one",
|
||||
"dummy_proxy_two",
|
||||
"dummy_proxy_three",
|
||||
"dummy_proxy_four",
|
||||
]
|
||||
|
||||
|
||||
|
|
31
tests/pytests/functional/files/SALTSTACK-GPG-KEY.pub
Normal file
31
tests/pytests/functional/files/SALTSTACK-GPG-KEY.pub
Normal file
|
@ -0,0 +1,31 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: GnuPG v2
|
||||
|
||||
mQENBFOpvpgBCADkP656H41i8fpplEEB8IeLhugyC2rTEwwSclb8tQNYtUiGdna9
|
||||
m38kb0OS2DDrEdtdQb2hWCnswxaAkUunb2qq18vd3dBvlnI+C4/xu5ksZZkRj+fW
|
||||
tArNR18V+2jkwcG26m8AxIrT+m4M6/bgnSfHTBtT5adNfVcTHqiT1JtCbQcXmwVw
|
||||
WbqS6v/LhcsBE//SHne4uBCK/GHxZHhQ5jz5h+3vWeV4gvxS3Xu6v1IlIpLDwUts
|
||||
kT1DumfynYnnZmWTGc6SYyIFXTPJLtnoWDb9OBdWgZxXfHEcBsKGha+bXO+m2tHA
|
||||
gNneN9i5f8oNxo5njrL8jkCckOpNpng18BKXABEBAAG0MlNhbHRTdGFjayBQYWNr
|
||||
YWdpbmcgVGVhbSA8cGFja2FnaW5nQHNhbHRzdGFjay5jb20+iQE4BBMBAgAiBQJT
|
||||
qb6YAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRAOCKFJ3le/vhkqB/0Q
|
||||
WzELZf4d87WApzolLG+zpsJKtt/ueXL1W1KA7JILhXB1uyvVORt8uA9FjmE083o1
|
||||
yE66wCya7V8hjNn2lkLXboOUd1UTErlRg1GYbIt++VPscTxHxwpjDGxDB1/fiX2o
|
||||
nK5SEpuj4IeIPJVE/uLNAwZyfX8DArLVJ5h8lknwiHlQLGlnOu9ulEAejwAKt9CU
|
||||
4oYTszYM4xrbtjB/fR+mPnYh2fBoQO4d/NQiejIEyd9IEEMd/03AJQBuMux62tjA
|
||||
/NwvQ9eqNgLw9NisFNHRWtP4jhAOsshv1WW+zPzu3ozoO+lLHixUIz7fqRk38q8Q
|
||||
9oNR31KvrkSNrFbA3D89uQENBFOpvpgBCADJ79iH10AfAfpTBEQwa6vzUI3Eltqb
|
||||
9aZ0xbZV8V/8pnuU7rqM7Z+nJgldibFk4gFG2bHCG1C5aEH/FmcOMvTKDhJSFQUx
|
||||
uhgxttMArXm2c22OSy1hpsnVG68G32Nag/QFEJ++3hNnbyGZpHnPiYgej3FrerQJ
|
||||
zv456wIsxRDMvJ1NZQB3twoCqwapC6FJE2hukSdWB5yCYpWlZJXBKzlYz/gwD/Fr
|
||||
GL578WrLhKw3UvnJmlpqQaDKwmV2s7MsoZogC6wkHE92kGPG2GmoRD3ALjmCvN1E
|
||||
PsIsQGnwpcXsRpYVCoW7e2nW4wUf7IkFZ94yOCmUq6WreWI4NggRcFC5ABEBAAGJ
|
||||
AR8EGAECAAkFAlOpvpgCGwwACgkQDgihSd5Xv74/NggA08kEdBkiWWwJZUZEy7cK
|
||||
WWcgjnRuOHd4rPeT+vQbOWGu6x4bxuVf9aTiYkf7ZjVF2lPn97EXOEGFWPZeZbH4
|
||||
vdRFH9jMtP+rrLt6+3c9j0M8SIJYwBL1+CNpEC/BuHj/Ra/cmnG5ZNhYebm76h5f
|
||||
T9iPW9fFww36FzFka4VPlvA4oB7ebBtquFg3sdQNU/MmTVV4jPFWXxh4oRDDR+8N
|
||||
1bcPnbB11b5ary99F/mqr7RgQ+YFF0uKRE3SKa7a+6cIuHEZ7Za+zhPaQlzAOZlx
|
||||
fuBmScum8uQTrEF5+Um5zkwC7EXTdH1co/+/V/fpOtxIg4XO4kcugZefVm5ERfVS
|
||||
MA==
|
||||
=dtMN
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
|
@ -18,6 +18,11 @@ pytestmark = [
|
|||
pytest.mark.skip_if_binaries_missing("apt-cache", "grep"),
|
||||
]
|
||||
|
||||
KEY_FILES = (
|
||||
"salt-archive-keyring.gpg",
|
||||
"SALTSTACK-GPG-KEY.pub",
|
||||
)
|
||||
|
||||
|
||||
class Key:
|
||||
def __init__(self, aptkey=True):
|
||||
|
@ -35,13 +40,13 @@ class Key:
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def get_key_file(state_tree, functional_files_dir):
|
||||
def get_key_file(request, state_tree, functional_files_dir):
|
||||
"""
|
||||
Create the key file used for the repo
|
||||
Create the key file used for the repo by file name passed to the test
|
||||
"""
|
||||
key = Key()
|
||||
shutil.copy(str(functional_files_dir / key.keyname), str(state_tree))
|
||||
yield key.keyname
|
||||
keyname = request.param
|
||||
shutil.copy(str(functional_files_dir / keyname), str(state_tree))
|
||||
yield keyname
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -267,9 +272,10 @@ def add_key(request, get_key_file):
|
|||
key.del_key()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("get_key_file", KEY_FILES, indirect=True)
|
||||
@pytest.mark.parametrize("add_key", [False, True], indirect=True)
|
||||
@pytest.mark.destructive_test
|
||||
def test_get_repo_keys(add_key):
|
||||
def test_get_repo_keys(get_key_file, add_key):
|
||||
"""
|
||||
Test aptpkg.get_repo_keys when aptkey is False and True
|
||||
"""
|
||||
|
@ -294,17 +300,21 @@ def test_get_repo_keys_keydir_not_exist(key):
|
|||
assert ret
|
||||
|
||||
|
||||
@pytest.mark.parametrize("get_key_file", KEY_FILES, indirect=True)
|
||||
@pytest.mark.parametrize("aptkey", [False, True])
|
||||
def test_add_del_repo_key(get_key_file, aptkey):
|
||||
"""
|
||||
Test both add_repo_key and del_repo_key when
|
||||
aptkey is both False and True
|
||||
and using both binary and armored gpg keys
|
||||
"""
|
||||
try:
|
||||
assert aptpkg.add_repo_key("salt://{}".format(get_key_file), aptkey=aptkey)
|
||||
keyfile = pathlib.Path("/etc", "apt", "keyrings", get_key_file)
|
||||
if not aptkey:
|
||||
assert keyfile.is_file()
|
||||
assert oct(keyfile.stat().st_mode)[-3:] == "644"
|
||||
assert keyfile.read_bytes()
|
||||
query_key = aptpkg.get_repo_keys(aptkey=aptkey)
|
||||
assert (
|
||||
query_key["0E08A149DE57BFBE"]["uid"]
|
||||
|
|
|
@ -54,7 +54,7 @@ def test_adding_repo_file(pkgrepo, tmp_path):
|
|||
|
||||
|
||||
@pytest.mark.requires_salt_states("pkgrepo.managed")
|
||||
def test_adding_repo_file_arch(pkgrepo, tmp_path):
|
||||
def test_adding_repo_file_arch(pkgrepo, tmp_path, subtests):
|
||||
"""
|
||||
test adding a repo file using pkgrepo.managed
|
||||
and setting architecture
|
||||
|
@ -68,6 +68,35 @@ def test_adding_repo_file_arch(pkgrepo, tmp_path):
|
|||
file_content.strip()
|
||||
== "deb [arch=amd64] http://www.deb-multimedia.org stable main"
|
||||
)
|
||||
with subtests.test("With multiple archs"):
|
||||
repo_content = (
|
||||
"deb [arch=amd64,i386 ] http://www.deb-multimedia.org stable main"
|
||||
)
|
||||
pkgrepo.managed(name=repo_content, file=repo_file, clean_file=True)
|
||||
with salt.utils.files.fopen(repo_file, "r") as fp:
|
||||
file_content = fp.read()
|
||||
assert (
|
||||
file_content.strip()
|
||||
== "deb [arch=amd64,i386] http://www.deb-multimedia.org stable main"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.requires_salt_states("pkgrepo.managed")
|
||||
def test_adding_repo_file_cdrom(pkgrepo, tmp_path):
|
||||
"""
|
||||
test adding a repo file using pkgrepo.managed
|
||||
The issue is that CDROM installs often have [] in the line, and we
|
||||
should still add the repo even though it's not setting arch(for example)
|
||||
"""
|
||||
repo_file = str(tmp_path / "cdrom.list")
|
||||
repo_content = "deb cdrom:[Debian GNU/Linux 11.4.0 _Bullseye_ - Official amd64 NETINST 20220709-10:31]/ stable main"
|
||||
pkgrepo.managed(name=repo_content, file=repo_file, clean_file=True)
|
||||
with salt.utils.files.fopen(repo_file, "r") as fp:
|
||||
file_content = fp.read()
|
||||
assert (
|
||||
file_content.strip()
|
||||
== "deb cdrom:[Debian GNU/Linux 11.4.0 _Bullseye_ - Official amd64 NETINST 20220709-10:31]/ stable main"
|
||||
)
|
||||
|
||||
|
||||
def system_aptsources_ids(value):
|
||||
|
@ -576,7 +605,7 @@ class Repo:
|
|||
fullname = attr.ib()
|
||||
alt_repo = attr.ib(init=False)
|
||||
key_file = attr.ib()
|
||||
tmp_path = attr.ib()
|
||||
sources_list_file = attr.ib()
|
||||
repo_file = attr.ib()
|
||||
repo_content = attr.ib()
|
||||
key_url = attr.ib()
|
||||
|
@ -609,7 +638,7 @@ class Repo:
|
|||
|
||||
@repo_file.default
|
||||
def _default_repo_file(self):
|
||||
return self.tmp_path / "stable-binary.list"
|
||||
return self.sources_list_file
|
||||
|
||||
@repo_content.default
|
||||
def _default_repo_content(self):
|
||||
|
@ -649,35 +678,43 @@ class Repo:
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def repo(request, grains, tmp_path):
|
||||
def repo(request, grains, sources_list_file):
|
||||
signedby = False
|
||||
if "signedby" in request.node.name:
|
||||
signedby = True
|
||||
repo = Repo(grains=grains, tmp_path=tmp_path, signedby=signedby)
|
||||
repo = Repo(grains=grains, sources_list_file=sources_list_file, signedby=signedby)
|
||||
yield repo
|
||||
for key in [repo.key_file, repo.key_file.parent / "salt-alt-key.gpg"]:
|
||||
if key.is_file():
|
||||
key.unlink()
|
||||
|
||||
|
||||
def test_adding_repo_file_signedby(pkgrepo, states, repo):
|
||||
def test_adding_repo_file_signedby(pkgrepo, states, repo, subtests):
|
||||
"""
|
||||
Test adding a repo file using pkgrepo.managed
|
||||
and setting signedby
|
||||
"""
|
||||
ret = states.pkgrepo.managed(
|
||||
name=repo.repo_content,
|
||||
file=str(repo.repo_file),
|
||||
clean_file=True,
|
||||
signedby=str(repo.key_file),
|
||||
key_url=repo.key_url,
|
||||
aptkey=False,
|
||||
)
|
||||
|
||||
def _run(test=False):
|
||||
return states.pkgrepo.managed(
|
||||
name=repo.repo_content,
|
||||
file=str(repo.repo_file),
|
||||
clean_file=True,
|
||||
signedby=str(repo.key_file),
|
||||
key_url=repo.key_url,
|
||||
aptkey=False,
|
||||
test=test,
|
||||
)
|
||||
|
||||
ret = _run()
|
||||
with salt.utils.files.fopen(str(repo.repo_file), "r") as fp:
|
||||
file_content = fp.read()
|
||||
assert file_content.strip() == repo.repo_content
|
||||
assert repo.key_file.is_file()
|
||||
assert repo.repo_content in ret.comment
|
||||
with subtests.test("test=True"):
|
||||
ret = _run(test=True)
|
||||
assert ret.changes == {}
|
||||
|
||||
|
||||
def test_adding_repo_file_signedby_keyserver(pkgrepo, states, repo):
|
||||
|
|
26
tests/pytests/functional/test_config.py
Normal file
26
tests/pytests/functional/test_config.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
import pytest
|
||||
import salt.config
|
||||
|
||||
pytestmark = [
|
||||
pytest.mark.windows_whitelisted,
|
||||
]
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def test_minion_config_type_check(caplog):
|
||||
msg = "Config option 'ipc_write_buffer' with value"
|
||||
caplog.set_level(logging.WARNING)
|
||||
fd, path = tempfile.mkstemp()
|
||||
try:
|
||||
with os.fdopen(fd, "w") as tmp:
|
||||
tmp.write("ipc_write_buffer: 'dynamic'\n")
|
||||
salt.config.minion_config(path)
|
||||
|
||||
assert msg not in caplog.text
|
||||
finally:
|
||||
os.remove(path)
|
|
@ -17,8 +17,8 @@ def envvar(request):
|
|||
@pytest.fixture
|
||||
def meipass(envvar):
|
||||
with mock.patch("salt.utils.pyinstaller.rthooks._overrides.sys") as patched_sys:
|
||||
patched_sys._MEIPASS = envvar
|
||||
assert overrides.sys._MEIPASS == envvar
|
||||
patched_sys._MEIPASS = "{}_VALUE".format(envvar)
|
||||
assert overrides.sys._MEIPASS == "{}_VALUE".format(envvar)
|
||||
yield "{}_VALUE".format(envvar)
|
||||
assert not hasattr(sys, "_MEIPASS")
|
||||
assert not hasattr(overrides.sys, "_MEIPASS")
|
||||
|
@ -116,7 +116,7 @@ def test_vt_terminal_environ_cleanup(envvar, meipass):
|
|||
|
||||
def test_vt_terminal_environ_cleanup_passed_directly_not_removed(envvar, meipass):
|
||||
env = {
|
||||
envvar: meipass,
|
||||
envvar: envvar,
|
||||
}
|
||||
original_env = dict(os.environ)
|
||||
|
||||
|
@ -139,4 +139,4 @@ def test_vt_terminal_environ_cleanup_passed_directly_not_removed(envvar, meipass
|
|||
returned_env = json.loads(buffer_o)
|
||||
assert returned_env != original_env
|
||||
assert envvar in returned_env
|
||||
assert returned_env[envvar] == meipass
|
||||
assert returned_env[envvar] == envvar
|
||||
|
|
|
@ -18,8 +18,8 @@ def envvar(request):
|
|||
@pytest.fixture
|
||||
def meipass(envvar):
|
||||
with mock.patch("salt.utils.pyinstaller.rthooks._overrides.sys") as patched_sys:
|
||||
patched_sys._MEIPASS = envvar
|
||||
assert overrides.sys._MEIPASS == envvar
|
||||
patched_sys._MEIPASS = "{}_VALUE".format(envvar)
|
||||
assert overrides.sys._MEIPASS == "{}_VALUE".format(envvar)
|
||||
yield "{}_VALUE".format(envvar)
|
||||
assert not hasattr(sys, "_MEIPASS")
|
||||
assert not hasattr(overrides.sys, "_MEIPASS")
|
||||
|
@ -93,7 +93,7 @@ def test_subprocess_popen_environ_cleanup(envvar, meipass):
|
|||
|
||||
def test_subprocess_popen_environ_cleanup_passed_directly_not_removed(envvar, meipass):
|
||||
env = {
|
||||
envvar: meipass,
|
||||
envvar: envvar,
|
||||
}
|
||||
original_env = dict(os.environ)
|
||||
|
||||
|
@ -108,4 +108,4 @@ def test_subprocess_popen_environ_cleanup_passed_directly_not_removed(envvar, me
|
|||
returned_env = json.loads(stdout)
|
||||
assert returned_env != original_env
|
||||
assert envvar in returned_env
|
||||
assert returned_env[envvar] == meipass
|
||||
assert returned_env[envvar] == envvar
|
||||
|
|
|
@ -16,7 +16,13 @@ def deltaproxy_pillar_tree(salt_master, salt_delta_proxy_factory):
|
|||
"""
|
||||
Create the pillar files for controlproxy and two dummy proxy minions
|
||||
"""
|
||||
proxy_one, proxy_two = pytest.helpers.proxy.delta_proxy_minion_ids()
|
||||
(
|
||||
proxy_one,
|
||||
proxy_two,
|
||||
proxy_three,
|
||||
proxy_four,
|
||||
) = pytest.helpers.proxy.delta_proxy_minion_ids()
|
||||
|
||||
top_file = """
|
||||
base:
|
||||
{control}:
|
||||
|
@ -25,10 +31,16 @@ def deltaproxy_pillar_tree(salt_master, salt_delta_proxy_factory):
|
|||
- {one}
|
||||
{two}:
|
||||
- {two}
|
||||
{three}:
|
||||
- {three}
|
||||
{four}:
|
||||
- {four}
|
||||
""".format(
|
||||
control=salt_delta_proxy_factory.id,
|
||||
one=proxy_one,
|
||||
two=proxy_two,
|
||||
three=proxy_three,
|
||||
four=proxy_four,
|
||||
)
|
||||
controlproxy_pillar_file = """
|
||||
proxy:
|
||||
|
@ -36,16 +48,16 @@ def deltaproxy_pillar_tree(salt_master, salt_delta_proxy_factory):
|
|||
ids:
|
||||
- {}
|
||||
- {}
|
||||
- {}
|
||||
- {}
|
||||
""".format(
|
||||
proxy_one, proxy_two
|
||||
proxy_one,
|
||||
proxy_two,
|
||||
proxy_three,
|
||||
proxy_four,
|
||||
)
|
||||
|
||||
dummy_proxy_one_pillar_file = """
|
||||
proxy:
|
||||
proxytype: dummy
|
||||
"""
|
||||
|
||||
dummy_proxy_two_pillar_file = """
|
||||
dummy_proxy_pillar_file = """
|
||||
proxy:
|
||||
proxytype: dummy
|
||||
"""
|
||||
|
@ -55,12 +67,18 @@ def deltaproxy_pillar_tree(salt_master, salt_delta_proxy_factory):
|
|||
"controlproxy.sls", controlproxy_pillar_file
|
||||
)
|
||||
dummy_proxy_one_tempfile = salt_master.pillar_tree.base.temp_file(
|
||||
"{}.sls".format(proxy_one), dummy_proxy_one_pillar_file
|
||||
"{}.sls".format(proxy_one), dummy_proxy_pillar_file
|
||||
)
|
||||
dummy_proxy_two_tempfile = salt_master.pillar_tree.base.temp_file(
|
||||
"{}.sls".format(proxy_two), dummy_proxy_two_pillar_file
|
||||
"{}.sls".format(proxy_two), dummy_proxy_pillar_file
|
||||
)
|
||||
with top_tempfile, controlproxy_tempfile, dummy_proxy_one_tempfile, dummy_proxy_two_tempfile:
|
||||
dummy_proxy_three_tempfile = salt_master.pillar_tree.base.temp_file(
|
||||
"{}.sls".format(proxy_three), dummy_proxy_pillar_file
|
||||
)
|
||||
dummy_proxy_four_tempfile = salt_master.pillar_tree.base.temp_file(
|
||||
"{}.sls".format(proxy_four), dummy_proxy_pillar_file
|
||||
)
|
||||
with top_tempfile, controlproxy_tempfile, dummy_proxy_one_tempfile, dummy_proxy_two_tempfile, dummy_proxy_three_tempfile, dummy_proxy_four_tempfile:
|
||||
yield
|
||||
|
||||
|
||||
|
|
|
@ -25,7 +25,12 @@ def proxy_id(request, salt_delta_proxy, skip_on_tcp_transport):
|
|||
return request.param
|
||||
|
||||
|
||||
def test_can_it_ping(salt_cli, proxy_id):
|
||||
@pytest.fixture
|
||||
def proxy_ids(request, salt_delta_proxy, skip_on_tcp_transport):
|
||||
return pytest.helpers.proxy.delta_proxy_minion_ids()
|
||||
|
||||
|
||||
def test_can_it_ping(salt_cli, proxy_id, proxy_ids):
|
||||
"""
|
||||
Ensure the proxy can ping
|
||||
"""
|
||||
|
@ -33,6 +38,15 @@ def test_can_it_ping(salt_cli, proxy_id):
|
|||
assert ret.data is True
|
||||
|
||||
|
||||
def test_can_it_ping_all(salt_cli, proxy_ids):
|
||||
"""
|
||||
Ensure the proxy can ping (all proxy minions)
|
||||
"""
|
||||
ret = salt_cli.run("-L", "test.ping", minion_tgt=",".join(proxy_ids))
|
||||
for _id in proxy_ids:
|
||||
assert ret.data[_id] is True
|
||||
|
||||
|
||||
def test_list_pkgs(salt_cli, proxy_id):
|
||||
"""
|
||||
Package test 1, really just tests that the virtual function capability
|
||||
|
|
30
tests/pytests/integration/ssh/test_jinja_mods.py
Normal file
30
tests/pytests/integration/ssh/test_jinja_mods.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
import pytest
|
||||
from saltfactories.utils.functional import StateResult
|
||||
|
||||
pytestmark = [
|
||||
pytest.mark.skip_on_windows(reason="salt-ssh not available on Windows"),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_echo(salt_ssh_cli, base_env_state_tree_root_dir):
|
||||
"""
|
||||
verify salt-ssh can use imported map files in states
|
||||
"""
|
||||
name = "echo"
|
||||
echo = "hello"
|
||||
state_file = """
|
||||
ssh_test_echo:
|
||||
test.show_notification:
|
||||
- text: {{{{ salt['test.echo']('{echo}') }}}}
|
||||
""".format(
|
||||
echo=echo
|
||||
)
|
||||
state_tempfile = pytest.helpers.temp_file(
|
||||
"{}.sls".format(name), state_file, base_env_state_tree_root_dir
|
||||
)
|
||||
|
||||
with state_tempfile:
|
||||
ret = salt_ssh_cli.run("state.apply", name)
|
||||
result = StateResult(ret.data)
|
||||
assert result.comment == echo
|
|
@ -7,35 +7,6 @@ pytestmark = [
|
|||
]
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def test_opts_state_tree(base_env_state_tree_root_dir):
|
||||
top_file = """
|
||||
base:
|
||||
'localhost':
|
||||
- test_opts
|
||||
"""
|
||||
state_file = """
|
||||
{%- set is_test = salt['config.get']('test') %}
|
||||
|
||||
config.get check for is_test:
|
||||
cmd.run:
|
||||
- name: echo '{{ is_test }}'
|
||||
|
||||
opts.get check for test:
|
||||
cmd.run:
|
||||
- name: echo '{{ opts.get('test') }}'
|
||||
"""
|
||||
top_tempfile = pytest.helpers.temp_file(
|
||||
"top.sls", top_file, base_env_state_tree_root_dir
|
||||
)
|
||||
state_tempfile = pytest.helpers.temp_file(
|
||||
"test_opts.sls", state_file, base_env_state_tree_root_dir
|
||||
)
|
||||
|
||||
with top_tempfile, state_tempfile:
|
||||
yield
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def state_tree(base_env_state_tree_root_dir):
|
||||
top_file = """
|
||||
|
@ -125,33 +96,6 @@ def test_state_with_import_from_dir(salt_ssh_cli, nested_state_tree):
|
|||
assert ret.data
|
||||
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_state_opts_test(salt_ssh_cli, test_opts_state_tree):
|
||||
"""
|
||||
verify salt-ssh can get the value of test correctly
|
||||
"""
|
||||
|
||||
def _verify_output(ret):
|
||||
assert ret.returncode == 0
|
||||
assert (
|
||||
ret.data["cmd_|-config.get check for is_test_|-echo 'True'_|-run"]["name"]
|
||||
== "echo 'True'"
|
||||
)
|
||||
assert (
|
||||
ret.data["cmd_|-opts.get check for test_|-echo 'True'_|-run"]["name"]
|
||||
== "echo 'True'"
|
||||
)
|
||||
|
||||
ret = salt_ssh_cli.run("state.apply", "test_opts", "test=True")
|
||||
_verify_output(ret)
|
||||
|
||||
ret = salt_ssh_cli.run("state.highstate", "test=True")
|
||||
_verify_output(ret)
|
||||
|
||||
ret = salt_ssh_cli.run("state.top", "top.sls", "test=True")
|
||||
_verify_output(ret)
|
||||
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_state_low(salt_ssh_cli):
|
||||
"""
|
||||
|
|
|
@ -12,6 +12,7 @@ from pytestshellutils.utils import ports
|
|||
|
||||
import salt.utils.files
|
||||
import salt.utils.path
|
||||
import salt.utils.platform
|
||||
from salt.utils.versions import LooseVersion as _LooseVersion
|
||||
from tests.support.helpers import SKIP_INITIAL_PHOTONOS_FAILURES
|
||||
|
||||
|
@ -332,6 +333,7 @@ def test_issue_50221(
|
|||
assert target_path.read_text().replace("\r\n", "\n") == expected_content
|
||||
|
||||
|
||||
@pytest.mark.skip_if_not_root
|
||||
def test_issue_60426(
|
||||
salt_master,
|
||||
salt_call_cli,
|
||||
|
@ -1299,3 +1301,45 @@ def test_issue_62117(
|
|||
assert ret.data
|
||||
state_run = next(iter(ret.data.values()))
|
||||
assert state_run["result"] is True
|
||||
|
||||
|
||||
def test_issue_62611(
|
||||
salt_master,
|
||||
salt_call_cli,
|
||||
pillar_tree,
|
||||
tmp_path,
|
||||
salt_minion,
|
||||
):
|
||||
name = "test_jinja/issue-62611"
|
||||
|
||||
jinja_contents = '{% set myvar = "MOOP" -%}'
|
||||
|
||||
jinja_file = salt_master.state_tree.base.paths[0] / "{}.jinja".format(name)
|
||||
if salt.utils.platform.is_windows():
|
||||
jinja_file = str(jinja_file).replace("\\", "\\\\")
|
||||
|
||||
sls_contents = """
|
||||
{%- from "REPLACEME" import myvar with context %}
|
||||
|
||||
test_jinja/issue-62611/cmd.run:
|
||||
cmd.run:
|
||||
- name: echo MEEP {{ myvar }}
|
||||
""".replace(
|
||||
"REPLACEME", str(jinja_file)
|
||||
)
|
||||
|
||||
jinja_tempfile = salt_master.state_tree.base.temp_file(
|
||||
"{}.jinja".format(name), jinja_contents
|
||||
)
|
||||
|
||||
sls_tempfile = salt_master.state_tree.base.temp_file(
|
||||
"{}.sls".format(name), sls_contents
|
||||
)
|
||||
|
||||
with jinja_tempfile, sls_tempfile:
|
||||
ret = salt_call_cli.run("--local", "state.apply", name.replace("/", "."))
|
||||
assert ret.returncode == 0
|
||||
assert ret.data
|
||||
state_run = next(iter(ret.data.values()))
|
||||
assert state_run["name"] == "echo MEEP MOOP"
|
||||
assert state_run["result"] is True
|
||||
|
|
|
@ -68,14 +68,15 @@ def test_service_running():
|
|||
|
||||
assert ret == (True, "Valid beacon configuration")
|
||||
|
||||
ret = service_beacon.beacon(config)
|
||||
assert ret == [
|
||||
{
|
||||
"service_name": "salt-master",
|
||||
"tag": "salt-master",
|
||||
"salt-master": {"running": True},
|
||||
}
|
||||
]
|
||||
with patch.dict(service_beacon.LAST_STATUS, {}):
|
||||
ret = service_beacon.beacon(config)
|
||||
assert ret == [
|
||||
{
|
||||
"service_name": "salt-master",
|
||||
"tag": "salt-master",
|
||||
"salt-master": {"running": True},
|
||||
}
|
||||
]
|
||||
|
||||
# When onchangeonly is True and emitatstartup is False ,
|
||||
# we should not see a return when the beacon is run.
|
||||
|
@ -91,8 +92,13 @@ def test_service_running():
|
|||
|
||||
assert ret == (True, "Valid beacon configuration")
|
||||
|
||||
ret = service_beacon.beacon(config)
|
||||
assert ret == []
|
||||
# The return is empty because the beacon did not run
|
||||
# but the LAST_STATUS should contain the last status
|
||||
# for the service.
|
||||
with patch.dict(service_beacon.LAST_STATUS, {}):
|
||||
ret = service_beacon.beacon(config)
|
||||
assert "salt-master" in service_beacon.LAST_STATUS
|
||||
assert ret == []
|
||||
|
||||
# When onchangeonly is True and emitatstartup is
|
||||
# the default value True, we should see a return
|
||||
|
@ -103,14 +109,15 @@ def test_service_running():
|
|||
|
||||
assert ret == (True, "Valid beacon configuration")
|
||||
|
||||
ret = service_beacon.beacon(config)
|
||||
assert ret == [
|
||||
{
|
||||
"service_name": "salt-master",
|
||||
"tag": "salt-master",
|
||||
"salt-master": {"running": True},
|
||||
}
|
||||
]
|
||||
with patch.dict(service_beacon.LAST_STATUS, {}):
|
||||
ret = service_beacon.beacon(config)
|
||||
assert ret == [
|
||||
{
|
||||
"service_name": "salt-master",
|
||||
"tag": "salt-master",
|
||||
"salt-master": {"running": True},
|
||||
}
|
||||
]
|
||||
|
||||
# LAST_STATUS has service name and status has not changed
|
||||
config = [{"services": {"salt-master": {"onchangeonly": True}}}]
|
||||
|
@ -146,6 +153,29 @@ def test_service_running():
|
|||
}
|
||||
]
|
||||
|
||||
# When onchangeonly is True and emitatstartup is True,
|
||||
# we should see a return when the beacon is run.
|
||||
config = [
|
||||
{"services": {"salt-master": {"emitatstartup": True, "onchangeonly": True}}}
|
||||
]
|
||||
|
||||
ret = service_beacon.validate(config)
|
||||
|
||||
assert ret == (True, "Valid beacon configuration")
|
||||
|
||||
with patch.dict(service_beacon.LAST_STATUS, {}):
|
||||
ret = service_beacon.beacon(config)
|
||||
assert ret == [
|
||||
{
|
||||
"salt-master": {"running": True},
|
||||
"service_name": "salt-master",
|
||||
"tag": "salt-master",
|
||||
}
|
||||
]
|
||||
|
||||
ret = service_beacon.beacon(config)
|
||||
assert ret == []
|
||||
|
||||
|
||||
def test_service_not_running():
|
||||
with patch.dict(
|
||||
|
|
|
@ -4,6 +4,7 @@ import types
|
|||
import pytest
|
||||
|
||||
import salt.client.ssh.shell as shell
|
||||
from tests.support.mock import patch
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
@ -28,3 +29,26 @@ def test_ssh_shell_key_gen(keys):
|
|||
timeout=30,
|
||||
)
|
||||
assert ret.decode().startswith("ssh-rsa")
|
||||
|
||||
|
||||
@pytest.mark.skip_on_windows(reason="Windows does not support salt-ssh")
|
||||
@pytest.mark.skip_if_binaries_missing("ssh", "ssh-keygen", check_all=True)
|
||||
def test_ssh_shell_exec_cmd(caplog):
|
||||
"""
|
||||
Test executing a command and ensuring the password
|
||||
is not in the stdout/stderr logs.
|
||||
"""
|
||||
passwd = "12345"
|
||||
opts = {"_ssh_version": (4, 9)}
|
||||
host = ""
|
||||
_shell = shell.Shell(opts=opts, host=host)
|
||||
_shell.passwd = passwd
|
||||
with patch.object(_shell, "_split_cmd", return_value=["echo", passwd]):
|
||||
ret = _shell.exec_cmd("echo {}".format(passwd))
|
||||
assert not any([x for x in ret if passwd in str(x)])
|
||||
assert passwd not in caplog.text
|
||||
|
||||
with patch.object(_shell, "_split_cmd", return_value=["ls", passwd]):
|
||||
ret = _shell.exec_cmd("ls {}".format(passwd))
|
||||
assert not any([x for x in ret if passwd in str(x)])
|
||||
assert passwd not in caplog.text
|
||||
|
|
|
@ -853,8 +853,9 @@ def test__skip_source():
|
|||
assert ret is False
|
||||
|
||||
|
||||
def test__parse_source():
|
||||
cases = (
|
||||
@pytest.mark.parametrize(
|
||||
"case",
|
||||
(
|
||||
{"ok": False, "line": "", "invalid": True, "disabled": False},
|
||||
{"ok": False, "line": "#", "invalid": True, "disabled": True},
|
||||
{"ok": False, "line": "##", "invalid": True, "disabled": True},
|
||||
|
@ -881,19 +882,31 @@ def test__parse_source():
|
|||
"invalid": False,
|
||||
"disabled": False,
|
||||
},
|
||||
)
|
||||
{
|
||||
"ok": True,
|
||||
"line": (
|
||||
"# deb cdrom:[Debian GNU/Linux 11.4.0 _Bullseye_ - Official amd64 NETINST 20220709-10:31]/ bullseye main\n"
|
||||
"\n"
|
||||
"deb http://httpredir.debian.org/debian bullseye main\n"
|
||||
"deb-src http://httpredir.debian.org/debian bullseye main\n"
|
||||
),
|
||||
"invalid": False,
|
||||
"disabled": True,
|
||||
},
|
||||
),
|
||||
)
|
||||
def test__parse_source(case):
|
||||
with patch.dict("sys.modules", {"aptsources.sourceslist": None}):
|
||||
importlib.reload(aptpkg)
|
||||
NoAptSourceEntry = aptpkg.SourceEntry
|
||||
importlib.reload(aptpkg)
|
||||
|
||||
for case in cases:
|
||||
source = NoAptSourceEntry(case["line"])
|
||||
ok = source._parse_sources(case["line"])
|
||||
source = NoAptSourceEntry(case["line"])
|
||||
ok = source._parse_sources(case["line"])
|
||||
|
||||
assert ok is case["ok"]
|
||||
assert source.invalid is case["invalid"]
|
||||
assert source.disabled is case["disabled"]
|
||||
assert ok is case["ok"]
|
||||
assert source.invalid is case["invalid"]
|
||||
assert source.disabled is case["disabled"]
|
||||
|
||||
|
||||
def test_normalize_name():
|
||||
|
@ -949,16 +962,10 @@ def test_list_repos():
|
|||
assert repos[source_uri][0]["uri"][-1] == "/"
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
HAS_APTSOURCES is False, reason="The 'aptsources' library is missing."
|
||||
)
|
||||
def test_expand_repo_def():
|
||||
"""
|
||||
Checks results from expand_repo_def
|
||||
"""
|
||||
source_type = "deb"
|
||||
source_uri = "http://cdn-aws.deb.debian.org/debian/"
|
||||
source_line = "deb http://cdn-aws.deb.debian.org/debian/ stretch main\n"
|
||||
source_file = "/etc/apt/sources.list"
|
||||
|
||||
# Valid source
|
||||
|
@ -988,6 +995,40 @@ def test_expand_repo_def():
|
|||
)
|
||||
|
||||
|
||||
def test_expand_repo_def_cdrom():
|
||||
"""
|
||||
Checks results from expand_repo_def
|
||||
"""
|
||||
source_file = "/etc/apt/sources.list"
|
||||
|
||||
# Valid source
|
||||
repo = "# deb cdrom:[Debian GNU/Linux 11.4.0 _Bullseye_ - Official amd64 NETINST 20220709-10:31]/ bullseye main\n"
|
||||
sanitized = aptpkg.expand_repo_def(repo=repo, file=source_file)
|
||||
log.warning("SAN: %s", sanitized)
|
||||
|
||||
assert isinstance(sanitized, dict)
|
||||
assert "uri" in sanitized
|
||||
|
||||
# Make sure last character in of the URI is still a /
|
||||
assert sanitized["uri"][-1] == "/"
|
||||
|
||||
# Pass the architecture and make sure it is added the the line attribute
|
||||
repo = "deb http://cdn-aws.deb.debian.org/debian/ stretch main\n"
|
||||
sanitized = aptpkg.expand_repo_def(
|
||||
repo=repo, file=source_file, architectures="amd64"
|
||||
)
|
||||
|
||||
# Make sure line is in the dict
|
||||
assert isinstance(sanitized, dict)
|
||||
assert "line" in sanitized
|
||||
|
||||
# Make sure the architecture is in line
|
||||
assert (
|
||||
sanitized["line"]
|
||||
== "deb [arch=amd64] http://cdn-aws.deb.debian.org/debian/ stretch main"
|
||||
)
|
||||
|
||||
|
||||
def test_list_pkgs():
|
||||
"""
|
||||
Test packages listing.
|
||||
|
|
|
@ -1089,3 +1089,35 @@ def test_valid_ipv4_master_address_ipv6_enabled():
|
|||
"master_ip": "127.0.0.1",
|
||||
}
|
||||
assert salt.minion.resolve_dns(opts) == expected
|
||||
|
||||
|
||||
async def test_master_type_disable():
|
||||
"""
|
||||
Tests master_type "disable" to not even attempt connecting to a master.
|
||||
"""
|
||||
mock_opts = salt.config.DEFAULT_MINION_OPTS.copy()
|
||||
mock_opts.update(
|
||||
{
|
||||
"master_type": "disable",
|
||||
"master": None,
|
||||
"__role": "",
|
||||
"pub_ret": False,
|
||||
"file_client": "local",
|
||||
}
|
||||
)
|
||||
|
||||
minion = salt.minion.Minion(mock_opts)
|
||||
try:
|
||||
|
||||
try:
|
||||
minion_man = salt.minion.MinionManager(mock_opts)
|
||||
minion_man._connect_minion(minion)
|
||||
except RuntimeError:
|
||||
pytest.fail("_connect_minion(minion) threw an error, This was not expected")
|
||||
|
||||
# Make sure beacons and sheduler are initialized
|
||||
assert "beacons" in minion.periodic_callbacks
|
||||
assert "schedule" in minion.periodic_callbacks
|
||||
assert minion.connected is False
|
||||
finally:
|
||||
minion.destroy()
|
||||
|
|
|
@ -27,3 +27,26 @@ def test_isalive_no_child():
|
|||
aliveness = term.isalive()
|
||||
assert term.exitstatus == 0
|
||||
assert aliveness is False
|
||||
|
||||
|
||||
@pytest.mark.parametrize("test_cmd", ["echo", "ls"])
|
||||
@pytest.mark.skip_on_windows()
|
||||
def test_log_sanitize(test_cmd, caplog):
|
||||
"""
|
||||
test when log_sanitize is passed in
|
||||
we do not see the password in either
|
||||
standard out or standard error logs
|
||||
"""
|
||||
password = "123456"
|
||||
cmd = [test_cmd, password]
|
||||
term = vt.Terminal(
|
||||
cmd,
|
||||
log_stdout=True,
|
||||
log_stderr=True,
|
||||
log_sanitize=password,
|
||||
stream_stdout=False,
|
||||
stream_stderr=False,
|
||||
)
|
||||
ret = term.recv()
|
||||
assert password not in caplog.text
|
||||
assert "******" in caplog.text
|
||||
|
|
Loading…
Add table
Reference in a new issue