Merge branch '2017.7' into fix_49660

This commit is contained in:
Nicole Thomas 2018-09-30 15:26:47 -04:00 committed by GitHub
commit 0a4f5fcc7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 973 additions and 599 deletions

View File

@ -1,8 +1,11 @@
pipeline {
agent { label 'docs' }
agent {
label 'docs'
}
options {
timestamps()
ansiColor('xterm')
timeout(time: 2, unit: 'HOURS')
}
environment {
PYENV_ROOT = "/usr/local/pyenv"

View File

@ -1,73 +1,80 @@
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'
timeout(time: 6, unit: 'HOURS') {
node('kitchen-slave') {
timestamps {
ansiColor('xterm') {
withEnv([
'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',
]) {
stage('checkout-scm') {
cleanWs notFailBuild: true
checkout scm
}
}}
}
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'
try {
stage('github-pending') {
githubNotify credentialsId: 'test-jenkins-credentials',
description: "running ${TEST_SUITE}-${TEST_PLATFORM}...",
status: 'PENDING',
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
}
}}
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
archiveArtifacts artifacts: 'artifacts/logs/minion'
archiveArtifacts artifacts: 'artifacts/logs/salt-runtests.log'
stage('setup-bundle') {
sh 'bundle install --with ec2 windows --without opennebula docker'
}
try {
stage('run kitchen') {
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'
}
}
}
} finally {
stage('cleanup kitchen') {
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'
archiveArtifacts artifacts: 'artifacts/logs/minion'
archiveArtifacts artifacts: 'artifacts/logs/salt-runtests.log'
}
}
} finally {
try {
junit 'artifacts/xml-unittests-output/*.xml'
} finally {
cleanWs notFailBuild: true
def currentResult = currentBuild.result ?: 'SUCCESS'
if (currentResult == 'SUCCESS') {
githubNotify credentialsId: 'test-jenkins-credentials',
description: "The ${TEST_SUITE}-${TEST_PLATFORM} job has passed",
status: 'SUCCESS',
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
} else {
githubNotify credentialsId: 'test-jenkins-credentials',
description: "The ${TEST_SUITE}-${TEST_PLATFORM} job has failed",
status: 'FAILURE',
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
}
}
}
}
}
}
}
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}"
}
}
}

View File

@ -1,73 +1,80 @@
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'
timeout(time: 6, unit: 'HOURS') {
node('kitchen-slave') {
timestamps {
ansiColor('xterm') {
withEnv([
'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',
]) {
stage('checkout-scm') {
cleanWs notFailBuild: true
checkout scm
}
}}
}
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'
try {
stage('github-pending') {
githubNotify credentialsId: 'test-jenkins-credentials',
description: "running ${TEST_SUITE}-${TEST_PLATFORM}...",
status: 'PENDING',
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
}
}}
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
archiveArtifacts artifacts: 'artifacts/logs/minion'
archiveArtifacts artifacts: 'artifacts/logs/salt-runtests.log'
stage('setup-bundle') {
sh 'bundle install --with ec2 windows --without opennebula docker'
}
try {
stage('run kitchen') {
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'
}
}
}
} finally {
stage('cleanup kitchen') {
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'
archiveArtifacts artifacts: 'artifacts/logs/minion'
archiveArtifacts artifacts: 'artifacts/logs/salt-runtests.log'
}
}
} finally {
try {
junit 'artifacts/xml-unittests-output/*.xml'
} finally {
cleanWs notFailBuild: true
def currentResult = currentBuild.result ?: 'SUCCESS'
if (currentResult == 'SUCCESS') {
githubNotify credentialsId: 'test-jenkins-credentials',
description: "The ${TEST_SUITE}-${TEST_PLATFORM} job has passed",
status: 'SUCCESS',
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
} else {
githubNotify credentialsId: 'test-jenkins-credentials',
description: "The ${TEST_SUITE}-${TEST_PLATFORM} job has failed",
status: 'FAILURE',
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
}
}
}
}
}
}
}
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}"
}
}
}

View File

@ -1,73 +1,80 @@
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'
timeout(time: 6, unit: 'HOURS') {
node('kitchen-slave') {
timestamps {
ansiColor('xterm') {
withEnv([
'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',
]) {
stage('checkout-scm') {
cleanWs notFailBuild: true
checkout scm
}
}}
}
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'
try {
stage('github-pending') {
githubNotify credentialsId: 'test-jenkins-credentials',
description: "running ${TEST_SUITE}-${TEST_PLATFORM}...",
status: 'PENDING',
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
}
}}
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
archiveArtifacts artifacts: 'artifacts/logs/minion'
archiveArtifacts artifacts: 'artifacts/logs/salt-runtests.log'
stage('setup-bundle') {
sh 'bundle install --with ec2 windows --without opennebula docker'
}
try {
stage('run kitchen') {
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'
}
}
}
} finally {
stage('cleanup kitchen') {
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'
archiveArtifacts artifacts: 'artifacts/logs/minion'
archiveArtifacts artifacts: 'artifacts/logs/salt-runtests.log'
}
}
} finally {
try {
junit 'artifacts/xml-unittests-output/*.xml'
} finally {
cleanWs notFailBuild: true
def currentResult = currentBuild.result ?: 'SUCCESS'
if ( currentResult == 'SUCCESS') {
githubNotify credentialsId: 'test-jenkins-credentials',
description: "The ${TEST_SUITE}-${TEST_PLATFORM} job has passed",
status: 'SUCCESS',
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
} else {
githubNotify credentialsId: 'test-jenkins-credentials',
description: "The ${TEST_SUITE}-${TEST_PLATFORM} job has failed",
status: 'FAILURE',
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
}
}
}
}
}
}
}
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}"
}
}
}

View File

@ -1,73 +1,80 @@
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'
timeout(time: 6, unit: 'HOURS') {
node('kitchen-slave') {
timestamps {
ansiColor('xterm') {
withEnv([
'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',
]) {
stage('checkout-scm') {
cleanWs notFailBuild: true
checkout scm
}
}}
}
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'
try {
stage('github-pending') {
githubNotify credentialsId: 'test-jenkins-credentials',
description: "running ${TEST_SUITE}-${TEST_PLATFORM}...",
status: 'PENDING',
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
}
}}
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
archiveArtifacts artifacts: 'artifacts/logs/minion'
archiveArtifacts artifacts: 'artifacts/logs/salt-runtests.log'
stage('setup-bundle') {
sh 'bundle install --with ec2 windows --without opennebula docker'
}
try {
stage('run kitchen') {
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'
}
}
}
} finally {
stage('cleanup kitchen') {
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'
archiveArtifacts artifacts: 'artifacts/logs/minion'
archiveArtifacts artifacts: 'artifacts/logs/salt-runtests.log'
}
}
} finally {
try {
junit 'artifacts/xml-unittests-output/*.xml'
} finally {
cleanWs notFailBuild: true
def currentResult = currentBuild.result ?: 'SUCCESS'
if (currentResult == 'SUCCESS') {
githubNotify credentialsId: 'test-jenkins-credentials',
description: "The ${TEST_SUITE}-${TEST_PLATFORM} job has passed",
status: 'SUCCESS',
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
} else {
githubNotify credentialsId: 'test-jenkins-credentials',
description: "The ${TEST_SUITE}-${TEST_PLATFORM} job has failed",
status: 'FAILURE',
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
}
}
}
}
}
}
}
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}"
}
}
}

View File

@ -1,73 +1,80 @@
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 = "windows-2016"
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'
timeout(time: 6, unit: 'HOURS') {
node('kitchen-slave') {
timestamps {
ansiColor('xterm') {
withEnv([
'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=windows-2016',
'PY_COLORS=1',
]) {
stage('checkout-scm') {
cleanWs notFailBuild: true
checkout scm
}
}}
}
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'
try {
stage('github-pending') {
githubNotify credentialsId: 'test-jenkins-credentials',
description: "running ${TEST_SUITE}-${TEST_PLATFORM}...",
status: 'PENDING',
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
}
}}
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
archiveArtifacts artifacts: 'artifacts/logs/minion'
archiveArtifacts artifacts: 'artifacts/logs/salt-runtests.log'
stage('setup-bundle') {
sh 'bundle install --with ec2 windows --without opennebula docker'
}
try {
stage('run kitchen') {
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'
}
}
}
} finally {
stage('cleanup kitchen') {
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'
archiveArtifacts artifacts: 'artifacts/logs/minion'
archiveArtifacts artifacts: 'artifacts/logs/salt-runtests.log'
}
}
} finally {
try {
junit 'artifacts/xml-unittests-output/*.xml'
} finally {
cleanWs notFailBuild: true
def currentResult = currentBuild.result ?: 'SUCCESS'
if (currentResult == 'SUCCESS') {
githubNotify credentialsId: 'test-jenkins-credentials',
description: "The ${TEST_SUITE}-${TEST_PLATFORM} job has passed",
status: 'SUCCESS',
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
} else {
githubNotify credentialsId: 'test-jenkins-credentials',
description: "The ${TEST_SUITE}-${TEST_PLATFORM} job has failed",
status: 'FAILURE',
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
}
}
}
}
}
}
}
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}"
}
}
}

View File

@ -1,73 +1,80 @@
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 = "windows-2016"
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'
timeout(time: 6, unit: 'HOURS') {
node('kitchen-slave') {
timestamps {
ansiColor('xterm') {
withEnv([
'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=windows-2016',
'PY_COLORS=1',
]) {
stage('checkout-scm') {
cleanWs notFailBuild: true
checkout scm
}
}}
}
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'
try {
stage('github-pending') {
githubNotify credentialsId: 'test-jenkins-credentials',
description: "running ${TEST_SUITE}-${TEST_PLATFORM}...",
status: 'PENDING',
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
}
}}
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
archiveArtifacts artifacts: 'artifacts/logs/minion'
archiveArtifacts artifacts: 'artifacts/logs/salt-runtests.log'
stage('setup-bundle') {
sh 'bundle install --with ec2 windows --without opennebula docker'
}
try {
stage('run kitchen') {
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'
}
}
}
} finally {
stage('cleanup kitchen') {
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'
archiveArtifacts artifacts: 'artifacts/logs/minion'
archiveArtifacts artifacts: 'artifacts/logs/salt-runtests.log'
}
}
} finally {
try {
junit 'artifacts/xml-unittests-output/*.xml'
} finally {
cleanWs notFailBuild: true
def currentResult = currentBuild.result ?: 'SUCCESS'
if (currentResult == 'SUCCESS') {
githubNotify credentialsId: 'test-jenkins-credentials',
description: "The ${TEST_SUITE}-${TEST_PLATFORM} job has passed",
status: 'SUCCESS',
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
} else {
githubNotify credentialsId: 'test-jenkins-credentials',
description: "The ${TEST_SUITE}-${TEST_PLATFORM} job has failed",
status: 'FAILURE',
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
}
}
}
}
}
}
}
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}"
}
}
}

View File

@ -3,6 +3,7 @@ pipeline {
options {
timestamps()
ansiColor('xterm')
timeout(time: 1, unit: 'HOURS')
}
environment {
PYENV_ROOT = "/usr/local/pyenv"

View File

@ -921,7 +921,7 @@ def owner(*paths):
.. versionadded:: 2014.7.0
Return the name of the package that owns the file. Multiple file paths can
be passed. Like :mod:`pkg.version <salt.modules.yumpkg.version`, if a
be passed. Like :mod:`pkg.version <salt.modules.yumpkg.version>`, if a
single path is passed, a string will be returned, and if multiple paths are
passed, a dictionary of file/package name pairs will be returned.

View File

@ -178,7 +178,9 @@ def enable(iface):
'''
if is_enabled(iface):
return True
cmd = ['netsh', 'interface', 'set', 'interface', iface, 'admin=ENABLED']
cmd = ['netsh', 'interface', 'set', 'interface',
'name={0}'.format(iface),
'admin=ENABLED']
__salt__['cmd.run'](cmd, python_shell=False)
return is_enabled(iface)
@ -195,7 +197,9 @@ def disable(iface):
'''
if is_disabled(iface):
return True
cmd = ['netsh', 'interface', 'set', 'interface', iface, 'admin=DISABLED']
cmd = ['netsh', 'interface', 'set', 'interface',
'name={0}'.format(iface),
'admin=DISABLED']
__salt__['cmd.run'](cmd, python_shell=False)
return is_disabled(iface)
@ -319,6 +323,18 @@ def set_static_dns(iface, *addrs):
'''
Set static DNS configuration on a Windows NIC
Args:
iface (str): The name of the interface to set
addrs (*):
One or more DNS servers to be added. To clear the list of DNS
servers pass an empty list (``[]``). If undefined or ``None`` no
changes will be made.
Returns:
dict: A dictionary containing the new DNS settings
CLI Example:
.. code-block:: bash
@ -326,17 +342,31 @@ def set_static_dns(iface, *addrs):
salt -G 'os_family:Windows' ip.set_static_dns 'Local Area Connection' '192.168.1.1'
salt -G 'os_family:Windows' ip.set_static_dns 'Local Area Connection' '192.168.1.252' '192.168.1.253'
'''
if addrs is () or str(addrs[0]).lower() == 'none':
return {'Interface': iface, 'DNS Server': 'No Changes'}
# Clear the list of DNS servers if [] is passed
if str(addrs[0]).lower() == '[]':
log.debug('Clearing list of DNS servers')
cmd = ['netsh', 'interface', 'ip', 'set', 'dns',
'name={0}'.format(iface),
'source=static',
'address=none']
__salt__['cmd.run'](cmd, python_shell=False)
return {'Interface': iface, 'DNS Server': []}
addr_index = 1
for addr in addrs:
if addr_index == 1:
cmd = ['netsh', 'int', 'ip', 'set', 'dns',
iface, 'static', addrs[0], 'primary']
cmd = ['netsh', 'interface', 'ip', 'set', 'dns',
'name={0}'.format(iface),
'source=static',
'address={0}'.format(addr),
'register=primary']
__salt__['cmd.run'](cmd, python_shell=False)
addr_index = addr_index + 1
else:
cmd = ['netsh', 'interface', 'ip', 'add', 'dns',
'name={0}'.format(iface),
'addr={0}'.format(addr),
'address={0}'.format(addr),
'index={0}'.format(addr_index)]
__salt__['cmd.run'](cmd, python_shell=False)
addr_index = addr_index + 1

View File

@ -2774,7 +2774,7 @@ def owner(*paths):
.. versionadded:: 2014.7.0
Return the name of the package that owns the file. Multiple file paths can
be passed. Like :mod:`pkg.version <salt.modules.yumpkg.version`, if a
be passed. Like :mod:`pkg.version <salt.modules.yumpkg.version>`, if a
single path is passed, a string will be returned, and if multiple paths are
passed, a dictionary of file/package name pairs will be returned.

View File

@ -35,6 +35,7 @@ import salt.fileclient
import salt.utils.crypt
import salt.utils.dictupdate
import salt.utils.event
import salt.utils.hashutils
import salt.utils.url
import salt.utils.process
import salt.utils.files
@ -1732,7 +1733,9 @@ class State(object):
ret['duration'] = duration
troot = os.path.join(self.opts['cachedir'], self.jid)
tfile = os.path.join(troot, _clean_tag(tag))
tfile = os.path.join(
troot,
salt.utils.hashutils.sha1_digest(tag))
if not os.path.isdir(troot):
try:
os.makedirs(troot)
@ -2091,7 +2094,10 @@ class State(object):
proc = running[tag].get('proc')
if proc:
if not proc.is_alive():
ret_cache = os.path.join(self.opts['cachedir'], self.jid, _clean_tag(tag))
ret_cache = os.path.join(
self.opts['cachedir'],
self.jid,
salt.utils.hashutils.sha1_digest(tag))
if not os.path.isfile(ret_cache):
ret = {'result': False,
'comment': 'Parallel process failed to return',

View File

@ -4921,7 +4921,9 @@ def append(name,
check_res, check_msg = _check_file(name)
if not check_res:
# Try to create the file
touch(name, makedirs=makedirs)
touch_ret = touch(name, makedirs=makedirs)
if __opts__['test']:
return touch_ret
retry_res, retry_msg = _check_file(name)
if not retry_res:
return _error(ret, check_msg)
@ -5202,7 +5204,9 @@ def prepend(name,
check_res, check_msg = _check_file(name)
if not check_res:
# Try to create the file
touch(name, makedirs=makedirs)
touch_ret = touch(name, makedirs=makedirs)
if __opts__['test']:
return touch_ret
retry_res, retry_msg = _check_file(name)
if not retry_res:
return _error(ret, check_msg)

View File

@ -3,6 +3,8 @@
Managing software RAID with mdadm
==================================
:depends: mdadm
A state module for creating or destroying software RAID devices.
.. code-block:: yaml

View File

@ -100,22 +100,20 @@ def _validate(dns_proto, dns_servers, ip_proto, ip_addrs, gateway):
if dns_servers is not None:
errors.append(
'The dns_servers param cannot be set if unless dns_proto is '
'set to \'static\'.'
'set to \'static\''
)
else:
if not dns_servers:
errors.append(
'The dns_servers param is required to set static DNS servers.'
)
if str(dns_servers).lower() in ['none', '[]']:
pass
elif not isinstance(dns_servers, list):
errors.append(
'The dns_servers param must be formatted as a list.'
'The dns_servers param must be formatted as a list'
)
else:
bad_ips = [x for x in dns_servers
if not salt.utils.validate.net.ipv4_addr(x)]
if bad_ips:
errors.append('Invalid DNS server IPs: {0}.'
errors.append('Invalid DNS server IPs: {0}'
.format(', '.join(bad_ips)))
# Validate IP configuration
@ -123,33 +121,33 @@ def _validate(dns_proto, dns_servers, ip_proto, ip_addrs, gateway):
if ip_addrs is not None:
errors.append(
'The ip_addrs param cannot be set if unless ip_proto is set '
'to \'static\'.'
'to \'static\''
)
if gateway is not None:
errors.append(
'A gateway IP cannot be set if unless ip_proto is set to '
'\'static\'.'
'\'static\''
)
else:
if not ip_addrs:
errors.append(
'The ip_addrs param is required to set static IPs.'
'The ip_addrs param is required to set static IPs'
)
elif not isinstance(ip_addrs, list):
errors.append(
'The ip_addrs param must be formatted as a list.'
'The ip_addrs param must be formatted as a list'
)
else:
bad_ips = [x for x in ip_addrs
if not salt.utils.validate.net.ipv4_addr(x)]
if bad_ips:
errors.append('The following static IPs are invalid: '
'{0}.'.format(', '.join(bad_ips)))
'{0}'.format(', '.join(bad_ips)))
# Validate default gateway
if gateway is not None:
if not salt.utils.validate.net.ipv4_addr(gateway):
errors.append('Gateway IP {0} is invalid.'.format(gateway))
errors.append('Gateway IP {0} is invalid'.format(gateway))
return errors
@ -176,7 +174,10 @@ def _changes(cur, dns_proto, dns_servers, ip_proto, ip_addrs, gateway):
else 'dhcp'
)
if cur_dns_proto == 'static':
cur_dns_servers = cur['Statically Configured DNS Servers']
if isinstance(cur['Statically Configured DNS Servers'], list):
cur_dns_servers = cur['Statically Configured DNS Servers']
else:
cur_dns_servers = [cur['Statically Configured DNS Servers']]
if set(dns_servers or ['None']) != set(cur_dns_servers):
changes['dns_servers'] = dns_servers
elif 'DNS servers configured through DHCP' in cur:
@ -214,37 +215,66 @@ def managed(name,
'''
Ensure that the named interface is configured properly.
name
The name of the interface to manage
Args:
dns_proto : None
Set to ``static`` and use the ``dns_servers`` parameter to provide a
list of DNS nameservers. set to ``dhcp`` to use DHCP to get the DNS
servers.
name (str):
The name of the interface to manage
dns_servers : None
A list of static DNS servers.
dns_proto (str): None
Set to ``static`` and use the ``dns_servers`` parameter to provide a
list of DNS nameservers. set to ``dhcp`` to use DHCP to get the DNS
servers.
ip_proto : None
Set to ``static`` and use the ``ip_addrs`` and (optionally) ``gateway``
parameters to provide a list of static IP addresses and the default
gateway. Set to ``dhcp`` to use DHCP.
dns_servers (list): None
A list of static DNS servers. To clear the list of DNS servers pass
an empty list (``[]``). ``None`` will make no changes.
ip_addrs : None
A list of static IP addresses.
ip_proto (str): None
Set to ``static`` and use the ``ip_addrs`` and (optionally)
``gateway`` parameters to provide a list of static IP addresses and
the default gateway. Set to ``dhcp`` to use DHCP.
gateway : None
A list of static IP addresses.
ip_addrs (list): None
A list of static IP addresses with netmask flag, ie: 192.168.0.11/24
enabled : True
Set to ``False`` to ensure that this interface is disabled.
gateway (str): None
The gateway to set for the interface
enabled (bool): True
Set to ``False`` to ensure that this interface is disabled.
Returns:
dict: A dictionary of old and new settings
Example:
.. code-block:: yaml
Ethernet1:
network.managed:
- dns_proto: static
- dns_servers:
- 8.8.8.8
- 8.8.8.4
- ip_proto: static
- ip_addrs:
- 192.168.0.100/24
Clear DNS entries example:
.. code-block:: yaml
Ethernet1:
network.managed:
- dns_proto: static
- dns_servers: []
- ip_proto: dhcp
'''
ret = {
'name': name,
'changes': {},
'result': True,
'comment': 'Interface \'{0}\' is up to date.'.format(name)
'comment': 'Interface \'{0}\' is up to date'.format(name)
}
dns_proto = str(dns_proto).lower()
@ -253,16 +283,16 @@ def managed(name,
errors = []
if dns_proto not in __VALID_PROTO:
ret['result'] = False
errors.append('dns_proto must be one of the following: {0}.'
errors.append('dns_proto must be one of the following: {0}'
.format(', '.join(__VALID_PROTO)))
if ip_proto not in __VALID_PROTO:
errors.append('ip_proto must be one of the following: {0}.'
errors.append('ip_proto must be one of the following: {0}'
.format(', '.join(__VALID_PROTO)))
if errors:
ret['result'] = False
ret['comment'] = ' '.join(errors)
ret['comment'] = '\n'.join(errors)
return ret
try:
@ -301,7 +331,7 @@ def managed(name,
if errors:
ret['result'] = False
ret['comment'] = ('The following SLS configuration errors were '
'detected: {0}'.format(' '.join(errors)))
'detected:\n- {0}'.format('\n- '.join(errors)))
return ret
old = __salt__['ip.get_interface'](name)
@ -317,49 +347,63 @@ def managed(name,
ip_proto,
ip_addrs,
gateway)
# If dns_servers is the default `None` make no changes
# To clear the list, pass an empty dict
if str(dns_servers).lower() == 'none':
changes.pop('dns_servers', None)
if not changes:
return ret
if __opts__['test']:
comments = []
if 'dns_proto' in changes:
comments.append('DNS protocol will be changed to: {0}.'
comments.append('DNS protocol will be changed to: {0}'
.format(changes['dns_proto']))
if dns_proto == 'static' and 'dns_servers' in changes:
comments.append(
'DNS servers will be set to the following: {0}.'
.format(', '.join(changes['dns_servers']))
)
if len(changes['dns_servers']) == 0:
comments.append('The list of DNS servers will be cleared')
else:
comments.append(
'DNS servers will be set to the following: {0}'
.format(', '.join(changes['dns_servers']))
)
if 'ip_proto' in changes:
comments.append('IP protocol will be changed to: {0}.'
comments.append('IP protocol will be changed to: {0}'
.format(changes['ip_proto']))
if ip_proto == 'static':
if 'ip_addrs' in changes:
comments.append(
'IP addresses will be set to the following: {0}.'
'IP addresses will be set to the following: {0}'
.format(', '.join(changes['ip_addrs']))
)
if 'gateway' in changes:
if changes['gateway'] is None:
comments.append('Default gateway will be removed.')
comments.append('Default gateway will be removed')
else:
comments.append(
'Default gateway will be set to {0}.'
'Default gateway will be set to {0}'
.format(changes['gateway'])
)
ret['result'] = None
ret['comment'] = ('The following changes will be made to '
'interface \'{0}\': {1}'
.format(name, ' '.join(comments)))
'interface \'{0}\':\n- {1}'
.format(name, '\n- '.join(comments)))
return ret
if changes.get('dns_proto') == 'dhcp':
__salt__['ip.set_dhcp_dns'](name)
elif changes.get('dns_servers'):
if changes.get('dns_servers'):
__salt__['ip.set_static_dns'](name, *changes['dns_servers'])
elif 'dns_servers' in changes:
if len(changes['dns_servers']) == 0:
# To clear the list of DNS servers you have to pass []. Later
# changes gets passed like *args and a single empty list is
# converted to an empty tuple. So, you have to add [] here
changes['dns_servers'] = [[]]
__salt__['ip.set_static_dns'](name, *changes['dns_servers'])
if changes.get('ip_proto') == 'dhcp':
__salt__['ip.set_dhcp_ip'](name)

View File

@ -82,6 +82,16 @@ def md5_digest(instr):
return hashlib.md5(instr).hexdigest()
def sha1_digest(instr):
'''
Generate an sha1 hash of a given string.
'''
if six.PY3:
b = salt.utils.to_bytes(instr)
return hashlib.sha1(b).hexdigest()
return hashlib.sha1(instr).hexdigest()
def sha256_digest(instr):
'''
Generate an sha256 hash of a given string.

View File

@ -0,0 +1,9 @@
test_cmd_too_long:
cmd.run:
- name: {{ pillar['long_command'] }}
- parallel: True
test_cmd_not_found:
cmd.run:
- name: {{ pillar['short_command'] }}
- parallel: True

View File

@ -4,6 +4,7 @@
from __future__ import absolute_import
import os
import shutil
import sys
import tempfile
import textwrap
import threading
@ -12,48 +13,20 @@ import time
# Import Salt Testing libs
from tests.support.case import ModuleCase
from tests.support.unit import skipIf
from tests.support.paths import TMP, FILES
from tests.support.paths import TMP, BASE_FILES
from tests.support.mixins import SaltReturnAssertsMixin
# Import salt libs
import salt.utils
import salt.utils.atomicfile
from salt.modules.virtualenv_mod import KNOWN_BINARY_NAMES
# Import 3rd-party libs
import salt.ext.six as six
DEFAULT_ENDING = salt.utils.to_bytes(os.linesep)
def trim_line_end(line):
'''
Remove CRLF or LF from the end of line.
'''
if line[-2:] == salt.utils.to_bytes('\r\n'):
return line[:-2]
elif line[-1:] == salt.utils.to_bytes('\n'):
return line[:-1]
raise Exception("Invalid line ending")
def reline(source, dest, force=False, ending=DEFAULT_ENDING):
'''
Normalize the line endings of a file.
'''
fp, tmp = tempfile.mkstemp()
os.close(fp)
with salt.utils.fopen(tmp, 'wb') as tmp_fd:
with salt.utils.fopen(source, 'rb') as fd:
lines = fd.readlines()
for line in lines:
line_noend = trim_line_end(line)
tmp_fd.write(line_noend + ending)
if os.path.exists(dest) and force:
os.remove(dest)
os.rename(tmp, dest)
class StateModuleTest(ModuleCase, SaltReturnAssertsMixin):
'''
Validate the state module
@ -61,12 +34,22 @@ class StateModuleTest(ModuleCase, SaltReturnAssertsMixin):
maxDiff = None
def setUp(self):
super(StateModuleTest, self).setUp()
destpath = os.path.join(FILES, 'file', 'base', 'testappend', 'firstif')
reline(destpath, destpath, force=True)
destpath = os.path.join(FILES, 'file', 'base', 'testappend', 'secondif')
reline(destpath, destpath, force=True)
@classmethod
def setUpClass(cls):
def _reline(path, ending=DEFAULT_ENDING):
'''
Normalize the line endings of a file.
'''
with salt.utils.fopen(path, 'rb') as fhr:
lines = fhr.read().splitlines()
with salt.utils.atomicfile.atomic_open(path, 'wb') as fhw:
for line in lines:
fhw.write(line + ending)
destpath = os.path.join(BASE_FILES, 'testappend', 'firstif')
_reline(destpath)
destpath = os.path.join(BASE_FILES, 'testappend', 'secondif')
_reline(destpath)
def test_show_highstate(self):
'''
@ -1423,20 +1406,47 @@ class StateModuleTest(ModuleCase, SaltReturnAssertsMixin):
test state.sls with saltenv using a nonbase environment
with a salt source
'''
file_name = os.path.join(TMP, 'nonbase_env')
state_run = self.run_function(
'state.sls',
mods='non-base-env',
saltenv='prod'
)
state_id = 'file_|-test_file_|-{0}_|-managed'.format(file_name)
self.assertEqual(state_run[state_id]['comment'],
'File {0} updated'.format(file_name))
self.assertTrue(
state_run['file_|-test_file_|-{0}_|-managed'.format(file_name)]['result'])
self.assertTrue(os.path.isfile(file_name))
filename = os.path.join(TMP, 'nonbase_env')
try:
ret = self.run_function(
'state.sls',
mods='non-base-env',
saltenv='prod'
)
ret = ret[next(iter(ret))]
assert ret['result']
assert ret['comment'] == 'File {0} updated'.format(filename)
assert os.path.isfile(filename)
finally:
try:
os.remove(filename)
except OSError:
pass
def tearDown(self):
nonbase_file = os.path.join(TMP, 'nonbase_env')
if os.path.isfile(nonbase_file):
os.remove(nonbase_file)
@skipIf(sys.platform.startswith('win'), 'Skipped until parallel states can be fixed on Windows')
def test_parallel_state_with_long_tag(self):
'''
This tests the case where the state being executed has a long ID dec or
name and states are being run in parallel. The filenames used for the
parallel state cache were previously based on the tag for each chunk,
and longer ID decs or name params can cause the cache file to be longer
than the operating system's max file name length. To counter this we
instead generate a SHA1 hash of the chunk's tag to use as the cache
filename. This test will ensure that long tags don't cause caching
failures.
See https://github.com/saltstack/salt/issues/49738 for more info.
'''
short_command = 'helloworld'
long_command = short_command * 25
ret = self.run_function(
'state.sls',
mods='issue-49738',
pillar={'short_command': short_command,
'long_command': long_command}
)
comments = sorted([x['comment'] for x in six.itervalues(ret)])
expected = sorted(['Command "{0}" run'.format(x)
for x in (short_command, long_command)])
assert comments == expected, '{0} != {1}'.format(comments, expected)

View File

@ -13,7 +13,8 @@ from tests.support.mock import (
MagicMock,
patch,
NO_MOCK,
NO_MOCK_REASON
NO_MOCK_REASON,
call
)
# Import Salt Libs
@ -124,13 +125,21 @@ class WinShadowTestCase(TestCase, LoaderModuleMockMixin):
'''
Test if it enable an interface.
'''
mock_cmd = MagicMock(return_value=ETHERNET_ENABLE)
with patch.dict(win_ip.__salt__, {'cmd.run': mock_cmd}):
# Test with enabled interface
with patch.object(win_ip, 'is_enabled', return_value=True):
self.assertTrue(win_ip.enable('Ethernet'))
mock_cmd = MagicMock(return_value='Connect state: Disconnected')
with patch.dict(win_ip.__salt__, {'cmd.run': mock_cmd}):
self.assertFalse(win_ip.enable('Ethernet'))
mock_cmd = MagicMock()
with patch.object(win_ip, 'is_enabled', side_effect=[False, True]), \
patch.dict(win_ip.__salt__, {'cmd.run': mock_cmd}):
self.assertTrue(win_ip.enable('Ethernet'))
mock_cmd.called_once_with(
['netsh', 'interface', 'set', 'interface',
'name=Ethernet',
'admin=ENABLED'],
python_shell=False
)
# 'disable' function tests: 1
@ -138,14 +147,21 @@ class WinShadowTestCase(TestCase, LoaderModuleMockMixin):
'''
Test if it disable an interface.
'''
mock_cmd = MagicMock(return_value=ETHERNET_ENABLE)
with patch.dict(win_ip.__salt__, {'cmd.run': mock_cmd}):
self.assertFalse(win_ip.disable('Ethernet'))
mock_cmd = MagicMock(return_value='Connect state: Disconnected')
with patch.dict(win_ip.__salt__, {'cmd.run': mock_cmd}):
with patch.object(win_ip, 'is_disabled', return_value=True):
self.assertTrue(win_ip.disable('Ethernet'))
mock_cmd = MagicMock()
with patch.object(win_ip, 'is_disabled', side_effect=[False, True]),\
patch.dict(win_ip.__salt__, {'cmd.run': mock_cmd}):
self.assertTrue(win_ip.disable('Ethernet'))
mock_cmd.called_once_with(
['netsh', 'interface', 'set', 'interface',
'name=Ethernet',
'admin=DISABLED'],
python_shell=False
)
# 'get_subnet_length' function tests: 1
def test_get_subnet_length(self):
@ -203,7 +219,7 @@ class WinShadowTestCase(TestCase, LoaderModuleMockMixin):
'''
Test if it set static DNS configuration on a Windows NIC.
'''
mock_cmd = MagicMock(return_value=ETHERNET_CONFIG)
mock_cmd = MagicMock()
with patch.dict(win_ip.__salt__, {'cmd.run': mock_cmd}):
self.assertDictEqual(win_ip.set_static_dns('Ethernet',
'192.168.1.252',
@ -211,6 +227,54 @@ class WinShadowTestCase(TestCase, LoaderModuleMockMixin):
{'DNS Server': ('192.168.1.252',
'192.168.1.253'),
'Interface': 'Ethernet'})
mock_cmd.assert_has_calls([
call(['netsh', 'interface', 'ip', 'set', 'dns',
'name=Ethernet',
'source=static',
'address=192.168.1.252',
'register=primary'],
python_shell=False),
call(['netsh', 'interface', 'ip', 'add', 'dns',
'name=Ethernet',
'address=192.168.1.253',
'index=2'],
python_shell=False)]
)
def test_set_static_dns_clear(self):
'''
Test if it set static DNS configuration on a Windows NIC.
'''
mock_cmd = MagicMock()
with patch.dict(win_ip.__salt__, {'cmd.run': mock_cmd}):
self.assertDictEqual(win_ip.set_static_dns('Ethernet', []),
{'DNS Server': [],
'Interface': 'Ethernet'})
mock_cmd.assert_called_once_with(
['netsh', 'interface', 'ip', 'set', 'dns',
'name=Ethernet',
'source=static',
'address=none'],
python_shell=False
)
def test_set_static_dns_no_action(self):
'''
Test if it set static DNS configuration on a Windows NIC.
'''
# Test passing nothing
self.assertDictEqual(win_ip.set_static_dns('Ethernet'),
{'DNS Server': 'No Changes',
'Interface': 'Ethernet'})
# Test passing None
self.assertDictEqual(win_ip.set_static_dns('Ethernet', None),
{'DNS Server': 'No Changes',
'Interface': 'Ethernet'})
# Test passing string None
self.assertDictEqual(win_ip.set_static_dns('Ethernet', 'None'),
{'DNS Server': 'No Changes',
'Interface': 'Ethernet'})
# 'set_dhcp_dns' function tests: 1

View File

@ -28,93 +28,242 @@ class WinNetworkTestCase(TestCase, LoaderModuleMockMixin):
def setup_loader_modules(self):
return {win_network: {}}
def test_managed(self):
def test_managed_missing_parameters(self):
'''
Test to ensure that the named interface is configured properly.
Test to ensure that the named interface is configured properly.
'''
ret = {'name': 'salt',
'changes': {},
'result': False,
'comment': ''}
ret.update({'comment': 'dns_proto must be one of the following:'
' static, dhcp. ip_proto must be one of the following:'
' static, dhcp.'})
'comment': 'dns_proto must be one of the following: static, dhcp\n'
'ip_proto must be one of the following: static, dhcp'}
self.assertDictEqual(win_network.managed('salt'), ret)
def test_managed_static_enabled_false(self):
ret = {'name': 'salt',
'changes': {},
'result': True,
'comment': 'Interface \'salt\' is up to date (already disabled)'}
mock_false = MagicMock(return_value=False)
with patch.dict(win_network.__salt__, {"ip.is_enabled": mock_false}):
self.assertDictEqual(
win_network.managed(
'salt', dns_proto='static', ip_proto='static', enabled=False),
ret)
def test_managed_test_true(self):
ret = {'name': 'salt',
'changes': {},
'result': False,
'comment': 'Failed to enable interface \'salt\' to make changes'}
mock_false = MagicMock(return_value=False)
mock_true = MagicMock(return_value=True)
mock1 = MagicMock(side_effect=[False, True, True, True, True, True,
True])
mock2 = MagicMock(side_effect=[False, True, True, {'salt': 'True'},
{'salt': 'True'}])
with patch.dict(win_network.__salt__, {"ip.is_enabled": mock_false,
"ip.is_disabled": mock1,
"ip.enable": mock_false,
"ip.get_interface": mock2,
"ip.set_dhcp_dns": mock_false,
"ip.set_dhcp_ip": mock_false}):
ret.update({'comment': "Interface 'salt' is up to date."
" (already disabled)", 'result': True})
self.assertDictEqual(win_network.managed('salt',
dns_proto='static',
ip_proto='static',
enabled=False), ret)
"ip.enable": mock_false}), \
patch.dict(win_network.__opts__, {"test": False}):
self.assertDictEqual(
win_network.managed(
'salt', dns_proto='static', ip_proto='static'),
ret)
with patch.dict(win_network.__opts__, {"test": False}):
ret.update({'comment': "Failed to enable interface 'salt'"
" to make changes", 'result': False})
self.assertDictEqual(win_network.managed('salt',
dns_proto='static',
ip_proto='static'),
ret)
mock_false = MagicMock(side_effect=['True', False, False, False, False,
False])
def test_managed_validate_errors(self):
ret = {'name': 'salt',
'changes': {},
'result': False,
'comment': 'The following SLS configuration errors were '
'detected:\n'
'- First Error\n'
'- Second Error'}
mock_true = MagicMock(return_value=True)
mock_validate = MagicMock(return_value=['First Error', 'Second Error'])
with patch.dict(win_network.__salt__, {"ip.is_enabled": mock_true}),\
patch.object(win_network, '_validate', mock_validate):
self.assertDictEqual(
win_network.managed(
'salt', dns_proto='static', ip_proto='static'),
ret)
with patch.dict(win_network.__salt__, {"ip.is_enabled": mock_true}):
with patch.object(win_network, '_validate', mock_false):
ret.update({'comment': 'The following SLS configuration'
' errors were detected: T r u e'})
self.assertDictEqual(win_network.managed('salt',
dns_proto='static',
ip_proto='static'),
ret)
def test_managed_get_current_config_failed(self):
ret = {'name': 'salt',
'changes': {},
'result': False,
'comment': 'Unable to get current configuration for interface '
'\'salt\''}
mock_true = MagicMock(return_value=True)
mock_false = MagicMock(return_value=False)
mock_validate = MagicMock(return_value=[])
with patch.dict(win_network.__salt__, {'ip.is_enabled': mock_true,
'ip.get_interface': mock_false}), \
patch.object(win_network, '_validate', mock_validate):
ret.update({'comment': "Unable to get current"
" configuration for interface 'salt'",
'result': False})
self.assertDictEqual(win_network.managed('salt',
dns_proto='dhcp',
ip_proto='dhcp'),
ret)
self.assertDictEqual(
win_network.managed('salt', dns_proto='dhcp', ip_proto='dhcp'),
ret)
mock_false = MagicMock(side_effect=[False, [''],
{'dns_proto': 'dhcp',
'ip_proto': 'dhcp'},
{'dns_proto': 'dhcp',
'ip_proto': 'dhcp'}])
ret.update({'comment': "Interface 'salt' is up to date.",
'result': True})
with patch.object(win_network, '_changes', mock_false):
self.assertDictEqual(win_network.managed('salt',
dns_proto='dhcp',
ip_proto='dhcp'
), ret)
def test_managed_test_true_no_changes(self):
ret = {'name': 'salt',
'changes': {},
'result': True,
'comment': 'Interface \'salt\' is up to date'}
mock_true = MagicMock(return_value=True)
mock_validate = MagicMock(return_value=[])
mock_get_int = MagicMock(return_value={
'DHCP enabled': 'yes',
'DNS servers configured through DHCP': '192.168.0.10'})
with patch.dict(win_network.__salt__, {'ip.is_enabled': mock_true,
'ip.get_interface': mock_get_int}), \
patch.dict(win_network.__opts__, {"test": True}), \
patch.object(win_network, '_validate', mock_validate):
self.assertDictEqual(
win_network.managed('salt', dns_proto='dhcp', ip_proto='dhcp'),
ret)
ret.update({'comment': "The following changes will be made"
" to interface 'salt': ", 'result': None})
with patch.dict(win_network.__opts__, {"test": True}):
self.assertDictEqual(win_network.managed('salt',
dns_proto='dh'
'cp',
ip_proto='dhcp'
), ret)
def test_managed_test_true_changes(self):
ret = {'name': 'salt',
'changes': {},
'result': None,
'comment': 'The following changes will be made to interface '
'\'salt\':\n'
'- DNS protocol will be changed to: dhcp'}
mock_true = MagicMock(return_value=True)
mock_validate = MagicMock(return_value=[])
mock_get_int = MagicMock(return_value={
'DHCP enabled': 'no',
'Statically Configured DNS Servers': '192.168.0.10'})
with patch.dict(win_network.__salt__, {'ip.is_enabled': mock_true,
'ip.get_interface': mock_get_int}), \
patch.dict(win_network.__opts__, {"test": True}), \
patch.object(win_network, '_validate', mock_validate):
with patch.dict(win_network.__opts__, {"test": False}):
ret.update({'comment': "Failed to set desired"
" configuration settings for interface"
" 'salt'", 'result': False})
self.assertDictEqual(win_network.managed('salt',
dns_proto='dh'
'cp',
ip_proto='dhcp'
), ret)
self.assertDictEqual(
win_network.managed('salt', dns_proto='dhcp', ip_proto='dhcp'),
ret)
def test_managed_failed(self):
ret = {'name': 'salt',
'changes': {},
'result': False,
'comment': 'Failed to set desired configuration settings for '
'interface \'salt\''}
mock_true = MagicMock(return_value=True)
mock_validate = MagicMock(return_value=[])
mock_get_int = MagicMock(return_value={
'DHCP enabled': 'no',
'Statically Configured DNS Servers': '192.168.0.10'})
with patch.dict(win_network.__salt__, {'ip.is_enabled': mock_true,
'ip.get_interface': mock_get_int,
'ip.set_dhcp_dns': mock_true,
'ip.set_dhcp_ip': mock_true}), \
patch.dict(win_network.__opts__, {"test": False}), \
patch.object(win_network, '_validate', mock_validate):
self.assertDictEqual(
win_network.managed('salt', dns_proto='dhcp', ip_proto='dhcp'),
ret)
def test_managed(self):
ret = {'name': 'salt',
'changes': {
'DHCP enabled': {
'new': 'yes',
'old': 'no'},
'DNS servers configured through DHCP': {
'new': '192.168.0.10',
'old': ''},
'Statically Configured DNS Servers': {
'new': '',
'old': '192.168.0.10'
}
},
'result': True,
'comment': 'Successfully updated configuration for interface '
'\'salt\''}
mock_true = MagicMock(return_value=True)
mock_validate = MagicMock(return_value=[])
mock_get_int = MagicMock(side_effect=[
{'DHCP enabled': 'no', 'Statically Configured DNS Servers': '192.168.0.10'},
{'DHCP enabled': 'yes', 'DNS servers configured through DHCP': '192.168.0.10'},
])
with patch.dict(win_network.__salt__, {'ip.is_enabled': mock_true,
'ip.get_interface': mock_get_int,
'ip.set_dhcp_dns': mock_true,
'ip.set_dhcp_ip': mock_true}), \
patch.dict(win_network.__opts__, {"test": False}), \
patch.object(win_network, '_validate', mock_validate):
self.assertDictEqual(
win_network.managed('salt', dns_proto='dhcp', ip_proto='dhcp'),
ret)
def test_managed_static_dns_clear(self):
expected = {'name': 'salt',
'changes': {
'Statically Configured DNS Servers': {
'new': 'None',
'old': '192.168.0.10'
}
},
'result': True,
'comment': 'Successfully updated configuration for '
'interface \'salt\''}
mock_true = MagicMock(return_value=True)
mock_validate = MagicMock(return_value=[])
mock_get_int = MagicMock(side_effect=[
{'DHCP enabled': 'no', 'Statically Configured DNS Servers': '192.168.0.10'},
{'DHCP enabled': 'no', 'Statically Configured DNS Servers': 'None'},
])
with patch.dict(win_network.__salt__, {'ip.is_enabled': mock_true,
'ip.get_interface': mock_get_int,
'ip.set_static_dns': mock_true}), \
patch.dict(win_network.__opts__, {"test": False}), \
patch.object(win_network, '_validate', mock_validate):
ret = win_network.managed(
'salt', dns_proto='static', dns_servers=[], ip_proto='dhcp')
self.assertDictEqual(ret, expected)
def test_managed_static_dns(self):
expected = {'name': 'salt',
'changes': {
'Statically Configured DNS Servers': {
'new': '192.168.0.10',
'old': 'None'
}
},
'result': True,
'comment': 'Successfully updated configuration for '
'interface \'salt\''}
mock_true = MagicMock(return_value=True)
mock_validate = MagicMock(return_value=[])
mock_get_int = MagicMock(side_effect=[
{'DHCP enabled': 'no', 'Statically Configured DNS Servers': 'None'},
{'DHCP enabled': 'no', 'Statically Configured DNS Servers': '192.168.0.10'},
])
with patch.dict(win_network.__salt__, {'ip.is_enabled': mock_true,
'ip.get_interface': mock_get_int,
'ip.set_static_dns': mock_true}), \
patch.dict(win_network.__opts__, {"test": False}), \
patch.object(win_network, '_validate', mock_validate):
ret = win_network.managed(
'salt', dns_proto='static', dns_servers=['192.168.0.10'], ip_proto='dhcp')
self.assertDictEqual(ret, expected)
def test_managed_static_dns_no_action(self):
expected = {'name': 'salt',
'changes': {},
'result': True,
'comment': 'Interface \'salt\' is up to date'}
mock_true = MagicMock(return_value=True)
mock_validate = MagicMock(return_value=[])
mock_get_int = MagicMock(return_value={
'DHCP enabled': 'no',
'Statically Configured DNS Servers': '192.168.0.10'
})
with patch.dict(win_network.__salt__, {'ip.is_enabled': mock_true,
'ip.get_interface': mock_get_int,
'ip.set_static_dns': mock_true}), \
patch.dict(win_network.__opts__, {"test": False}), \
patch.object(win_network, '_validate', mock_validate):
# Don't pass dns_servers
ret = win_network.managed('salt', dns_proto='static', ip_proto='dhcp')
self.assertDictEqual(ret, expected)
# Pass dns_servers=None
ret = win_network.managed(
'salt', dns_proto='static', dns_servers=None, ip_proto='dhcp')
self.assertDictEqual(ret, expected)