mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge branch '2017.7' into parted-naming
This commit is contained in:
commit
563ad25eb7
141 changed files with 5552 additions and 1088 deletions
50
.ci/docs
Normal file
50
.ci/docs
Normal file
|
@ -0,0 +1,50 @@
|
|||
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') {
|
||||
steps {
|
||||
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||
description: 'Testing docs...',
|
||||
status: 'PENDING',
|
||||
context: "jenkins/pr/docs"
|
||||
}
|
||||
}
|
||||
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 sphinx -e .'
|
||||
}
|
||||
}
|
||||
stage('build') {
|
||||
steps {
|
||||
sh 'eval "$(pyenv init -)"; make -C doc clean html'
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
cleanWs()
|
||||
}
|
||||
success {
|
||||
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||
description: 'The docs job has passed',
|
||||
status: 'SUCCESS',
|
||||
context: "jenkins/pr/docs"
|
||||
}
|
||||
failure {
|
||||
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||
description: 'The docs job has failed',
|
||||
status: 'FAILURE',
|
||||
context: "jenkins/pr/docs"
|
||||
}
|
||||
}
|
||||
}
|
71
.ci/kitchen-centos7-py2
Normal file
71
.ci/kitchen-centos7-py2
Normal file
|
@ -0,0 +1,71 @@
|
|||
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"
|
||||
PATH = "/usr/local/rbenv/shims/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin"
|
||||
RBENV_VERSION = "2.4.2"
|
||||
TEST_SUITE = "py2"
|
||||
TEST_PLATFORM = "centos-7"
|
||||
PY_COLORS = 1
|
||||
}
|
||||
stages {
|
||||
stage('github-pending') {
|
||||
steps {
|
||||
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||
description: "running ${TEST_SUITE}-${TEST_PLATFORM}...",
|
||||
status: 'PENDING',
|
||||
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
|
||||
}
|
||||
}
|
||||
stage('setup') {
|
||||
steps {
|
||||
sh 'bundle install --with ec2 windows --without opennebula docker'
|
||||
}
|
||||
}
|
||||
stage('run kitchen') {
|
||||
steps {
|
||||
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-testing.pem'
|
||||
sh 'bundle exec kitchen converge $TEST_SUITE-$TEST_PLATFORM || bundle exec kitchen converge $TEST_SUITE-$TEST_PLATFORM'
|
||||
sh 'bundle exec kitchen verify $TEST_SUITE-$TEST_PLATFORM'
|
||||
}
|
||||
}}
|
||||
}
|
||||
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-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",
|
||||
status: 'SUCCESS',
|
||||
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
|
||||
}
|
||||
failure {
|
||||
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||
description: "The ${TEST_SUITE}-${TEST_PLATFORM} job has failed",
|
||||
status: 'FAILURE',
|
||||
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
|
||||
}
|
||||
}
|
||||
}
|
71
.ci/kitchen-centos7-py3
Normal file
71
.ci/kitchen-centos7-py3
Normal file
|
@ -0,0 +1,71 @@
|
|||
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"
|
||||
PATH = "/usr/local/rbenv/shims/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin"
|
||||
RBENV_VERSION = "2.4.2"
|
||||
TEST_SUITE = "py3"
|
||||
TEST_PLATFORM = "centos-7"
|
||||
PY_COLORS = 1
|
||||
}
|
||||
stages {
|
||||
stage('github-pending') {
|
||||
steps {
|
||||
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||
description: "running ${TEST_SUITE}-${TEST_PLATFORM}...",
|
||||
status: 'PENDING',
|
||||
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
|
||||
}
|
||||
}
|
||||
stage('setup') {
|
||||
steps {
|
||||
sh 'bundle install --with ec2 windows --without opennebula docker'
|
||||
}
|
||||
}
|
||||
stage('run kitchen') {
|
||||
steps {
|
||||
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-testing.pem'
|
||||
sh 'bundle exec kitchen converge $TEST_SUITE-$TEST_PLATFORM || bundle exec kitchen converge $TEST_SUITE-$TEST_PLATFORM'
|
||||
sh 'bundle exec kitchen verify $TEST_SUITE-$TEST_PLATFORM'
|
||||
}
|
||||
}}
|
||||
}
|
||||
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-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",
|
||||
status: 'SUCCESS',
|
||||
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
|
||||
}
|
||||
failure {
|
||||
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||
description: "The ${TEST_SUITE}-${TEST_PLATFORM} job has failed",
|
||||
status: 'FAILURE',
|
||||
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
|
||||
}
|
||||
}
|
||||
}
|
71
.ci/kitchen-ubuntu1604-py2
Normal file
71
.ci/kitchen-ubuntu1604-py2
Normal file
|
@ -0,0 +1,71 @@
|
|||
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"
|
||||
PATH = "/usr/local/rbenv/shims/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin"
|
||||
RBENV_VERSION = "2.4.2"
|
||||
TEST_SUITE = "py2"
|
||||
TEST_PLATFORM = "ubuntu-1604"
|
||||
PY_COLORS = 1
|
||||
}
|
||||
stages {
|
||||
stage('github-pending') {
|
||||
steps {
|
||||
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||
description: "running ${TEST_SUITE}-${TEST_PLATFORM}...",
|
||||
status: 'PENDING',
|
||||
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
|
||||
}
|
||||
}
|
||||
stage('setup') {
|
||||
steps {
|
||||
sh 'bundle install --with ec2 windows --without opennebula docker'
|
||||
}
|
||||
}
|
||||
stage('run kitchen') {
|
||||
steps {
|
||||
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-testing.pem'
|
||||
sh 'bundle exec kitchen converge $TEST_SUITE-$TEST_PLATFORM || bundle exec kitchen converge $TEST_SUITE-$TEST_PLATFORM'
|
||||
sh 'bundle exec kitchen verify $TEST_SUITE-$TEST_PLATFORM'
|
||||
}
|
||||
}}
|
||||
}
|
||||
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-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",
|
||||
status: 'SUCCESS',
|
||||
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
|
||||
}
|
||||
failure {
|
||||
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||
description: "The ${TEST_SUITE}-${TEST_PLATFORM} job has failed",
|
||||
status: 'FAILURE',
|
||||
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
|
||||
}
|
||||
}
|
||||
}
|
71
.ci/kitchen-ubuntu1604-py3
Normal file
71
.ci/kitchen-ubuntu1604-py3
Normal file
|
@ -0,0 +1,71 @@
|
|||
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"
|
||||
PATH = "/usr/local/rbenv/shims/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin"
|
||||
RBENV_VERSION = "2.4.2"
|
||||
TEST_SUITE = "py3"
|
||||
TEST_PLATFORM = "ubuntu-1604"
|
||||
PY_COLORS = 1
|
||||
}
|
||||
stages {
|
||||
stage('github-pending') {
|
||||
steps {
|
||||
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||
description: "running ${TEST_SUITE}-${TEST_PLATFORM}...",
|
||||
status: 'PENDING',
|
||||
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
|
||||
}
|
||||
}
|
||||
stage('setup') {
|
||||
steps {
|
||||
sh 'bundle install --with ec2 windows --without opennebula docker'
|
||||
}
|
||||
}
|
||||
stage('run kitchen') {
|
||||
steps {
|
||||
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-testing.pem'
|
||||
sh 'bundle exec kitchen converge $TEST_SUITE-$TEST_PLATFORM || bundle exec kitchen converge $TEST_SUITE-$TEST_PLATFORM'
|
||||
sh 'bundle exec kitchen verify $TEST_SUITE-$TEST_PLATFORM'
|
||||
}
|
||||
}}
|
||||
}
|
||||
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-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",
|
||||
status: 'SUCCESS',
|
||||
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
|
||||
}
|
||||
failure {
|
||||
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||
description: "The ${TEST_SUITE}-${TEST_PLATFORM} job has failed",
|
||||
status: 'FAILURE',
|
||||
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
|
||||
}
|
||||
}
|
||||
}
|
72
.ci/lint
Normal file
72
.ci/lint
Normal file
|
@ -0,0 +1,72 @@
|
|||
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') {
|
||||
steps {
|
||||
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||
description: 'Testing lint...',
|
||||
status: 'PENDING',
|
||||
context: "jenkins/pr/lint"
|
||||
}
|
||||
}
|
||||
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 tox'
|
||||
}
|
||||
}
|
||||
stage('linting') {
|
||||
failFast false
|
||||
parallel {
|
||||
stage('salt linting') {
|
||||
steps {
|
||||
sh 'eval "$(pyenv init -)"; tox -e pylint-salt $(find salt/ -name "*.py" -exec git diff --name-only "origin/$CHANGE_TARGET" "origin/$BRANCH_NAME" setup.py {} +) | tee pylint-report.xml'
|
||||
archiveArtifacts artifacts: 'pylint-report.xml'
|
||||
}
|
||||
}
|
||||
stage('test linting') {
|
||||
steps {
|
||||
sh 'eval "$(pyenv init -)"; tox -e pylint-tests $(find tests/ -name "*.py" -exec git diff --name-only "origin/$CHANGE_TARGET" "origin/$BRANCH_NAME" {} +) | tee pylint-report-tests.xml'
|
||||
archiveArtifacts artifacts: 'pylint-report-tests.xml'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
step([$class: 'WarningsPublisher',
|
||||
parserConfigurations: [[
|
||||
parserName: 'PyLint',
|
||||
pattern: 'pylint-report*.xml'
|
||||
]],
|
||||
failedTotalAll: '0',
|
||||
useDeltaValues: false,
|
||||
canRunOnFailed: true,
|
||||
usePreviousBuildAsReference: true
|
||||
])
|
||||
cleanWs()
|
||||
}
|
||||
success {
|
||||
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||
description: 'The lint job has passed',
|
||||
status: 'SUCCESS',
|
||||
context: "jenkins/pr/lint"
|
||||
}
|
||||
failure {
|
||||
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||
description: 'The lint job has failed',
|
||||
status: 'FAILURE',
|
||||
context: "jenkins/pr/lint"
|
||||
}
|
||||
}
|
||||
}
|
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
|
||||
|
||||
|
|
13
.kitchen.yml
13
.kitchen.yml
|
@ -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:
|
||||
|
@ -43,21 +43,20 @@ provisioner:
|
|||
repo: git
|
||||
testingdir: /testing
|
||||
salt_copy_filter:
|
||||
- __pycache__
|
||||
- '*.pyc'
|
||||
- .bundle
|
||||
- .tox
|
||||
- .kitchen
|
||||
- .kitchen.yml
|
||||
- artifacts
|
||||
- Gemfile
|
||||
- Gemfile.lock
|
||||
- README.rst
|
||||
- .travis.yml
|
||||
state_top:
|
||||
base:
|
||||
"os:Windows":
|
||||
- match: grain
|
||||
- prep_windows
|
||||
"*":
|
||||
- git.salt
|
||||
- <%= ENV['KITCHEN_STATE'] || 'git.salt' %>
|
||||
pillars:
|
||||
top.sls:
|
||||
base:
|
||||
|
|
8
doc/_themes/saltstack2/layout.html
vendored
8
doc/_themes/saltstack2/layout.html
vendored
|
@ -138,7 +138,7 @@
|
|||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a href="http://saltstack.com/" target="_blank"><img src="{{ pathto('_static/images/saltstack.svg', 1) }}" class="nolightbox" height="40px" width="170px"></a>
|
||||
<a href="http://saltstack.com/" target="_blank"><img src="{{ pathto('_static/images/SaltStack_white.svg', 1) }}" class="nolightbox" height="40px" width="170px"></a>
|
||||
</div>
|
||||
<!-- Collect the nav links, forms, and other content for toggling -->
|
||||
<div class="collapse navbar-collapse" id="navbarCollapse">
|
||||
|
@ -252,13 +252,11 @@
|
|||
<p>© {{ copyright }} SaltStack. All Rights Reserved, SaltStack Inc. | <a href="http://saltstack.com/privacy-policy" target="_blank">Privacy Policy</a></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6">
|
||||
|
||||
<!--
|
||||
<a href="https://saltstack.com/saltstack-enterprise/" target="_blank"><img class="nolightbox footer-banner center" src="{{ pathto('_static/images/enterprise_ad.jpg', 1) }}"/></a>
|
||||
-->
|
||||
<a href="http://saltconf.com" target="_blank"><img class="nolightbox footer-banner center" src="{{ pathto('_static/images/DOCBANNER.jpg', 1) }}"/></a>
|
||||
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
|
BIN
doc/_themes/saltstack2/static/images/DOCBANNER.jpg
vendored
BIN
doc/_themes/saltstack2/static/images/DOCBANNER.jpg
vendored
Binary file not shown.
Before Width: | Height: | Size: 240 KiB After Width: | Height: | Size: 589 KiB |
1
doc/_themes/saltstack2/static/images/SaltStack_white.svg
vendored
Normal file
1
doc/_themes/saltstack2/static/images/SaltStack_white.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 301.57 44.47"><defs><style>.cls-1{fill:#fff;}</style></defs><title>Asset 2</title><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M50.63,6.05h8.79L72.58,43.24H64.15L61.7,35.6H48l-2.52,7.64H37.35Zm-.51,23.14h9.52l-4.7-14.64Z"/><path class="cls-1" d="M76.12,6.05h7.77V36.56h18.58v6.68H76.12Z"/><path class="cls-1" d="M127.07,6.05v6.58H115.94V43.24h-7.82V12.63H96.94V6.05Z"/><path class="cls-1" d="M190.53,6.05v6.58H179.41V43.24h-7.83V12.63H160.4V6.05Z"/><path class="cls-1" d="M200.41,6.05h8.8l13.16,37.19h-8.43l-2.45-7.64h-13.7l-2.52,7.64h-8.13Zm-.51,23.14h9.53l-4.7-14.64Z"/><path class="cls-1" d="M227.91,10.17a15.34,15.34,0,0,1,11.34-4.83q9.28-.2,13.71,5.87a13.46,13.46,0,0,1,2.69,6.89l-7.77.16a10.78,10.78,0,0,0-2-4A7.68,7.68,0,0,0,239.68,12a7.59,7.59,0,0,0-6.48,3.56Q230.88,19,231,25.25t2.73,9.32a7.91,7.91,0,0,0,6.49,3,7.27,7.27,0,0,0,6-2.8,11.86,11.86,0,0,0,1.84-4.35l7.72-.17a16.79,16.79,0,0,1-4.9,10,14.83,14.83,0,0,1-10.44,4q-7.94.16-12.59-4.88t-4.84-14.09Q222.85,15.56,227.91,10.17Z"/><path class="cls-1" d="M260.39,6.05H268V21.37L282.4,6.05h10.05L277.18,21.34l16.05,21.9h-10L271.78,27,268,30.8V43.24h-7.64Z"/><path class="cls-1" d="M15.65,12.47a9.05,9.05,0,0,1,4.6-1.05,10.15,10.15,0,0,1,4.63.94,5.29,5.29,0,0,1,3,4.77h7.47a11.06,11.06,0,0,0-4.4-9A16.57,16.57,0,0,0,20.79,5a23,23,0,0,0-5.14.54Z"/><path class="cls-1" d="M33.21,24.77a16.6,16.6,0,0,0-6.43-2.7l-6.53-1.54A22.45,22.45,0,0,1,15.31,19a3.18,3.18,0,0,1-1.81-3c0-.12,0-.22,0-.34H6.35c0,.3,0,.59,0,.9q0,5.47,3.76,8.05,2.22,1.54,8.15,2.85l4,.89a17.48,17.48,0,0,1,5.17,1.74A3.17,3.17,0,0,1,29,33c0,2.1-1.1,3.54-3.32,4.31a14.08,14.08,0,0,1-4.56.61c-3.13,0-5.33-.77-6.62-2.3a7.48,7.48,0,0,1-1.42-3.81H5.7a11,11,0,0,0,4.21,9.12q4.22,3.33,11.56,3.32,7.19,0,11.13-3.37a10.64,10.64,0,0,0,3.94-8.46A9.1,9.1,0,0,0,33.21,24.77Z"/><path class="cls-1" d="M137.55,12.73a9,9,0,0,1,4.6-1.05,10.18,10.18,0,0,1,4.63.94,5.33,5.33,0,0,1,3,4.77h7.47a11,11,0,0,0-4.41-9,16.54,16.54,0,0,0-10.15-3.12,23,23,0,0,0-5.14.54Z"/><path class="cls-1" d="M155.11,25a16.83,16.83,0,0,0-6.43-2.7l-6.53-1.54a21.71,21.71,0,0,1-4.94-1.54,3.17,3.17,0,0,1-1.81-3c0-.13,0-.23,0-.35h-7.19c0,.3-.05.6-.05.9,0,3.65,1.26,6.34,3.77,8.05,1.48,1,4.19,2,8.15,2.85l4,.89a17.29,17.29,0,0,1,5.16,1.74,3.16,3.16,0,0,1,1.63,2.85q0,3.15-3.32,4.32a14.39,14.39,0,0,1-4.56.6c-3.13,0-5.34-.76-6.62-2.3A7.48,7.48,0,0,1,135,32H127.6a11,11,0,0,0,4.21,9.13c2.8,2.21,6.66,3.32,11.55,3.32s8.51-1.13,11.14-3.37a10.7,10.7,0,0,0,3.94-8.47A9.1,9.1,0,0,0,155.11,25Z"/><rect class="cls-1" width="9.85" height="9.85"/><path class="cls-1" d="M299.8,40.44a.94.94,0,0,0,.16-.57,1.06,1.06,0,0,0-.08-.45.82.82,0,0,0-.24-.32,1,1,0,0,0-.38-.19,1.72,1.72,0,0,0-.52-.07h-1.2v3.4h.59V40.93h.66l.68,1.31h.63v0l-.76-1.42A1,1,0,0,0,299.8,40.44Zm-.59-.14a.52.52,0,0,1-.19.12,1.18,1.18,0,0,1-.28,0h-.61V39.32h.61a.79.79,0,0,1,.28,0,.55.55,0,0,1,.2.11.76.76,0,0,1,.12.19.85.85,0,0,1,0,.23.56.56,0,0,1,0,.23A.36.36,0,0,1,299.21,40.3Z"/><path class="cls-1" d="M298.7,37.68a2.88,2.88,0,1,0,2.87,2.87A2.88,2.88,0,0,0,298.7,37.68Zm0,5.27a2.4,2.4,0,1,1,2.39-2.4A2.41,2.41,0,0,1,298.7,43Z"/></g></g></svg>
|
After Width: | Height: | Size: 3.1 KiB |
|
@ -250,8 +250,8 @@ on_saltstack = 'SALT_ON_SALTSTACK' in os.environ
|
|||
project = 'Salt'
|
||||
|
||||
version = salt.version.__version__
|
||||
latest_release = '2018.3.0' # latest release
|
||||
previous_release = '2017.7.5' # latest release from previous branch
|
||||
latest_release = '2018.3.2' # latest release
|
||||
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
|
||||
|
|
23
doc/faq.rst
23
doc/faq.rst
|
@ -148,22 +148,23 @@ Why aren't my custom modules/states/etc. available on my Minions?
|
|||
-----------------------------------------------------------------
|
||||
|
||||
Custom modules are synced to Minions when
|
||||
:mod:`saltutil.sync_modules <salt.modules.saltutil.sync_modules>`,
|
||||
or :mod:`saltutil.sync_all <salt.modules.saltutil.sync_all>` is run.
|
||||
Custom modules are also synced by :mod:`state.apply` when run without
|
||||
any arguments.
|
||||
:py:func:`saltutil.sync_modules <salt.modules.saltutil.sync_modules>`,
|
||||
or :py:func:`saltutil.sync_all <salt.modules.saltutil.sync_all>` is run.
|
||||
|
||||
Similarly, custom states are synced to Minions when :py:func:`saltutil.sync_states
|
||||
<salt.modules.saltutil.sync_states>`, or :py:func:`saltutil.sync_all
|
||||
<salt.modules.saltutil.sync_all>` is run.
|
||||
|
||||
Similarly, custom states are synced to Minions
|
||||
when :mod:`state.apply <salt.modules.state.apply_>`,
|
||||
:mod:`saltutil.sync_states <salt.modules.saltutil.sync_states>`, or
|
||||
:mod:`saltutil.sync_all <salt.modules.saltutil.sync_all>` is run.
|
||||
They are both also synced when a :ref:`highstate <running-highstate>` is
|
||||
triggered.
|
||||
|
||||
Custom states are also synced by :mod:`state.apply<salt.modules.state.apply_>`
|
||||
when run without any arguments.
|
||||
As of the Fluorine release, as well as 2017.7.7 and 2018.3.2 in their
|
||||
respective release cycles, the ``sync`` argument to :py:func:`state.apply
|
||||
<salt.modules.state.apply_>`/:py:func:`state.sls <salt.modules.state.sls>` can
|
||||
be used to sync custom types when running individual SLS files.
|
||||
|
||||
Other custom types (renderers, outputters, etc.) have similar behavior, see the
|
||||
documentation for the :mod:`saltutil <salt.modules.saltutil>` module for more
|
||||
documentation for the :py:func:`saltutil <salt.modules.saltutil>` module for more
|
||||
information.
|
||||
|
||||
:ref:`This reactor example <minion-start-reactor>` can be used to automatically
|
||||
|
|
|
@ -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
|
||||
.
|
||||
|
|
|
@ -1162,6 +1162,40 @@ The password used for HTTP proxy access.
|
|||
|
||||
proxy_password: obolus
|
||||
|
||||
Docker Configuration
|
||||
====================
|
||||
|
||||
.. conf_minion:: docker.update_mine
|
||||
|
||||
``docker.update_mine``
|
||||
----------------------
|
||||
|
||||
.. versionadded:: 2017.7.8,2018.3.3
|
||||
.. versionchanged:: Fluorine
|
||||
The default value is now ``False``
|
||||
|
||||
Default: ``True``
|
||||
|
||||
If enabled, when containers are added, removed, stopped, started, etc., the
|
||||
:ref:`mine <salt-mine>` will be updated with the results of :py:func:`docker.ps
|
||||
verbose=True all=True host=True <salt.modules.dockermod.ps>`. This mine data is
|
||||
used by :py:func:`mine.get_docker <salt.modules.mine.get_docker>`. Set this
|
||||
option to ``False`` to keep Salt from updating the mine with this information.
|
||||
|
||||
.. note::
|
||||
This option can also be set in Grains or Pillar data, with Grains
|
||||
overriding Pillar and the minion config file overriding Grains.
|
||||
|
||||
.. note::
|
||||
Disabling this will of course keep :py:func:`mine.get_docker
|
||||
<salt.modules.mine.get_docker>` from returning any information for a given
|
||||
minion.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
docker.update_mine: False
|
||||
|
||||
|
||||
Minion Module Management
|
||||
========================
|
||||
|
||||
|
|
|
@ -21,11 +21,21 @@ SaltStack has its own coding style guide that informs contributors on various co
|
|||
approaches. Please review the :ref:`Salt Coding Style <coding-style>` documentation
|
||||
for information about Salt's particular coding patterns.
|
||||
|
||||
Within the :ref:`Salt Coding Style <coding-style>` documentation, there is a section
|
||||
about running Salt's ``.pylintrc`` file. SaltStack recommends running the ``.pylintrc``
|
||||
file on any files you are changing with your code contribution before submitting a
|
||||
pull request to Salt's repository. Please see the :ref:`Linting<pylint-instructions>`
|
||||
documentation for more information.
|
||||
Within the :ref:`Salt Coding Style <coding-style>` documentation, there is a
|
||||
section about running Salt's ``.testing.pylintrc`` file. SaltStack recommends
|
||||
running the ``.testing.pylintrc`` file on any files you are changing with your
|
||||
code contribution before submitting a pull request to Salt's repository. Please
|
||||
see the :ref:`Linting<pylint-instructions>` documentation for more information.
|
||||
|
||||
.. note::
|
||||
|
||||
There are two pylint files in the ``salt`` directory. One is the
|
||||
``.pylintrc`` file and the other is the ``.testing.pylintrc`` file. The
|
||||
tests that run in Jenkins against GitHub Pull Requests use
|
||||
``.testing.pylintrc``. The ``testing.pylintrc`` file is a little less
|
||||
strict than the ``.pylintrc`` and is used to make it easier for contributors
|
||||
to submit changes. The ``.pylintrc`` file can be used for linting, but the
|
||||
``testing.pylintrc`` is the source of truth when submitting pull requests.
|
||||
|
||||
|
||||
.. _github-pull-request:
|
||||
|
|
|
@ -22,21 +22,31 @@ improve Salt)!!
|
|||
Linting
|
||||
=======
|
||||
|
||||
Most Salt style conventions are codified in Salt's ``.pylintrc`` file. Salt's
|
||||
pylint file has two dependencies: pylint_ and saltpylint_. You can install
|
||||
these dependencies with ``pip``:
|
||||
Most Salt style conventions are codified in Salt's ``.testing.pylintrc`` file.
|
||||
Salt's pylint file has two dependencies: pylint_ and saltpylint_. You can
|
||||
install these dependencies with ``pip``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pip install pylint
|
||||
pip install saltpylint
|
||||
|
||||
The ``.pylintrc`` file is found in the root of the Salt project and can be passed
|
||||
as an argument to the pylint_ program as follows:
|
||||
The ``.testing.pylintrc`` file is found in the root of the Salt project and can
|
||||
be passed as an argument to the pylint_ program as follows:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pylint --rcfile=/path/to/salt/.pylintrc salt/dir/to/lint
|
||||
pylint --rcfile=/path/to/salt/.testing.pylintrc salt/dir/to/lint
|
||||
|
||||
.. note::
|
||||
|
||||
There are two pylint files in the ``salt`` directory. One is the
|
||||
``.pylintrc`` file and the other is the ``.testing.pylintrc`` file. The
|
||||
tests that run in Jenkins against GitHub Pull Requests use
|
||||
``.testing.pylintrc``. The ``testing.pylintrc`` file is a little less
|
||||
strict than the ``.pylintrc`` and is used to make it easier for contributors
|
||||
to submit changes. The ``.pylintrc`` file can be used for linting, but the
|
||||
``testing.pylintrc`` is the source of truth when submitting pull requests.
|
||||
|
||||
.. _pylint: http://www.pylint.org
|
||||
.. _saltpylint: https://github.com/saltstack/salt-pylint
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
========================================
|
||||
In Progress: Salt 2017.7.6 Release Notes
|
||||
========================================
|
||||
|
||||
Version 2017.7.6 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.
|
||||
===========================
|
||||
Salt 2017.7.6 Release Notes
|
||||
===========================
|
||||
|
||||
Version 2017.7.6 is a bugfix release for :ref:`2017.7.0 <release-2017-7-0>`.
|
||||
|
||||
Statistics
|
||||
==========
|
||||
|
@ -16,6 +13,15 @@ Statistics
|
|||
|
||||
- Contributors: **47** (`Ch3LL`_, `DmitryKuzmenko`_, `GwiYeong`_, `Quarky9`_, `RichardW42`_, `UtahDave`_, `amaclean199`_, `arif-ali`_, `baniobloom`_, `bdrung`_, `benediktwerner`_, `bmiguel-teixeira`_, `cachedout`_, `dafenko`_, `damon-atkins`_, `dwoz`_, `ezh`_, `folti`_, `fpicot`_, `frogunder`_, `garethgreenaway`_, `gtmanfred`_, `isbm`_, `jeroennijhof`_, `jfindlay`_, `jfoboss`_, `kstreee`_, `lomeroe`_, `mattp-`_, `meaksh`_, `mirceaulinic`_, `myinitialsarepm`_, `mzbroch`_, `nages13`_, `paclat`_, `pcjeff`_, `pruiz`_, `psyer`_, `rallytime`_, `s0undt3ch`_, `skizunov`_, `smitty42`_, `terminalmage`_, `twangboy`_, `vutny`_, `yagnik`_, `yannj-fr`_)
|
||||
|
||||
Tornado 5.0 Support for Python 2 Only
|
||||
-------------------------------------
|
||||
|
||||
Tornado 5.0 moves to using asyncio for all python3 versions. Because of this
|
||||
and changes in asyncio between python 3.4 and 3.5 to only be able to use one
|
||||
ioloop, which requires some rearchitecting, support for tornado 5.0 and python3
|
||||
versions of salt has been delayed to a later release.
|
||||
|
||||
For now, to use tornado 5.0, the python 2 version of salt must be used.
|
||||
|
||||
Option to Return to Previous Pillar Include Behavior
|
||||
====================================================
|
||||
|
|
|
@ -1,19 +1,89 @@
|
|||
========================================
|
||||
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>`.
|
||||
|
||||
New win_snmp behavior
|
||||
=====================
|
||||
The ``2017.7.7`` release contains only a small number of fixes, which are detailed
|
||||
below.
|
||||
|
||||
- :py:func:`win_snmp.get_community_names
|
||||
<salt.modules.win_snmp.get_community_names>` now returns the SNMP settings
|
||||
actually in effect on the box. If settings are managed via GroupPolicy, those
|
||||
settings will be returned. Otherwise, normal settings are returned.
|
||||
This release fixes two critical issues.
|
||||
|
||||
- :py:func:`win_snmp.set_community_names
|
||||
<salt.modules.win_snmp.set_community_names>` now raises an error when SNMP
|
||||
settings are being managed by GroupPolicy.
|
||||
The first is Issue `#48038`_, which is a critical bug that occurs in a multi-syndic
|
||||
setup where the same job is run multiple times on a minion.
|
||||
|
||||
The second issue is `#48130`_. This bug appears in certain setups where the Master
|
||||
reports a Minion time-out, even though the job is still running on the Minion.
|
||||
|
||||
Both of these issues have been fixed with this release.
|
||||
|
||||
Statistics
|
||||
==========
|
||||
|
||||
- Total Merges: **5**
|
||||
- Total Issue References: **2**
|
||||
- Total PR References: **6**
|
||||
|
||||
- Contributors: **3** (`garethgreenaway`_, `gtmanfred`_, `rallytime`_)
|
||||
|
||||
Changelog for v2017.7.6..v2017.7.7
|
||||
==================================
|
||||
|
||||
*Generated at: 2018-06-17 19:26:52 UTC*
|
||||
|
||||
* **ISSUE** `#48130`_: (`rmarchei`_) Minion timeouts with 2018.3.1 (refs: `#48157`_)
|
||||
|
||||
* **PR** `#48157`_: (`gtmanfred`_) always listen when gathering job info
|
||||
@ *2018-06-17 19:04:09 UTC*
|
||||
|
||||
* 8af4452134 Merge pull request `#48157`_ from gtmanfred/2017.7.7
|
||||
|
||||
* d8209e8a40 always listen when gathering job info
|
||||
|
||||
* **PR** `#48140`_: (`rallytime`_) Update man pages for 2017.7.7
|
||||
@ *2018-06-14 21:22:43 UTC*
|
||||
|
||||
* b98c52ee51 Merge pull request `#48140`_ from rallytime/man-pages-2017.7.7
|
||||
|
||||
* 8893bf0d4c Update man pages for 2017.7.7
|
||||
|
||||
* **PR** `#48136`_: (`gtmanfred`_) [2017.7.7] bootstrap kitchen branch tests with 2017.7.6
|
||||
@ *2018-06-14 21:20:16 UTC*
|
||||
|
||||
* baa0363336 Merge pull request `#48136`_ from gtmanfred/2017.7.7
|
||||
|
||||
* fce1c31146 bootstrap kitchen branch tests with 2017.7.6
|
||||
|
||||
* **PR** `#48134`_: (`rallytime`_) Add release notes file for 2017.7.7
|
||||
@ *2018-06-14 16:31:34 UTC*
|
||||
|
||||
* b0ba08f4d9 Merge pull request `#48134`_ from rallytime/release-notes-2017.7.7
|
||||
|
||||
* 217005b8f1 Add missing `v` for tag reference
|
||||
|
||||
* d53569d1e3 Add release notes file for 2017.7.7
|
||||
|
||||
* **ISSUE** `#48038`_: (`austinpapp`_) jobs are not dedup'ing minion side (refs: `#48075`_)
|
||||
|
||||
* **PR** `#48098`_: (`rallytime`_) Back-port `#48075`_ to 2017.7.7
|
||||
@ *2018-06-14 12:53:42 UTC*
|
||||
|
||||
* **PR** `#48075`_: (`garethgreenaway`_) [2017.7] Ensure that the shared list of jids is passed (refs: `#48098`_)
|
||||
|
||||
* 084de927fe Merge pull request `#48098`_ from rallytime/bp-48075-2017.7.7
|
||||
|
||||
* e4e62e8b3a Ensure that the shared list of jids is passed when creating the Minion. Fixes an issue when minions are pointed at multiple syndics.
|
||||
|
||||
.. _`#48038`: https://github.com/saltstack/salt/issues/48038
|
||||
.. _`#48075`: https://github.com/saltstack/salt/pull/48075
|
||||
.. _`#48098`: https://github.com/saltstack/salt/pull/48098
|
||||
.. _`#48130`: https://github.com/saltstack/salt/issues/48130
|
||||
.. _`#48134`: https://github.com/saltstack/salt/pull/48134
|
||||
.. _`#48136`: https://github.com/saltstack/salt/pull/48136
|
||||
.. _`#48140`: https://github.com/saltstack/salt/pull/48140
|
||||
.. _`#48157`: https://github.com/saltstack/salt/pull/48157
|
||||
.. _`austinpapp`: https://github.com/austinpapp
|
||||
.. _`garethgreenaway`: https://github.com/garethgreenaway
|
||||
.. _`gtmanfred`: https://github.com/gtmanfred
|
||||
.. _`rallytime`: https://github.com/rallytime
|
||||
.. _`rmarchei`: https://github.com/rmarchei
|
||||
|
|
31
doc/topics/releases/2017.7.8.rst
Normal file
31
doc/topics/releases/2017.7.8.rst
Normal file
|
@ -0,0 +1,31 @@
|
|||
========================================
|
||||
In Progress: Salt 2017.7.8 Release Notes
|
||||
========================================
|
||||
|
||||
Version 2017.7.8 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.
|
||||
|
||||
New win_snmp behavior
|
||||
=====================
|
||||
|
||||
- :py:func:`win_snmp.get_community_names
|
||||
<salt.modules.win_snmp.get_community_names>` now returns the SNMP settings
|
||||
actually in effect on the box. If settings are managed via GroupPolicy, those
|
||||
settings will be returned. Otherwise, normal settings are returned.
|
||||
|
||||
- :py:func:`win_snmp.set_community_names
|
||||
<salt.modules.win_snmp.set_community_names>` now raises an error when SNMP
|
||||
settings are being managed by GroupPolicy.
|
||||
|
||||
Option Added to Disable Docker Mine Updates
|
||||
===========================================
|
||||
|
||||
When a docker container is added, removed, started, stopped, etc., the results
|
||||
of a :py:func:`docker.ps verbose=True all=True host=True
|
||||
<salt.modules.dockermod.ps>` are sent to the :ref:`mine <salt-mine>`, to be
|
||||
used by :py:func:`mine.get_docker <salt.modules.mine.get_docker>`.
|
||||
|
||||
A new config option (:conf_minion:`docker.update_mine`) has been added. When
|
||||
set to ``False``, Salt will not send this information to the mine. This is
|
||||
useful in cases where sensitive information is stored in the container's
|
||||
environment.
|
|
@ -509,9 +509,8 @@ overrides all levels below it):
|
|||
.. code-block:: yaml
|
||||
|
||||
gitfs_saltenv:
|
||||
- saltenv:
|
||||
- dev:
|
||||
- mountpoint: salt://bar
|
||||
- dev:
|
||||
- mountpoint: salt://bar
|
||||
|
||||
3. Per-remote configuration parameter
|
||||
|
||||
|
|
|
@ -330,7 +330,13 @@ Nested pillar values can also be set via the command line:
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' state.sls my_sls_file pillar='{"foo": {"bar": "baz"}}'
|
||||
salt '*' state.sls my_sls_file pillar='{"foo": {"bar": "baz"}}'
|
||||
|
||||
Lists can be passed via command line pillar data as follows:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' state.sls my_sls_file pillar='{"some_list": ["foo", "bar", "baz"]}'
|
||||
|
||||
.. note::
|
||||
|
||||
|
|
|
@ -135,13 +135,18 @@ where it is necessary to invoke the same function from a custom :ref:`outputter
|
|||
<all-salt.output>`/returner, as well as an execution module.
|
||||
|
||||
Utility modules placed in ``salt://_utils/`` will be synced to the minions when
|
||||
any of the following Salt functions are called:
|
||||
a :ref:`highstate <running-highstate>` is run, as well as when any of the
|
||||
following Salt functions are called:
|
||||
|
||||
* :mod:`state.apply <salt.modules.state.apply_>`
|
||||
* :mod:`saltutil.sync_utils <salt.modules.saltutil.sync_utils>`
|
||||
* :mod:`saltutil.sync_all <salt.modules.saltutil.sync_all>`
|
||||
* :py:func:`saltutil.sync_utils <salt.modules.saltutil.sync_utils>`
|
||||
* :py:func:`saltutil.sync_all <salt.modules.saltutil.sync_all>`
|
||||
|
||||
As of the Fluorine release, as well as 2017.7.7 and 2018.3.2 in their
|
||||
respective release cycles, the ``sync`` argument to :py:func:`state.apply
|
||||
<salt.modules.state.apply_>`/:py:func:`state.sls <salt.modules.state.sls>` can
|
||||
be used to sync custom types when running individual SLS files.
|
||||
|
||||
To sync to the Master, use either of the following:
|
||||
|
||||
* :mod:`saltutil.sync_utils <salt.runners.saltutil.sync_utils>`
|
||||
* :mod:`saltutil.sync_all <salt.runners.saltutil.sync_all>`
|
||||
* :py:func:`saltutil.sync_utils <salt.runners.saltutil.sync_utils>`
|
||||
* :py:func:`saltutil.sync_all <salt.runners.saltutil.sync_all>`
|
||||
|
|
|
@ -197,17 +197,17 @@ Write-Output " ----------------------------------------------------------------"
|
|||
Write-Output " - $script_name :: Updating PIP and SetupTools . . ."
|
||||
Write-Output " ----------------------------------------------------------------"
|
||||
if ( ! [bool]$Env:SALT_PIP_LOCAL_CACHE) {
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python2Dir'])\python.exe -m pip --no-cache-dir install -r $($script_path)\req_pip.txt" "python pip"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python2Dir'])\python.exe -m pip --disable-pip-version-check --no-cache-dir install -r $($script_path)\req_pip.txt" "python pip"
|
||||
} else {
|
||||
$p = New-Item $Env:SALT_PIP_LOCAL_CACHE -ItemType Directory -Force # Ensure directory exists
|
||||
if ( (Get-ChildItem $Env:SALT_PIP_LOCAL_CACHE | Measure-Object).Count -eq 0 ) {
|
||||
# folder empty
|
||||
Write-Output " pip download from req_pip.txt into empty local cache SALT_REQ_PIP $Env:SALT_PIP_LOCAL_CACHE"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python2Dir'])\python.exe -m pip download --dest $Env:SALT_PIP_LOCAL_CACHE -r $($script_path)\req_pip.txt" "pip download"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python2Dir'])\python.exe -m pip --disable-pip-version-check download --dest $Env:SALT_PIP_LOCAL_CACHE -r $($script_path)\req_pip.txt" "pip download"
|
||||
}
|
||||
Write-Output " reading from local pip cache $Env:SALT_PIP_LOCAL_CACHE"
|
||||
Write-Output " If a (new) resource is missing, please delete all files in this cache, go online and repeat"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python2Dir'])\python.exe -m pip install --no-index --find-links=$Env:SALT_PIP_LOCAL_CACHE -r $($script_path)\req_pip.txt" "pip install"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python2Dir'])\python.exe -m pip --disable-pip-version-check install --no-index --find-links=$Env:SALT_PIP_LOCAL_CACHE -r $($script_path)\req_pip.txt" "pip install"
|
||||
}
|
||||
|
||||
#==============================================================================
|
||||
|
@ -218,16 +218,16 @@ Write-Output " ----------------------------------------------------------------"
|
|||
Write-Output " - $script_name :: Installing pypi resources using pip . . ."
|
||||
Write-Output " ----------------------------------------------------------------"
|
||||
if ( ! [bool]$Env:SALT_REQ_LOCAL_CACHE) {
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python2Dir'])\python.exe -m pip --no-cache-dir install -r $($script_path)\req.txt" "pip install"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python2Dir'])\python.exe -m pip --disable-pip-version-check --no-cache-dir install -r $($script_path)\req.txt" "pip install"
|
||||
} else {
|
||||
if ( (Get-ChildItem $Env:SALT_REQ_LOCAL_CACHE | Measure-Object).Count -eq 0 ) {
|
||||
# folder empty
|
||||
Write-Output " pip download from req.txt into empty local cache SALT_REQ $Env:SALT_REQ_LOCAL_CACHE"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python2Dir'])\python.exe -m pip download --dest $Env:SALT_REQ_LOCAL_CACHE -r $($script_path)\req.txt" "pip download"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python2Dir'])\python.exe -m pip --disable-pip-version-check download --dest $Env:SALT_REQ_LOCAL_CACHE -r $($script_path)\req.txt" "pip download"
|
||||
}
|
||||
Write-Output " reading from local pip cache $Env:SALT_REQ_LOCAL_CACHE"
|
||||
Write-Output " If a (new) resource is missing, please delete all files in this cache, go online and repeat"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python2Dir'])\python.exe -m pip install --no-index --find-links=$Env:SALT_REQ_LOCAL_CACHE -r $($script_path)\req.txt" "pip install"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python2Dir'])\python.exe -m pip --disable-pip-version-check install --no-index --find-links=$Env:SALT_REQ_LOCAL_CACHE -r $($script_path)\req.txt" "pip install"
|
||||
}
|
||||
|
||||
#==============================================================================
|
||||
|
|
|
@ -197,17 +197,17 @@ Write-Output " ----------------------------------------------------------------"
|
|||
Write-Output " - $script_name :: Updating PIP and SetupTools . . ."
|
||||
Write-Output " ----------------------------------------------------------------"
|
||||
if ( ! [bool]$Env:SALT_PIP_LOCAL_CACHE) {
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python3Dir'])\python.exe -m pip --no-cache-dir install -r $($script_path)\req_pip.txt" "python pip"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python3Dir'])\python.exe -m pip --disable-pip-version-check --no-cache-dir install -r $($script_path)\req_pip.txt" "python pip"
|
||||
} else {
|
||||
$p = New-Item $Env:SALT_PIP_LOCAL_CACHE -ItemType Directory -Force # Ensure directory exists
|
||||
if ( (Get-ChildItem $Env:SALT_PIP_LOCAL_CACHE | Measure-Object).Count -eq 0 ) {
|
||||
# folder empty
|
||||
Write-Output " pip download from req_pip.txt into empty local cache SALT_REQ_PIP $Env:SALT_PIP_LOCAL_CACHE"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python3Dir'])\python.exe -m pip download --dest $Env:SALT_PIP_LOCAL_CACHE -r $($script_path)\req_pip.txt" "pip download"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python3Dir'])\python.exe -m pip --disable-pip-version-check download --dest $Env:SALT_PIP_LOCAL_CACHE -r $($script_path)\req_pip.txt" "pip download"
|
||||
}
|
||||
Write-Output " reading from local pip cache $Env:SALT_PIP_LOCAL_CACHE"
|
||||
Write-Output " If a (new) resource is missing, please delete all files in this cache, go online and repeat"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python3Dir'])\python.exe -m pip install --no-index --find-links=$Env:SALT_PIP_LOCAL_CACHE -r $($script_path)\req_pip.txt" "pip install"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python3Dir'])\python.exe -m pip --disable-pip-version-check install --no-index --find-links=$Env:SALT_PIP_LOCAL_CACHE -r $($script_path)\req_pip.txt" "pip install"
|
||||
}
|
||||
|
||||
#==============================================================================
|
||||
|
@ -218,16 +218,16 @@ Write-Output " ----------------------------------------------------------------"
|
|||
Write-Output " - $script_name :: Installing pypi resources using pip . . ."
|
||||
Write-Output " ----------------------------------------------------------------"
|
||||
if ( ! [bool]$Env:SALT_REQ_LOCAL_CACHE) {
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python3Dir'])\python.exe -m pip --no-cache-dir install -r $($script_path)\req.txt" "pip install"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python3Dir'])\python.exe -m pip --disable-pip-version-check --no-cache-dir install -r $($script_path)\req.txt" "pip install"
|
||||
} else {
|
||||
if ( (Get-ChildItem $Env:SALT_REQ_LOCAL_CACHE | Measure-Object).Count -eq 0 ) {
|
||||
# folder empty
|
||||
Write-Output " pip download from req.txt into empty local cache SALT_REQ $Env:SALT_REQ_LOCAL_CACHE"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python3Dir'])\python.exe -m pip download --dest $Env:SALT_REQ_LOCAL_CACHE -r $($script_path)\req.txt" "pip download"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python3Dir'])\python.exe -m pip --disable-pip-version-check download --dest $Env:SALT_REQ_LOCAL_CACHE -r $($script_path)\req.txt" "pip download"
|
||||
}
|
||||
Write-Output " reading from local pip cache $Env:SALT_REQ_LOCAL_CACHE"
|
||||
Write-Output " If a (new) resource is missing, please delete all files in this cache, go online and repeat"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python3Dir'])\python.exe -m pip install --no-index --find-links=$Env:SALT_REQ_LOCAL_CACHE -r $($script_path)\req.txt" "pip install"
|
||||
Start_Process_and_test_exitcode "cmd" "/c $($ini['Settings']['Python3Dir'])\python.exe -m pip --disable-pip-version-check install --no-index --find-links=$Env:SALT_REQ_LOCAL_CACHE -r $($script_path)\req.txt" "pip install"
|
||||
}
|
||||
|
||||
#==============================================================================
|
||||
|
|
|
@ -130,20 +130,18 @@ If Defined ProgramFiles(x86) (
|
|||
)
|
||||
@echo.
|
||||
|
||||
@echo Copying VCRedist to Prerequisites
|
||||
@echo ----------------------------------------------------------------------
|
||||
:: Make sure the "prereq" directory exists
|
||||
If NOT Exist "%PreDir%" mkdir "%PreDir%"
|
||||
|
||||
:: Set the location of the vcredist to download
|
||||
If %Python%==3 (
|
||||
Set Url64="http://repo.saltstack.com/windows/dependencies/64/vcredist_x64_2015.exe"
|
||||
Set Url32="http://repo.saltstack.com/windows/dependencies/32/vcredist_x86_2015.exe"
|
||||
:: Don't include the vcredist for Py3 installations
|
||||
If %Python%==3 goto :vcredist_end
|
||||
|
||||
) Else (
|
||||
Set Url64="http://repo.saltstack.com/windows/dependencies/64/vcredist_x64_2008_mfc.exe"
|
||||
Set Url32="http://repo.saltstack.com/windows/dependencies/32/vcredist_x86_2008_mfc.exe"
|
||||
)
|
||||
@echo Copying VCRedist to Prerequisites
|
||||
@echo ----------------------------------------------------------------------
|
||||
|
||||
:: Set the location of the vcredist to download
|
||||
Set Url64="http://repo.saltstack.com/windows/dependencies/64/vcredist_x64_2008_mfc.exe"
|
||||
Set Url32="http://repo.saltstack.com/windows/dependencies/32/vcredist_x86_2008_mfc.exe"
|
||||
|
||||
:: Check for 64 bit by finding the Program Files (x86) directory
|
||||
If Defined ProgramFiles(x86) (
|
||||
|
@ -153,6 +151,8 @@ If Defined ProgramFiles(x86) (
|
|||
)
|
||||
@echo.
|
||||
|
||||
:vcredist_end
|
||||
|
||||
:: Remove the fixed path in .exe files
|
||||
@echo Removing fixed path from .exe files
|
||||
@echo ----------------------------------------------------------------------
|
||||
|
|
|
@ -211,26 +211,13 @@ Section -Prerequisites
|
|||
Var /Global CheckVcRedist
|
||||
StrCpy $CheckVcRedist "False"
|
||||
|
||||
# Visual C++ 2015 redist packages
|
||||
!define PY3_VC_REDIST_NAME "VC_Redist_2015"
|
||||
!define PY3_VC_REDIST_X64_GUID "{50A2BC33-C9CD-3BF1-A8FF-53C10A0B183C}"
|
||||
!define PY3_VC_REDIST_X86_GUID "{BBF2AC74-720C-3CB3-8291-5E34039232FA}"
|
||||
|
||||
# Visual C++ 2008 SP1 MFC Security Update redist packages
|
||||
!define PY2_VC_REDIST_NAME "VC_Redist_2008_SP1_MFC"
|
||||
!define PY2_VC_REDIST_X64_GUID "{5FCE6D76-F5DC-37AB-B2B8-22AB8CEDB1D4}"
|
||||
!define PY2_VC_REDIST_X86_GUID "{9BE518E6-ECC6-35A9-88E4-87755C07200F}"
|
||||
|
||||
${If} ${PYTHON_VERSION} == 3
|
||||
StrCpy $VcRedistName ${PY3_VC_REDIST_NAME}
|
||||
${If} ${CPUARCH} == "AMD64"
|
||||
StrCpy $VcRedistGuid ${PY3_VC_REDIST_X64_GUID}
|
||||
${Else}
|
||||
StrCpy $VcRedistGuid ${PY3_VC_REDIST_X86_GUID}
|
||||
${EndIf}
|
||||
StrCpy $CheckVcRedist "True"
|
||||
|
||||
${Else}
|
||||
# VCRedist only needs to be installed for Python 2
|
||||
${If} ${PYTHON_VERSION} == 2
|
||||
|
||||
StrCpy $VcRedistName ${PY2_VC_REDIST_NAME}
|
||||
${If} ${CPUARCH} == "AMD64"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
[pytest]
|
||||
addopts = --ssh-tests -ra -sv
|
||||
testpaths = tests
|
||||
norecursedirs = tests/kitchen
|
|
@ -7,5 +7,6 @@ MarkupSafe
|
|||
requests>=1.0.0
|
||||
tornado>=4.2.1,<6.0; python_version < '3'
|
||||
tornado>=4.2.1,<5.0; python_version >= '3.4'
|
||||
|
||||
# Required by Tornado to handle threads stuff.
|
||||
futures>=2.0; python_version < '3.0'
|
||||
|
|
|
@ -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,3 +1,4 @@
|
|||
pytest>=3.5.0
|
||||
pytest-helpers-namespace
|
||||
pytest-tempdir
|
||||
pytest-cov
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
||||
|
|
|
@ -1106,7 +1106,10 @@ ARGS = {10}\n'''.format(self.minion_config,
|
|||
shim_tmp_file.write(salt.utils.to_bytes(cmd_str))
|
||||
|
||||
# Copy shim to target system, under $HOME/.<randomized name>
|
||||
target_shim_file = '.{0}.{1}'.format(binascii.hexlify(os.urandom(6)), extension)
|
||||
target_shim_file = '.{0}.{1}'.format(
|
||||
binascii.hexlify(os.urandom(6)).decode('ascii'),
|
||||
extension
|
||||
)
|
||||
if self.winrm:
|
||||
target_shim_file = saltwinshell.get_target_shim_file(self, target_shim_file)
|
||||
self.shell.send(shim_tmp_file.name, target_shim_file, makedirs=True)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -935,7 +935,7 @@ class Minion(MinionBase):
|
|||
# Flag meaning minion has finished initialization including first connect to the master.
|
||||
# True means the Minion is fully functional and ready to handle events.
|
||||
self.ready = False
|
||||
self.jid_queue = jid_queue or []
|
||||
self.jid_queue = [] if jid_queue is None else jid_queue
|
||||
self.periodic_callbacks = {}
|
||||
|
||||
if io_loop is None:
|
||||
|
@ -1032,10 +1032,11 @@ class Minion(MinionBase):
|
|||
# I made the following 3 line oddity to preserve traceback.
|
||||
# Please read PR #23978 before changing, hopefully avoiding regressions.
|
||||
# Good luck, we're all counting on you. Thanks.
|
||||
future_exception = self._connect_master_future.exception()
|
||||
if future_exception:
|
||||
# This needs to be re-raised to preserve restart_on_error behavior.
|
||||
raise six.reraise(*future_exception)
|
||||
if self._connect_master_future.done():
|
||||
future_exception = self._connect_master_future.exception()
|
||||
if future_exception:
|
||||
# This needs to be re-raised to preserve restart_on_error behavior.
|
||||
raise six.reraise(*future_exception)
|
||||
if timeout and self._sync_connect_master_success is False:
|
||||
raise SaltDaemonNotRunning('Failed to connect to the salt-master')
|
||||
|
||||
|
@ -1527,7 +1528,9 @@ class Minion(MinionBase):
|
|||
)
|
||||
ret['out'] = 'nested'
|
||||
except TypeError as exc:
|
||||
msg = 'Passed invalid arguments to {0}: {1}\n{2}'.format(function_name, exc, func.__doc__, )
|
||||
msg = 'Passed invalid arguments to {0}: {1}\n{2}'.format(
|
||||
function_name, exc, func.__doc__ or ''
|
||||
)
|
||||
log.warning(msg, exc_info_on_loglevel=logging.DEBUG)
|
||||
ret['return'] = msg
|
||||
ret['out'] = 'nested'
|
||||
|
|
|
@ -101,6 +101,7 @@ def cert(name,
|
|||
server=None,
|
||||
owner='root',
|
||||
group='root',
|
||||
mode='0640',
|
||||
certname=None):
|
||||
'''
|
||||
Obtain/renew a certificate from an ACME CA, probably Let's Encrypt.
|
||||
|
@ -113,8 +114,9 @@ def cert(name,
|
|||
:param renew: True/'force' to force a renewal, or a window of renewal before expiry in days
|
||||
:param keysize: RSA key bits
|
||||
:param server: API endpoint to talk to
|
||||
:param owner: owner of private key
|
||||
:param group: group of private key
|
||||
:param owner: owner of the private key file
|
||||
:param group: group of the private key file
|
||||
:param mode: mode of the private key file
|
||||
:param certname: Name of the certificate to save
|
||||
:return: dict with 'result' True/False/None, 'comment' and certificate's expiry date ('not_after')
|
||||
|
||||
|
@ -170,27 +172,17 @@ def cert(name,
|
|||
return {'result': False, 'comment': 'Certificate {0} renewal failed with:\n{1}'.format(name, res['stderr'])}
|
||||
|
||||
if 'no action taken' in res['stdout']:
|
||||
return {'result': None,
|
||||
'comment': 'No action taken on certificate {0}'.format(cert_file),
|
||||
'not_after': expires(name)}
|
||||
|
||||
if renew:
|
||||
comment = 'Certificate {0} unchanged'.format(cert_file)
|
||||
elif renew:
|
||||
comment = 'Certificate {0} renewed'.format(name)
|
||||
else:
|
||||
comment = 'Certificate {0} obtained'.format(name)
|
||||
ret = {'comment': comment, 'not_after': expires(name)}
|
||||
|
||||
res = __salt__['file.check_perms'](_cert_file(name, 'privkey'), {}, owner, group, '0600', follow_symlinks=True)
|
||||
|
||||
if res is None:
|
||||
ret['result'] = False
|
||||
ret['comment'] += ', but setting permissions failed.'
|
||||
elif not res[0].get('result', False):
|
||||
ret['result'] = False
|
||||
ret['comment'] += ', but setting permissions failed with \n{0}'.format(res[0]['comment'])
|
||||
else:
|
||||
ret['result'] = True
|
||||
ret['comment'] += '.'
|
||||
ret = {'comment': comment, 'not_after': expires(name), 'changes': {}, 'result': True}
|
||||
ret, _ = __salt__['file.check_perms'](_cert_file(name, 'privkey'),
|
||||
ret,
|
||||
owner, group, mode,
|
||||
follow_symlinks=True)
|
||||
|
||||
return ret
|
||||
|
||||
|
|
|
@ -304,7 +304,7 @@ def install(name=None,
|
|||
# We don't support installing specific version for now
|
||||
# so transform the dict in list ignoring version provided
|
||||
pkgs = [
|
||||
p.keys()[0] for p in pkgs
|
||||
next(iter(p)) for p in pkgs
|
||||
if isinstance(p, dict)
|
||||
]
|
||||
pkg_to_install.extend(pkgs)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -436,11 +436,20 @@ def _refresh_mine_cache(wrapped):
|
|||
refresh salt mine on exit.
|
||||
'''
|
||||
returned = wrapped(*args, **salt.utils.clean_kwargs(**kwargs))
|
||||
__salt__['mine.send']('docker.ps', verbose=True, all=True, host=True)
|
||||
if _check_update_mine():
|
||||
__salt__['mine.send']('docker.ps', verbose=True, all=True, host=True)
|
||||
return returned
|
||||
return wrapper
|
||||
|
||||
|
||||
def _check_update_mine():
|
||||
try:
|
||||
ret = __context__['docker.update_mine']
|
||||
except KeyError:
|
||||
ret = __context__['docker.update_mine'] = __salt__['config.get']('docker.update_mine', default=True)
|
||||
return ret
|
||||
|
||||
|
||||
# Helper functions
|
||||
def _change_state(name, action, expected, *args, **kwargs):
|
||||
'''
|
||||
|
@ -5226,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)
|
||||
)
|
||||
|
|
|
@ -870,7 +870,7 @@ def _network_conf(conf_tuples=None, **kwargs):
|
|||
# on old versions of lxc, still support the gateway auto mode
|
||||
# if we didn't explicitly say no to
|
||||
# (lxc.network.ipv4.gateway: auto)
|
||||
if _LooseVersion(version()) <= '1.0.7' and \
|
||||
if _LooseVersion(version()) <= _LooseVersion('1.0.7') and \
|
||||
True not in ['lxc.network.ipv4.gateway' in a for a in ret] and \
|
||||
True in ['lxc.network.ipv4' in a for a in ret]:
|
||||
ret.append({'lxc.network.ipv4.gateway': 'auto'})
|
||||
|
@ -2079,7 +2079,7 @@ def clone(name,
|
|||
if backing in ('dir', 'overlayfs', 'btrfs'):
|
||||
size = None
|
||||
# LXC commands and options changed in 2.0 - CF issue #34086 for details
|
||||
if version() >= _LooseVersion('2.0'):
|
||||
if _LooseVersion(version()) >= _LooseVersion('2.0'):
|
||||
# https://linuxcontainers.org/lxc/manpages//man1/lxc-copy.1.html
|
||||
cmd = 'lxc-copy'
|
||||
cmd += ' {0} -n {1} -N {2}'.format(snapshot, orig, name)
|
||||
|
@ -2270,22 +2270,22 @@ def _change_state(cmd,
|
|||
# as te command itself mess with double forks; we must not
|
||||
# communicate with it, but just wait for the exit status
|
||||
pkwargs = {'python_shell': False,
|
||||
'redirect_stderr': True,
|
||||
'with_communicate': with_communicate,
|
||||
'use_vt': use_vt,
|
||||
'stdin': stdin,
|
||||
'stdout': stdout,
|
||||
'stderr': stderr}
|
||||
'stdout': stdout}
|
||||
for i in [a for a in pkwargs]:
|
||||
val = pkwargs[i]
|
||||
if val is _marker:
|
||||
pkwargs.pop(i, None)
|
||||
|
||||
error = __salt__['cmd.run_stderr'](cmd, **pkwargs)
|
||||
_cmdout = __salt__['cmd.run_all'](cmd, **pkwargs)
|
||||
|
||||
if error:
|
||||
if _cmdout['retcode'] != 0:
|
||||
raise CommandExecutionError(
|
||||
'Error changing state for container \'{0}\' using command '
|
||||
'\'{1}\': {2}'.format(name, cmd, error)
|
||||
'\'{1}\': {2}'.format(name, cmd, _cmdout['stdout'])
|
||||
)
|
||||
if expected is not None:
|
||||
# some commands do not wait, so we will
|
||||
|
@ -3507,7 +3507,9 @@ def bootstrap(name,
|
|||
configdir = '/var/tmp/.c_{0}'.format(rstr)
|
||||
|
||||
cmd = 'install -m 0700 -d {0}'.format(configdir)
|
||||
if run(name, cmd, python_shell=False):
|
||||
if run_all(
|
||||
name, cmd, path=path, python_shell=False
|
||||
)['retcode'] != 0:
|
||||
log.error('tmpdir {0} creation failed ({1}'
|
||||
.format(configdir, cmd))
|
||||
return False
|
||||
|
@ -3518,6 +3520,7 @@ def bootstrap(name,
|
|||
copy_to(name, bs_, script, path=path)
|
||||
result = run_all(name,
|
||||
'sh -c "chmod +x {0}"'.format(script),
|
||||
path=path,
|
||||
python_shell=True)
|
||||
|
||||
copy_to(name, cfg_files['config'],
|
||||
|
@ -3544,6 +3547,7 @@ def bootstrap(name,
|
|||
run_all(name,
|
||||
'sh -c \'if [ -f "{0}" ];then rm -f "{0}";fi\''
|
||||
''.format(script),
|
||||
path=path,
|
||||
ignore_retcode=True,
|
||||
python_shell=True)
|
||||
else:
|
||||
|
|
|
@ -374,10 +374,18 @@ def flush():
|
|||
|
||||
def get_docker(interfaces=None, cidrs=None, with_container_id=False):
|
||||
'''
|
||||
Get all mine data for 'docker.get_containers' and run an aggregation
|
||||
routine. The "interfaces" parameter allows for specifying which network
|
||||
interfaces to select ip addresses from. The "cidrs" parameter allows for
|
||||
specifying a list of cidrs which the ip address must match.
|
||||
.. versionchanged:: 2017.7.8,2018.3.3
|
||||
When :conf_minion:`docker.update_mine` is set to ``False`` for a given
|
||||
minion, no mine data will be populated for that minion, and thus none
|
||||
will be returned for it.
|
||||
.. versionchanged:: Fluorine
|
||||
:conf_minion:`docker.update_mine` now defaults to ``False``
|
||||
|
||||
Get all mine data for :py:func:`docker.ps <salt.modules.dockermod.ps_>` and
|
||||
run an aggregation routine. The ``interfaces`` parameter allows for
|
||||
specifying the network interfaces from which to select IP addresses. The
|
||||
``cidrs`` parameter allows for specifying a list of subnets which the IP
|
||||
address must match.
|
||||
|
||||
with_container_id
|
||||
Boolean, to expose container_id in the list of results
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -168,20 +168,7 @@ def _get_pip_bin(bin_env):
|
|||
# If the python binary was passed, return it
|
||||
if 'python' in os.path.basename(bin_env):
|
||||
return [os.path.normpath(bin_env), '-m', 'pip']
|
||||
# Try to find the python binary based on the location of pip in a
|
||||
# virtual environment, should be relative
|
||||
if 'pip' in os.path.basename(bin_env):
|
||||
# Look in the same directory as the pip binary, and also its
|
||||
# parent directories.
|
||||
pip_dirname = os.path.dirname(bin_env)
|
||||
pip_parent_dir = os.path.dirname(pip_dirname)
|
||||
for bin_path in _search_paths(pip_dirname, pip_parent_dir):
|
||||
if os.path.isfile(bin_path):
|
||||
logger.debug('pip: Found python binary: %s', bin_path)
|
||||
return [os.path.normpath(bin_path), '-m', 'pip']
|
||||
|
||||
# Couldn't find python, use the passed pip binary
|
||||
# This has the limitation of being unable to update pip itself
|
||||
# We have been passed a pip binary, use the pip binary.
|
||||
return [os.path.normpath(bin_env)]
|
||||
|
||||
raise CommandExecutionError(
|
||||
|
@ -457,6 +444,13 @@ def install(pkgs=None, # pylint: disable=R0912,R0913,R0914
|
|||
``/usr/bin/pip-2.7`` or ``/usr/bin/pip-2.6``. If a directory path is
|
||||
specified, it is assumed to be a virtualenv.
|
||||
|
||||
.. note::
|
||||
|
||||
For Windows, if the pip module is being used to upgrade the pip
|
||||
package, bin_env should be the path to the virtualenv or to the
|
||||
python binary that should be used. The pip command is unable to
|
||||
upgrade itself in Windows.
|
||||
|
||||
use_wheel
|
||||
Prefer wheel archives (requires pip>=1.4)
|
||||
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -223,6 +223,7 @@ def list_users(runas=None):
|
|||
runas = salt.utils.get_user()
|
||||
res = __salt__['cmd.run_all'](
|
||||
[RABBITMQCTL, 'list_users', '-q'],
|
||||
reset_system_locale=False,
|
||||
runas=runas,
|
||||
python_shell=False)
|
||||
|
||||
|
@ -246,6 +247,7 @@ def list_vhosts(runas=None):
|
|||
runas = salt.utils.get_user()
|
||||
res = __salt__['cmd.run_all'](
|
||||
[RABBITMQCTL, 'list_vhosts', '-q'],
|
||||
reset_system_locale=False,
|
||||
runas=runas,
|
||||
python_shell=False)
|
||||
_check_response(res)
|
||||
|
@ -320,6 +322,7 @@ def add_user(name, password=None, runas=None):
|
|||
|
||||
res = __salt__['cmd.run_all'](
|
||||
cmd,
|
||||
reset_system_locale=False,
|
||||
output_loglevel='quiet',
|
||||
runas=runas,
|
||||
python_shell=python_shell)
|
||||
|
@ -352,6 +355,7 @@ def delete_user(name, runas=None):
|
|||
runas = salt.utils.get_user()
|
||||
res = __salt__['cmd.run_all'](
|
||||
[RABBITMQCTL, 'delete_user', name],
|
||||
reset_system_locale=False,
|
||||
python_shell=False,
|
||||
runas=runas)
|
||||
msg = 'Deleted'
|
||||
|
@ -387,6 +391,7 @@ def change_password(name, password, runas=None):
|
|||
cmd = [RABBITMQCTL, 'change_password', name, password]
|
||||
res = __salt__['cmd.run_all'](
|
||||
cmd,
|
||||
reset_system_locale=False,
|
||||
runas=runas,
|
||||
output_loglevel='quiet',
|
||||
python_shell=python_shell)
|
||||
|
@ -409,6 +414,7 @@ def clear_password(name, runas=None):
|
|||
runas = salt.utils.get_user()
|
||||
res = __salt__['cmd.run_all'](
|
||||
[RABBITMQCTL, 'clear_password', name],
|
||||
reset_system_locale=False,
|
||||
runas=runas,
|
||||
python_shell=False)
|
||||
msg = 'Password Cleared'
|
||||
|
@ -434,7 +440,7 @@ def check_password(name, password, runas=None):
|
|||
runas = salt.utils.get_user()
|
||||
|
||||
try:
|
||||
res = __salt__['cmd.run']([RABBITMQCTL, 'status'], runas=runas, python_shell=False)
|
||||
res = __salt__['cmd.run']([RABBITMQCTL, 'status'], reset_system_locale=False, runas=runas, python_shell=False)
|
||||
server_version = re.search(r'\{rabbit,"RabbitMQ","(.+)"\}', res)
|
||||
|
||||
if server_version is None:
|
||||
|
@ -466,6 +472,7 @@ def check_password(name, password, runas=None):
|
|||
|
||||
res = __salt__['cmd.run_all'](
|
||||
cmd,
|
||||
reset_system_locale=False,
|
||||
runas=runas,
|
||||
output_loglevel='quiet',
|
||||
python_shell=python_shell)
|
||||
|
@ -481,6 +488,7 @@ def check_password(name, password, runas=None):
|
|||
|
||||
res = __salt__['cmd.run_all'](
|
||||
[RABBITMQCTL, 'eval', cmd],
|
||||
reset_system_locale=False,
|
||||
runas=runas,
|
||||
output_loglevel='quiet',
|
||||
python_shell=False)
|
||||
|
@ -509,6 +517,7 @@ def add_vhost(vhost, runas=None):
|
|||
runas = salt.utils.get_user()
|
||||
res = __salt__['cmd.run_all'](
|
||||
[RABBITMQCTL, 'add_vhost', vhost],
|
||||
reset_system_locale=False,
|
||||
runas=runas,
|
||||
python_shell=False)
|
||||
|
||||
|
@ -530,6 +539,7 @@ def delete_vhost(vhost, runas=None):
|
|||
runas = salt.utils.get_user()
|
||||
res = __salt__['cmd.run_all'](
|
||||
[RABBITMQCTL, 'delete_vhost', vhost],
|
||||
reset_system_locale=False,
|
||||
runas=runas,
|
||||
python_shell=False)
|
||||
msg = 'Deleted'
|
||||
|
@ -551,6 +561,7 @@ def set_permissions(vhost, user, conf='.*', write='.*', read='.*', runas=None):
|
|||
res = __salt__['cmd.run_all'](
|
||||
[RABBITMQCTL, 'set_permissions', '-p',
|
||||
vhost, user, conf, write, read],
|
||||
reset_system_locale=False,
|
||||
runas=runas,
|
||||
python_shell=False)
|
||||
msg = 'Permissions Set'
|
||||
|
@ -571,6 +582,7 @@ def list_permissions(vhost, runas=None):
|
|||
runas = salt.utils.get_user()
|
||||
res = __salt__['cmd.run_all'](
|
||||
[RABBITMQCTL, 'list_permissions', '-q', '-p', vhost],
|
||||
reset_system_locale=False,
|
||||
runas=runas,
|
||||
python_shell=False)
|
||||
|
||||
|
@ -591,6 +603,7 @@ def list_user_permissions(name, runas=None):
|
|||
runas = salt.utils.get_user()
|
||||
res = __salt__['cmd.run_all'](
|
||||
[RABBITMQCTL, 'list_user_permissions', name, '-q'],
|
||||
reset_system_locale=False,
|
||||
runas=runas,
|
||||
python_shell=False)
|
||||
|
||||
|
@ -614,6 +627,7 @@ def set_user_tags(name, tags, runas=None):
|
|||
|
||||
res = __salt__['cmd.run_all'](
|
||||
[RABBITMQCTL, 'set_user_tags', name] + list(tags),
|
||||
reset_system_locale=False,
|
||||
runas=runas,
|
||||
python_shell=False)
|
||||
msg = "Tag(s) set"
|
||||
|
@ -634,6 +648,7 @@ def status(runas=None):
|
|||
runas = salt.utils.get_user()
|
||||
res = __salt__['cmd.run_all'](
|
||||
[RABBITMQCTL, 'status'],
|
||||
reset_system_locale=False,
|
||||
runas=runas,
|
||||
python_shell=False)
|
||||
_check_response(res)
|
||||
|
@ -654,6 +669,7 @@ def cluster_status(runas=None):
|
|||
runas = salt.utils.get_user()
|
||||
res = __salt__['cmd.run_all'](
|
||||
[RABBITMQCTL, 'cluster_status'],
|
||||
reset_system_locale=False,
|
||||
runas=runas,
|
||||
python_shell=False)
|
||||
_check_response(res)
|
||||
|
@ -678,7 +694,7 @@ def join_cluster(host, user='rabbit', ram_node=None, runas=None):
|
|||
if runas is None and not salt.utils.is_windows():
|
||||
runas = salt.utils.get_user()
|
||||
stop_app(runas)
|
||||
res = __salt__['cmd.run_all'](cmd, runas=runas, python_shell=False)
|
||||
res = __salt__['cmd.run_all'](cmd, reset_system_locale=False, runas=runas, python_shell=False)
|
||||
start_app(runas)
|
||||
|
||||
return _format_response(res, 'Join')
|
||||
|
@ -698,6 +714,7 @@ def stop_app(runas=None):
|
|||
runas = salt.utils.get_user()
|
||||
res = __salt__['cmd.run_all'](
|
||||
[RABBITMQCTL, 'stop_app'],
|
||||
reset_system_locale=False,
|
||||
runas=runas,
|
||||
python_shell=False)
|
||||
_check_response(res)
|
||||
|
@ -718,6 +735,7 @@ def start_app(runas=None):
|
|||
runas = salt.utils.get_user()
|
||||
res = __salt__['cmd.run_all'](
|
||||
[RABBITMQCTL, 'start_app'],
|
||||
reset_system_locale=False,
|
||||
runas=runas,
|
||||
python_shell=False)
|
||||
_check_response(res)
|
||||
|
@ -738,6 +756,7 @@ def reset(runas=None):
|
|||
runas = salt.utils.get_user()
|
||||
res = __salt__['cmd.run_all'](
|
||||
[RABBITMQCTL, 'reset'],
|
||||
reset_system_locale=False,
|
||||
runas=runas,
|
||||
python_shell=False)
|
||||
_check_response(res)
|
||||
|
@ -758,6 +777,7 @@ def force_reset(runas=None):
|
|||
runas = salt.utils.get_user()
|
||||
res = __salt__['cmd.run_all'](
|
||||
[RABBITMQCTL, 'force_reset'],
|
||||
reset_system_locale=False,
|
||||
runas=runas,
|
||||
python_shell=False)
|
||||
_check_response(res)
|
||||
|
@ -778,7 +798,7 @@ def list_queues(runas=None, *args):
|
|||
runas = salt.utils.get_user()
|
||||
cmd = [RABBITMQCTL, 'list_queues', '-q']
|
||||
cmd.extend(args)
|
||||
res = __salt__['cmd.run_all'](cmd, runas=runas, python_shell=False)
|
||||
res = __salt__['cmd.run_all'](cmd, reset_system_locale=False, runas=runas, python_shell=False)
|
||||
_check_response(res)
|
||||
return _output_to_dict(res['stdout'])
|
||||
|
||||
|
@ -800,7 +820,7 @@ def list_queues_vhost(vhost, runas=None, *args):
|
|||
runas = salt.utils.get_user()
|
||||
cmd = [RABBITMQCTL, 'list_queues', '-q', '-p', vhost]
|
||||
cmd.extend(args)
|
||||
res = __salt__['cmd.run_all'](cmd, runas=runas, python_shell=False)
|
||||
res = __salt__['cmd.run_all'](cmd, reset_system_locale=False, runas=runas, python_shell=False)
|
||||
_check_response(res)
|
||||
return _output_to_dict(res['stdout'])
|
||||
|
||||
|
@ -823,6 +843,7 @@ def list_policies(vhost="/", runas=None):
|
|||
runas = salt.utils.get_user()
|
||||
res = __salt__['cmd.run_all'](
|
||||
[RABBITMQCTL, 'list_policies', '-q', '-p', vhost],
|
||||
reset_system_locale=False,
|
||||
runas=runas,
|
||||
python_shell=False)
|
||||
_check_response(res)
|
||||
|
@ -873,8 +894,8 @@ def set_policy(vhost, name, pattern, definition, priority=None, runas=None):
|
|||
if priority:
|
||||
cmd.extend(['--priority', priority])
|
||||
cmd.extend([name, pattern, definition])
|
||||
res = __salt__['cmd.run_all'](cmd, runas=runas, python_shell=False)
|
||||
log.debug('Set policy: {0}'.format(res['stdout']))
|
||||
res = __salt__['cmd.run_all'](cmd, reset_system_locale=False, runas=runas, python_shell=False)
|
||||
log.debug('Set policy: %s', res['stdout'])
|
||||
return _format_response(res, 'Set')
|
||||
|
||||
|
||||
|
@ -894,6 +915,7 @@ def delete_policy(vhost, name, runas=None):
|
|||
runas = salt.utils.get_user()
|
||||
res = __salt__['cmd.run_all'](
|
||||
[RABBITMQCTL, 'clear_policy', '-p', vhost, name],
|
||||
reset_system_locale=False,
|
||||
runas=runas,
|
||||
python_shell=False)
|
||||
log.debug('Delete policy: {0}'.format(res['stdout']))
|
||||
|
@ -931,7 +953,7 @@ def list_available_plugins(runas=None):
|
|||
if runas is None and not salt.utils.is_windows():
|
||||
runas = salt.utils.get_user()
|
||||
cmd = [_get_rabbitmq_plugin(), 'list', '-m']
|
||||
ret = __salt__['cmd.run_all'](cmd, python_shell=False, runas=runas)
|
||||
ret = __salt__['cmd.run_all'](cmd, reset_system_locale=False, python_shell=False, runas=runas)
|
||||
_check_response(ret)
|
||||
return _output_to_list(ret['stdout'])
|
||||
|
||||
|
@ -949,7 +971,7 @@ def list_enabled_plugins(runas=None):
|
|||
if runas is None and not salt.utils.is_windows():
|
||||
runas = salt.utils.get_user()
|
||||
cmd = [_get_rabbitmq_plugin(), 'list', '-m', '-e']
|
||||
ret = __salt__['cmd.run_all'](cmd, python_shell=False, runas=runas)
|
||||
ret = __salt__['cmd.run_all'](cmd, reset_system_locale=False, python_shell=False, runas=runas)
|
||||
_check_response(ret)
|
||||
return _output_to_list(ret['stdout'])
|
||||
|
||||
|
@ -982,7 +1004,7 @@ def enable_plugin(name, runas=None):
|
|||
if runas is None and not salt.utils.is_windows():
|
||||
runas = salt.utils.get_user()
|
||||
cmd = [_get_rabbitmq_plugin(), 'enable', name]
|
||||
ret = __salt__['cmd.run_all'](cmd, runas=runas, python_shell=False)
|
||||
ret = __salt__['cmd.run_all'](cmd, reset_system_locale=False, runas=runas, python_shell=False)
|
||||
return _format_response(ret, 'Enabled')
|
||||
|
||||
|
||||
|
@ -999,5 +1021,5 @@ def disable_plugin(name, runas=None):
|
|||
if runas is None and not salt.utils.is_windows():
|
||||
runas = salt.utils.get_user()
|
||||
cmd = [_get_rabbitmq_plugin(), 'disable', name]
|
||||
ret = __salt__['cmd.run_all'](cmd, runas=runas, python_shell=False)
|
||||
ret = __salt__['cmd.run_all'](cmd, reset_system_locale=False, runas=runas, python_shell=False)
|
||||
return _format_response(ret, 'Disabled')
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -458,8 +458,7 @@ def template_str(tem, queue=False, **kwargs):
|
|||
return ret
|
||||
|
||||
|
||||
def apply_(mods=None,
|
||||
**kwargs):
|
||||
def apply_(mods=None, **kwargs):
|
||||
'''
|
||||
.. versionadded:: 2015.5.0
|
||||
|
||||
|
@ -599,6 +598,22 @@ def apply_(mods=None,
|
|||
.. code-block:: bash
|
||||
|
||||
salt '*' state.apply test localconfig=/path/to/minion.yml
|
||||
|
||||
sync_mods
|
||||
If specified, the desired custom module types will be synced prior to
|
||||
running the SLS files:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' state.apply test sync_mods=states,modules
|
||||
salt '*' state.apply test sync_mods=all
|
||||
|
||||
.. note::
|
||||
This option is ignored when no SLS files are specified, as a
|
||||
:ref:`highstate <running-highstate>` automatically syncs all custom
|
||||
module types.
|
||||
|
||||
.. versionadded:: 2017.7.8,2018.3.3,Fluorine
|
||||
'''
|
||||
if mods:
|
||||
return sls(mods, **kwargs)
|
||||
|
@ -928,7 +943,7 @@ def highstate(test=None, queue=False, **kwargs):
|
|||
return ret
|
||||
|
||||
|
||||
def sls(mods, test=None, exclude=None, queue=False, **kwargs):
|
||||
def sls(mods, test=None, exclude=None, queue=False, sync_mods=None, **kwargs):
|
||||
'''
|
||||
Execute the states in one or more SLS files
|
||||
|
||||
|
@ -1019,6 +1034,17 @@ def sls(mods, test=None, exclude=None, queue=False, **kwargs):
|
|||
|
||||
.. versionadded:: 2015.8.4
|
||||
|
||||
sync_mods
|
||||
If specified, the desired custom module types will be synced prior to
|
||||
running the SLS files:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' state.sls test sync_mods=states,modules
|
||||
salt '*' state.sls test sync_mods=all
|
||||
|
||||
.. versionadded:: 2017.7.8,2018.3.3,Fluorine
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
@ -1087,6 +1113,28 @@ def sls(mods, test=None, exclude=None, queue=False, **kwargs):
|
|||
'{0}.cache.p'.format(kwargs.get('cache_name', 'highstate'))
|
||||
)
|
||||
|
||||
if sync_mods is True:
|
||||
sync_mods = ['all']
|
||||
if sync_mods is not None:
|
||||
sync_mods = salt.utils.split_input(sync_mods)
|
||||
else:
|
||||
sync_mods = []
|
||||
|
||||
if 'all' in sync_mods and sync_mods != ['all']:
|
||||
# Prevent unnecessary extra syncing
|
||||
sync_mods = ['all']
|
||||
|
||||
for module_type in sync_mods:
|
||||
try:
|
||||
__salt__['saltutil.sync_{0}'.format(module_type)](
|
||||
saltenv=opts['environment']
|
||||
)
|
||||
except KeyError:
|
||||
log.warning(
|
||||
'Invalid custom module type \'%s\', ignoring',
|
||||
module_type
|
||||
)
|
||||
|
||||
try:
|
||||
st_ = salt.state.HighState(opts,
|
||||
pillar_override,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -484,60 +484,67 @@ def set_hwclock(clock):
|
|||
|
||||
salt '*' timezone.set_hwclock UTC
|
||||
'''
|
||||
if 'AIX' in __grains__['os_family']:
|
||||
if clock.lower() != 'utc':
|
||||
raise SaltInvocationError(
|
||||
'UTC is the only permitted value'
|
||||
)
|
||||
return True
|
||||
|
||||
timezone = get_zone()
|
||||
|
||||
if 'Solaris' in __grains__['os_family']:
|
||||
if clock.lower() not in ('localtime', 'utc'):
|
||||
raise SaltInvocationError(
|
||||
'localtime and UTC are the only permitted values'
|
||||
)
|
||||
if 'sparc' in __grains__['cpuarch']:
|
||||
raise SaltInvocationError(
|
||||
'UTC is the only choice for SPARC architecture'
|
||||
)
|
||||
cmd = ['rtc', '-z', 'GMT' if clock.lower() == 'utc' else timezone]
|
||||
return __salt__['cmd.retcode'](cmd, python_shell=False) == 0
|
||||
|
||||
zonepath = '/usr/share/zoneinfo/{0}'.format(timezone)
|
||||
|
||||
if not os.path.exists(zonepath):
|
||||
raise CommandExecutionError(
|
||||
'Zone \'{0}\' does not exist'.format(zonepath)
|
||||
)
|
||||
|
||||
os.unlink('/etc/localtime')
|
||||
os.symlink(zonepath, '/etc/localtime')
|
||||
|
||||
if 'Arch' in __grains__['os_family']:
|
||||
cmd = ['timezonectl', 'set-local-rtc',
|
||||
if salt.utils.which('timedatectl'):
|
||||
cmd = ['timedatectl', 'set-local-rtc',
|
||||
'true' if clock == 'localtime' else 'false']
|
||||
return __salt__['cmd.retcode'](cmd, python_shell=False) == 0
|
||||
elif 'RedHat' in __grains__['os_family']:
|
||||
__salt__['file.sed'](
|
||||
'/etc/sysconfig/clock', '^ZONE=.*', 'ZONE="{0}"'.format(timezone))
|
||||
elif 'Suse' in __grains__['os_family']:
|
||||
__salt__['file.sed'](
|
||||
'/etc/sysconfig/clock', '^TIMEZONE=.*', 'TIMEZONE="{0}"'.format(timezone))
|
||||
elif 'Debian' in __grains__['os_family']:
|
||||
if clock == 'UTC':
|
||||
__salt__['file.sed']('/etc/default/rcS', '^UTC=.*', 'UTC=yes')
|
||||
elif clock == 'localtime':
|
||||
__salt__['file.sed']('/etc/default/rcS', '^UTC=.*', 'UTC=no')
|
||||
elif 'Gentoo' in __grains__['os_family']:
|
||||
if clock not in ('UTC', 'localtime'):
|
||||
raise SaltInvocationError(
|
||||
'Only \'UTC\' and \'localtime\' are allowed'
|
||||
else:
|
||||
os_family = __grains__['os_family']
|
||||
if os_family in ('AIX', 'NILinuxRT'):
|
||||
if clock.lower() != 'utc':
|
||||
raise SaltInvocationError(
|
||||
'UTC is the only permitted value'
|
||||
)
|
||||
return True
|
||||
|
||||
timezone = get_zone()
|
||||
|
||||
if 'Solaris' in __grains__['os_family']:
|
||||
if clock.lower() not in ('localtime', 'utc'):
|
||||
raise SaltInvocationError(
|
||||
'localtime and UTC are the only permitted values'
|
||||
)
|
||||
if 'sparc' in __grains__['cpuarch']:
|
||||
raise SaltInvocationError(
|
||||
'UTC is the only choice for SPARC architecture'
|
||||
)
|
||||
cmd = ['rtc', '-z', 'GMT' if clock.lower() == 'utc' else timezone]
|
||||
return __salt__['cmd.retcode'](cmd, python_shell=False) == 0
|
||||
|
||||
zonepath = '/usr/share/zoneinfo/{0}'.format(timezone)
|
||||
|
||||
if not os.path.exists(zonepath):
|
||||
raise CommandExecutionError(
|
||||
'Zone \'{0}\' does not exist'.format(zonepath)
|
||||
)
|
||||
if clock == 'localtime':
|
||||
clock = 'local'
|
||||
__salt__['file.sed'](
|
||||
'/etc/conf.d/hwclock', '^clock=.*', 'clock="{0}"'.format(clock))
|
||||
|
||||
os.unlink('/etc/localtime')
|
||||
os.symlink(zonepath, '/etc/localtime')
|
||||
|
||||
if 'Arch' in __grains__['os_family']:
|
||||
cmd = ['timezonectl', 'set-local-rtc',
|
||||
'true' if clock == 'localtime' else 'false']
|
||||
return __salt__['cmd.retcode'](cmd, python_shell=False) == 0
|
||||
elif 'RedHat' in __grains__['os_family']:
|
||||
__salt__['file.sed'](
|
||||
'/etc/sysconfig/clock', '^ZONE=.*', 'ZONE="{0}"'.format(timezone))
|
||||
elif 'Suse' in __grains__['os_family']:
|
||||
__salt__['file.sed'](
|
||||
'/etc/sysconfig/clock', '^TIMEZONE=.*', 'TIMEZONE="{0}"'.format(timezone))
|
||||
elif 'Debian' in __grains__['os_family']:
|
||||
if clock == 'UTC':
|
||||
__salt__['file.sed']('/etc/default/rcS', '^UTC=.*', 'UTC=yes')
|
||||
elif clock == 'localtime':
|
||||
__salt__['file.sed']('/etc/default/rcS', '^UTC=.*', 'UTC=no')
|
||||
elif 'Gentoo' in __grains__['os_family']:
|
||||
if clock not in ('UTC', 'localtime'):
|
||||
raise SaltInvocationError(
|
||||
'Only \'UTC\' and \'localtime\' are allowed'
|
||||
)
|
||||
if clock == 'localtime':
|
||||
clock = 'local'
|
||||
__salt__['file.sed'](
|
||||
'/etc/conf.d/hwclock', '^clock=.*', 'clock="{0}"'.format(clock))
|
||||
|
||||
return True
|
||||
|
|
|
@ -7,50 +7,55 @@ powercfg.
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
# Set monitor to never turn off on Battery power
|
||||
salt '*' powercfg.set_monitor_timeout 0 power=dc
|
||||
# Set disk timeout to 120 minutes on AC power
|
||||
salt '*' powercfg.set_disk_timeout 120 power=ac
|
||||
'''
|
||||
|
||||
# Import Python Libs
|
||||
from __future__ import absolute_import
|
||||
import re
|
||||
import logging
|
||||
|
||||
# Import Salt Libs
|
||||
import salt.utils
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
__virtualname__ = "powercfg"
|
||||
__virtualname__ = 'powercfg'
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
Only work on Windows
|
||||
'''
|
||||
if __grains__['os'] == 'Windows':
|
||||
return __virtualname__
|
||||
return (False, 'Module only works on Windows.')
|
||||
if not salt.utils.is_windows():
|
||||
return False, 'PowerCFG: Module only works on Windows'
|
||||
return __virtualname__
|
||||
|
||||
|
||||
def _get_current_scheme():
|
||||
cmd = "powercfg /getactivescheme"
|
||||
cmd = 'powercfg /getactivescheme'
|
||||
out = __salt__['cmd.run'](cmd, python_shell=False)
|
||||
matches = re.search(r"GUID: (.*) \(", out)
|
||||
matches = re.search(r'GUID: (.*) \(', out)
|
||||
return matches.groups()[0].strip()
|
||||
|
||||
|
||||
def _get_powercfg_minute_values(scheme, guid, subguid, safe_name):
|
||||
'''
|
||||
Returns the AC/DC values in an array for a guid and subguid for a the given scheme
|
||||
Returns the AC/DC values in an dict for a guid and subguid for a the given
|
||||
scheme
|
||||
'''
|
||||
if scheme is None:
|
||||
scheme = _get_current_scheme()
|
||||
|
||||
if __grains__['osrelease'] == '7':
|
||||
cmd = "powercfg /q {0} {1}".format(scheme, guid)
|
||||
cmd = 'powercfg /q {0} {1}'.format(scheme, guid)
|
||||
else:
|
||||
cmd = "powercfg /q {0} {1} {2}".format(scheme, guid, subguid)
|
||||
cmd = 'powercfg /q {0} {1} {2}'.format(scheme, guid, subguid)
|
||||
out = __salt__['cmd.run'](cmd, python_shell=False)
|
||||
|
||||
split = out.split("\r\n\r\n")
|
||||
split = out.split('\r\n\r\n')
|
||||
if len(split) > 1:
|
||||
for s in split:
|
||||
if safe_name in s or subguid in s:
|
||||
|
@ -59,172 +64,309 @@ def _get_powercfg_minute_values(scheme, guid, subguid, safe_name):
|
|||
else:
|
||||
out = split[0]
|
||||
|
||||
raw_settings = re.findall(r"Power Setting Index: ([0-9a-fx]+)", out)
|
||||
return {"ac": int(raw_settings[0], 0) / 60, "dc": int(raw_settings[1], 0) / 60}
|
||||
raw_settings = re.findall(r'Power Setting Index: ([0-9a-fx]+)', out)
|
||||
return {'ac': int(raw_settings[0], 0) / 60,
|
||||
'dc': int(raw_settings[1], 0) / 60}
|
||||
|
||||
|
||||
def _set_powercfg_value(scheme, sub_group, setting_guid, power, value):
|
||||
'''
|
||||
Sets the value of a setting with a given power (ac/dc) to
|
||||
the given scheme
|
||||
Sets the AC/DC values of a setting with the given power for the given scheme
|
||||
'''
|
||||
salt.utils.warn_until(
|
||||
'Fluorine',
|
||||
'This function now expects the timeout value in minutes instead of '
|
||||
'seconds as stated in the documentation. This warning will be removed '
|
||||
'in Salt Fluorine.')
|
||||
if scheme is None:
|
||||
scheme = _get_current_scheme()
|
||||
|
||||
cmd = "powercfg /set{0}valueindex {1} {2} {3} {4}".format(power, scheme, sub_group, setting_guid, value)
|
||||
return __salt__['cmd.run'](cmd, python_shell=False)
|
||||
cmd = 'powercfg /set{0}valueindex {1} {2} {3} {4}' \
|
||||
''.format(power, scheme, sub_group, setting_guid, value * 60)
|
||||
return __salt__['cmd.retcode'](cmd, python_shell=False) == 0
|
||||
|
||||
|
||||
def set_monitor_timeout(timeout, power="ac", scheme=None):
|
||||
def set_monitor_timeout(timeout, power='ac', scheme=None):
|
||||
'''
|
||||
Set the monitor timeout in minutes for the given power scheme
|
||||
|
||||
Args:
|
||||
timeout (int):
|
||||
The amount of time in minutes before the monitor will timeout
|
||||
|
||||
power (str):
|
||||
Set the value for AC or DC power. Default is ``ac``. Valid options
|
||||
are:
|
||||
|
||||
- ``ac`` (AC Power)
|
||||
- ``dc`` (Battery)
|
||||
|
||||
scheme (str):
|
||||
The scheme to use, leave as ``None`` to use the current. Default is
|
||||
``None``. This can be the GUID or the Alias for the Scheme. Known
|
||||
Aliases are:
|
||||
|
||||
- ``SCHEME_BALANCED`` - Balanced
|
||||
- ``SCHEME_MAX`` - Power saver
|
||||
- ``SCHEME_MIN`` - High performance
|
||||
|
||||
Returns:
|
||||
bool: ``True`` if successful, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' powercfg.set_monitor_timeout 30 power=ac
|
||||
|
||||
timeout
|
||||
The amount of time in minutes before the monitor will timeout
|
||||
|
||||
power
|
||||
Should we set the value for AC or DC (battery)? Valid options ac,dc.
|
||||
|
||||
scheme
|
||||
The scheme to use, leave as None to use the current.
|
||||
|
||||
# Sets the monitor timeout to 30 minutes
|
||||
salt '*' powercfg.set_monitor_timeout 30
|
||||
'''
|
||||
return _set_powercfg_value(scheme, "SUB_VIDEO", "VIDEOIDLE", power, timeout)
|
||||
return _set_powercfg_value(
|
||||
scheme=scheme,
|
||||
sub_group='SUB_VIDEO',
|
||||
setting_guid='VIDEOIDLE',
|
||||
power=power,
|
||||
value=timeout)
|
||||
|
||||
|
||||
def get_monitor_timeout(scheme=None):
|
||||
'''
|
||||
Get the current monitor timeout of the given scheme
|
||||
|
||||
Args:
|
||||
scheme (str):
|
||||
The scheme to use, leave as ``None`` to use the current. Default is
|
||||
``None``. This can be the GUID or the Alias for the Scheme. Known
|
||||
Aliases are:
|
||||
|
||||
- ``SCHEME_BALANCED`` - Balanced
|
||||
- ``SCHEME_MAX`` - Power saver
|
||||
- ``SCHEME_MIN`` - High performance
|
||||
|
||||
Returns:
|
||||
dict: A dictionary of both the AC and DC settings
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' powercfg.get_monitor_timeout
|
||||
|
||||
scheme
|
||||
The scheme to use, leave as None to use the current.
|
||||
'''
|
||||
return _get_powercfg_minute_values(scheme, "SUB_VIDEO", "VIDEOIDLE", "Turn off display after")
|
||||
return _get_powercfg_minute_values(
|
||||
scheme=scheme,
|
||||
guid='SUB_VIDEO',
|
||||
subguid='VIDEOIDLE',
|
||||
safe_name='Turn off display after')
|
||||
|
||||
|
||||
def set_disk_timeout(timeout, power="ac", scheme=None):
|
||||
def set_disk_timeout(timeout, power='ac', scheme=None):
|
||||
'''
|
||||
Set the disk timeout in minutes for the given power scheme
|
||||
|
||||
Args:
|
||||
timeout (int):
|
||||
The amount of time in minutes before the disk will timeout
|
||||
|
||||
power (str):
|
||||
Set the value for AC or DC power. Default is ``ac``. Valid options
|
||||
are:
|
||||
|
||||
- ``ac`` (AC Power)
|
||||
- ``dc`` (Battery)
|
||||
|
||||
scheme (str):
|
||||
The scheme to use, leave as ``None`` to use the current. Default is
|
||||
``None``. This can be the GUID or the Alias for the Scheme. Known
|
||||
Aliases are:
|
||||
|
||||
- ``SCHEME_BALANCED`` - Balanced
|
||||
- ``SCHEME_MAX`` - Power saver
|
||||
- ``SCHEME_MIN`` - High performance
|
||||
|
||||
Returns:
|
||||
bool: ``True`` if successful, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# Sets the disk timeout to 30 minutes on battery
|
||||
salt '*' powercfg.set_disk_timeout 30 power=dc
|
||||
|
||||
timeout
|
||||
The amount of time in minutes before the disk will timeout
|
||||
|
||||
power
|
||||
Should we set the value for AC or DC (battery)? Valid options ac,dc.
|
||||
|
||||
scheme
|
||||
The scheme to use, leave as None to use the current.
|
||||
|
||||
'''
|
||||
return _set_powercfg_value(scheme, "SUB_DISK", "DISKIDLE", power, timeout)
|
||||
return _set_powercfg_value(
|
||||
scheme=scheme,
|
||||
sub_group='SUB_DISK',
|
||||
setting_guid='DISKIDLE',
|
||||
power=power,
|
||||
value=timeout)
|
||||
|
||||
|
||||
def get_disk_timeout(scheme=None):
|
||||
'''
|
||||
Get the current disk timeout of the given scheme
|
||||
|
||||
Args:
|
||||
scheme (str):
|
||||
The scheme to use, leave as ``None`` to use the current. Default is
|
||||
``None``. This can be the GUID or the Alias for the Scheme. Known
|
||||
Aliases are:
|
||||
|
||||
- ``SCHEME_BALANCED`` - Balanced
|
||||
- ``SCHEME_MAX`` - Power saver
|
||||
- ``SCHEME_MIN`` - High performance
|
||||
|
||||
Returns:
|
||||
dict: A dictionary of both the AC and DC settings
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' powercfg.get_disk_timeout
|
||||
|
||||
scheme
|
||||
The scheme to use, leave as None to use the current.
|
||||
'''
|
||||
return _get_powercfg_minute_values(scheme, "SUB_DISK", "DISKIDLE", "Turn off hard disk after")
|
||||
return _get_powercfg_minute_values(
|
||||
scheme=scheme,
|
||||
guid='SUB_DISK',
|
||||
subguid='DISKIDLE',
|
||||
safe_name='Turn off hard disk after')
|
||||
|
||||
|
||||
def set_standby_timeout(timeout, power="ac", scheme=None):
|
||||
def set_standby_timeout(timeout, power='ac', scheme=None):
|
||||
'''
|
||||
Set the standby timeout in minutes for the given power scheme
|
||||
|
||||
Args:
|
||||
timeout (int):
|
||||
The amount of time in minutes before the computer sleeps
|
||||
|
||||
power (str):
|
||||
Set the value for AC or DC power. Default is ``ac``. Valid options
|
||||
are:
|
||||
|
||||
- ``ac`` (AC Power)
|
||||
- ``dc`` (Battery)
|
||||
|
||||
scheme (str):
|
||||
The scheme to use, leave as ``None`` to use the current. Default is
|
||||
``None``. This can be the GUID or the Alias for the Scheme. Known
|
||||
Aliases are:
|
||||
|
||||
- ``SCHEME_BALANCED`` - Balanced
|
||||
- ``SCHEME_MAX`` - Power saver
|
||||
- ``SCHEME_MIN`` - High performance
|
||||
|
||||
Returns:
|
||||
bool: ``True`` if successful, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# Sets the system standby timeout to 30 minutes on Battery
|
||||
salt '*' powercfg.set_standby_timeout 30 power=dc
|
||||
|
||||
timeout
|
||||
The amount of time in minutes before the computer sleeps
|
||||
|
||||
power
|
||||
Should we set the value for AC or DC (battery)? Valid options ac,dc.
|
||||
|
||||
scheme
|
||||
The scheme to use, leave as None to use the current.
|
||||
|
||||
'''
|
||||
return _set_powercfg_value(scheme, "SUB_SLEEP", "STANDBYIDLE", power, timeout)
|
||||
return _set_powercfg_value(
|
||||
scheme=scheme,
|
||||
sub_group='SUB_SLEEP',
|
||||
setting_guid='STANDBYIDLE',
|
||||
power=power,
|
||||
value=timeout)
|
||||
|
||||
|
||||
def get_standby_timeout(scheme=None):
|
||||
'''
|
||||
Get the current standby timeout of the given scheme
|
||||
|
||||
scheme (str):
|
||||
The scheme to use, leave as ``None`` to use the current. Default is
|
||||
``None``. This can be the GUID or the Alias for the Scheme. Known
|
||||
Aliases are:
|
||||
|
||||
- ``SCHEME_BALANCED`` - Balanced
|
||||
- ``SCHEME_MAX`` - Power saver
|
||||
- ``SCHEME_MIN`` - High performance
|
||||
|
||||
Returns:
|
||||
dict: A dictionary of both the AC and DC settings
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' powercfg.get_standby_timeout
|
||||
|
||||
scheme
|
||||
The scheme to use, leave as None to use the current.
|
||||
'''
|
||||
return _get_powercfg_minute_values(scheme, "SUB_SLEEP", "STANDBYIDLE", "Sleep after")
|
||||
return _get_powercfg_minute_values(
|
||||
scheme=scheme,
|
||||
guid='SUB_SLEEP',
|
||||
subguid='STANDBYIDLE',
|
||||
safe_name='Sleep after')
|
||||
|
||||
|
||||
def set_hibernate_timeout(timeout, power="ac", scheme=None):
|
||||
def set_hibernate_timeout(timeout, power='ac', scheme=None):
|
||||
'''
|
||||
Set the hibernate timeout in minutes for the given power scheme
|
||||
|
||||
Args:
|
||||
timeout (int):
|
||||
The amount of time in minutes before the computer hibernates
|
||||
|
||||
power (str):
|
||||
Set the value for AC or DC power. Default is ``ac``. Valid options
|
||||
are:
|
||||
|
||||
- ``ac`` (AC Power)
|
||||
- ``dc`` (Battery)
|
||||
|
||||
scheme (str):
|
||||
The scheme to use, leave as ``None`` to use the current. Default is
|
||||
``None``. This can be the GUID or the Alias for the Scheme. Known
|
||||
Aliases are:
|
||||
|
||||
- ``SCHEME_BALANCED`` - Balanced
|
||||
- ``SCHEME_MAX`` - Power saver
|
||||
- ``SCHEME_MIN`` - High performance
|
||||
|
||||
Returns:
|
||||
bool: ``True`` if successful, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' powercfg.set_hibernate_timeout 30 power=pc
|
||||
|
||||
timeout
|
||||
The amount of time in minutes before the computer hibernates
|
||||
|
||||
power
|
||||
Should we set the value for AC or DC (battery)? Valid options ac,dc.
|
||||
|
||||
scheme
|
||||
The scheme to use, leave as None to use the current.
|
||||
# Sets the hibernate timeout to 30 minutes on Battery
|
||||
salt '*' powercfg.set_hibernate_timeout 30 power=dc
|
||||
'''
|
||||
return _set_powercfg_value(scheme, "SUB_SLEEP", "HIBERNATEIDLE", power, timeout)
|
||||
return _set_powercfg_value(
|
||||
scheme=scheme,
|
||||
sub_group='SUB_SLEEP',
|
||||
setting_guid='HIBERNATEIDLE',
|
||||
power=power,
|
||||
value=timeout)
|
||||
|
||||
|
||||
def get_hibernate_timeout(scheme=None):
|
||||
'''
|
||||
Get the current hibernate timeout of the given scheme
|
||||
|
||||
scheme (str):
|
||||
The scheme to use, leave as ``None`` to use the current. Default is
|
||||
``None``. This can be the GUID or the Alias for the Scheme. Known
|
||||
Aliases are:
|
||||
|
||||
- ``SCHEME_BALANCED`` - Balanced
|
||||
- ``SCHEME_MAX`` - Power saver
|
||||
- ``SCHEME_MIN`` - High performance
|
||||
|
||||
Returns:
|
||||
dict: A dictionary of both the AC and DC settings
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' powercfg.get_hibernate_timeout
|
||||
|
||||
scheme
|
||||
The scheme to use, leave as None to use the current.
|
||||
'''
|
||||
return _get_powercfg_minute_values(scheme, "SUB_SLEEP", "HIBERNATEIDLE", "Hibernate after")
|
||||
return _get_powercfg_minute_values(
|
||||
scheme=scheme,
|
||||
guid='SUB_SLEEP',
|
||||
subguid='HIBERNATEIDLE',
|
||||
safe_name='Hibernate after')
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -9,6 +9,12 @@ import salt.utils
|
|||
import logging
|
||||
import re
|
||||
|
||||
try:
|
||||
import tzlocal
|
||||
HAS_TZLOCAL = True
|
||||
except ImportError:
|
||||
HAS_TZLOCAL = False
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# Maybe put in a different file ... ? %-0
|
||||
|
@ -473,6 +479,10 @@ def get_zone():
|
|||
|
||||
salt '*' timezone.get_zone
|
||||
'''
|
||||
if HAS_TZLOCAL:
|
||||
return tzlocal.get_localzone().zone
|
||||
|
||||
log.warning('tzutil not installed. get_zone might be inaccurate')
|
||||
winzone = __salt__['cmd.run'](['tzutil', '/g'], python_shell=False)
|
||||
for key in LINTOWIN:
|
||||
if LINTOWIN[key] == winzone:
|
||||
|
|
|
@ -942,7 +942,6 @@ def create_crl( # pylint: disable=too-many-arguments,too-many-locals
|
|||
rev_item['not_after'] = rev_cert['Not After']
|
||||
|
||||
serial_number = rev_item['serial_number'].replace(':', '')
|
||||
serial_number = str(int(serial_number, 16))
|
||||
|
||||
if 'not_after' in rev_item and not include_expired:
|
||||
not_after = datetime.datetime.strptime(
|
||||
|
|
|
@ -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,9 +923,11 @@ class SaltAPIHandler(BaseSaltAPIHandler): # pylint: disable=W0223
|
|||
# Generate jid before triggering a job to subscribe all returns from minions
|
||||
chunk['jid'] = salt.utils.jid.gen_jid()
|
||||
|
||||
# Subscribe returns from minions before firing a job
|
||||
minions = set(self.ckminions.check_minions(chunk['tgt'], chunk.get('tgt_type', 'glob')))
|
||||
future_minion_map = self.subscribe_minion_returns(chunk['jid'], minions)
|
||||
# start listening for the event before we fire the job to avoid races
|
||||
events = [
|
||||
self.application.event_listener.get_event(self, tag='salt/job/'+chunk['jid']),
|
||||
self.application.event_listener.get_event(self, tag='syndic/job/'+chunk['jid']),
|
||||
]
|
||||
|
||||
f_call = self._format_call_run_job_async(chunk)
|
||||
# fire a job off
|
||||
|
@ -937,88 +939,92 @@ class SaltAPIHandler(BaseSaltAPIHandler): # pylint: disable=W0223
|
|||
# if the job didn't publish, lets not wait around for nothing
|
||||
# TODO: set header??
|
||||
if 'jid' not in pub_data:
|
||||
for future in future_minion_map:
|
||||
for future in events:
|
||||
try:
|
||||
future.set_result(None)
|
||||
except Exception:
|
||||
pass
|
||||
raise tornado.gen.Return('No minions matched the target. No command was sent, no jid was assigned.')
|
||||
|
||||
# Map of minion_id -> returned for all minions we think we need to wait on
|
||||
minions = {m: False for m in pub_data['minions']}
|
||||
|
||||
# minimum time required for return to complete. By default no waiting, if
|
||||
# we are a syndic then we must wait syndic_wait at a minimum
|
||||
min_wait_time = Future()
|
||||
min_wait_time.set_result(True)
|
||||
|
||||
# wait syndic a while to avoid missing published events
|
||||
if self.application.opts['order_masters']:
|
||||
yield tornado.gen.sleep(self.application.opts['syndic_wait'])
|
||||
min_wait_time = tornado.gen.sleep(self.application.opts['syndic_wait'])
|
||||
|
||||
# To ensure job_not_running and all_return are terminated by each other, communicate using a future
|
||||
is_finished = Future()
|
||||
is_finished = tornado.gen.sleep(self.application.opts['gather_job_timeout'])
|
||||
|
||||
job_not_running_future = self.job_not_running(pub_data['jid'],
|
||||
# ping until the job is not running, while doing so, if we see new minions returning
|
||||
# that they are running the job, add them to the list
|
||||
tornado.ioloop.IOLoop.current().spawn_callback(self.job_not_running, pub_data['jid'],
|
||||
chunk['tgt'],
|
||||
f_call['kwargs']['tgt_type'],
|
||||
minions,
|
||||
is_finished)
|
||||
|
||||
minion_returns_future = self.sanitize_minion_returns(future_minion_map, pub_data['minions'], is_finished)
|
||||
|
||||
yield job_not_running_future
|
||||
raise tornado.gen.Return((yield minion_returns_future))
|
||||
|
||||
def subscribe_minion_returns(self, jid, minions):
|
||||
# Subscribe each minion event
|
||||
future_minion_map = {}
|
||||
for minion in minions:
|
||||
tag = tagify([jid, 'ret', minion], 'job')
|
||||
minion_future = self.application.event_listener.get_event(self,
|
||||
tag=tag,
|
||||
matcher=EventListener.exact_matcher)
|
||||
future_minion_map[minion_future] = minion
|
||||
return future_minion_map
|
||||
|
||||
@tornado.gen.coroutine
|
||||
def sanitize_minion_returns(self, future_minion_map, minions, is_finished):
|
||||
'''
|
||||
Return a future which will complete once all returns are completed
|
||||
(according to minions), or one of the passed in "finish_chunk_ret_future" completes
|
||||
'''
|
||||
if minions is None:
|
||||
minions = []
|
||||
|
||||
# Remove redundant minions
|
||||
redundant_minion_futures = [future for future in future_minion_map.keys() if future_minion_map[future] not in minions]
|
||||
for redundant_minion_future in redundant_minion_futures:
|
||||
try:
|
||||
redundant_minion_future.set_result(None)
|
||||
except Exception:
|
||||
pass
|
||||
del future_minion_map[redundant_minion_future]
|
||||
def more_todo():
|
||||
'''Check if there are any more minions we are waiting on returns from
|
||||
'''
|
||||
return any(x is False for x in six.itervalues(minions))
|
||||
|
||||
# here we want to follow the behavior of LocalClient.get_iter_returns
|
||||
# namely we want to wait at least syndic_wait (assuming we are a syndic)
|
||||
# and that there are no more jobs running on minions. We are allowed to exit
|
||||
# early if gather_job_timeout has been exceeded
|
||||
chunk_ret = {}
|
||||
while True:
|
||||
f = yield Any(list(future_minion_map.keys()) + [is_finished])
|
||||
to_wait = events+[is_finished]
|
||||
if not min_wait_time.done():
|
||||
to_wait += [min_wait_time]
|
||||
|
||||
def cancel_inflight_futures():
|
||||
for event in to_wait:
|
||||
if not event.done():
|
||||
event.set_result(None)
|
||||
f = yield Any(to_wait)
|
||||
try:
|
||||
# When finished entire routine, cleanup other futures and return result
|
||||
if f is is_finished:
|
||||
for event in future_minion_map.keys():
|
||||
if not event.done():
|
||||
event.set_result(None)
|
||||
cancel_inflight_futures()
|
||||
raise tornado.gen.Return(chunk_ret)
|
||||
elif f is min_wait_time:
|
||||
if not more_todo():
|
||||
cancel_inflight_futures()
|
||||
raise tornado.gen.Return(chunk_ret)
|
||||
continue
|
||||
f_result = f.result()
|
||||
chunk_ret[f_result['data']['id']] = f_result['data']['return']
|
||||
# if this is a start, then we need to add it to the pile
|
||||
if f_result['tag'].endswith('/new'):
|
||||
for minion_id in f_result['data']['minions']:
|
||||
if minion_id not in minions:
|
||||
minions[minion_id] = False
|
||||
else:
|
||||
chunk_ret[f_result['data']['id']] = f_result['data']['return']
|
||||
# clear finished event future
|
||||
minions[f_result['data']['id']] = True
|
||||
|
||||
# if there are no more minions to wait for, then we are done
|
||||
if not more_todo() and min_wait_time.done():
|
||||
cancel_inflight_futures()
|
||||
raise tornado.gen.Return(chunk_ret)
|
||||
|
||||
except TimeoutException:
|
||||
pass
|
||||
|
||||
# clear finished event future
|
||||
try:
|
||||
minions.remove(future_minion_map[f])
|
||||
del future_minion_map[f]
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
if not minions:
|
||||
if not is_finished.done():
|
||||
is_finished.set_result(True)
|
||||
raise tornado.gen.Return(chunk_ret)
|
||||
if f == events[0]:
|
||||
events[0] = self.application.event_listener.get_event(self, tag='salt/job/'+chunk['jid'])
|
||||
else:
|
||||
events[1] = self.application.event_listener.get_event(self, tag='syndic/job/'+chunk['jid'])
|
||||
|
||||
@tornado.gen.coroutine
|
||||
def job_not_running(self, jid, tgt, tgt_type, is_finished):
|
||||
def job_not_running(self, jid, tgt, tgt_type, minions, is_finished):
|
||||
'''
|
||||
Return a future which will complete once jid (passed in) is no longer
|
||||
running on tgt
|
||||
|
@ -1044,8 +1050,6 @@ class SaltAPIHandler(BaseSaltAPIHandler): # pylint: disable=W0223
|
|||
event = f.result()
|
||||
except TimeoutException:
|
||||
if not minion_running:
|
||||
if not is_finished.done():
|
||||
is_finished.set_result(True)
|
||||
raise tornado.gen.Return(True)
|
||||
else:
|
||||
ping_pub_data = yield self.saltclients['local'](tgt,
|
||||
|
@ -1059,6 +1063,8 @@ class SaltAPIHandler(BaseSaltAPIHandler): # pylint: disable=W0223
|
|||
# Minions can return, we want to see if the job is running...
|
||||
if event['data'].get('return', {}) == {}:
|
||||
continue
|
||||
if event['data']['id'] not in minions:
|
||||
minions[event['data']['id']] = False
|
||||
minion_running = True
|
||||
|
||||
@tornado.gen.coroutine
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -154,7 +154,7 @@ def action(func=None,
|
|||
info = {}
|
||||
client = _get_client()
|
||||
try:
|
||||
info = client.action(func, cloudmap, instances, provider, instance, **_filter_kwargs(kwargs))
|
||||
info = client.action(func, cloudmap, instances, provider, instance, _filter_kwargs(kwargs))
|
||||
except SaltCloudConfigError as err:
|
||||
log.error(err)
|
||||
return info
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -171,7 +171,9 @@ def init(
|
|||
start=True,
|
||||
disk='default',
|
||||
saltenv='base',
|
||||
enable_vnc=False):
|
||||
enable_vnc=False,
|
||||
seed_cmd='seed.apply',
|
||||
enable_qcow=False):
|
||||
'''
|
||||
This routine is used to create a new virtual machine. This routines takes
|
||||
a number of options to determine what the newly created virtual machine
|
||||
|
@ -193,14 +195,14 @@ def init(
|
|||
on the salt fileserver, but http, https and ftp can also be used.
|
||||
|
||||
hypervisor
|
||||
The hypervisor to use for the new virtual machine. Default is 'kvm'.
|
||||
The hypervisor to use for the new virtual machine. Default is `kvm`.
|
||||
|
||||
host
|
||||
The host to use for the new virtual machine, if this is omitted
|
||||
Salt will automatically detect what host to use.
|
||||
|
||||
seed
|
||||
Set to False to prevent Salt from seeding the new virtual machine.
|
||||
Set to `False` to prevent Salt from seeding the new virtual machine.
|
||||
|
||||
nic
|
||||
The nic profile to use, defaults to the "default" nic profile which
|
||||
|
@ -216,6 +218,17 @@ def init(
|
|||
|
||||
saltenv
|
||||
The Salt environment to use
|
||||
|
||||
enable_vnc
|
||||
Whether a VNC screen is attached to resulting VM. Default is `False`.
|
||||
|
||||
seed_cmd
|
||||
If seed is `True`, use this execution module function to seed new VM.
|
||||
Default is `seed.apply`.
|
||||
|
||||
enable_qcow
|
||||
Clone disk image as a copy-on-write qcow2 image, using downloaded
|
||||
`image` as backing file.
|
||||
'''
|
||||
__jid_event__.fire_event({'message': 'Searching for hosts'}, 'progress')
|
||||
data = query(host, quiet=True)
|
||||
|
@ -256,25 +269,29 @@ def init(
|
|||
)
|
||||
try:
|
||||
cmd_ret = client.cmd_iter(
|
||||
host,
|
||||
'virt.init',
|
||||
[
|
||||
name,
|
||||
cpu,
|
||||
mem,
|
||||
image,
|
||||
nic,
|
||||
hypervisor,
|
||||
start,
|
||||
disk,
|
||||
saltenv,
|
||||
seed,
|
||||
install,
|
||||
pub_key,
|
||||
priv_key,
|
||||
enable_vnc,
|
||||
],
|
||||
timeout=600)
|
||||
host,
|
||||
'virt.init',
|
||||
[
|
||||
name,
|
||||
cpu,
|
||||
mem
|
||||
],
|
||||
timeout=600,
|
||||
kwarg={
|
||||
'image': image,
|
||||
'nic': nic,
|
||||
'hypervisor': hypervisor,
|
||||
'start': start,
|
||||
'disk': disk,
|
||||
'saltenv': saltenv,
|
||||
'seed': seed,
|
||||
'install': install,
|
||||
'pub_key': pub_key,
|
||||
'priv_key': priv_key,
|
||||
'seed_cmd': seed_cmd,
|
||||
'enable_vnc': enable_vnc,
|
||||
'enable_qcow': enable_qcow,
|
||||
})
|
||||
except SaltClientError as client_error:
|
||||
# Fall through to ret error handling below
|
||||
print(client_error)
|
||||
|
|
|
@ -69,7 +69,7 @@ def set_(key, value, service=None, profile=None): # pylint: disable=W0613
|
|||
'''
|
||||
key, profile = _parse_key(key, profile)
|
||||
cache = salt.cache.Cache(__opts__)
|
||||
cache.set(profile['bank'], key=key, value=value)
|
||||
cache.store(profile['bank'], key, value)
|
||||
return get(key, service, profile)
|
||||
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ def cert(name,
|
|||
server=None,
|
||||
owner='root',
|
||||
group='root',
|
||||
mode='0640',
|
||||
certname=None):
|
||||
'''
|
||||
Obtain/renew a certificate from an ACME CA, probably Let's Encrypt.
|
||||
|
@ -61,8 +62,9 @@ def cert(name,
|
|||
:param renew: True/'force' to force a renewal, or a window of renewal before expiry in days
|
||||
:param keysize: RSA key bits
|
||||
:param server: API endpoint to talk to
|
||||
:param owner: owner of private key
|
||||
:param group: group of private key
|
||||
:param owner: owner of the private key file
|
||||
:param group: group of the private key file
|
||||
:param mode: mode of the private key file
|
||||
:param certname: Name of the certificate to save
|
||||
'''
|
||||
|
||||
|
@ -105,7 +107,8 @@ def cert(name,
|
|||
keysize=keysize,
|
||||
server=server,
|
||||
owner=owner,
|
||||
group=group
|
||||
group=group,
|
||||
mode=mode
|
||||
)
|
||||
|
||||
ret = {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1225,7 +1225,7 @@ def _makedirs(name,
|
|||
Helper function for creating directories when the ``makedirs`` option is set
|
||||
to ``True``. Handles Unix and Windows based systems
|
||||
|
||||
.. versionadded:: 2017.7.7
|
||||
.. versionadded:: 2017.7.8
|
||||
|
||||
Args:
|
||||
name (str): The directory path to create
|
||||
|
@ -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:
|
||||
|
|
|
@ -713,8 +713,8 @@ def repo_present(
|
|||
ret['result'] = None
|
||||
else:
|
||||
result = __salt__['github.add_team_repo'](name, team_name,
|
||||
permission,
|
||||
profile=profile)
|
||||
profile=profile,
|
||||
permission=permission)
|
||||
if result:
|
||||
ret['changes'][team_name] = team_change
|
||||
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)
|
||||
|
|
|
@ -255,7 +255,12 @@ def _disable(name, started, result=True, **kwargs):
|
|||
return ret
|
||||
|
||||
# Service can be disabled
|
||||
before_toggle_disable_status = __salt__['service.disabled'](name)
|
||||
if salt.utils.is_windows():
|
||||
# service.disabled in Windows returns True for services that are set to
|
||||
# Manual start, so we need to check specifically for Disabled
|
||||
before_toggle_disable_status = __salt__['service.info'](name)['StartType'] in ['Disabled']
|
||||
else:
|
||||
before_toggle_disable_status = __salt__['service.disabled'](name)
|
||||
if before_toggle_disable_status:
|
||||
# Service is disabled
|
||||
if started is True:
|
||||
|
@ -549,7 +554,12 @@ def dead(name,
|
|||
# command, so it is just an indicator but can not be fully trusted
|
||||
before_toggle_status = __salt__['service.status'](name, sig)
|
||||
if 'service.enabled' in __salt__:
|
||||
before_toggle_enable_status = __salt__['service.enabled'](name)
|
||||
if salt.utils.is_windows():
|
||||
# service.enabled in Windows returns True for services that are set
|
||||
# to Auto start, but services set to Manual can also be disabled
|
||||
before_toggle_enable_status = __salt__['service.info'](name)['StartType'] in ['Auto', 'Manual']
|
||||
else:
|
||||
before_toggle_enable_status = __salt__['service.enabled'](name)
|
||||
else:
|
||||
before_toggle_enable_status = True
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ powercfg.
|
|||
|
||||
.. code-block:: yaml
|
||||
|
||||
# Set timeout to 30 minutes on battery power
|
||||
monitor:
|
||||
powercfg.set_timeout:
|
||||
- value: 30
|
||||
|
@ -18,82 +19,131 @@ powercfg.
|
|||
from __future__ import absolute_import
|
||||
import logging
|
||||
|
||||
# Import Salt Libs
|
||||
import salt.utils
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
__virtualname__ = "powercfg"
|
||||
__virtualname__ = 'powercfg'
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
Only work on Windows
|
||||
'''
|
||||
if __grains__['os'] == 'Windows':
|
||||
return __virtualname__
|
||||
return False
|
||||
if not salt.utils.is_windows():
|
||||
return False, 'PowerCFG: Module only works on Windows'
|
||||
return __virtualname__
|
||||
|
||||
|
||||
def _check_or_set(check_func, set_func, value, power):
|
||||
values = check_func()
|
||||
if values[power] == value:
|
||||
return True
|
||||
else:
|
||||
set_func(value, power)
|
||||
return False
|
||||
|
||||
|
||||
def set_timeout(name, value, power="ac", scheme=None):
|
||||
def set_timeout(name, value, power='ac', scheme=None):
|
||||
'''
|
||||
Set the sleep timeouts of specific items such as disk, monitor.
|
||||
Set the sleep timeouts of specific items such as disk, monitor, etc.
|
||||
|
||||
Args:
|
||||
|
||||
name (str)
|
||||
The setting to change, can be one of the following:
|
||||
|
||||
- ``monitor``
|
||||
- ``disk``
|
||||
- ``standby``
|
||||
- ``hibernate``
|
||||
|
||||
value (int):
|
||||
The amount of time in minutes before the item will timeout
|
||||
|
||||
power (str):
|
||||
Set the value for AC or DC power. Default is ``ac``. Valid options
|
||||
are:
|
||||
|
||||
- ``ac`` (AC Power)
|
||||
- ``dc`` (Battery)
|
||||
|
||||
scheme (str):
|
||||
The scheme to use, leave as ``None`` to use the current. Default is
|
||||
``None``. This can be the GUID or the Alias for the Scheme. Known
|
||||
Aliases are:
|
||||
|
||||
- ``SCHEME_BALANCED`` - Balanced
|
||||
- ``SCHEME_MAX`` - Power saver
|
||||
- ``SCHEME_MIN`` - High performance
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
# Set monitor timeout to 30 minutes on Battery
|
||||
monitor:
|
||||
powercfg.set_timeout:
|
||||
- value: 30
|
||||
- power: dc
|
||||
powercfg.set_timeout:
|
||||
- value: 30
|
||||
- power: dc
|
||||
|
||||
# Set disk timeout to 10 minutes on AC Power
|
||||
disk:
|
||||
powercfg.set_timeout:
|
||||
- value: 12
|
||||
- power: ac
|
||||
|
||||
name
|
||||
The setting to change, can be one of the following: monitor, disk, standby, hibernate
|
||||
|
||||
timeout
|
||||
The amount of time in minutes before the item will timeout i.e the monitor
|
||||
|
||||
power
|
||||
Should we set the value for AC or DC (battery)? Valid options ac,dc.
|
||||
|
||||
scheme
|
||||
The scheme to use, leave as None to use the current.
|
||||
powercfg.set_timeout:
|
||||
- value: 10
|
||||
- power: ac
|
||||
'''
|
||||
ret = {'name': name,
|
||||
'result': True,
|
||||
'comment': '',
|
||||
'changes': {}}
|
||||
|
||||
comment = []
|
||||
# Validate name values
|
||||
name = name.lower()
|
||||
if name not in ['monitor', 'disk', 'standby', 'hibernate']:
|
||||
ret['result'] = False
|
||||
ret['comment'] = '"{0}" is not a valid setting'.format(name)
|
||||
log.debug(ret['comment'])
|
||||
return ret
|
||||
|
||||
if name not in ["monitor", "disk", "standby", "hibernate"]:
|
||||
ret["result"] = False
|
||||
comment.append("{0} is not a valid setting".format(name))
|
||||
elif power not in ["ac", "dc"]:
|
||||
ret["result"] = False
|
||||
comment.append("{0} is not a power type".format(power))
|
||||
# Validate power values
|
||||
power = power.lower()
|
||||
if power not in ['ac', 'dc']:
|
||||
ret['result'] = False
|
||||
ret['comment'] = '"{0}" is not a power type'.format(power)
|
||||
log.debug(ret['comment'])
|
||||
return ret
|
||||
|
||||
# Get current settings
|
||||
old = __salt__['powercfg.get_{0}_timeout'.format(name)](scheme=scheme)
|
||||
|
||||
# Check current settings
|
||||
if old[power] == value:
|
||||
ret['comment'] = '{0} timeout on {1} power is already set to {2}' \
|
||||
''.format(name.capitalize(), power.upper(), value)
|
||||
return ret
|
||||
else:
|
||||
check_func = __salt__["powercfg.get_{0}_timeout".format(name)]
|
||||
set_func = __salt__["powercfg.set_{0}_timeout".format(name)]
|
||||
ret['comment'] = '{0} timeout on {1} power will be set to {2}' \
|
||||
''.format(name.capitalize(), power.upper(), value)
|
||||
|
||||
values = check_func(scheme=scheme)
|
||||
if values[power] == value:
|
||||
comment.append("{0} {1} is already set with the value {2}.".format(name, power, value))
|
||||
else:
|
||||
ret['changes'] = {name: {power: value}}
|
||||
set_func(value, power, scheme=scheme)
|
||||
# Check for test=True
|
||||
if __opts__['test']:
|
||||
ret['result'] = None
|
||||
return ret
|
||||
|
||||
# Set the timeout value
|
||||
__salt__['powercfg.set_{0}_timeout'.format(name)](
|
||||
timeout=value,
|
||||
power=power,
|
||||
scheme=scheme)
|
||||
|
||||
# Get the setting after the change
|
||||
new = __salt__['powercfg.get_{0}_timeout'.format(name)](scheme=scheme)
|
||||
|
||||
changes = salt.utils.compare_dicts(old, new)
|
||||
|
||||
if changes:
|
||||
ret['changes'] = {name: changes}
|
||||
ret['comment'] = '{0} timeout on {1} power set to {2}' \
|
||||
''.format(name.capitalize(), power.upper(), value)
|
||||
log.debug(ret['comment'])
|
||||
else:
|
||||
ret['changes'] = {}
|
||||
ret['comment'] = 'Failed to set {0} timeout on {1} power to {2}' \
|
||||
''.format(name, power.upper(), value)
|
||||
log.debug(ret['comment'])
|
||||
ret['result'] = False
|
||||
|
||||
ret['comment'] = ' '.join(comment)
|
||||
return ret
|
||||
|
|
|
@ -752,9 +752,9 @@ class IPCMessageSubscriber(IPCClient):
|
|||
# This will prevent this message from showing up:
|
||||
# '[ERROR ] Future exception was never retrieved:
|
||||
# StreamClosedError'
|
||||
if self._read_sync_future is not None:
|
||||
if self._read_sync_future is not None and self._read_sync_future.done():
|
||||
self._read_sync_future.exception()
|
||||
if self._read_stream_future is not None:
|
||||
if self._read_stream_future is not None and self._read_stream_future.done():
|
||||
self._read_stream_future.exception()
|
||||
|
||||
def __del__(self):
|
||||
|
|
|
@ -896,10 +896,9 @@ class SaltMessageClient(object):
|
|||
# This happens because the logic is always waiting to read
|
||||
# the next message and the associated read future is marked
|
||||
# 'StreamClosedError' when the stream is closed.
|
||||
self._read_until_future.exception()
|
||||
if (not self._stream_return_future.done() and
|
||||
self.io_loop != tornado.ioloop.IOLoop.current(
|
||||
instance=False)):
|
||||
if self._read_until_future.done():
|
||||
self._read_until_future.exception()
|
||||
elif self.io_loop != tornado.ioloop.IOLoop.current(instance=False):
|
||||
self.io_loop.add_future(
|
||||
self._stream_return_future,
|
||||
lambda future: self.io_loop.stop()
|
||||
|
@ -1134,7 +1133,7 @@ class Subscriber(object):
|
|||
self._closing = True
|
||||
if not self.stream.closed():
|
||||
self.stream.close()
|
||||
if self._read_until_future is not None:
|
||||
if self._read_until_future is not None and self._read_until_future.done():
|
||||
# This will prevent this message from showing up:
|
||||
# '[ERROR ] Future exception was never retrieved:
|
||||
# StreamClosedError'
|
||||
|
|
|
@ -2360,7 +2360,7 @@ def alias_function(fun, name, doc=None):
|
|||
orig_name = fun.__name__
|
||||
alias_msg = ('\nThis function is an alias of '
|
||||
'``{0}``.\n'.format(orig_name))
|
||||
alias_fun.__doc__ = alias_msg + fun.__doc__
|
||||
alias_fun.__doc__ = alias_msg + (fun.__doc__ or '')
|
||||
|
||||
return alias_fun
|
||||
|
||||
|
|
|
@ -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,6 +14,7 @@ import tarfile
|
|||
import zipfile
|
||||
import tempfile
|
||||
import subprocess
|
||||
import concurrent
|
||||
|
||||
# Import third party libs
|
||||
import jinja2
|
||||
|
@ -106,6 +107,8 @@ def get_tops(extra_mods='', so_mods=''):
|
|||
os.path.dirname(msgpack.__file__),
|
||||
]
|
||||
|
||||
if _six.PY2:
|
||||
tops.append(os.path.dirname(concurrent.__file__))
|
||||
tops.append(_six.__file__.replace('.pyc', '.py'))
|
||||
tops.append(backports_abc.__file__.replace('.pyc', '.py'))
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue