mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge branch '2017.7' into fix_48169
This commit is contained in:
commit
ead19725b6
78 changed files with 3632 additions and 520 deletions
9
.ci/docs
9
.ci/docs
|
@ -1,8 +1,13 @@
|
|||
pipeline {
|
||||
agent { label 'docs' }
|
||||
options {
|
||||
timestamps()
|
||||
ansiColor('xterm')
|
||||
}
|
||||
environment {
|
||||
PYENV_ROOT = "/usr/local/pyenv"
|
||||
PATH = "$PYENV_ROOT/bin:$PATH"
|
||||
PY_COLORS = 1
|
||||
}
|
||||
stages {
|
||||
stage('github-pending') {
|
||||
|
@ -22,11 +27,13 @@ pipeline {
|
|||
stage('build') {
|
||||
steps {
|
||||
sh 'eval "$(pyenv init -)"; make -C doc clean html'
|
||||
archiveArtifacts artifacts: 'doc/_build/html/'
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
cleanWs()
|
||||
}
|
||||
success {
|
||||
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||
description: 'The docs job has passed',
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
pipeline {
|
||||
agent { label 'kitchen-slave' }
|
||||
options {
|
||||
timestamps()
|
||||
ansiColor('xterm')
|
||||
}
|
||||
environment {
|
||||
SALT_KITCHEN_PLATFORMS = "/var/jenkins/workspace/platforms.yml"
|
||||
SALT_KITCHEN_DRIVER = "/var/jenkins/workspace/driver.yml"
|
||||
|
@ -7,6 +11,7 @@ pipeline {
|
|||
RBENV_VERSION = "2.4.2"
|
||||
TEST_SUITE = "py2"
|
||||
TEST_PLATFORM = "centos-7"
|
||||
PY_COLORS = 1
|
||||
}
|
||||
stages {
|
||||
stage('github-pending') {
|
||||
|
@ -31,21 +36,25 @@ pipeline {
|
|||
sh 'bundle exec kitchen verify $TEST_SUITE-$TEST_PLATFORM'
|
||||
}
|
||||
}}
|
||||
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
|
||||
}
|
||||
post {
|
||||
always {
|
||||
script { withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) {
|
||||
sshagent(credentials: ['jenkins-testing-ssh-key']) {
|
||||
sh 'ssh-add ~/.ssh/jenkins/jenkins-testing.pem'
|
||||
sh 'ssh-add ~/.ssh/jenkins-testing.pem'
|
||||
sh 'bundle exec kitchen destroy $TEST_SUITE-$TEST_PLATFORM'
|
||||
}
|
||||
}}
|
||||
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
junit 'artifacts/xml-unittests-output/*.xml'
|
||||
cleanWs()
|
||||
}
|
||||
success {
|
||||
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||
description: "The ${TEST_SUITE}-${TEST_PLATFORM} job has passed",
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
pipeline {
|
||||
agent { label 'kitchen-slave' }
|
||||
options {
|
||||
timestamps()
|
||||
ansiColor('xterm')
|
||||
}
|
||||
environment {
|
||||
SALT_KITCHEN_PLATFORMS = "/var/jenkins/workspace/platforms.yml"
|
||||
SALT_KITCHEN_DRIVER = "/var/jenkins/workspace/driver.yml"
|
||||
|
@ -7,6 +11,7 @@ pipeline {
|
|||
RBENV_VERSION = "2.4.2"
|
||||
TEST_SUITE = "py3"
|
||||
TEST_PLATFORM = "centos-7"
|
||||
PY_COLORS = 1
|
||||
}
|
||||
stages {
|
||||
stage('github-pending') {
|
||||
|
@ -31,21 +36,25 @@ pipeline {
|
|||
sh 'bundle exec kitchen verify $TEST_SUITE-$TEST_PLATFORM'
|
||||
}
|
||||
}}
|
||||
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
|
||||
}
|
||||
post {
|
||||
always {
|
||||
script { withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) {
|
||||
sshagent(credentials: ['jenkins-testing-ssh-key']) {
|
||||
sh 'ssh-add ~/.ssh/jenkins/jenkins-testing.pem'
|
||||
sh 'ssh-add ~/.ssh/jenkins-testing.pem'
|
||||
sh 'bundle exec kitchen destroy $TEST_SUITE-$TEST_PLATFORM'
|
||||
}
|
||||
}}
|
||||
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
junit 'artifacts/xml-unittests-output/*.xml'
|
||||
cleanWs()
|
||||
}
|
||||
success {
|
||||
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||
description: "The ${TEST_SUITE}-${TEST_PLATFORM} job has passed",
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
pipeline {
|
||||
agent { label 'kitchen-slave' }
|
||||
options {
|
||||
timestamps()
|
||||
ansiColor('xterm')
|
||||
}
|
||||
environment {
|
||||
SALT_KITCHEN_PLATFORMS = "/var/jenkins/workspace/platforms.yml"
|
||||
SALT_KITCHEN_DRIVER = "/var/jenkins/workspace/driver.yml"
|
||||
|
@ -7,6 +11,7 @@ pipeline {
|
|||
RBENV_VERSION = "2.4.2"
|
||||
TEST_SUITE = "py2"
|
||||
TEST_PLATFORM = "ubuntu-1604"
|
||||
PY_COLORS = 1
|
||||
}
|
||||
stages {
|
||||
stage('github-pending') {
|
||||
|
@ -31,21 +36,25 @@ pipeline {
|
|||
sh 'bundle exec kitchen verify $TEST_SUITE-$TEST_PLATFORM'
|
||||
}
|
||||
}}
|
||||
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
|
||||
}
|
||||
post {
|
||||
always {
|
||||
script { withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) {
|
||||
sshagent(credentials: ['jenkins-testing-ssh-key']) {
|
||||
sh 'ssh-add ~/.ssh/jenkins/jenkins-testing.pem'
|
||||
sh 'ssh-add ~/.ssh/jenkins-testing.pem'
|
||||
sh 'bundle exec kitchen destroy $TEST_SUITE-$TEST_PLATFORM'
|
||||
}
|
||||
}}
|
||||
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
junit 'artifacts/xml-unittests-output/*.xml'
|
||||
cleanWs()
|
||||
}
|
||||
success {
|
||||
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||
description: "The ${TEST_SUITE}-${TEST_PLATFORM} job has passed",
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
pipeline {
|
||||
agent { label 'kitchen-slave' }
|
||||
options {
|
||||
timestamps()
|
||||
ansiColor('xterm')
|
||||
}
|
||||
environment {
|
||||
SALT_KITCHEN_PLATFORMS = "/var/jenkins/workspace/platforms.yml"
|
||||
SALT_KITCHEN_DRIVER = "/var/jenkins/workspace/driver.yml"
|
||||
|
@ -7,6 +11,7 @@ pipeline {
|
|||
RBENV_VERSION = "2.4.2"
|
||||
TEST_SUITE = "py3"
|
||||
TEST_PLATFORM = "ubuntu-1604"
|
||||
PY_COLORS = 1
|
||||
}
|
||||
stages {
|
||||
stage('github-pending') {
|
||||
|
@ -31,21 +36,25 @@ pipeline {
|
|||
sh 'bundle exec kitchen verify $TEST_SUITE-$TEST_PLATFORM'
|
||||
}
|
||||
}}
|
||||
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
|
||||
}
|
||||
post {
|
||||
always {
|
||||
script { withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) {
|
||||
sshagent(credentials: ['jenkins-testing-ssh-key']) {
|
||||
sh 'ssh-add ~/.ssh/jenkins/jenkins-testing.pem'
|
||||
sh 'ssh-add ~/.ssh/jenkins-testing.pem'
|
||||
sh 'bundle exec kitchen destroy $TEST_SUITE-$TEST_PLATFORM'
|
||||
}
|
||||
}}
|
||||
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
junit 'artifacts/xml-unittests-output/*.xml'
|
||||
cleanWs()
|
||||
}
|
||||
success {
|
||||
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||
description: "The ${TEST_SUITE}-${TEST_PLATFORM} job has passed",
|
||||
|
|
23
.ci/lint
23
.ci/lint
|
@ -1,8 +1,13 @@
|
|||
pipeline {
|
||||
agent { label 'pr-lint-slave' }
|
||||
options {
|
||||
timestamps()
|
||||
ansiColor('xterm')
|
||||
}
|
||||
environment {
|
||||
PYENV_ROOT = "/usr/local/pyenv"
|
||||
PATH = "$PYENV_ROOT/bin:$PATH"
|
||||
PY_COLORS = 1
|
||||
}
|
||||
stages {
|
||||
stage('github-pending') {
|
||||
|
@ -16,8 +21,7 @@ pipeline {
|
|||
stage('setup') {
|
||||
steps {
|
||||
sh 'eval "$(pyenv init -)"; pyenv install 2.7.14 || echo "We already have this python."; pyenv local 2.7.14; pyenv shell 2.7.14'
|
||||
sh 'eval "$(pyenv init -)"; pip install pylint SaltPyLint'
|
||||
sh 'eval "$(pyenv init -)"; which pylint; pylint --version'
|
||||
sh 'eval "$(pyenv init -)"; pip install tox'
|
||||
}
|
||||
}
|
||||
stage('linting') {
|
||||
|
@ -25,13 +29,13 @@ pipeline {
|
|||
parallel {
|
||||
stage('salt linting') {
|
||||
steps {
|
||||
sh 'eval "$(pyenv init -)"; pylint --rcfile=.testing.pylintrc --disable=W1307,str-format-in-logging setup.py salt/ | tee pylint-report.xml'
|
||||
sh 'eval "$(pyenv init -)"; tox -e pylint-salt | tee pylint-report.xml'
|
||||
archiveArtifacts artifacts: 'pylint-report.xml'
|
||||
}
|
||||
}
|
||||
stage('test linting') {
|
||||
steps {
|
||||
sh 'eval "$(pyenv init -)"; pylint --rcfile=.testing.pylintrc --disable=W0232,E1002,W1307,str-format-in-logging tests/ | tee pylint-report-tests.xml'
|
||||
sh 'eval "$(pyenv init -)"; tox -e pylint-tests | tee pylint-report-tests.xml'
|
||||
archiveArtifacts artifacts: 'pylint-report-tests.xml'
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +43,17 @@ pipeline {
|
|||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
step([$class: 'WarningsPublisher',
|
||||
parserConfigurations: [[
|
||||
parserName: 'PyLint',
|
||||
pattern: 'pylint-report*.xml'
|
||||
]],
|
||||
failedTotalAll: '1',
|
||||
usePreviousBuildAsReference: true
|
||||
])
|
||||
cleanWs()
|
||||
}
|
||||
success {
|
||||
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||
description: 'The lint job has passed',
|
||||
|
|
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
|
@ -48,6 +48,7 @@ salt/spm/* @saltstack/team-spm
|
|||
# Team SSH
|
||||
salt/cli/ssh.py @saltstack/team-ssh
|
||||
salt/client/ssh/* @saltstack/team-ssh
|
||||
salt/roster/* @saltstack/team-ssh
|
||||
salt/runners/ssh.py @saltstack/team-ssh
|
||||
salt/**/thin.py @saltstack/team-ssh
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
<% vagrant = system('gem list -i kitchen-vagrant 2>/dev/null >/dev/null') %>
|
||||
<% version = '2017.7.4' %>
|
||||
<% version = '2017.7.6' %>
|
||||
<% platformsfile = ENV['SALT_KITCHEN_PLATFORMS'] || '.kitchen/platforms.yml' %>
|
||||
<% driverfile = ENV['SALT_KITCHEN_DRIVER'] || '.kitchen/driver.yml' %>
|
||||
<% verifierfile = ENV['SALT_KITCHEN_VERIFIER'] || '.kitchen/verifier.yml' %>
|
||||
|
@ -31,7 +31,7 @@ provisioner:
|
|||
salt_version: latest
|
||||
salt_bootstrap_url: https://bootstrap.saltstack.com
|
||||
salt_bootstrap_options: -X -p rsync stable <%= version %>
|
||||
log_level: debug
|
||||
log_level: info
|
||||
sudo: true
|
||||
require_chef: false
|
||||
retry_on_exit_code:
|
||||
|
|
|
@ -251,7 +251,7 @@ project = 'Salt'
|
|||
|
||||
version = salt.version.__version__
|
||||
latest_release = '2018.3.2' # latest release
|
||||
previous_release = '2017.7.6' # latest release from previous branch
|
||||
previous_release = '2017.7.7' # latest release from previous branch
|
||||
previous_release_dir = '2017.7' # path on web server for previous branch
|
||||
next_release = '' # next release
|
||||
next_release_dir = '' # path on web server for next release branch
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-API" "1" "May 07, 2018" "2017.7.6" "Salt"
|
||||
.TH "SALT-API" "1" "Jun 14, 2018" "2017.7.7" "Salt"
|
||||
.SH NAME
|
||||
salt-api \- salt-api Command
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-CALL" "1" "May 07, 2018" "2017.7.6" "Salt"
|
||||
.TH "SALT-CALL" "1" "Jun 14, 2018" "2017.7.7" "Salt"
|
||||
.SH NAME
|
||||
salt-call \- salt-call Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-CLOUD" "1" "May 07, 2018" "2017.7.6" "Salt"
|
||||
.TH "SALT-CLOUD" "1" "Jun 14, 2018" "2017.7.7" "Salt"
|
||||
.SH NAME
|
||||
salt-cloud \- Salt Cloud Command
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-CP" "1" "May 07, 2018" "2017.7.6" "Salt"
|
||||
.TH "SALT-CP" "1" "Jun 14, 2018" "2017.7.7" "Salt"
|
||||
.SH NAME
|
||||
salt-cp \- salt-cp Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-KEY" "1" "May 07, 2018" "2017.7.6" "Salt"
|
||||
.TH "SALT-KEY" "1" "Jun 14, 2018" "2017.7.7" "Salt"
|
||||
.SH NAME
|
||||
salt-key \- salt-key Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-MASTER" "1" "May 07, 2018" "2017.7.6" "Salt"
|
||||
.TH "SALT-MASTER" "1" "Jun 14, 2018" "2017.7.7" "Salt"
|
||||
.SH NAME
|
||||
salt-master \- salt-master Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-MINION" "1" "May 07, 2018" "2017.7.6" "Salt"
|
||||
.TH "SALT-MINION" "1" "Jun 14, 2018" "2017.7.7" "Salt"
|
||||
.SH NAME
|
||||
salt-minion \- salt-minion Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-PROXY" "1" "May 07, 2018" "2017.7.6" "Salt"
|
||||
.TH "SALT-PROXY" "1" "Jun 14, 2018" "2017.7.7" "Salt"
|
||||
.SH NAME
|
||||
salt-proxy \- salt-proxy Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-RUN" "1" "May 07, 2018" "2017.7.6" "Salt"
|
||||
.TH "SALT-RUN" "1" "Jun 14, 2018" "2017.7.7" "Salt"
|
||||
.SH NAME
|
||||
salt-run \- salt-run Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-SSH" "1" "May 07, 2018" "2017.7.6" "Salt"
|
||||
.TH "SALT-SSH" "1" "Jun 14, 2018" "2017.7.7" "Salt"
|
||||
.SH NAME
|
||||
salt-ssh \- salt-ssh Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-SYNDIC" "1" "May 07, 2018" "2017.7.6" "Salt"
|
||||
.TH "SALT-SYNDIC" "1" "Jun 14, 2018" "2017.7.7" "Salt"
|
||||
.SH NAME
|
||||
salt-syndic \- salt-syndic Documentation
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT-UNITY" "1" "May 07, 2018" "2017.7.6" "Salt"
|
||||
.TH "SALT-UNITY" "1" "Jun 14, 2018" "2017.7.7" "Salt"
|
||||
.SH NAME
|
||||
salt-unity \- salt-unity Command
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "SALT" "1" "May 07, 2018" "2017.7.6" "Salt"
|
||||
.TH "SALT" "1" "Jun 14, 2018" "2017.7.7" "Salt"
|
||||
.SH NAME
|
||||
salt \- salt
|
||||
.
|
||||
|
|
2559
doc/man/salt.7
2559
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" "May 07, 2018" "2017.7.6" "Salt"
|
||||
.TH "SPM" "1" "Jun 14, 2018" "2017.7.7" "Salt"
|
||||
.SH NAME
|
||||
spm \- Salt Package Manager Command
|
||||
.
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
========================================
|
||||
In Progress: Salt 2017.7.7 Release Notes
|
||||
========================================
|
||||
===========================
|
||||
Salt 2017.7.7 Release Notes
|
||||
===========================
|
||||
|
||||
Version 2017.7.7 is an **unreleased** bugfix release for :ref:`2017.7.0 <release-2017-7-0>`.
|
||||
This release is still in progress and has not been released yet.
|
||||
Version 2017.7.7 is a bugfix release for :ref:`2017.7.0 <release-2017-7-0>`.
|
||||
|
||||
The ``2017.7.7`` release contains only a small number of fixes, which are detailed
|
||||
below.
|
||||
|
|
|
@ -77,6 +77,7 @@ Function Get-Settings {
|
|||
"SSLeay" = "ssleay32.dll"
|
||||
"OpenSSLLic" = "OpenSSL_License.txt"
|
||||
"msvcr" = "msvcr120.dll"
|
||||
"Libsodium" = "libsodium.dll"
|
||||
}
|
||||
$ini.Add("64bitDLLs", $64bitDLLs)
|
||||
|
||||
|
@ -86,6 +87,7 @@ Function Get-Settings {
|
|||
"SSLeay" = "ssleay32.dll"
|
||||
"OpenSSLLic" = "OpenSSL_License.txt"
|
||||
"msvcr" = "msvcr120.dll"
|
||||
"Libsodium" = "libsodium.dll"
|
||||
}
|
||||
$ini.Add("32bitDLLs", $32bitDLLs)
|
||||
|
||||
|
|
|
@ -9,34 +9,36 @@ salt for Windows with their corresponding licenses:
|
|||
| certifi | ISC |
|
||||
| cffi | MIT |
|
||||
| CherryPy | BSD |
|
||||
| cryptography | BSD |
|
||||
| enum34 | BSD |
|
||||
| futures | BSD |
|
||||
| gitdb | BSD |
|
||||
| GitPython | BSD |
|
||||
| idna | BSD-like |
|
||||
| ioflo | Apache 2.0 |
|
||||
| ioloop | MIT |
|
||||
| ipaddress | PSF |
|
||||
| Jinja2 | BSD |
|
||||
| libnacl | --- |
|
||||
| libnacl | Apache |
|
||||
| lxml | BSD |
|
||||
| Mako | MIT |
|
||||
| MarkupSafe | BSD |
|
||||
| msgpack-python | --- |
|
||||
| msgpack-python | Apache 2.0 |
|
||||
| pip | MIT |
|
||||
| psutil | BSD |
|
||||
| pyasn1 | BSD |
|
||||
| pycparser | BSD |
|
||||
| pycurl | LGPL + MIT |
|
||||
| PyMySQL | MIT |
|
||||
| pypiwin32 | PSF |
|
||||
| PyOpenSSL | Apache 2.0 |
|
||||
| python-certifi-win32 | BSD |
|
||||
| python-dateutil | Simplified BSD |
|
||||
| python-gnupg | BSD |
|
||||
| pywin32 | PSF |
|
||||
| PyYAML | MIT |
|
||||
| pyzmq | LGPL + BSD |
|
||||
| requests | Apache 2.0 |
|
||||
| setuptools | MIT |
|
||||
| singledispatch | MIT |
|
||||
| six | MIT |
|
||||
| smmap | BSD |
|
||||
| timelib | ZLIB/PHP |
|
||||
| tornado | Apache 2.0 |
|
||||
|
|
|
@ -12,6 +12,7 @@ idna==2.5
|
|||
ioloop==0.1a0
|
||||
ipaddress==1.0.18
|
||||
Jinja2==2.9.6
|
||||
libnacl==1.6.1 # required by the nacl module
|
||||
lxml==3.7.3
|
||||
Mako==1.0.6
|
||||
MarkupSafe==1.0
|
||||
|
@ -23,6 +24,7 @@ pycrypto==2.6.1
|
|||
pycurl==7.43.0
|
||||
PyMySQL==0.7.11
|
||||
pyOpenSSL==17.0.0
|
||||
#python-certifi-win32==1.2
|
||||
python-dateutil==2.6.0
|
||||
python-gnupg==0.4.0
|
||||
pywin32==223
|
||||
|
|
|
@ -10,3 +10,4 @@ git+https://github.com/saltstack/pytest-salt.git@master#egg=pytest-salt
|
|||
# satisfy other requirements, and httpretty 0.8.10 has bugs in setup.py that
|
||||
# prevent it from being successfully installed (at least on Python 3.4).
|
||||
httpretty; python_version >= '3.4'
|
||||
pylint==1.6.5
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
-r base.txt
|
||||
|
||||
pycrypto>=2.6.1
|
||||
pyzmq>=2.2.0
|
||||
pyzmq>=2.2.0,<17.1.0; python_version == '3.4' # pyzmq 17.1.0 stopped building wheels for python3.4
|
||||
pyzmq>=2.2.0; python_version != '3.4'
|
||||
|
|
|
@ -221,7 +221,7 @@ class LocalClient(object):
|
|||
# Looks like the timeout is invalid, use config
|
||||
return self.opts['timeout']
|
||||
|
||||
def gather_job_info(self, jid, tgt, tgt_type, **kwargs):
|
||||
def gather_job_info(self, jid, tgt, tgt_type, listen=True, **kwargs):
|
||||
'''
|
||||
Return the information about a given job
|
||||
'''
|
||||
|
@ -233,6 +233,7 @@ class LocalClient(object):
|
|||
arg=[jid],
|
||||
tgt_type=tgt_type,
|
||||
timeout=timeout,
|
||||
listen=listen,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
|
|
|
@ -164,7 +164,7 @@ def salt_refs(data, ret=None):
|
|||
return ret
|
||||
|
||||
|
||||
def prep_trans_tar(opts, file_client, chunks, file_refs, pillar=None, id_=None):
|
||||
def prep_trans_tar(file_client, chunks, file_refs, pillar=None, id_=None):
|
||||
'''
|
||||
Generate the execution package from the saltenv file refs and a low state
|
||||
data structure
|
||||
|
|
|
@ -32,6 +32,59 @@ __func_alias__ = {
|
|||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _ssh_state(chunks, st_kwargs,
|
||||
kwargs, test=False):
|
||||
'''
|
||||
Function to run a state with the given chunk via salt-ssh
|
||||
'''
|
||||
file_refs = salt.client.ssh.state.lowstate_file_refs(
|
||||
chunks,
|
||||
_merge_extra_filerefs(
|
||||
kwargs.get('extra_filerefs', ''),
|
||||
__opts__.get('extra_filerefs', '')
|
||||
)
|
||||
)
|
||||
# Create the tar containing the state pkg and relevant files.
|
||||
trans_tar = salt.client.ssh.state.prep_trans_tar(
|
||||
__context__['fileclient'],
|
||||
chunks,
|
||||
file_refs,
|
||||
__pillar__,
|
||||
st_kwargs['id_'])
|
||||
trans_tar_sum = salt.utils.get_hash(trans_tar, __opts__['hash_type'])
|
||||
cmd = 'state.pkg {0}/salt_state.tgz test={1} pkg_sum={2} hash_type={3}'.format(
|
||||
__opts__['thin_dir'],
|
||||
test,
|
||||
trans_tar_sum,
|
||||
__opts__['hash_type'])
|
||||
single = salt.client.ssh.Single(
|
||||
__opts__,
|
||||
cmd,
|
||||
fsclient=__context__['fileclient'],
|
||||
minion_opts=__salt__.minion_opts,
|
||||
**st_kwargs)
|
||||
single.shell.send(
|
||||
trans_tar,
|
||||
'{0}/salt_state.tgz'.format(__opts__['thin_dir']))
|
||||
stdout, stderr, _ = single.cmd_block()
|
||||
|
||||
# Clean up our tar
|
||||
try:
|
||||
os.remove(trans_tar)
|
||||
except (OSError, IOError):
|
||||
pass
|
||||
|
||||
# Read in the JSON data and return the data structure
|
||||
try:
|
||||
return json.loads(stdout, object_hook=salt.utils.decode_dict)
|
||||
except Exception as e:
|
||||
log.error("JSON Render failed for: %s\n%s", stdout, stderr)
|
||||
log.error(str(e))
|
||||
|
||||
# If for some reason the json load fails, return the stdout
|
||||
return stdout
|
||||
|
||||
|
||||
def _set_retcode(ret, highstate=None):
|
||||
'''
|
||||
Set the return code based on the data back from the state system
|
||||
|
@ -156,7 +209,6 @@ def sls(mods, saltenv='base', test=None, exclude=None, **kwargs):
|
|||
# Create the tar containing the state pkg and relevant files.
|
||||
_cleanup_slsmod_low_data(chunks)
|
||||
trans_tar = salt.client.ssh.state.prep_trans_tar(
|
||||
__opts__,
|
||||
__context__['fileclient'],
|
||||
chunks,
|
||||
file_refs,
|
||||
|
@ -323,7 +375,6 @@ def low(data, **kwargs):
|
|||
)
|
||||
# Create the tar containing the state pkg and relevant files.
|
||||
trans_tar = salt.client.ssh.state.prep_trans_tar(
|
||||
__opts__,
|
||||
__context__['fileclient'],
|
||||
chunks,
|
||||
file_refs,
|
||||
|
@ -408,7 +459,6 @@ def high(data, **kwargs):
|
|||
# Create the tar containing the state pkg and relevant files.
|
||||
_cleanup_slsmod_low_data(chunks)
|
||||
trans_tar = salt.client.ssh.state.prep_trans_tar(
|
||||
__opts__,
|
||||
__context__['fileclient'],
|
||||
chunks,
|
||||
file_refs,
|
||||
|
@ -642,7 +692,6 @@ def highstate(test=None, **kwargs):
|
|||
# Create the tar containing the state pkg and relevant files.
|
||||
_cleanup_slsmod_low_data(chunks)
|
||||
trans_tar = salt.client.ssh.state.prep_trans_tar(
|
||||
__opts__,
|
||||
__context__['fileclient'],
|
||||
chunks,
|
||||
file_refs,
|
||||
|
@ -719,7 +768,6 @@ def top(topfn, test=None, **kwargs):
|
|||
# Create the tar containing the state pkg and relevant files.
|
||||
_cleanup_slsmod_low_data(chunks)
|
||||
trans_tar = salt.client.ssh.state.prep_trans_tar(
|
||||
__opts__,
|
||||
__context__['fileclient'],
|
||||
chunks,
|
||||
file_refs,
|
||||
|
@ -835,6 +883,7 @@ def sls_id(id_, mods, test=None, queue=False, **kwargs):
|
|||
|
||||
salt '*' state.sls_id my_state my_module,a_common_module
|
||||
'''
|
||||
st_kwargs = __salt__.kwargs
|
||||
conflict = _check_queue(queue, kwargs)
|
||||
if conflict is not None:
|
||||
return conflict
|
||||
|
@ -847,13 +896,11 @@ def sls_id(id_, mods, test=None, queue=False, **kwargs):
|
|||
if opts['environment'] is None:
|
||||
opts['environment'] = 'base'
|
||||
|
||||
try:
|
||||
st_ = salt.state.HighState(opts,
|
||||
proxy=__proxy__,
|
||||
initial_pillar=_get_initial_pillar(opts))
|
||||
except NameError:
|
||||
st_ = salt.state.HighState(opts,
|
||||
initial_pillar=_get_initial_pillar(opts))
|
||||
st_ = salt.client.ssh.state.SSHHighState(
|
||||
__opts__,
|
||||
__pillar__,
|
||||
__salt__,
|
||||
__context__['fileclient'])
|
||||
|
||||
if not _check_pillar(kwargs, st_.opts['pillar']):
|
||||
__context__['retcode'] = 5
|
||||
|
@ -864,10 +911,7 @@ def sls_id(id_, mods, test=None, queue=False, **kwargs):
|
|||
if isinstance(mods, six.string_types):
|
||||
split_mods = mods.split(',')
|
||||
st_.push_active()
|
||||
try:
|
||||
high_, errors = st_.render_highstate({opts['environment']: split_mods})
|
||||
finally:
|
||||
st_.pop_active()
|
||||
high_, errors = st_.render_highstate({opts['environment']: split_mods})
|
||||
errors += st_.state.verify_high(high_)
|
||||
# Apply requisites to high data
|
||||
high_, req_in_errors = st_.state.requisite_in(high_)
|
||||
|
@ -879,20 +923,22 @@ def sls_id(id_, mods, test=None, queue=False, **kwargs):
|
|||
__context__['retcode'] = 1
|
||||
return errors
|
||||
chunks = st_.state.compile_high_data(high_)
|
||||
ret = {}
|
||||
for chunk in chunks:
|
||||
if chunk.get('__id__', '') == id_:
|
||||
ret.update(st_.state.call_chunk(chunk, {}, chunks))
|
||||
chunk = [x for x in chunks if x.get('__id__', '') == id_]
|
||||
|
||||
_set_retcode(ret, highstate=highstate)
|
||||
# Work around Windows multiprocessing bug, set __opts__['test'] back to
|
||||
# value from before this function was run.
|
||||
__opts__['test'] = orig_test
|
||||
if not ret:
|
||||
if not chunk:
|
||||
raise SaltInvocationError(
|
||||
'No matches for ID \'{0}\' found in SLS \'{1}\' within saltenv '
|
||||
'\'{2}\''.format(id_, mods, opts['environment'])
|
||||
)
|
||||
|
||||
ret = _ssh_state(chunk,
|
||||
st_kwargs,
|
||||
kwargs,
|
||||
test=test)
|
||||
_set_retcode(ret, highstate=highstate)
|
||||
# Work around Windows multiprocessing bug, set __opts__['test'] back to
|
||||
# value from before this function was run.
|
||||
__opts__['test'] = orig_test
|
||||
return ret
|
||||
|
||||
|
||||
|
@ -1078,7 +1124,6 @@ def single(fun, name, test=None, **kwargs):
|
|||
|
||||
# Create the tar containing the state pkg and relevant files.
|
||||
trans_tar = salt.client.ssh.state.prep_trans_tar(
|
||||
__opts__,
|
||||
__context__['fileclient'],
|
||||
chunks,
|
||||
file_refs,
|
||||
|
|
|
@ -520,9 +520,17 @@ class AsyncAuth(object):
|
|||
error = SaltClientError('Detect mode is on')
|
||||
break
|
||||
if self.opts.get('caller'):
|
||||
print('Minion failed to authenticate with the master, '
|
||||
'has the minion key been accepted?')
|
||||
sys.exit(2)
|
||||
# We have a list of masters, so we should break
|
||||
# and try the next one in the list.
|
||||
if self.opts.get('local_masters', None):
|
||||
error = SaltClientError('Minion failed to authenticate'
|
||||
' with the master, has the '
|
||||
'minion key been accepted?')
|
||||
break
|
||||
else:
|
||||
print('Minion failed to authenticate with the master, '
|
||||
'has the minion key been accepted?')
|
||||
sys.exit(2)
|
||||
if acceptance_wait_time:
|
||||
log.info('Waiting {0} seconds before retry.'.format(acceptance_wait_time))
|
||||
yield tornado.gen.sleep(acceptance_wait_time)
|
||||
|
|
|
@ -64,10 +64,10 @@ if USE_IMPORTLIB:
|
|||
SUFFIXES = []
|
||||
for suffix in importlib.machinery.EXTENSION_SUFFIXES:
|
||||
SUFFIXES.append((suffix, 'rb', MODULE_KIND_EXTENSION))
|
||||
for suffix in importlib.machinery.BYTECODE_SUFFIXES:
|
||||
SUFFIXES.append((suffix, 'rb', MODULE_KIND_COMPILED))
|
||||
for suffix in importlib.machinery.SOURCE_SUFFIXES:
|
||||
SUFFIXES.append((suffix, 'rb', MODULE_KIND_SOURCE))
|
||||
for suffix in importlib.machinery.BYTECODE_SUFFIXES:
|
||||
SUFFIXES.append((suffix, 'rb', MODULE_KIND_COMPILED))
|
||||
MODULE_KIND_MAP = {
|
||||
MODULE_KIND_SOURCE: importlib.machinery.SourceFileLoader,
|
||||
MODULE_KIND_COMPILED: importlib.machinery.SourcelessFileLoader,
|
||||
|
|
|
@ -282,12 +282,14 @@ def raw_cron(user):
|
|||
# Preserve line endings
|
||||
lines = sdecode(__salt__['cmd.run_stdout'](cmd,
|
||||
runas=user,
|
||||
ignore_retcode=True,
|
||||
rstrip=False,
|
||||
python_shell=False)).splitlines(True)
|
||||
else:
|
||||
cmd = 'crontab -u {0} -l'.format(user)
|
||||
# Preserve line endings
|
||||
lines = sdecode(__salt__['cmd.run_stdout'](cmd,
|
||||
ignore_retcode=True,
|
||||
rstrip=False,
|
||||
python_shell=False)).splitlines(True)
|
||||
|
||||
|
|
|
@ -5235,7 +5235,6 @@ def _prepare_trans_tar(name, mods=None, saltenv='base', pillar=None):
|
|||
refs = salt.client.ssh.state.lowstate_file_refs(chunks)
|
||||
_mk_fileclient()
|
||||
trans_tar = salt.client.ssh.state.prep_trans_tar(
|
||||
__opts__,
|
||||
__context__['cp.fileclient'],
|
||||
chunks, refs, pillar, name)
|
||||
return trans_tar
|
||||
|
|
|
@ -84,6 +84,9 @@ def fire_master(data, tag, preload=None):
|
|||
channel = salt.transport.Channel.factory(__opts__, master_uri=master)
|
||||
try:
|
||||
channel.send(load)
|
||||
# channel.send was successful.
|
||||
# Ensure ret is True.
|
||||
ret = True
|
||||
except Exception:
|
||||
ret = False
|
||||
return ret
|
||||
|
|
|
@ -4262,26 +4262,6 @@ def check_perms(name, ret, user, group, mode, follow_symlinks=False):
|
|||
perms['lgroup'] = cur['group']
|
||||
perms['lmode'] = salt.utils.normalize_mode(cur['mode'])
|
||||
|
||||
# Mode changes if needed
|
||||
if mode is not None:
|
||||
# File is a symlink, ignore the mode setting
|
||||
# if follow_symlinks is False
|
||||
if os.path.islink(name) and not follow_symlinks:
|
||||
pass
|
||||
else:
|
||||
mode = salt.utils.normalize_mode(mode)
|
||||
if mode != perms['lmode']:
|
||||
if __opts__['test'] is True:
|
||||
ret['changes']['mode'] = mode
|
||||
else:
|
||||
set_mode(name, mode)
|
||||
if mode != salt.utils.normalize_mode(get_mode(name)):
|
||||
ret['result'] = False
|
||||
ret['comment'].append(
|
||||
'Failed to change mode to {0}'.format(mode)
|
||||
)
|
||||
else:
|
||||
ret['changes']['mode'] = mode
|
||||
# user/group changes if needed, then check if it worked
|
||||
if user:
|
||||
if isinstance(user, int):
|
||||
|
@ -4358,6 +4338,27 @@ def check_perms(name, ret, user, group, mode, follow_symlinks=False):
|
|||
elif 'cgroup' in perms and user != '':
|
||||
ret['changes']['group'] = group
|
||||
|
||||
# Mode changes if needed
|
||||
if mode is not None:
|
||||
# File is a symlink, ignore the mode setting
|
||||
# if follow_symlinks is False
|
||||
if os.path.islink(name) and not follow_symlinks:
|
||||
pass
|
||||
else:
|
||||
mode = salt.utils.normalize_mode(mode)
|
||||
if mode != perms['lmode']:
|
||||
if __opts__['test'] is True:
|
||||
ret['changes']['mode'] = mode
|
||||
else:
|
||||
set_mode(name, mode)
|
||||
if mode != salt.utils.normalize_mode(get_mode(name)):
|
||||
ret['result'] = False
|
||||
ret['comment'].append(
|
||||
'Failed to change mode to {0}'.format(mode)
|
||||
)
|
||||
else:
|
||||
ret['changes']['mode'] = mode
|
||||
|
||||
if isinstance(orig_comment, six.string_types):
|
||||
if orig_comment:
|
||||
ret['comment'].insert(0, orig_comment)
|
||||
|
@ -4484,6 +4485,11 @@ def check_managed_changes(
|
|||
defaults,
|
||||
skip_verify,
|
||||
**kwargs)
|
||||
|
||||
# Ensure that user-provided hash string is lowercase
|
||||
if source_sum and ('hsum' in source_sum):
|
||||
source_sum['hsum'] = source_sum['hsum'].lower()
|
||||
|
||||
if comments:
|
||||
__clean_tmp(sfn)
|
||||
return False, comments
|
||||
|
@ -4725,7 +4731,7 @@ def manage_file(name,
|
|||
source
|
||||
file reference on the master
|
||||
|
||||
source_hash
|
||||
source_sum
|
||||
sum hash for source
|
||||
|
||||
user
|
||||
|
|
|
@ -26,15 +26,16 @@ def __virtual__():
|
|||
return (False, 'glusterfs server is not installed')
|
||||
|
||||
|
||||
def _get_minor_version():
|
||||
# Set default version to 6 for tests
|
||||
version = 6
|
||||
def _get_version():
|
||||
# Set the default minor version to 6 for tests
|
||||
version = [3, 6]
|
||||
cmd = 'gluster --version'
|
||||
result = __salt__['cmd.run'](cmd).splitlines()
|
||||
for line in result:
|
||||
if line.startswith('glusterfs'):
|
||||
version = int(line.split()[1].split('.')[1])
|
||||
return version
|
||||
version = line.split()[-1].split('.')
|
||||
version = [int(i) for i in version]
|
||||
return tuple(version)
|
||||
|
||||
|
||||
def _gluster_ok(xml_data):
|
||||
|
@ -67,7 +68,7 @@ def _gluster_xml(cmd):
|
|||
# We will pass the command string as stdin to allow for much longer
|
||||
# command strings. This is especially useful for creating large volumes
|
||||
# where the list of bricks exceeds 128 characters.
|
||||
if _get_minor_version() < 6:
|
||||
if _get_version() < (3, 6,):
|
||||
result = __salt__['cmd.run'](
|
||||
'script -q -c "gluster --xml --mode=script"', stdin="{0}\n\004".format(cmd)
|
||||
)
|
||||
|
|
|
@ -160,7 +160,11 @@ def install(pkg=None,
|
|||
env.update({'SUDO_UID': uid, 'SUDO_USER': ''})
|
||||
|
||||
cmd = ' '.join(cmd)
|
||||
result = __salt__['cmd.run_all'](cmd, python_shell=True, cwd=dir, runas=runas, env=env)
|
||||
result = __salt__['cmd.run_all'](cmd,
|
||||
python_shell=True,
|
||||
cwd=dir,
|
||||
runas=runas,
|
||||
env=env)
|
||||
|
||||
if result['retcode'] != 0:
|
||||
raise CommandExecutionError(result['stderr'])
|
||||
|
@ -168,33 +172,9 @@ def install(pkg=None,
|
|||
# npm >1.2.21 is putting the output to stderr even though retcode is 0
|
||||
npm_output = result['stdout'] or result['stderr']
|
||||
try:
|
||||
return json.loads(npm_output)
|
||||
return salt.utils.find_json(npm_output)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
json_npm_output = _extract_json(npm_output)
|
||||
return json_npm_output or npm_output
|
||||
|
||||
|
||||
def _extract_json(npm_output):
|
||||
lines = npm_output.splitlines()
|
||||
log.error(lines)
|
||||
|
||||
# Strip all lines until JSON output starts
|
||||
while lines and not lines[0].startswith('{') and not lines[0].startswith('['):
|
||||
lines = lines[1:]
|
||||
while lines and not lines[-1].startswith('}') and not lines[-1].startswith(']'):
|
||||
lines = lines[:-1]
|
||||
# macOS with fsevents includes the following line in the return
|
||||
# when a new module is installed which is invalid JSON:
|
||||
# [fsevents] Success: "..."
|
||||
while lines and (lines[0].startswith('[fsevents]') or lines[0].startswith('Pass ')):
|
||||
lines = lines[1:]
|
||||
try:
|
||||
return json.loads(''.join(lines))
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
return npm_output
|
||||
|
||||
|
||||
def uninstall(pkg, dir=None, runas=None, env=None):
|
||||
|
|
|
@ -25,13 +25,13 @@ def __virtual__():
|
|||
'''
|
||||
if salt.utils.is_darwin() or salt.utils.is_windows():
|
||||
return True
|
||||
return (False, 'Module proxy: module only works on Windows or MacOS systems')
|
||||
return False, 'Module proxy: module only works on Windows or MacOS systems'
|
||||
|
||||
|
||||
def _get_proxy_osx(function, network_service):
|
||||
def _get_proxy_osx(cmd_function, network_service):
|
||||
ret = {}
|
||||
|
||||
out = __salt__['cmd.run']('networksetup -{0} {1}'.format(function, network_service))
|
||||
out = __salt__['cmd.run']('networksetup -{0} {1}'.format(cmd_function, network_service))
|
||||
match = re.match('Enabled: (.*)\nServer: (.*)\nPort: (.*)\n', out)
|
||||
if match is not None:
|
||||
g = match.groups()
|
||||
|
@ -41,8 +41,8 @@ def _get_proxy_osx(function, network_service):
|
|||
return ret
|
||||
|
||||
|
||||
def _set_proxy_osx(function, server, port, user, password, network_service):
|
||||
cmd = 'networksetup -{0} {1} {2} {3}'.format(function, network_service, server, port)
|
||||
def _set_proxy_osx(cmd_function, server, port, user, password, network_service):
|
||||
cmd = 'networksetup -{0} {1} {2} {3}'.format(cmd_function, network_service, server, port)
|
||||
|
||||
if user is not None and password is not None:
|
||||
cmd = cmd + ' On {0} {1}'.format(user, password)
|
||||
|
@ -58,12 +58,12 @@ def _get_proxy_windows(types=None):
|
|||
if types is None:
|
||||
types = ['http', 'https', 'ftp']
|
||||
|
||||
reg_val = __salt__['reg.read_value']('HKEY_CURRENT_USER',
|
||||
r'SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings',
|
||||
'ProxyServer')
|
||||
servers = reg_val['vdata']
|
||||
servers = __salt__['reg.read_value'](
|
||||
hive='HKEY_CURRENT_USER',
|
||||
key=r'SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings',
|
||||
vname='ProxyServer')['vdata']
|
||||
|
||||
if "=" in servers:
|
||||
if servers and "=" in servers:
|
||||
split = servers.split(";")
|
||||
for s in split:
|
||||
if len(s) == 0:
|
||||
|
@ -87,16 +87,19 @@ def _get_proxy_windows(types=None):
|
|||
del ret[key]
|
||||
|
||||
# Return enabled info
|
||||
reg_val = __salt__['reg.read_value']('HKEY_CURRENT_USER',
|
||||
r'SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings',
|
||||
'ProxyEnable')
|
||||
enabled = reg_val.get('vdata', 0)
|
||||
ret['enabled'] = True if enabled == 1 else False
|
||||
ret['enabled'] = __salt__['reg.read_value'](
|
||||
hive='HKEY_CURRENT_USER',
|
||||
key=r'SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings',
|
||||
vname='ProxyEnable')['vdata'] == 1
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def _set_proxy_windows(server, port, types=None, bypass_hosts=None, import_winhttp=True):
|
||||
def _set_proxy_windows(server,
|
||||
port,
|
||||
types=None,
|
||||
bypass_hosts=None,
|
||||
import_winhttp=True):
|
||||
if types is None:
|
||||
types = ['http', 'https', 'ftp']
|
||||
|
||||
|
@ -104,17 +107,27 @@ def _set_proxy_windows(server, port, types=None, bypass_hosts=None, import_winht
|
|||
for t in types:
|
||||
server_str += '{0}={1}:{2};'.format(t, server, port)
|
||||
|
||||
__salt__['reg.set_value']('HKEY_CURRENT_USER', r'SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings',
|
||||
'ProxyServer', server_str)
|
||||
__salt__['reg.set_value'](
|
||||
hive='HKEY_CURRENT_USER',
|
||||
key=r'SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings',
|
||||
vname='ProxyServer',
|
||||
vdata=server_str)
|
||||
|
||||
__salt__['reg.set_value']('HKEY_CURRENT_USER', r'SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings',
|
||||
'ProxyEnable', 1, vtype='REG_DWORD')
|
||||
__salt__['reg.set_value'](
|
||||
hive='HKEY_CURRENT_USER',
|
||||
key=r'SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings',
|
||||
vname='ProxyEnable',
|
||||
vdata=1,
|
||||
vtype='REG_DWORD')
|
||||
|
||||
if bypass_hosts is not None:
|
||||
bypass_hosts_str = '<local>;{0}'.format(';'.join(bypass_hosts))
|
||||
|
||||
__salt__['reg.set_value']('HKEY_CURRENT_USER', r'SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings',
|
||||
'ProxyOverride', bypass_hosts_str)
|
||||
__salt__['reg.set_value'](
|
||||
hive='HKEY_CURRENT_USER',
|
||||
key=r'SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings',
|
||||
vname='ProxyOverride',
|
||||
vdata=bypass_hosts_str)
|
||||
|
||||
if import_winhttp:
|
||||
cmd = 'netsh winhttp import proxy source=ie'
|
||||
|
@ -138,15 +151,22 @@ def get_http_proxy(network_service="Ethernet"):
|
|||
salt '*' proxy.get_http_proxy Ethernet
|
||||
'''
|
||||
if __grains__['os'] == 'Windows':
|
||||
return _get_proxy_windows(['http'])
|
||||
return _get_proxy_windows(types=['http'])
|
||||
|
||||
return _get_proxy_osx("getwebproxy", network_service)
|
||||
return _get_proxy_osx(cmd_function="getwebproxy",
|
||||
network_service=network_service)
|
||||
|
||||
|
||||
def set_http_proxy(server, port, user=None, password=None, network_service="Ethernet", bypass_hosts=None):
|
||||
def set_http_proxy(server,
|
||||
port,
|
||||
user=None,
|
||||
password=None,
|
||||
network_service="Ethernet",
|
||||
bypass_hosts=None):
|
||||
'''
|
||||
Sets the http proxy settings. Note: On Windows this will override any other proxy settings you have,
|
||||
the preferred method of updating proxies on windows is using set_proxy.
|
||||
Sets the http proxy settings. Note: On Windows this will override any other
|
||||
proxy settings you have, the preferred method of updating proxies on windows
|
||||
is using set_proxy.
|
||||
|
||||
server
|
||||
The proxy server to use
|
||||
|
@ -165,8 +185,8 @@ def set_http_proxy(server, port, user=None, password=None, network_service="Ethe
|
|||
macOS
|
||||
|
||||
bypass_hosts
|
||||
The hosts that are allowed to by pass the proxy. Only used on Windows for other OS's use
|
||||
set_proxy_bypass to edit the bypass hosts.
|
||||
The hosts that are allowed to by pass the proxy. Only used on Windows
|
||||
for other OS's use set_proxy_bypass to edit the bypass hosts.
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -175,9 +195,17 @@ def set_http_proxy(server, port, user=None, password=None, network_service="Ethe
|
|||
salt '*' proxy.set_http_proxy example.com 1080 user=proxy_user password=proxy_pass network_service=Ethernet
|
||||
'''
|
||||
if __grains__['os'] == 'Windows':
|
||||
return _set_proxy_windows(server, port, ['http'], bypass_hosts)
|
||||
return _set_proxy_windows(server=server,
|
||||
port=port,
|
||||
types=['http'],
|
||||
bypass_hosts=bypass_hosts)
|
||||
|
||||
return _set_proxy_osx("setwebproxy", server, port, user, password, network_service)
|
||||
return _set_proxy_osx(cmd_function="setwebproxy",
|
||||
server=server,
|
||||
port=port,
|
||||
user=user,
|
||||
password=password,
|
||||
network_service=network_service)
|
||||
|
||||
|
||||
def get_https_proxy(network_service="Ethernet"):
|
||||
|
@ -195,15 +223,22 @@ def get_https_proxy(network_service="Ethernet"):
|
|||
salt '*' proxy.get_https_proxy Ethernet
|
||||
'''
|
||||
if __grains__['os'] == 'Windows':
|
||||
return _get_proxy_windows(['https'])
|
||||
return _get_proxy_windows(types=['https'])
|
||||
|
||||
return _get_proxy_osx("getsecurewebproxy", network_service)
|
||||
return _get_proxy_osx(cmd_function="getsecurewebproxy",
|
||||
network_service=network_service)
|
||||
|
||||
|
||||
def set_https_proxy(server, port, user=None, password=None, network_service="Ethernet", bypass_hosts=None):
|
||||
def set_https_proxy(server,
|
||||
port,
|
||||
user=None,
|
||||
password=None,
|
||||
network_service="Ethernet",
|
||||
bypass_hosts=None):
|
||||
'''
|
||||
Sets the https proxy settings. Note: On Windows this will override any other proxy settings you have,
|
||||
the preferred method of updating proxies on windows is using set_proxy.
|
||||
Sets the https proxy settings. Note: On Windows this will override any other
|
||||
proxy settings you have, the preferred method of updating proxies on windows
|
||||
is using set_proxy.
|
||||
|
||||
server
|
||||
The proxy server to use
|
||||
|
@ -222,8 +257,8 @@ def set_https_proxy(server, port, user=None, password=None, network_service="Eth
|
|||
macOS
|
||||
|
||||
bypass_hosts
|
||||
The hosts that are allowed to by pass the proxy. Only used on Windows for other OS's use
|
||||
set_proxy_bypass to edit the bypass hosts.
|
||||
The hosts that are allowed to by pass the proxy. Only used on Windows
|
||||
for other OS's use set_proxy_bypass to edit the bypass hosts.
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -232,9 +267,17 @@ def set_https_proxy(server, port, user=None, password=None, network_service="Eth
|
|||
salt '*' proxy.set_https_proxy example.com 1080 user=proxy_user password=proxy_pass network_service=Ethernet
|
||||
'''
|
||||
if __grains__['os'] == 'Windows':
|
||||
return _set_proxy_windows(server, port, ['https'], bypass_hosts)
|
||||
return _set_proxy_windows(server=server,
|
||||
port=port,
|
||||
types=['https'],
|
||||
bypass_hosts=bypass_hosts)
|
||||
|
||||
return _set_proxy_osx("setsecurewebproxy", server, port, user, password, network_service)
|
||||
return _set_proxy_osx(cmd_function="setsecurewebproxy",
|
||||
server=server,
|
||||
port=port,
|
||||
user=user,
|
||||
password=password,
|
||||
network_service=network_service)
|
||||
|
||||
|
||||
def get_ftp_proxy(network_service="Ethernet"):
|
||||
|
@ -252,12 +295,18 @@ def get_ftp_proxy(network_service="Ethernet"):
|
|||
salt '*' proxy.get_ftp_proxy Ethernet
|
||||
'''
|
||||
if __grains__['os'] == 'Windows':
|
||||
return _get_proxy_windows(['ftp'])
|
||||
return _get_proxy_windows(types=['ftp'])
|
||||
|
||||
return _get_proxy_osx("getftpproxy", network_service)
|
||||
return _get_proxy_osx(cmd_function="getftpproxy",
|
||||
network_service=network_service)
|
||||
|
||||
|
||||
def set_ftp_proxy(server, port, user=None, password=None, network_service="Ethernet", bypass_hosts=None):
|
||||
def set_ftp_proxy(server,
|
||||
port,
|
||||
user=None,
|
||||
password=None,
|
||||
network_service="Ethernet",
|
||||
bypass_hosts=None):
|
||||
'''
|
||||
Sets the ftp proxy settings
|
||||
|
||||
|
@ -278,8 +327,8 @@ def set_ftp_proxy(server, port, user=None, password=None, network_service="Ether
|
|||
macOS
|
||||
|
||||
bypass_hosts
|
||||
The hosts that are allowed to by pass the proxy. Only used on Windows for other OS's use
|
||||
set_proxy_bypass to edit the bypass hosts.
|
||||
The hosts that are allowed to by pass the proxy. Only used on Windows
|
||||
for other OS's use set_proxy_bypass to edit the bypass hosts.
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -288,9 +337,17 @@ def set_ftp_proxy(server, port, user=None, password=None, network_service="Ether
|
|||
salt '*' proxy.set_ftp_proxy example.com 1080 user=proxy_user password=proxy_pass network_service=Ethernet
|
||||
'''
|
||||
if __grains__['os'] == 'Windows':
|
||||
return _set_proxy_windows(server, port, ['ftp'], bypass_hosts)
|
||||
return _set_proxy_windows(server=server,
|
||||
port=port,
|
||||
types=['ftp'],
|
||||
bypass_hosts=bypass_hosts)
|
||||
|
||||
return _set_proxy_osx("setftpproxy", server, port, user, password, network_service)
|
||||
return _set_proxy_osx(cmd_function="setftpproxy",
|
||||
server=server,
|
||||
port=port,
|
||||
user=user,
|
||||
password=password,
|
||||
network_service=network_service)
|
||||
|
||||
|
||||
def get_proxy_bypass(network_service="Ethernet"):
|
||||
|
@ -309,12 +366,16 @@ def get_proxy_bypass(network_service="Ethernet"):
|
|||
|
||||
'''
|
||||
if __grains__['os'] == 'Windows':
|
||||
reg_val = __salt__['reg.read_value']('HKEY_CURRENT_USER',
|
||||
r'SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings',
|
||||
'ProxyOverride')
|
||||
bypass_servers = reg_val['vdata'].replace("<local>", "").split(";")
|
||||
reg_val = __salt__['reg.read_value'](
|
||||
hive='HKEY_CURRENT_USER',
|
||||
key=r'SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings',
|
||||
vname='ProxyOverride')['vdata']
|
||||
|
||||
return bypass_servers
|
||||
# `reg.read_value` returns None if the key doesn't exist
|
||||
if reg_val is None:
|
||||
return []
|
||||
|
||||
return reg_val.replace('<local>', '').split(';')
|
||||
|
||||
out = __salt__['cmd.run']('networksetup -getproxybypassdomains {0}'.format(network_service))
|
||||
|
||||
|
@ -357,7 +418,12 @@ def set_proxy_win(server, port, types=None, bypass_hosts=None):
|
|||
The password to use if required by the server
|
||||
|
||||
types
|
||||
The types of proxy connections should be setup with this server. Valid types are http and https.
|
||||
The types of proxy connections should be setup with this server. Valid
|
||||
types are:
|
||||
|
||||
- ``http``
|
||||
- ``https``
|
||||
- ``ftp``
|
||||
|
||||
bypass_hosts
|
||||
The hosts that are allowed to by pass the proxy.
|
||||
|
@ -369,7 +435,10 @@ def set_proxy_win(server, port, types=None, bypass_hosts=None):
|
|||
salt '*' proxy.set_http_proxy example.com 1080 types="['http', 'https']"
|
||||
'''
|
||||
if __grains__['os'] == 'Windows':
|
||||
return _set_proxy_windows(server, port, types, bypass_hosts)
|
||||
return _set_proxy_windows(server=server,
|
||||
port=port,
|
||||
types=types,
|
||||
bypass_hosts=bypass_hosts)
|
||||
|
||||
|
||||
def get_proxy_win():
|
||||
|
|
|
@ -19,6 +19,7 @@ Module to provide redis functionality to Salt
|
|||
from __future__ import absolute_import
|
||||
from salt.ext.six.moves import zip
|
||||
from salt.ext import six
|
||||
from salt.utils import clean_kwargs
|
||||
from datetime import datetime
|
||||
|
||||
# Import third party libs
|
||||
|
@ -395,7 +396,7 @@ def hmset(key, **fieldsvals):
|
|||
database = fieldsvals.pop('db', None)
|
||||
password = fieldsvals.pop('password', None)
|
||||
server = _connect(host, port, database, password)
|
||||
return server.hmset(key, **fieldsvals)
|
||||
return server.hmset(key, clean_kwargs(**fieldsvals))
|
||||
|
||||
|
||||
def hset(key, field, value, host=None, port=None, db=None, password=None):
|
||||
|
|
|
@ -35,6 +35,7 @@ def __virtual__():
|
|||
'Devuan',
|
||||
'Arch',
|
||||
'Arch ARM',
|
||||
'Manjaro',
|
||||
'ALT',
|
||||
'SUSE Enterprise Server',
|
||||
'SUSE',
|
||||
|
|
|
@ -296,7 +296,7 @@ def _register_functions():
|
|||
modules_ = [module_ for module_ in modules.modules]
|
||||
|
||||
for mod_name in modules_:
|
||||
mod_name = _to_snake_case(module_)
|
||||
mod_name = _to_snake_case(mod_name)
|
||||
mod_func = _copy_function(mod_name, str(mod_name))
|
||||
mod_func.__doc__ = _build_doc(mod_name)
|
||||
__all__.append(mod_name)
|
||||
|
|
|
@ -683,7 +683,7 @@ def modify(name,
|
|||
win32service.SERVICE_QUERY_CONFIG)
|
||||
except pywintypes.error as exc:
|
||||
raise CommandExecutionError(
|
||||
'Failed To Open {0}: {1}'.format(name, exc[2]))
|
||||
'Failed To Open {0}: {1}'.format(name, exc))
|
||||
|
||||
config_info = win32service.QueryServiceConfig(handle_svc)
|
||||
|
||||
|
|
|
@ -581,6 +581,8 @@ def latest_version(*names, **kwargs):
|
|||
status = pkg_info.get('status', '').lower()
|
||||
if status.find('not installed') > -1 or status.find('out-of-date') > -1:
|
||||
ret[name] = pkg_info.get('version')
|
||||
else:
|
||||
ret[name] = ''
|
||||
|
||||
# Return a string if only one package name passed
|
||||
if len(names) == 1 and len(ret):
|
||||
|
|
|
@ -210,7 +210,7 @@ import tornado
|
|||
TORNADO_50 = tornado.version_info >= (5,)
|
||||
|
||||
if not TORNADO_50:
|
||||
import zmq.eventloop.ioloop
|
||||
import zmq.eventloop.ioloop # pylint: disable=import-error
|
||||
# instantiate the zmq IOLoop (specialized poller)
|
||||
zmq.eventloop.ioloop.install()
|
||||
|
||||
|
|
|
@ -923,6 +923,11 @@ class Pillar(object):
|
|||
decrypt_errors = self.decrypt_pillar(pillar)
|
||||
if decrypt_errors:
|
||||
pillar.setdefault('_errors', []).extend(decrypt_errors)
|
||||
|
||||
# Reset the file_roots for the renderers
|
||||
for mod_name in sys.modules:
|
||||
if mod_name.startswith('salt.loaded.int.render.'):
|
||||
sys.modules[mod_name].__opts__['file_roots'] = self.actual_file_roots
|
||||
return pillar
|
||||
|
||||
def decrypt_pillar(self, pillar):
|
||||
|
|
|
@ -150,7 +150,7 @@ def lookup_jid(jid,
|
|||
try:
|
||||
# Check if the return data has an 'out' key. We'll use that as the
|
||||
# outputter in the absence of one being passed on the CLI.
|
||||
outputter = data[next(iter(data))].get('out')
|
||||
outputter = returns[next(iter(returns))].get('out')
|
||||
except (StopIteration, AttributeError):
|
||||
outputter = None
|
||||
|
||||
|
|
|
@ -80,6 +80,8 @@ def _checksum_file_path(path):
|
|||
drive.rstrip(':'),
|
||||
path.lstrip('/\\'),
|
||||
)
|
||||
elif str(exc).startswith('Cannot mix UNC'):
|
||||
relpath = salt.utils.path_join('unc', path)
|
||||
else:
|
||||
raise
|
||||
ret = salt.utils.path_join(__opts__['cachedir'], 'archive_hash', relpath)
|
||||
|
|
|
@ -1396,19 +1396,25 @@ def symlink(
|
|||
preflight_errors = []
|
||||
if salt.utils.is_windows():
|
||||
# Make sure the passed owner exists
|
||||
if not salt.utils.win_functions.get_sid_from_name(win_owner):
|
||||
try:
|
||||
salt.utils.win_functions.get_sid_from_name(win_owner)
|
||||
except CommandExecutionError as exc:
|
||||
preflight_errors.append('User {0} does not exist'.format(win_owner))
|
||||
|
||||
# Make sure users passed in win_perms exist
|
||||
if win_perms:
|
||||
for name_check in win_perms:
|
||||
if not salt.utils.win_functions.get_sid_from_name(name_check):
|
||||
try:
|
||||
salt.utils.win_functions.get_sid_from_name(name_check)
|
||||
except CommandExecutionError as exc:
|
||||
preflight_errors.append('User {0} does not exist'.format(name_check))
|
||||
|
||||
# Make sure users passed in win_deny_perms exist
|
||||
if win_deny_perms:
|
||||
for name_check in win_deny_perms:
|
||||
if not salt.utils.win_functions.get_sid_from_name(name_check):
|
||||
try:
|
||||
salt.utils.win_functions.get_sid_from_name(name_check)
|
||||
except CommandExecutionError as exc:
|
||||
preflight_errors.append('User {0} does not exist'.format(name_check))
|
||||
else:
|
||||
uid = __salt__['file.user_to_uid'](user)
|
||||
|
@ -5663,7 +5669,7 @@ def copy(
|
|||
if not os.path.isdir(dname):
|
||||
if makedirs:
|
||||
try:
|
||||
_makedirs(name=name)
|
||||
_makedirs(name=name, user=user, group=group, dir_mode=mode)
|
||||
except CommandExecutionError as exc:
|
||||
return _error(ret, 'Drive {0} is not mapped'.format(exc.message))
|
||||
else:
|
||||
|
|
|
@ -72,9 +72,16 @@ def _changes(name,
|
|||
delusers = [salt.utils.win_functions.get_sam_name(user).lower() for user in delusers]
|
||||
|
||||
change = {}
|
||||
ret = {}
|
||||
if gid:
|
||||
if lgrp['gid'] != gid:
|
||||
change['gid'] = gid
|
||||
try:
|
||||
gid = int(gid)
|
||||
if lgrp['gid'] != gid:
|
||||
change['gid'] = gid
|
||||
except (TypeError, ValueError):
|
||||
ret['result'] = False
|
||||
ret['comment'] = 'Invalid gid'
|
||||
return ret
|
||||
|
||||
if members:
|
||||
# -- if new member list if different than the current
|
||||
|
|
|
@ -275,9 +275,13 @@ def bootstrap(name, user=None, silent=True):
|
|||
if __opts__['test']:
|
||||
try:
|
||||
call = __salt__['npm.install'](dir=name, runas=user, pkg=None, silent=silent, dry_run=True)
|
||||
ret['result'] = None
|
||||
ret['changes'] = {'old': [], 'new': call}
|
||||
ret['comment'] = '{0} is set to be bootstrapped'.format(name)
|
||||
if call:
|
||||
ret['result'] = None
|
||||
ret['changes'] = {'old': [], 'new': call}
|
||||
ret['comment'] = '{0} is set to be bootstrapped'.format(name)
|
||||
else:
|
||||
ret['result'] = True
|
||||
ret['comment'] = '{0} is already bootstrapped'.format(name)
|
||||
except (CommandNotFoundError, CommandExecutionError) as err:
|
||||
ret['result'] = False
|
||||
ret['comment'] = 'Error Bootstrapping \'{0}\': {1}'.format(name, err)
|
||||
|
|
|
@ -70,10 +70,9 @@ def _init_libcrypto():
|
|||
libcrypto.RSA_public_decrypt.argtypes = (c_int, c_char_p, c_char_p, c_void_p, c_int)
|
||||
|
||||
try:
|
||||
if libcrypto.OPENSSL_init_crypto(OPENSSL_INIT_NO_LOAD_CONFIG |
|
||||
OPENSSL_INIT_ADD_ALL_CIPHERS |
|
||||
OPENSSL_INIT_ADD_ALL_DIGESTS, None) != 1:
|
||||
raise OSError("Failed to initialize OpenSSL library (OPENSSL_init_crypto failed)")
|
||||
libcrypto.OPENSSL_init_crypto(OPENSSL_INIT_NO_LOAD_CONFIG |
|
||||
OPENSSL_INIT_ADD_ALL_CIPHERS |
|
||||
OPENSSL_INIT_ADD_ALL_DIGESTS, None)
|
||||
except AttributeError:
|
||||
# Support for OpenSSL < 1.1 (OPENSSL_API_COMPAT < 0x10100000L)
|
||||
libcrypto.OPENSSL_no_config()
|
||||
|
|
|
@ -156,20 +156,23 @@ def query(key, keyid, method='GET', params=None, headers=None,
|
|||
headers=headers,
|
||||
data=data,
|
||||
verify=verify_ssl,
|
||||
stream=True)
|
||||
stream=True,
|
||||
timeout=300)
|
||||
elif method == 'GET' and local_file and not return_bin:
|
||||
result = requests.request(method,
|
||||
requesturl,
|
||||
headers=headers,
|
||||
data=data,
|
||||
verify=verify_ssl,
|
||||
stream=True)
|
||||
stream=True,
|
||||
timeout=300)
|
||||
else:
|
||||
result = requests.request(method,
|
||||
requesturl,
|
||||
headers=headers,
|
||||
data=data,
|
||||
verify=verify_ssl)
|
||||
verify=verify_ssl,
|
||||
timeout=300)
|
||||
finally:
|
||||
if data is not None:
|
||||
data.close()
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
# Import python libs
|
||||
from __future__ import absolute_import
|
||||
# pylint: disable=blacklisted-module
|
||||
from distutils.version import StrictVersion as _StrictVersion
|
||||
from distutils.version import LooseVersion as _LooseVersion
|
||||
from distutils.version import StrictVersion as _StrictVersion # pylint: disable=no-name-in-module
|
||||
from distutils.version import LooseVersion as _LooseVersion # pylint: disable=no-name-in-module
|
||||
# pylint: enable=blacklisted-module
|
||||
|
||||
# Import 3rd-party libs
|
||||
|
|
|
@ -140,7 +140,7 @@ def accept_dict(match, include_rejected=False, include_denied=False):
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
>>> wheel.cmd('accept_dict',
|
||||
>>> wheel.cmd('key.accept_dict',
|
||||
{
|
||||
'minions_pre': [
|
||||
'jerry',
|
||||
|
|
4
setup.py
4
setup.py
|
@ -366,14 +366,14 @@ class DownloadWindowsDlls(Command):
|
|||
import pip
|
||||
# pip has moved many things to `_internal` starting with pip 10
|
||||
if LooseVersion(pip.__version__) < LooseVersion('10.0'):
|
||||
from pip.utils.logging import indent_log
|
||||
from pip.utils.logging import indent_log # pylint: disable=no-name-in-module
|
||||
else:
|
||||
from pip._internal.utils.logging import indent_log # pylint: disable=no-name-in-module
|
||||
platform_bits, _ = platform.architecture()
|
||||
url = 'https://repo.saltstack.com/windows/dependencies/{bits}/{fname}.dll'
|
||||
dest = os.path.join(os.path.dirname(sys.executable), '{fname}.dll')
|
||||
with indent_log():
|
||||
for fname in ('libeay32', 'ssleay32', 'msvcr120'):
|
||||
for fname in ('libeay32', 'libsodium', 'ssleay32', 'msvcr120'):
|
||||
# See if the library is already on the system
|
||||
if find_library(fname):
|
||||
continue
|
||||
|
|
1
tests/integration/files/file/base/hello_world.txt
Normal file
1
tests/integration/files/file/base/hello_world.txt
Normal file
|
@ -0,0 +1 @@
|
|||
Hello, World!
|
|
@ -3,3 +3,7 @@ ssh-file-test:
|
|||
file.managed:
|
||||
- name: /tmp/{{ jinja }}
|
||||
- contents: 'test'
|
||||
|
||||
second_id:
|
||||
cmd.run:
|
||||
- name: echo test
|
||||
|
|
|
@ -197,11 +197,12 @@ class MacServiceModuleTest(ModuleCase):
|
|||
self.assertFalse(
|
||||
self.run_function('service.disabled', [SERVICE_NAME]))
|
||||
|
||||
self.assertTrue(self.run_function('service.stop', [SERVICE_NAME]))
|
||||
self.assertTrue(self.run_function('service.disable', [SERVICE_NAME]))
|
||||
self.assertTrue(
|
||||
self.run_function('service.disabled', [SERVICE_NAME]))
|
||||
self.assertTrue(self.run_function('service.enable', [SERVICE_NAME]))
|
||||
|
||||
self.assertTrue(self.run_function('service.disabled', ['spongebob']))
|
||||
self.assertFalse(self.run_function('service.disabled', ['spongebob']))
|
||||
|
||||
def test_get_all(self):
|
||||
'''
|
||||
|
|
|
@ -11,7 +11,7 @@ import string
|
|||
# Import Salt Testing libs
|
||||
from tests.support.case import ModuleCase
|
||||
from tests.support.unit import skipIf
|
||||
from tests.support.helpers import destructiveTest, skip_if_not_root
|
||||
from tests.support.helpers import destructiveTest, skip_if_not_root, flaky
|
||||
|
||||
# Import salt libs
|
||||
import salt.utils
|
||||
|
@ -33,6 +33,7 @@ SET_SUBNET_NAME = __random_string()
|
|||
|
||||
|
||||
@skip_if_not_root
|
||||
@flaky
|
||||
@skipIf(not salt.utils.is_darwin(), 'Test only available on macOS')
|
||||
@skipIf(not salt.utils.which('systemsetup'), '\'systemsetup\' binary not found in $PATH')
|
||||
class MacSystemModuleTest(ModuleCase):
|
||||
|
|
|
@ -17,13 +17,14 @@ import datetime
|
|||
# Import Salt Testing libs
|
||||
from tests.support.case import ModuleCase
|
||||
from tests.support.unit import skipIf
|
||||
from tests.support.helpers import destructiveTest, skip_if_not_root
|
||||
from tests.support.helpers import destructiveTest, skip_if_not_root, flaky
|
||||
|
||||
# Import salt libs
|
||||
import salt.utils
|
||||
|
||||
|
||||
@skip_if_not_root
|
||||
@flaky
|
||||
@skipIf(not salt.utils.is_darwin(), 'Test only available on macOS')
|
||||
@skipIf(not salt.utils.which('systemsetup'), '\'systemsetup\' binary not found in $PATH')
|
||||
class MacTimezoneModuleTest(ModuleCase):
|
||||
|
|
|
@ -118,21 +118,21 @@ class ServiceModuleTest(ModuleCase):
|
|||
systemd = salt.utils.systemd.booted()
|
||||
|
||||
# check service was not enabled
|
||||
if systemd or salt.utils.is_windows():
|
||||
self.assertIn('ERROR', enable)
|
||||
else:
|
||||
try:
|
||||
self.assertFalse(enable)
|
||||
except AssertionError:
|
||||
self.assertIn('ERROR', enable)
|
||||
|
||||
# check service was not disabled
|
||||
if tuple(self.run_function('grains.item', ['osrelease_info'])['osrelease_info']) == (14, 0o4) and not systemd:
|
||||
# currently upstart does not have a mechanism to report if disabling a service fails if does not exist
|
||||
self.assertTrue(self.run_function('service.disable', [srv_name]))
|
||||
else:
|
||||
if salt.utils.is_windows():
|
||||
try:
|
||||
disable = self.run_function('service.disable', [srv_name])
|
||||
self.assertFalse(disable)
|
||||
except AssertionError:
|
||||
self.assertTrue('error' in disable.lower())
|
||||
else:
|
||||
self.assertFalse(self.run_function('service.disable', [srv_name]))
|
||||
|
||||
if salt.utils.is_darwin():
|
||||
self.assertFalse(self.run_function('service.disabled', [srv_name]))
|
||||
|
|
|
@ -382,3 +382,88 @@ class OrchEventTest(ShellCase):
|
|||
self.assertTrue(received)
|
||||
del listener
|
||||
signal.alarm(0)
|
||||
|
||||
def test_orchestration_with_pillar_dot_items(self):
|
||||
'''
|
||||
Test to confirm when using a state file that includes other state file, if
|
||||
one of those state files includes pillar related functions that will not
|
||||
be pulling from the pillar cache that all the state files are available and
|
||||
the file_roots has been preserved. See issues #48277 and #46986.
|
||||
'''
|
||||
self.write_conf({
|
||||
'fileserver_backend': ['roots'],
|
||||
'file_roots': {
|
||||
'base': [self.base_env],
|
||||
},
|
||||
})
|
||||
|
||||
orch_sls = os.path.join(self.base_env, 'main.sls')
|
||||
with salt.utils.fopen(orch_sls, 'w') as fp_:
|
||||
fp_.write(textwrap.dedent('''
|
||||
include:
|
||||
- one
|
||||
- two
|
||||
- three
|
||||
'''))
|
||||
|
||||
orch_sls = os.path.join(self.base_env, 'one.sls')
|
||||
with salt.utils.fopen(orch_sls, 'w') as fp_:
|
||||
fp_.write(textwrap.dedent('''
|
||||
{%- set foo = salt['saltutil.runner']('pillar.show_pillar') %}
|
||||
placeholder_one:
|
||||
test.succeed_without_changes
|
||||
'''))
|
||||
|
||||
orch_sls = os.path.join(self.base_env, 'two.sls')
|
||||
with salt.utils.fopen(orch_sls, 'w') as fp_:
|
||||
fp_.write(textwrap.dedent('''
|
||||
placeholder_two:
|
||||
test.succeed_without_changes
|
||||
'''))
|
||||
|
||||
orch_sls = os.path.join(self.base_env, 'three.sls')
|
||||
with salt.utils.fopen(orch_sls, 'w') as fp_:
|
||||
fp_.write(textwrap.dedent('''
|
||||
placeholder_three:
|
||||
test.succeed_without_changes
|
||||
'''))
|
||||
|
||||
orch_sls = os.path.join(self.base_env, 'main.sls')
|
||||
|
||||
listener = salt.utils.event.get_event(
|
||||
'master',
|
||||
sock_dir=self.master_opts['sock_dir'],
|
||||
transport=self.master_opts['transport'],
|
||||
opts=self.master_opts)
|
||||
|
||||
start_time = time.time()
|
||||
jid = self.run_run_plus(
|
||||
'state.orchestrate',
|
||||
'main',
|
||||
__reload_config=True).get('jid')
|
||||
|
||||
if jid is None:
|
||||
raise salt.exceptions.SaltInvocationError('jid missing from run_run_plus output')
|
||||
|
||||
signal.signal(signal.SIGALRM, self.alarm_handler)
|
||||
signal.alarm(self.timeout)
|
||||
received = False
|
||||
try:
|
||||
while True:
|
||||
event = listener.get_event(full=True)
|
||||
if event is None:
|
||||
continue
|
||||
if event.get('tag', '') == 'salt/run/{0}/ret'.format(jid):
|
||||
received = True
|
||||
# Don't wrap this in a try/except. We want to know if the
|
||||
# data structure is different from what we expect!
|
||||
ret = event['data']['return']['data']['master']
|
||||
for state in ret:
|
||||
data = ret[state]
|
||||
# Each state should be successful
|
||||
self.assertEqual(data['comment'], 'Success!')
|
||||
break
|
||||
finally:
|
||||
self.assertTrue(received)
|
||||
del listener
|
||||
signal.alarm(0)
|
||||
|
|
|
@ -24,9 +24,12 @@ class SSHStateTest(SSHCase):
|
|||
'''
|
||||
testing the state system with salt-ssh
|
||||
'''
|
||||
def _check_dict_ret(self, ret, val, exp_ret):
|
||||
def _check_dict_ret(self, ret, val, exp_ret, equal=True):
|
||||
for key, value in ret.items():
|
||||
self.assertEqual(value[val], exp_ret)
|
||||
if equal:
|
||||
self.assertEqual(value[val], exp_ret)
|
||||
else:
|
||||
self.assertNotEqual(value[val], exp_ret)
|
||||
|
||||
def _check_request(self, empty=False):
|
||||
check = self.run_function('state.check_request', wipe=False)
|
||||
|
@ -50,12 +53,31 @@ class SSHStateTest(SSHCase):
|
|||
'''
|
||||
test state.sls_id with salt-ssh
|
||||
'''
|
||||
# check state.sls_id with test=True
|
||||
ret = self.run_function('state.sls_id', ['ssh-file-test', SSH_SLS,
|
||||
'test=True'])
|
||||
self._check_dict_ret(ret=ret, val='comment',
|
||||
exp_ret='The file /tmp/test is set to be changed')
|
||||
|
||||
# check state.sls_id without test=True
|
||||
ret = self.run_function('state.sls_id', ['ssh-file-test', SSH_SLS])
|
||||
self._check_dict_ret(ret=ret, val='__sls__', exp_ret=SSH_SLS)
|
||||
|
||||
# make sure the other id in the state was not run
|
||||
self._check_dict_ret(ret=ret, val='__id__',
|
||||
exp_ret='second_id', equal=False)
|
||||
|
||||
check_file = self.run_function('file.file_exists', ['/tmp/test'])
|
||||
self.assertTrue(check_file)
|
||||
|
||||
def test_state_sls_wrong_id(self):
|
||||
'''
|
||||
test state.sls_id when id does not exist
|
||||
'''
|
||||
# check state.sls_id with test=True
|
||||
ret = self.run_function('state.sls_id', ['doesnotexist', SSH_SLS])
|
||||
assert 'No matches for ID' in ret
|
||||
|
||||
def test_state_show_sls(self):
|
||||
'''
|
||||
test state.show_sls with salt-ssh
|
||||
|
|
|
@ -25,6 +25,7 @@ from tests.support.case import ModuleCase
|
|||
from tests.support.unit import skipIf
|
||||
from tests.support.paths import FILES, TMP, TMP_STATE_TREE
|
||||
from tests.support.helpers import (
|
||||
destructiveTest,
|
||||
skip_if_not_root,
|
||||
with_system_user_and_group,
|
||||
with_tempfile,
|
||||
|
@ -137,6 +138,10 @@ class FileTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
'''
|
||||
remove files created in previous tests
|
||||
'''
|
||||
user = 'salt'
|
||||
if user in str(self.run_function('user.list_users', [user])):
|
||||
self.run_function('user.delete', [user])
|
||||
|
||||
for path in (FILEPILLAR, FILEPILLARDEF, FILEPILLARGIT):
|
||||
try:
|
||||
os.remove(path)
|
||||
|
@ -656,6 +661,57 @@ class FileTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
self.assertIn(
|
||||
'does not exist', ret['comment'])
|
||||
|
||||
def test_managed_source_hash_indifferent_case(self):
|
||||
'''
|
||||
Test passing a source_hash as an uppercase hash.
|
||||
|
||||
This is a regression test for Issue #38914 and Issue #48230 (test=true use).
|
||||
'''
|
||||
name = os.path.join(TMP, 'source_hash_indifferent_case')
|
||||
state_name = 'file_|-/tmp/salt-tests-tmpdir/source_hash_indifferent_case_|' \
|
||||
'-/tmp/salt-tests-tmpdir/source_hash_indifferent_case_|-managed'
|
||||
local_path = os.path.join(FILES, 'file', 'base', 'hello_world.txt')
|
||||
actual_hash = 'c98c24b677eff44860afea6f493bbaec5bb1c4cbb209c6fc2bbb47f66ff2ad31'
|
||||
uppercase_hash = actual_hash.upper()
|
||||
|
||||
try:
|
||||
# Lay down tmp file to test against
|
||||
self.run_state(
|
||||
'file.managed',
|
||||
name=name,
|
||||
source=local_path,
|
||||
source_hash=actual_hash
|
||||
)
|
||||
|
||||
# Test uppercase source_hash: should return True with no changes
|
||||
ret = self.run_state(
|
||||
'file.managed',
|
||||
name=name,
|
||||
source=local_path,
|
||||
source_hash=uppercase_hash
|
||||
)
|
||||
assert ret[state_name]['result'] is True
|
||||
assert ret[state_name]['pchanges'] == {}
|
||||
assert ret[state_name]['changes'] == {}
|
||||
|
||||
# Test uppercase source_hash using test=true
|
||||
# Should return True with no changes
|
||||
ret = self.run_state(
|
||||
'file.managed',
|
||||
name=name,
|
||||
source=local_path,
|
||||
source_hash=uppercase_hash,
|
||||
test=True
|
||||
)
|
||||
assert ret[state_name]['result'] is True
|
||||
assert ret[state_name]['pchanges'] == {}
|
||||
assert ret[state_name]['changes'] == {}
|
||||
|
||||
finally:
|
||||
# Clean Up File
|
||||
if os.path.exists(name):
|
||||
os.remove(name)
|
||||
|
||||
def test_directory(self):
|
||||
'''
|
||||
file.directory
|
||||
|
@ -2478,6 +2534,27 @@ class FileTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
os.remove(source)
|
||||
os.remove(dest)
|
||||
|
||||
@destructiveTest
|
||||
@with_tempfile
|
||||
def test_file_copy_make_dirs(self, source):
|
||||
'''
|
||||
ensure make_dirs creates correct user perms
|
||||
'''
|
||||
shutil.copyfile(os.path.join(FILES, 'hosts'), source)
|
||||
dest = os.path.join(TMP, 'dir1', 'dir2', 'copied_file.txt')
|
||||
|
||||
user = 'salt'
|
||||
mode = '0644'
|
||||
self.run_function('user.add', [user])
|
||||
ret = self.run_state('file.copy', name=dest, source=source, user=user,
|
||||
makedirs=True, mode=mode)
|
||||
file_checks = [dest, os.path.join(TMP, 'dir1'), os.path.join(TMP, 'dir1', 'dir2')]
|
||||
for check in file_checks:
|
||||
user_check = self.run_function('file.get_user', [check])
|
||||
mode_check = self.run_function('file.get_mode', [check])
|
||||
assert user_check == user
|
||||
assert salt.utils.normalize_mode(mode_check) == mode
|
||||
|
||||
def test_contents_pillar_with_pillar_list(self):
|
||||
'''
|
||||
This tests for any regressions for this issue:
|
||||
|
@ -2488,6 +2565,37 @@ class FileTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
ret = self.run_function('state.sls', mods=state_file)
|
||||
self.assertSaltTrueReturn(ret)
|
||||
|
||||
@skip_if_not_root
|
||||
@skipIf(not HAS_PWD, "pwd not available. Skipping test")
|
||||
@skipIf(not HAS_GRP, "grp not available. Skipping test")
|
||||
@with_system_user_and_group('user12209', 'group12209',
|
||||
on_existing='delete', delete=True)
|
||||
def test_issue_48336_file_managed_mode_setuid(self, user, group):
|
||||
'''
|
||||
Ensure that mode is correct with changing of ownership and group
|
||||
symlinks)
|
||||
'''
|
||||
tempfile = os.path.join(TMP, 'temp_file_issue_48336')
|
||||
|
||||
# Run the state
|
||||
ret = self.run_state(
|
||||
'file.managed', name=tempfile,
|
||||
user=user, group=group, mode='4750',
|
||||
)
|
||||
self.assertSaltTrueReturn(ret)
|
||||
|
||||
# Check that the owner and group are correct, and
|
||||
# the mode is what we expect
|
||||
temp_file_stats = os.stat(tempfile)
|
||||
|
||||
# Normalize the mode
|
||||
temp_file_mode = six.text_type(oct(stat.S_IMODE(temp_file_stats.st_mode)))
|
||||
temp_file_mode = salt.utils.normalize_mode(temp_file_mode)
|
||||
|
||||
self.assertEqual(temp_file_mode, '4750')
|
||||
self.assertEqual(pwd.getpwuid(temp_file_stats.st_uid).pw_name, user)
|
||||
self.assertEqual(grp.getgrgid(temp_file_stats.st_gid).gr_name, group)
|
||||
|
||||
|
||||
class BlockreplaceTest(ModuleCase, SaltReturnAssertsMixin):
|
||||
marker_start = '# start'
|
||||
|
|
|
@ -33,7 +33,7 @@ class NpmStateTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
Basic test to determine if NPM module was successfully installed and
|
||||
removed.
|
||||
'''
|
||||
ret = self.run_state('npm.installed', name='pm2', registry="http://registry.npmjs.org/")
|
||||
ret = self.run_state('npm.installed', name='pm2@2.10.4', registry="http://registry.npmjs.org/")
|
||||
self.assertSaltTrueReturn(ret)
|
||||
ret = self.run_state('npm.removed', name='pm2')
|
||||
self.assertSaltTrueReturn(ret)
|
||||
|
@ -69,7 +69,7 @@ class NpmStateTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
Basic test to determine if NPM module successfully installs multiple
|
||||
packages.
|
||||
'''
|
||||
ret = self.run_state('npm.installed', name=None, pkgs=['pm2', 'grunt'], registry="http://registry.npmjs.org/")
|
||||
ret = self.run_state('npm.installed', name=None, pkgs=['pm2@2.10.4', 'grunt@1.0.2'], registry="http://registry.npmjs.org/")
|
||||
self.assertSaltTrueReturn(ret)
|
||||
|
||||
@skipIf(salt.utils.which('npm') and LooseVersion(cmd.run('npm -v')) >= LooseVersion(MAX_NPM_VERSION),
|
||||
|
|
|
@ -22,6 +22,11 @@ from tests.support.mixins import SaltReturnAssertsMixin
|
|||
# Import salt libs
|
||||
import salt.utils
|
||||
|
||||
try:
|
||||
import grp
|
||||
except ImportError:
|
||||
grp = None
|
||||
|
||||
if salt.utils.is_darwin():
|
||||
USER = 'macuser'
|
||||
GROUP = 'macuser'
|
||||
|
@ -32,13 +37,11 @@ elif salt.utils.is_windows():
|
|||
GROUP = 'winuser'
|
||||
GID = randint(400, 500)
|
||||
NOGROUPGID = randint(400, 500)
|
||||
grp = None
|
||||
else:
|
||||
USER = 'nobody'
|
||||
GROUP = 'nobody'
|
||||
GID = 'nobody'
|
||||
NOGROUPGID = 'nogroup'
|
||||
import grp
|
||||
|
||||
|
||||
@destructiveTest
|
||||
|
|
|
@ -14,6 +14,7 @@ import logging
|
|||
import os
|
||||
import shutil
|
||||
import signal
|
||||
import socket
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
@ -590,8 +591,24 @@ class TestSaltProgram(six.with_metaclass(TestSaltProgramMeta, TestProgram)):
|
|||
'log_dir',
|
||||
'script_dir',
|
||||
])
|
||||
|
||||
pub_port = 4505
|
||||
ret_port = 4506
|
||||
for port in [pub_port, ret_port]:
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
try:
|
||||
connect = sock.bind(('localhost', port))
|
||||
except:
|
||||
# these ports are already in use, use different ones
|
||||
pub_port = 4606
|
||||
ret_port = 4607
|
||||
break
|
||||
sock.close()
|
||||
|
||||
config_base = {
|
||||
'root_dir': '{test_dir}',
|
||||
'publish_port': pub_port,
|
||||
'ret_port': ret_port,
|
||||
}
|
||||
configs = {}
|
||||
config_dir = os.path.join('etc', 'salt')
|
||||
|
|
|
@ -789,6 +789,7 @@ class CronTestCase(TestCase, LoaderModuleMockMixin):
|
|||
cron.raw_cron(STUB_USER)
|
||||
cron.__salt__['cmd.run_stdout'].assert_called_with("crontab -l",
|
||||
runas=STUB_USER,
|
||||
ignore_retcode=True,
|
||||
rstrip=False,
|
||||
python_shell=False)
|
||||
|
||||
|
@ -803,6 +804,7 @@ class CronTestCase(TestCase, LoaderModuleMockMixin):
|
|||
MagicMock(return_value=False)):
|
||||
cron.raw_cron(STUB_USER)
|
||||
cron.__salt__['cmd.run_stdout'].assert_called_with("crontab -u root -l",
|
||||
ignore_retcode=True,
|
||||
rstrip=False,
|
||||
python_shell=False)
|
||||
|
||||
|
@ -818,6 +820,7 @@ class CronTestCase(TestCase, LoaderModuleMockMixin):
|
|||
cron.raw_cron(STUB_USER)
|
||||
cron.__salt__['cmd.run_stdout'].assert_called_with("crontab -l",
|
||||
runas=STUB_USER,
|
||||
ignore_retcode=True,
|
||||
rstrip=False,
|
||||
python_shell=False)
|
||||
|
||||
|
@ -833,6 +836,7 @@ class CronTestCase(TestCase, LoaderModuleMockMixin):
|
|||
cron.raw_cron(STUB_USER)
|
||||
cron.__salt__['cmd.run_stdout'].assert_called_with("crontab -l",
|
||||
runas=STUB_USER,
|
||||
ignore_retcode=True,
|
||||
rstrip=False,
|
||||
python_shell=False)
|
||||
|
||||
|
@ -848,6 +852,7 @@ class CronTestCase(TestCase, LoaderModuleMockMixin):
|
|||
cron.raw_cron(STUB_USER)
|
||||
cron.__salt__['cmd.run_stdout'].assert_called_with("crontab -l",
|
||||
runas=STUB_USER,
|
||||
ignore_retcode=True,
|
||||
rstrip=False,
|
||||
python_shell=False)
|
||||
|
||||
|
@ -863,6 +868,7 @@ class CronTestCase(TestCase, LoaderModuleMockMixin):
|
|||
cron.raw_cron(STUB_USER)
|
||||
cron.__salt__['cmd.run_stdout'].assert_called_with("crontab -l",
|
||||
runas=STUB_USER,
|
||||
ignore_retcode=True,
|
||||
rstrip=False,
|
||||
python_shell=False)
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
# Import Python Libs
|
||||
from __future__ import absolute_import
|
||||
import json
|
||||
import textwrap
|
||||
|
||||
# Import Salt Testing Libs
|
||||
from tests.support.mixins import LoaderModuleMockMixin
|
||||
|
@ -34,43 +35,87 @@ class NpmTestCase(TestCase, LoaderModuleMockMixin):
|
|||
self.addCleanup(patcher.stop)
|
||||
return {npm: {}}
|
||||
|
||||
# 'install' function tests: 1
|
||||
# 'install' function tests: 4
|
||||
|
||||
def test_install(self):
|
||||
'''
|
||||
Test if it install an NPM package.
|
||||
Test if it installs an NPM package.
|
||||
'''
|
||||
mock = MagicMock(return_value={'retcode': 1, 'stderr': 'error'})
|
||||
with patch.dict(npm.__salt__, {'cmd.run_all': mock}):
|
||||
self.assertRaises(CommandExecutionError, npm.install,
|
||||
'coffee-script')
|
||||
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stderr': 'error',
|
||||
'stdout': '{"salt": ["SALT"]}'})
|
||||
with patch.dict(npm.__salt__, {'cmd.run_all': mock}):
|
||||
mock_err = MagicMock(return_value='SALT')
|
||||
with patch.object(json, 'loads', mock_err):
|
||||
self.assertEqual(npm.install('coffee-script'), 'SALT')
|
||||
# This is at least somewhat closer to the actual output format.
|
||||
mock_json_out = textwrap.dedent('''\
|
||||
[
|
||||
{
|
||||
"salt": "SALT"
|
||||
}
|
||||
]''')
|
||||
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stderr': 'error',
|
||||
'stdout': '{"salt": ["SALT"]}'})
|
||||
# Successful run, expected output format
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stderr': '',
|
||||
'stdout': mock_json_out})
|
||||
with patch.dict(npm.__salt__, {'cmd.run_all': mock}):
|
||||
self.assertEqual(npm.install('coffee-script'),
|
||||
[{u'salt': u'SALT'}])
|
||||
|
||||
mock_json_out_extra = textwrap.dedent('''\
|
||||
Compilation output here
|
||||
|
||||
[bcrypt] Success: "/tmp/node_modules/bcrypt/foo" is installed via remote"
|
||||
[grpc] Success: "/usr/lib/node_modules/@foo/bar" is installed via remote"
|
||||
[
|
||||
{
|
||||
"from" : "express@",
|
||||
"name" : "express",
|
||||
"dependencies" : {
|
||||
"escape-html" : {
|
||||
"from" : "escape-html@~1.0.3",
|
||||
"dependencies" : {},
|
||||
"version" : "1.0.3"
|
||||
}
|
||||
},
|
||||
"version" : "4.16.3"
|
||||
}
|
||||
]''')
|
||||
extra_expected = [{u'dependencies':
|
||||
{u'escape-html': {
|
||||
u'dependencies': {},
|
||||
u'from': u'escape-html@~1.0.3',
|
||||
u'version': u'1.0.3'}
|
||||
},
|
||||
u'from': u'express@',
|
||||
u'name': u'express',
|
||||
u'version': u'4.16.3'}]
|
||||
|
||||
# Successful run, expected output format with additional leading text
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stderr': '',
|
||||
'stdout': mock_json_out_extra})
|
||||
with patch.dict(npm.__salt__, {'cmd.run_all': mock}):
|
||||
self.assertEqual(npm.install('coffee-script'), extra_expected)
|
||||
|
||||
# Successful run, unexpected output format
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stderr': '',
|
||||
'stdout': 'SALT'})
|
||||
with patch.dict(npm.__salt__, {'cmd.run_all': mock}):
|
||||
mock_err = MagicMock(side_effect=ValueError())
|
||||
# When JSON isn't successfully parsed, return should equal input
|
||||
with patch.object(json, 'loads', mock_err):
|
||||
self.assertEqual(npm.install('coffee-script'),
|
||||
'{"salt": ["SALT"]}')
|
||||
self.assertEqual(npm.install('coffee-script'), 'SALT')
|
||||
|
||||
# 'uninstall' function tests: 1
|
||||
|
||||
def test_uninstall(self):
|
||||
'''
|
||||
Test if it uninstall an NPM package.
|
||||
Test if it uninstalls an NPM package.
|
||||
'''
|
||||
mock = MagicMock(return_value={'retcode': 1, 'stderr': 'error'})
|
||||
with patch.dict(npm.__salt__, {'cmd.run_all': mock}):
|
||||
self.assertFalse(npm.uninstall('coffee-script'))
|
||||
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stderr': 'error'})
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stderr': ''})
|
||||
with patch.dict(npm.__salt__, {'cmd.run_all': mock}):
|
||||
self.assertTrue(npm.uninstall('coffee-script'))
|
||||
|
||||
|
|
|
@ -126,65 +126,56 @@ class ProxyTestCase(TestCase, LoaderModuleMockMixin):
|
|||
|
||||
def test_get_http_proxy_windows(self):
|
||||
'''
|
||||
Test to make sure that we correctly get the current proxy info
|
||||
on Windows
|
||||
Test to make sure that we correctly get the current proxy info on
|
||||
Windows
|
||||
'''
|
||||
result = {'vdata': 'http=192.168.0.1:3128;https=192.168.0.2:3128;ftp=192.168.0.3:3128'}
|
||||
mock = MagicMock(return_value=result)
|
||||
expected = {'server': '192.168.0.1',
|
||||
'port': '3128'}
|
||||
with patch.dict(proxy.__grains__, {'os': 'Windows'}):
|
||||
result = {
|
||||
'vdata': 'http=192.168.0.1:3128;https=192.168.0.2:3128;ftp=192.168.0.3:3128'
|
||||
}
|
||||
mock = MagicMock(return_value=result)
|
||||
expected = {
|
||||
'server': '192.168.0.1',
|
||||
'port': '3128'
|
||||
}
|
||||
with patch.dict(proxy.__salt__, {'reg.read_value': mock}):
|
||||
out = proxy.get_http_proxy()
|
||||
mock.assert_called_once_with('HKEY_CURRENT_USER',
|
||||
'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'ProxyServer')
|
||||
mock.assert_called_once_with(
|
||||
hive='HKEY_CURRENT_USER',
|
||||
key='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
vname='ProxyServer')
|
||||
self.assertEqual(expected, out)
|
||||
|
||||
def test_get_https_proxy_windows(self):
|
||||
'''
|
||||
Test to make sure that we correctly get the current proxy info
|
||||
on Windows
|
||||
Test to make sure that we correctly get the current proxy info on
|
||||
Windows
|
||||
'''
|
||||
result = {'vdata': 'http=192.168.0.1:3128;https=192.168.0.2:3128;ftp=192.168.0.3:3128'}
|
||||
mock = MagicMock(return_value=result)
|
||||
expected = {'server': '192.168.0.2',
|
||||
'port': '3128'}
|
||||
with patch.dict(proxy.__grains__, {'os': 'Windows'}):
|
||||
result = {
|
||||
'vdata': 'http=192.168.0.1:3128;https=192.168.0.2:3128;ftp=192.168.0.3:3128'
|
||||
}
|
||||
mock = MagicMock(return_value=result)
|
||||
expected = {
|
||||
'server': '192.168.0.2',
|
||||
'port': '3128'
|
||||
}
|
||||
with patch.dict(proxy.__salt__, {'reg.read_value': mock}):
|
||||
out = proxy.get_https_proxy()
|
||||
mock.assert_called_once_with('HKEY_CURRENT_USER',
|
||||
'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'ProxyServer')
|
||||
mock.assert_called_once_with(
|
||||
hive='HKEY_CURRENT_USER',
|
||||
key='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
vname='ProxyServer')
|
||||
self.assertEqual(expected, out)
|
||||
|
||||
def test_get_ftp_proxy_windows(self):
|
||||
'''
|
||||
Test to make sure that we correctly get the current proxy info
|
||||
on Windows
|
||||
Test to make sure that we correctly get the current proxy info on
|
||||
Windows
|
||||
'''
|
||||
result = {'vdata': 'http=192.168.0.1:3128;https=192.168.0.2:3128;ftp=192.168.0.3:3128'}
|
||||
mock = MagicMock(return_value=result)
|
||||
expected = {'server': '192.168.0.3',
|
||||
'port': '3128'}
|
||||
with patch.dict(proxy.__grains__, {'os': 'Windows'}):
|
||||
result = {
|
||||
'vdata': 'http=192.168.0.1:3128;https=192.168.0.2:3128;ftp=192.168.0.3:3128'
|
||||
}
|
||||
mock = MagicMock(return_value=result)
|
||||
expected = {
|
||||
'server': '192.168.0.3',
|
||||
'port': '3128'
|
||||
}
|
||||
with patch.dict(proxy.__salt__, {'reg.read_value': mock}):
|
||||
out = proxy.get_ftp_proxy()
|
||||
mock.assert_called_once_with('HKEY_CURRENT_USER',
|
||||
'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'ProxyServer')
|
||||
mock.assert_called_once_with(
|
||||
hive='HKEY_CURRENT_USER',
|
||||
key='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
vname='ProxyServer')
|
||||
self.assertEqual(expected, out)
|
||||
|
||||
def test_get_all_proxies_macos_fails(self):
|
||||
|
@ -196,201 +187,179 @@ class ProxyTestCase(TestCase, LoaderModuleMockMixin):
|
|||
|
||||
def test_get_all_proxies_windows(self):
|
||||
'''
|
||||
Test to make sure that we correctly get the current proxy info
|
||||
on Windows
|
||||
Test to make sure that we correctly get the current proxy info on
|
||||
Windows
|
||||
'''
|
||||
results = [{'vdata': 'http=192.168.0.1:3128;https=192.168.0.2:3128;ftp=192.168.0.3:3128'},
|
||||
{'vdata': 1}]
|
||||
mock = MagicMock(side_effect=results)
|
||||
expected = {'enabled': True,
|
||||
'http': {'server': '192.168.0.1',
|
||||
'port': '3128'},
|
||||
'https': {'server': '192.168.0.2',
|
||||
'port': '3128'},
|
||||
'ftp': {'server': '192.168.0.3',
|
||||
'port': '3128'}}
|
||||
calls = [
|
||||
call(hive='HKEY_CURRENT_USER',
|
||||
key='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
vname='ProxyServer'),
|
||||
call(hive='HKEY_CURRENT_USER',
|
||||
key='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
vname='ProxyEnable')]
|
||||
with patch.dict(proxy.__grains__, {'os': 'Windows'}):
|
||||
results = [
|
||||
{
|
||||
'vdata': 'http=192.168.0.1:3128;https=192.168.0.2:3128;ftp=192.168.0.3:3128'
|
||||
},
|
||||
{
|
||||
'vdata': 1
|
||||
}
|
||||
]
|
||||
mock = MagicMock(side_effect=results)
|
||||
|
||||
expected = {
|
||||
'enabled': True,
|
||||
'http': {
|
||||
'server': '192.168.0.1',
|
||||
'port': '3128'
|
||||
},
|
||||
'https': {
|
||||
'server': '192.168.0.2',
|
||||
'port': '3128'
|
||||
},
|
||||
'ftp': {
|
||||
'server': '192.168.0.3',
|
||||
'port': '3128'
|
||||
}
|
||||
}
|
||||
with patch.dict(proxy.__salt__, {'reg.read_value': mock}):
|
||||
out = proxy.get_proxy_win()
|
||||
calls = [
|
||||
call('HKEY_CURRENT_USER',
|
||||
'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'ProxyServer'),
|
||||
call('HKEY_CURRENT_USER',
|
||||
'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'ProxyEnable'),
|
||||
]
|
||||
|
||||
mock.assert_has_calls(calls)
|
||||
self.assertEqual(expected, out)
|
||||
|
||||
def test_set_http_proxy_windows(self):
|
||||
'''
|
||||
Test to make sure that we correctly set the proxy info
|
||||
on Windows
|
||||
Test to make sure that we correctly set the proxy info on Windows
|
||||
'''
|
||||
calls = [
|
||||
call(hive='HKEY_CURRENT_USER',
|
||||
key='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
vname='ProxyServer',
|
||||
vdata='http=192.168.0.1:3128;'),
|
||||
call(hive='HKEY_CURRENT_USER',
|
||||
key='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
vname='ProxyEnable',
|
||||
vdata=1,
|
||||
vtype='REG_DWORD'),
|
||||
call(hive='HKEY_CURRENT_USER',
|
||||
key='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
vname='ProxyOverride',
|
||||
vdata='<local>;.moo.com;.salt.com')]
|
||||
mock_reg = MagicMock()
|
||||
mock_cmd = MagicMock()
|
||||
with patch.dict(proxy.__grains__, {'os': 'Windows'}):
|
||||
mock_reg = MagicMock()
|
||||
mock_cmd = MagicMock()
|
||||
|
||||
with patch.dict(proxy.__salt__, {'reg.set_value': mock_reg, 'cmd.run': mock_cmd}):
|
||||
out = proxy.set_http_proxy('192.168.0.1', 3128, bypass_hosts=['.moo.com', '.salt.com'])
|
||||
|
||||
calls = [
|
||||
call('HKEY_CURRENT_USER',
|
||||
'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'ProxyServer',
|
||||
'http=192.168.0.1:3128;'),
|
||||
call('HKEY_CURRENT_USER',
|
||||
'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'ProxyEnable',
|
||||
1,
|
||||
vtype='REG_DWORD'),
|
||||
call('HKEY_CURRENT_USER',
|
||||
'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'ProxyOverride',
|
||||
'<local>;.moo.com;.salt.com')
|
||||
]
|
||||
with patch.dict(proxy.__salt__, {'reg.set_value': mock_reg,
|
||||
'cmd.run': mock_cmd}):
|
||||
out = proxy.set_http_proxy(server='192.168.0.1',
|
||||
port=3128,
|
||||
bypass_hosts=['.moo.com', '.salt.com'])
|
||||
mock_reg.assert_has_calls(calls)
|
||||
mock_cmd.assert_called_once_with('netsh winhttp import proxy source=ie')
|
||||
self.assertTrue(out)
|
||||
|
||||
def test_set_https_proxy_windows(self):
|
||||
'''
|
||||
Test to make sure that we correctly set the proxy info
|
||||
on Windows
|
||||
Test to make sure that we correctly set the proxy info on Windows
|
||||
'''
|
||||
calls = [
|
||||
call(hive='HKEY_CURRENT_USER',
|
||||
key='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
vname='ProxyServer',
|
||||
vdata='https=192.168.0.1:3128;'),
|
||||
call(hive='HKEY_CURRENT_USER',
|
||||
key='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
vname='ProxyEnable',
|
||||
vdata=1,
|
||||
vtype='REG_DWORD'),
|
||||
call(hive='HKEY_CURRENT_USER',
|
||||
key='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
vname='ProxyOverride',
|
||||
vdata='<local>;.moo.com;.salt.com')]
|
||||
mock_reg = MagicMock()
|
||||
mock_cmd = MagicMock()
|
||||
with patch.dict(proxy.__grains__, {'os': 'Windows'}):
|
||||
mock_reg = MagicMock()
|
||||
mock_cmd = MagicMock()
|
||||
|
||||
with patch.dict(proxy.__salt__, {'reg.set_value': mock_reg, 'cmd.run': mock_cmd}):
|
||||
out = proxy.set_https_proxy('192.168.0.1', 3128, bypass_hosts=['.moo.com', '.salt.com'])
|
||||
|
||||
calls = [
|
||||
call('HKEY_CURRENT_USER',
|
||||
'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'ProxyServer',
|
||||
'https=192.168.0.1:3128;'),
|
||||
call('HKEY_CURRENT_USER',
|
||||
'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'ProxyEnable',
|
||||
1,
|
||||
vtype='REG_DWORD'),
|
||||
call('HKEY_CURRENT_USER',
|
||||
'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'ProxyOverride',
|
||||
'<local>;.moo.com;.salt.com')
|
||||
]
|
||||
with patch.dict(proxy.__salt__, {'reg.set_value': mock_reg,
|
||||
'cmd.run': mock_cmd}):
|
||||
out = proxy.set_https_proxy(server='192.168.0.1',
|
||||
port=3128,
|
||||
bypass_hosts=['.moo.com', '.salt.com'])
|
||||
mock_reg.assert_has_calls(calls)
|
||||
mock_cmd.assert_called_once_with('netsh winhttp import proxy source=ie')
|
||||
self.assertTrue(out)
|
||||
|
||||
def test_set_ftp_proxy_windows(self):
|
||||
'''
|
||||
Test to make sure that we correctly set the proxy info
|
||||
on Windows
|
||||
Test to make sure that we correctly set the proxy info on Windows
|
||||
'''
|
||||
calls = [
|
||||
call(hive='HKEY_CURRENT_USER',
|
||||
key='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
vname='ProxyServer',
|
||||
vdata='ftp=192.168.0.1:3128;'),
|
||||
call(hive='HKEY_CURRENT_USER',
|
||||
key='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
vname='ProxyEnable',
|
||||
vdata=1,
|
||||
vtype='REG_DWORD'),
|
||||
call(hive='HKEY_CURRENT_USER',
|
||||
key='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
vname='ProxyOverride',
|
||||
vdata='<local>;.moo.com;.salt.com')]
|
||||
mock_reg = MagicMock()
|
||||
mock_cmd = MagicMock()
|
||||
with patch.dict(proxy.__grains__, {'os': 'Windows'}):
|
||||
mock_reg = MagicMock()
|
||||
mock_cmd = MagicMock()
|
||||
|
||||
with patch.dict(proxy.__salt__, {'reg.set_value': mock_reg, 'cmd.run': mock_cmd}):
|
||||
out = proxy.set_ftp_proxy('192.168.0.1', 3128, bypass_hosts=['.moo.com', '.salt.com'])
|
||||
|
||||
calls = [
|
||||
call('HKEY_CURRENT_USER',
|
||||
'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'ProxyServer',
|
||||
'ftp=192.168.0.1:3128;'),
|
||||
call('HKEY_CURRENT_USER',
|
||||
'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'ProxyEnable',
|
||||
1,
|
||||
vtype='REG_DWORD'),
|
||||
call('HKEY_CURRENT_USER',
|
||||
'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'ProxyOverride',
|
||||
'<local>;.moo.com;.salt.com')
|
||||
]
|
||||
with patch.dict(proxy.__salt__, {'reg.set_value': mock_reg,
|
||||
'cmd.run': mock_cmd}):
|
||||
out = proxy.set_ftp_proxy(server='192.168.0.1',
|
||||
port=3128,
|
||||
bypass_hosts=['.moo.com', '.salt.com'])
|
||||
mock_reg.assert_has_calls(calls)
|
||||
mock_cmd.assert_called_once_with('netsh winhttp import proxy source=ie')
|
||||
self.assertTrue(out)
|
||||
|
||||
def test_set_proxy_windows(self):
|
||||
'''
|
||||
Test to make sure that we correctly set the proxy info
|
||||
on Windows
|
||||
Test to make sure that we correctly set the proxy info on Windows
|
||||
'''
|
||||
calls = [
|
||||
call(hive='HKEY_CURRENT_USER',
|
||||
key='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
vname='ProxyServer',
|
||||
vdata='http=192.168.0.1:3128;https=192.168.0.1:3128;ftp=192.168.0.1:3128;'),
|
||||
call(hive='HKEY_CURRENT_USER',
|
||||
key='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
vname='ProxyEnable',
|
||||
vdata=1,
|
||||
vtype='REG_DWORD'),
|
||||
call(hive='HKEY_CURRENT_USER',
|
||||
key='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
vname='ProxyOverride',
|
||||
vdata='<local>;.moo.com;.salt.com')]
|
||||
mock_reg = MagicMock()
|
||||
mock_cmd = MagicMock()
|
||||
with patch.dict(proxy.__grains__, {'os': 'Windows'}):
|
||||
mock_reg = MagicMock()
|
||||
mock_cmd = MagicMock()
|
||||
|
||||
with patch.dict(proxy.__salt__, {'reg.set_value': mock_reg, 'cmd.run': mock_cmd}):
|
||||
out = proxy.set_proxy_win('192.168.0.1', 3128, bypass_hosts=['.moo.com', '.salt.com'])
|
||||
|
||||
calls = [
|
||||
call('HKEY_CURRENT_USER',
|
||||
'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'ProxyServer',
|
||||
'http=192.168.0.1:3128;https=192.168.0.1:3128;ftp=192.168.0.1:3128;'),
|
||||
call('HKEY_CURRENT_USER',
|
||||
'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'ProxyEnable',
|
||||
1,
|
||||
vtype='REG_DWORD'),
|
||||
call('HKEY_CURRENT_USER',
|
||||
'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'ProxyOverride',
|
||||
'<local>;.moo.com;.salt.com')
|
||||
]
|
||||
with patch.dict(proxy.__salt__, {'reg.set_value': mock_reg,
|
||||
'cmd.run': mock_cmd}):
|
||||
out = proxy.set_proxy_win(server='192.168.0.1',
|
||||
port=3128,
|
||||
bypass_hosts=['.moo.com', '.salt.com'])
|
||||
mock_reg.assert_has_calls(calls)
|
||||
mock_cmd.assert_called_once_with('netsh winhttp import proxy source=ie')
|
||||
self.assertTrue(out)
|
||||
|
||||
def test_set_proxy_windows_no_ftp(self):
|
||||
'''
|
||||
Test to make sure that we correctly set the proxy info
|
||||
on Windows
|
||||
Test to make sure that we correctly set the proxy info on Windows
|
||||
'''
|
||||
calls = [
|
||||
call(hive='HKEY_CURRENT_USER',
|
||||
key='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
vname='ProxyServer',
|
||||
vdata='http=192.168.0.1:3128;https=192.168.0.1:3128;'),
|
||||
call(hive='HKEY_CURRENT_USER',
|
||||
key='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
vname='ProxyEnable',
|
||||
vdata=1,
|
||||
vtype='REG_DWORD'),
|
||||
call(hive='HKEY_CURRENT_USER',
|
||||
key='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
vname='ProxyOverride',
|
||||
vdata='<local>;.moo.com;.salt.com')]
|
||||
mock_reg = MagicMock()
|
||||
mock_cmd = MagicMock()
|
||||
with patch.dict(proxy.__grains__, {'os': 'Windows'}):
|
||||
mock_reg = MagicMock()
|
||||
mock_cmd = MagicMock()
|
||||
|
||||
with patch.dict(proxy.__salt__, {'reg.set_value': mock_reg, 'cmd.run': mock_cmd}):
|
||||
out = proxy.set_proxy_win('192.168.0.1', 3128, types=['http', 'https'],
|
||||
with patch.dict(proxy.__salt__, {'reg.set_value': mock_reg,
|
||||
'cmd.run': mock_cmd}):
|
||||
out = proxy.set_proxy_win(server='192.168.0.1',
|
||||
port=3128,
|
||||
types=['http', 'https'],
|
||||
bypass_hosts=['.moo.com', '.salt.com'])
|
||||
|
||||
calls = [
|
||||
call('HKEY_CURRENT_USER',
|
||||
'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'ProxyServer',
|
||||
'http=192.168.0.1:3128;https=192.168.0.1:3128;'),
|
||||
call('HKEY_CURRENT_USER',
|
||||
'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'ProxyEnable',
|
||||
1,
|
||||
vtype='REG_DWORD'),
|
||||
call('HKEY_CURRENT_USER',
|
||||
'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings',
|
||||
'ProxyOverride',
|
||||
'<local>;.moo.com;.salt.com')
|
||||
]
|
||||
mock_reg.assert_has_calls(calls)
|
||||
mock_cmd.assert_called_once_with('netsh winhttp import proxy source=ie')
|
||||
self.assertTrue(out)
|
||||
|
|
|
@ -361,6 +361,7 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin):
|
|||
ZyppCallMock(return_value=get_test_data('zypper-available.txt'))), \
|
||||
patch('salt.modules.zypper.refresh_db', MagicMock(return_value=True)):
|
||||
self.assertEqual(zypper.latest_version('vim'), '7.4.326-2.62')
|
||||
self.assertDictEqual(zypper.latest_version('vim', 'fakepkg'), {'vim': '7.4.326-2.62', 'fakepkg': ''})
|
||||
|
||||
def test_upgrade_success(self):
|
||||
'''
|
||||
|
|
|
@ -39,6 +39,7 @@ import salt.serializers.yaml as yamlserializer
|
|||
import salt.serializers.json as jsonserializer
|
||||
import salt.serializers.python as pythonserializer
|
||||
from salt.exceptions import CommandExecutionError
|
||||
import salt.utils.win_functions
|
||||
|
||||
|
||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
|
@ -60,6 +61,15 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
|
|||
}
|
||||
}
|
||||
|
||||
def tearDown(self):
|
||||
remove_dir = '/tmp/etc'
|
||||
if salt.utils.is_windows():
|
||||
remove_dir = 'c:\\tmp\\etc'
|
||||
try:
|
||||
salt.utils.rm_rf(remove_dir)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def test_serialize(self):
|
||||
def returner(contents, *args, **kwargs):
|
||||
returner.returned = contents
|
||||
|
@ -145,10 +155,15 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
|
|||
else:
|
||||
group = 'saltstack'
|
||||
|
||||
ret = {'name': name,
|
||||
'result': False,
|
||||
'comment': '',
|
||||
'changes': {}}
|
||||
def return_val(kwargs):
|
||||
val = {
|
||||
'name': name,
|
||||
'result': False,
|
||||
'comment': '',
|
||||
'changes': {},
|
||||
}
|
||||
val.update(kwargs)
|
||||
return val
|
||||
|
||||
mock_t = MagicMock(return_value=True)
|
||||
mock_f = MagicMock(return_value=False)
|
||||
|
@ -162,7 +177,7 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
|
|||
|
||||
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t}):
|
||||
comt = ('Must provide name to file.symlink')
|
||||
ret.update({'comment': comt, 'name': ''})
|
||||
ret = return_val({'comment': comt, 'name': ''})
|
||||
self.assertDictEqual(filestate.symlink('', target), ret)
|
||||
|
||||
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
|
||||
|
@ -170,8 +185,12 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
|
|||
'file.group_to_gid': mock_empty,
|
||||
'user.info': mock_empty,
|
||||
'user.current': mock_user}):
|
||||
comt = ('User {0} does not exist. Group {1} does not exist.'.format(user, group))
|
||||
ret.update({'comment': comt, 'name': name})
|
||||
if salt.utils.is_windows():
|
||||
comt = ('User {0} does not exist'.format(user))
|
||||
ret = return_val({'comment': comt, 'name': name})
|
||||
else:
|
||||
comt = ('User {0} does not exist. Group {1} does not exist.'.format(user, group))
|
||||
ret = return_val({'comment': comt, 'name': name})
|
||||
self.assertDictEqual(filestate.symlink(name, target, user=user,
|
||||
group=group), ret)
|
||||
|
||||
|
@ -183,11 +202,22 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
|
|||
'user.current': mock_user}):
|
||||
with patch.dict(filestate.__opts__, {'test': True}):
|
||||
with patch.object(os.path, 'exists', mock_f):
|
||||
comt = ('Symlink {0} to {1}'
|
||||
' is set for creation').format(name, target)
|
||||
ret.update({'comment': comt,
|
||||
'result': None,
|
||||
'pchanges': {'new': name}})
|
||||
if salt.utils.is_windows():
|
||||
comt = ('User {0} does not exist'.format(user))
|
||||
ret = return_val(
|
||||
{
|
||||
'comment': comt,
|
||||
'result': False,
|
||||
'name': name,
|
||||
'changes': {}
|
||||
}
|
||||
)
|
||||
else:
|
||||
comt = ('Symlink {0} to {1}'
|
||||
' is set for creation').format(name, target)
|
||||
ret = return_val({'comment': comt,
|
||||
'result': None,
|
||||
'pchanges': {'new': name}})
|
||||
self.assertDictEqual(filestate.symlink(name, target,
|
||||
user=user,
|
||||
group=group), ret)
|
||||
|
@ -201,10 +231,21 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
|
|||
with patch.dict(filestate.__opts__, {'test': False}):
|
||||
with patch.object(os.path, 'isdir', mock_f):
|
||||
with patch.object(os.path, 'exists', mock_f):
|
||||
comt = ('Directory {0} for symlink is not present').format(test_dir)
|
||||
ret.update({'comment': comt,
|
||||
if salt.utils.is_windows():
|
||||
comt = 'User {0} does not exist'.format(user)
|
||||
ret = return_val(
|
||||
{
|
||||
'comment': comt,
|
||||
'result': False,
|
||||
'pchanges': {'new': name}})
|
||||
'name': name,
|
||||
'changes': {},
|
||||
}
|
||||
)
|
||||
else:
|
||||
comt = ('Directory {0} for symlink is not present').format(test_dir)
|
||||
ret = return_val({'comment': comt,
|
||||
'result': False,
|
||||
'pchanges': {'new': name}})
|
||||
self.assertDictEqual(filestate.symlink(name, target,
|
||||
user=user,
|
||||
group=group), ret)
|
||||
|
@ -219,15 +260,19 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
|
|||
with patch.dict(filestate.__opts__, {'test': False}):
|
||||
with patch.object(os.path, 'isdir', mock_t):
|
||||
with patch.object(salt.states.file, '_check_symlink_ownership', mock_t):
|
||||
comt = ('Symlink {0} is present and owned by '
|
||||
'{1}:{2}'.format(name, user, group))
|
||||
ret.update({'comment': comt,
|
||||
'result': True,
|
||||
'pchanges': {}})
|
||||
self.assertDictEqual(filestate.symlink(name, target,
|
||||
user=user,
|
||||
group=group), ret)
|
||||
|
||||
with patch('salt.utils.win_functions.get_sid_from_name', return_value='test-sid'):
|
||||
if salt.utils.is_windows():
|
||||
comt = ('Symlink {0} is present and owned by '
|
||||
'{1}'.format(name, user))
|
||||
else:
|
||||
comt = ('Symlink {0} is present and owned by '
|
||||
'{1}:{2}'.format(name, user, group))
|
||||
ret = return_val({'comment': comt,
|
||||
'result': True,
|
||||
'pchanges': {}})
|
||||
self.assertDictEqual(filestate.symlink(name, target,
|
||||
user=user,
|
||||
group=group), ret)
|
||||
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
|
||||
'file.user_to_uid': mock_uid,
|
||||
'file.group_to_gid': mock_gid,
|
||||
|
@ -239,15 +284,16 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
|
|||
with patch.object(os.path, 'isdir', mock_t):
|
||||
with patch.object(os.path, 'exists', mock_f):
|
||||
with patch.object(os.path, 'lexists', mock_t):
|
||||
comt = ('File exists where the backup target SALT'
|
||||
' should go')
|
||||
ret.update({'comment': comt,
|
||||
'result': False,
|
||||
'pchanges': {'new': name}})
|
||||
self.assertDictEqual(filestate.symlink
|
||||
(name, target, user=user,
|
||||
group=group, backupname='SALT'),
|
||||
ret)
|
||||
with patch('salt.utils.win_functions.get_sid_from_name', return_value='test-sid'):
|
||||
comt = ('File exists where the backup target SALT'
|
||||
' should go')
|
||||
ret = return_val({'comment': comt,
|
||||
'result': False,
|
||||
'pchanges': {'new': name}})
|
||||
self.assertDictEqual(filestate.symlink
|
||||
(name, target, user=user,
|
||||
group=group, backupname='SALT'),
|
||||
ret)
|
||||
|
||||
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
|
||||
'file.user_to_uid': mock_uid,
|
||||
|
@ -260,14 +306,15 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
|
|||
with patch.object(os.path, 'isdir', mock_t):
|
||||
with patch.object(os.path, 'exists', mock_f):
|
||||
with patch.object(os.path, 'isfile', mock_t):
|
||||
comt = ('File exists where the symlink {0} should be'
|
||||
.format(name))
|
||||
ret.update({'comment': comt,
|
||||
'pchanges': {'new': name},
|
||||
'result': False})
|
||||
self.assertDictEqual(filestate.symlink
|
||||
(name, target, user=user,
|
||||
group=group), ret)
|
||||
with patch('salt.utils.win_functions.get_sid_from_name', return_value='test-sid'):
|
||||
comt = ('File exists where the symlink {0} should be'
|
||||
.format(name))
|
||||
ret = return_val({'comment': comt,
|
||||
'pchanges': {'new': name},
|
||||
'result': False})
|
||||
self.assertDictEqual(filestate.symlink
|
||||
(name, target, user=user,
|
||||
group=group), ret)
|
||||
|
||||
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
|
||||
'file.user_to_uid': mock_uid,
|
||||
|
@ -281,11 +328,12 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
|
|||
with patch.object(os.path, 'isdir', MagicMock(side_effect=[True, False])):
|
||||
with patch.object(os.path, 'isfile', mock_t):
|
||||
with patch.object(os.path, 'exists', mock_f):
|
||||
comt = ('File exists where the symlink {0} should be'.format(name))
|
||||
ret.update({'comment': comt, 'result': False})
|
||||
self.assertDictEqual(filestate.symlink
|
||||
(name, target, user=user,
|
||||
group=group), ret)
|
||||
with patch('salt.utils.win_functions.get_sid_from_name', return_value='test-sid'):
|
||||
comt = ('File exists where the symlink {0} should be'.format(name))
|
||||
ret = return_val({'comment': comt, 'result': False, 'pchanges': {'new': '/tmp/testfile.txt'}})
|
||||
self.assertDictEqual(filestate.symlink
|
||||
(name, target, user=user,
|
||||
group=group), ret)
|
||||
|
||||
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
|
||||
'file.user_to_uid': mock_uid,
|
||||
|
@ -299,11 +347,12 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
|
|||
with patch.object(os.path, 'isdir', MagicMock(side_effect=[True, False])):
|
||||
with patch.object(os.path, 'isdir', mock_t):
|
||||
with patch.object(os.path, 'exists', mock_f):
|
||||
comt = ('Directory exists where the symlink {0} should be'.format(name))
|
||||
ret.update({'comment': comt, 'result': False})
|
||||
self.assertDictEqual(filestate.symlink
|
||||
(name, target, user=user,
|
||||
group=group), ret)
|
||||
with patch('salt.utils.win_functions.get_sid_from_name', return_value='test-sid'):
|
||||
comt = ('Directory exists where the symlink {0} should be'.format(name))
|
||||
ret = return_val({'comment': comt, 'result': False, 'pchanges': {'new': '/tmp/testfile.txt'}})
|
||||
self.assertDictEqual(filestate.symlink
|
||||
(name, target, user=user,
|
||||
group=group), ret)
|
||||
|
||||
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
|
||||
'file.user_to_uid': mock_uid,
|
||||
|
@ -316,12 +365,13 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
|
|||
with patch.dict(filestate.__opts__, {'test': False}):
|
||||
with patch.object(os.path, 'isdir', MagicMock(side_effect=[True, False])):
|
||||
with patch.object(os.path, 'isfile', mock_f):
|
||||
comt = ('Unable to create new symlink {0} -> '
|
||||
'{1}: '.format(name, target))
|
||||
ret.update({'comment': comt, 'result': False})
|
||||
self.assertDictEqual(filestate.symlink
|
||||
(name, target, user=user,
|
||||
group=group), ret)
|
||||
with patch('salt.utils.win_functions.get_sid_from_name', return_value='test-sid'):
|
||||
comt = ('Unable to create new symlink {0} -> '
|
||||
'{1}: '.format(name, target))
|
||||
ret = return_val({'comment': comt, 'result': False, 'pchanges': {'new': '/tmp/testfile.txt'}})
|
||||
self.assertDictEqual(filestate.symlink
|
||||
(name, target, user=user,
|
||||
group=group), ret)
|
||||
|
||||
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
|
||||
'file.user_to_uid': mock_uid,
|
||||
|
@ -336,13 +386,15 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
|
|||
with patch.dict(filestate.__opts__, {'test': False}):
|
||||
with patch.object(os.path, 'isdir', MagicMock(side_effect=[True, False])):
|
||||
with patch.object(os.path, 'isfile', mock_f):
|
||||
comt = 'Created new symlink {0} -> {1}'.format(name, target)
|
||||
ret.update({'comment': comt,
|
||||
'result': True,
|
||||
'changes': {'new': name}})
|
||||
self.assertDictEqual(filestate.symlink
|
||||
(name, target, user=user,
|
||||
group=group), ret)
|
||||
with patch('salt.states.file._check_symlink_ownership', return_value=True):
|
||||
with patch('salt.utils.win_functions.get_sid_from_name', return_value='test-sid'):
|
||||
comt = 'Created new symlink {0} -> {1}'.format(name, target)
|
||||
ret = return_val({'comment': comt,
|
||||
'result': True, 'pchanges': {'new': '/tmp/testfile.txt'},
|
||||
'changes': {'new': name}})
|
||||
self.assertDictEqual(filestate.symlink
|
||||
(name, target, user=user,
|
||||
group=group), ret)
|
||||
|
||||
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
|
||||
'file.user_to_uid': mock_uid,
|
||||
|
@ -357,15 +409,19 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
|
|||
with patch.dict(filestate.__opts__, {'test': False}):
|
||||
with patch.object(os.path, 'isdir', MagicMock(side_effect=[True, False])):
|
||||
with patch.object(os.path, 'isfile', mock_f):
|
||||
comt = ('Created new symlink {0} -> {1}, '
|
||||
'but was unable to set ownership to '
|
||||
'{2}:{3}'.format(name, target, user, group))
|
||||
ret.update({'comment': comt,
|
||||
'result': False,
|
||||
'changes': {'new': name}})
|
||||
self.assertDictEqual(filestate.symlink
|
||||
(name, target, user=user,
|
||||
group=group), ret)
|
||||
with patch('salt.utils.win_functions.get_sid_from_name', return_value='test-sid'):
|
||||
with patch('salt.states.file._set_symlink_ownership', return_value=False):
|
||||
with patch('salt.states.file._check_symlink_ownership', return_value=False):
|
||||
comt = ('Created new symlink {0} -> {1}, '
|
||||
'but was unable to set ownership to '
|
||||
'{2}:{3}'.format(name, target, user, group))
|
||||
ret = return_val({'comment': comt,
|
||||
'result': False,
|
||||
'pchanges': {'new': '/tmp/testfile.txt'},
|
||||
'changes': {'new': name}})
|
||||
self.assertDictEqual(filestate.symlink
|
||||
(name, target, user=user,
|
||||
group=group), ret)
|
||||
|
||||
# 'absent' function tests: 1
|
||||
def test_absent(self):
|
||||
|
@ -1127,7 +1183,10 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
|
|||
'''
|
||||
Test to ensure that some text appears at the beginning of a file.
|
||||
'''
|
||||
name = '/etc/motd'
|
||||
name = '/tmp/etc/motd'
|
||||
if salt.utils.is_windows():
|
||||
name = 'c:\\tmp\\etc\\motd'
|
||||
assert not os.path.exists(os.path.split(name)[0])
|
||||
source = ['salt://motd/hr-messages.tmpl']
|
||||
sources = ['salt://motd/devops-messages.tmpl']
|
||||
text = ['Trust no one unless you have eaten much salt with him.']
|
||||
|
@ -1156,12 +1215,15 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
|
|||
'cp.get_template': mock_f,
|
||||
'file.search': mock_f,
|
||||
'file.prepend': mock_t}):
|
||||
with patch.object(os.path, 'isdir', mock_t):
|
||||
comt = ('The following files will be changed:\n/etc:'
|
||||
' directory - new\n')
|
||||
ret.update({'comment': comt, 'name': name, 'pchanges': {'/etc': {'directory': 'new'}}})
|
||||
self.assertDictEqual(filestate.prepend(name, makedirs=True),
|
||||
ret)
|
||||
comt = ('The following files will be changed:\n/tmp/etc:'
|
||||
' directory - new\n')
|
||||
pchanges = {'/tmp/etc': {'directory': 'new'}}
|
||||
if salt.utils.is_windows():
|
||||
comt = 'The directory "c:\\tmp\\etc" will be changed'
|
||||
pchanges = {'c:\\tmp\\etc': {'directory': 'new'}}
|
||||
ret.update({'comment': comt, 'name': name, 'pchanges': pchanges})
|
||||
self.assertDictEqual(filestate.prepend(name, makedirs=True),
|
||||
ret)
|
||||
|
||||
with patch.object(os.path, 'isabs', mock_f):
|
||||
comt = ('Specified file {0} is not an absolute path'
|
||||
|
|
|
@ -125,6 +125,7 @@ class ServiceTestCase(TestCase, LoaderModuleMockMixin):
|
|||
{'changes': 'saltstack',
|
||||
'comment': 'The service salt is already dead', 'name': 'salt',
|
||||
'result': True}]
|
||||
info_mock = MagicMock(return_value={'StartType': ''})
|
||||
|
||||
mock = MagicMock(return_value="salt")
|
||||
with patch.object(service, '_enabled_used_error', mock):
|
||||
|
@ -140,31 +141,36 @@ class ServiceTestCase(TestCase, LoaderModuleMockMixin):
|
|||
with patch.dict(service.__opts__, {'test': True}):
|
||||
with patch.dict(service.__salt__, {'service.enabled': fmock,
|
||||
'service.stop': tmock,
|
||||
'service.status': fmock}):
|
||||
'service.status': fmock,
|
||||
'service.info': info_mock}):
|
||||
with patch.object(service, '_enable', mock):
|
||||
self.assertDictEqual(service.dead("salt", True), ret[5])
|
||||
|
||||
with patch.dict(service.__salt__, {'service.enabled': tmock,
|
||||
'service.status': tmock}):
|
||||
'service.status': tmock,
|
||||
'service.info': info_mock}):
|
||||
self.assertDictEqual(service.dead("salt"), ret[2])
|
||||
|
||||
with patch.dict(service.__opts__, {'test': False}):
|
||||
with patch.dict(service.__salt__, {'service.enabled': fmock,
|
||||
'service.stop': tmock,
|
||||
'service.status': fmock}):
|
||||
'service.status': fmock,
|
||||
'service.info': info_mock}):
|
||||
with patch.object(service, '_enable', mock):
|
||||
self.assertDictEqual(service.dead("salt", True), ret[1])
|
||||
|
||||
with patch.dict(service.__salt__, {'service.enabled': MagicMock(side_effect=[True, True, False]),
|
||||
'service.status': MagicMock(side_effect=[True, False, False]),
|
||||
'service.stop': MagicMock(return_value="stack")}):
|
||||
'service.stop': MagicMock(return_value="stack"),
|
||||
'service.info': info_mock}):
|
||||
with patch.object(service, '_enable', MagicMock(return_value={'changes': 'saltstack'})):
|
||||
self.assertDictEqual(service.dead("salt", True), ret[3])
|
||||
|
||||
# test an initd which a wrong status (True even if dead)
|
||||
with patch.dict(service.__salt__, {'service.enabled': MagicMock(side_effect=[False, False, False]),
|
||||
'service.status': MagicMock(side_effect=[True, True, True]),
|
||||
'service.stop': MagicMock(return_value="stack")}):
|
||||
'service.stop': MagicMock(return_value="stack"),
|
||||
'service.info': info_mock}):
|
||||
with patch.object(service, '_disable', MagicMock(return_value={})):
|
||||
self.assertDictEqual(service.dead("salt", False), ret[4])
|
||||
|
||||
|
|
23
tox.ini
23
tox.ini
|
@ -1,10 +1,29 @@
|
|||
[tox]
|
||||
envlist = py27,py3
|
||||
envlist = py27,py34,py35,py36,pylint-salt,pylint-tests
|
||||
skip_missing_interpreters = True
|
||||
skipsdist = True
|
||||
|
||||
[testenv]
|
||||
deps = -r{toxinidir}/requirements/tests.txt
|
||||
deps = -Ur{toxinidir}/requirements/tests.txt
|
||||
commands = pytest --rootdir {toxinidir} {posargs}
|
||||
passenv = LANG HOME
|
||||
sitepackages = True
|
||||
|
||||
[testenv:pylint-salt]
|
||||
basepython = python2.7
|
||||
deps = -r{toxinidir}/requirements/dev.txt
|
||||
commands =
|
||||
pylint --version
|
||||
pylint --rcfile=.testing.pylintrc --disable=I,W1307,C0411,C0413,W8410,str-format-in-logging {posargs:setup.py salt/}
|
||||
sitepackages = False
|
||||
|
||||
[testenv:pylint-tests]
|
||||
basepython = python2.7
|
||||
deps = -r{toxinidir}/requirements/dev.txt
|
||||
commands =
|
||||
pylint --version
|
||||
pylint --rcfile=.testing.pylintrc --disable=I,W0232,E1002,W1307,C0411,C0413,W8410,str-format-in-logging {posargs:tests/}
|
||||
sitepackages = False
|
||||
|
||||
[pytest]
|
||||
addopts = --log-file /tmp/salt-runtests.log --no-print-logs --ssh-tests -ra -sv
|
||||
|
|
Loading…
Add table
Reference in a new issue