mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 00:55:19 +00:00
Merge branch 'fluorine' into proxy
This commit is contained in:
commit
40c6b9d50e
5
.ci/docs
5
.ci/docs
@ -1,8 +1,11 @@
|
|||||||
pipeline {
|
pipeline {
|
||||||
agent { label 'docs' }
|
agent {
|
||||||
|
label 'docs'
|
||||||
|
}
|
||||||
options {
|
options {
|
||||||
timestamps()
|
timestamps()
|
||||||
ansiColor('xterm')
|
ansiColor('xterm')
|
||||||
|
timeout(time: 2, unit: 'HOURS')
|
||||||
}
|
}
|
||||||
environment {
|
environment {
|
||||||
PYENV_ROOT = "/usr/local/pyenv"
|
PYENV_ROOT = "/usr/local/pyenv"
|
||||||
|
@ -1,73 +1,80 @@
|
|||||||
pipeline {
|
timeout(time: 6, unit: 'HOURS') {
|
||||||
agent { label 'kitchen-slave' }
|
node('kitchen-slave') {
|
||||||
options {
|
timestamps {
|
||||||
timestamps()
|
ansiColor('xterm') {
|
||||||
ansiColor('xterm')
|
withEnv([
|
||||||
}
|
'SALT_KITCHEN_PLATFORMS=/var/jenkins/workspace/platforms.yml',
|
||||||
environment {
|
'SALT_KITCHEN_DRIVER=/var/jenkins/workspace/driver.yml',
|
||||||
SALT_KITCHEN_PLATFORMS = "/var/jenkins/workspace/platforms.yml"
|
'PATH=/usr/local/rbenv/shims/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin',
|
||||||
SALT_KITCHEN_DRIVER = "/var/jenkins/workspace/driver.yml"
|
'RBENV_VERSION=2.4.2',
|
||||||
PATH = "/usr/local/rbenv/shims/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin"
|
'TEST_SUITE=py2',
|
||||||
RBENV_VERSION = "2.4.2"
|
'TEST_PLATFORM=centos-7',
|
||||||
TEST_SUITE = "py2"
|
'PY_COLORS=1',
|
||||||
TEST_PLATFORM = "centos-7"
|
]) {
|
||||||
PY_COLORS = 1
|
stage('checkout-scm') {
|
||||||
}
|
cleanWs notFailBuild: true
|
||||||
stages {
|
checkout scm
|
||||||
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'
|
|
||||||
}
|
}
|
||||||
}}
|
try {
|
||||||
}
|
stage('github-pending') {
|
||||||
post {
|
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||||
always {
|
description: "running ${TEST_SUITE}-${TEST_PLATFORM}...",
|
||||||
script { withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) {
|
status: 'PENDING',
|
||||||
sshagent(credentials: ['jenkins-testing-ssh-key']) {
|
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
|
||||||
sh 'ssh-add ~/.ssh/jenkins-testing.pem'
|
|
||||||
sh 'bundle exec kitchen destroy $TEST_SUITE-$TEST_PLATFORM'
|
|
||||||
}
|
}
|
||||||
}}
|
stage('setup-bundle') {
|
||||||
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
|
sh 'bundle install --with ec2 windows --without opennebula docker'
|
||||||
archiveArtifacts artifacts: 'artifacts/logs/minion'
|
}
|
||||||
archiveArtifacts artifacts: 'artifacts/logs/salt-runtests.log'
|
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}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,73 +1,80 @@
|
|||||||
pipeline {
|
timeout(time: 6, unit: 'HOURS') {
|
||||||
agent { label 'kitchen-slave' }
|
node('kitchen-slave') {
|
||||||
options {
|
timestamps {
|
||||||
timestamps()
|
ansiColor('xterm') {
|
||||||
ansiColor('xterm')
|
withEnv([
|
||||||
}
|
'SALT_KITCHEN_PLATFORMS=/var/jenkins/workspace/platforms.yml',
|
||||||
environment {
|
'SALT_KITCHEN_DRIVER=/var/jenkins/workspace/driver.yml',
|
||||||
SALT_KITCHEN_PLATFORMS = "/var/jenkins/workspace/platforms.yml"
|
'PATH=/usr/local/rbenv/shims/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin',
|
||||||
SALT_KITCHEN_DRIVER = "/var/jenkins/workspace/driver.yml"
|
'RBENV_VERSION=2.4.2',
|
||||||
PATH = "/usr/local/rbenv/shims/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin"
|
'TEST_SUITE=py3',
|
||||||
RBENV_VERSION = "2.4.2"
|
'TEST_PLATFORM=centos-7',
|
||||||
TEST_SUITE = "py3"
|
'PY_COLORS=1',
|
||||||
TEST_PLATFORM = "centos-7"
|
]) {
|
||||||
PY_COLORS = 1
|
stage('checkout-scm') {
|
||||||
}
|
cleanWs notFailBuild: true
|
||||||
stages {
|
checkout scm
|
||||||
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'
|
|
||||||
}
|
}
|
||||||
}}
|
try {
|
||||||
}
|
stage('github-pending') {
|
||||||
post {
|
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||||
always {
|
description: "running ${TEST_SUITE}-${TEST_PLATFORM}...",
|
||||||
script { withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) {
|
status: 'PENDING',
|
||||||
sshagent(credentials: ['jenkins-testing-ssh-key']) {
|
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
|
||||||
sh 'ssh-add ~/.ssh/jenkins-testing.pem'
|
|
||||||
sh 'bundle exec kitchen destroy $TEST_SUITE-$TEST_PLATFORM'
|
|
||||||
}
|
}
|
||||||
}}
|
stage('setup-bundle') {
|
||||||
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
|
sh 'bundle install --with ec2 windows --without opennebula docker'
|
||||||
archiveArtifacts artifacts: 'artifacts/logs/minion'
|
}
|
||||||
archiveArtifacts artifacts: 'artifacts/logs/salt-runtests.log'
|
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}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,73 +1,80 @@
|
|||||||
pipeline {
|
timeout(time: 6, unit: 'HOURS') {
|
||||||
agent { label 'kitchen-slave' }
|
node('kitchen-slave') {
|
||||||
options {
|
timestamps {
|
||||||
timestamps()
|
ansiColor('xterm') {
|
||||||
ansiColor('xterm')
|
withEnv([
|
||||||
}
|
'SALT_KITCHEN_PLATFORMS=/var/jenkins/workspace/platforms.yml',
|
||||||
environment {
|
'SALT_KITCHEN_DRIVER=/var/jenkins/workspace/driver.yml',
|
||||||
SALT_KITCHEN_PLATFORMS = "/var/jenkins/workspace/platforms.yml"
|
'PATH=/usr/local/rbenv/shims/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin',
|
||||||
SALT_KITCHEN_DRIVER = "/var/jenkins/workspace/driver.yml"
|
'RBENV_VERSION=2.4.2',
|
||||||
PATH = "/usr/local/rbenv/shims/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin"
|
'TEST_SUITE=py2',
|
||||||
RBENV_VERSION = "2.4.2"
|
'TEST_PLATFORM=ubuntu-1604',
|
||||||
TEST_SUITE = "py2"
|
'PY_COLORS=1',
|
||||||
TEST_PLATFORM = "ubuntu-1604"
|
]) {
|
||||||
PY_COLORS = 1
|
stage('checkout-scm') {
|
||||||
}
|
cleanWs notFailBuild: true
|
||||||
stages {
|
checkout scm
|
||||||
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'
|
|
||||||
}
|
}
|
||||||
}}
|
try {
|
||||||
}
|
stage('github-pending') {
|
||||||
post {
|
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||||
always {
|
description: "running ${TEST_SUITE}-${TEST_PLATFORM}...",
|
||||||
script { withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) {
|
status: 'PENDING',
|
||||||
sshagent(credentials: ['jenkins-testing-ssh-key']) {
|
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
|
||||||
sh 'ssh-add ~/.ssh/jenkins-testing.pem'
|
|
||||||
sh 'bundle exec kitchen destroy $TEST_SUITE-$TEST_PLATFORM'
|
|
||||||
}
|
}
|
||||||
}}
|
stage('setup-bundle') {
|
||||||
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
|
sh 'bundle install --with ec2 windows --without opennebula docker'
|
||||||
archiveArtifacts artifacts: 'artifacts/logs/minion'
|
}
|
||||||
archiveArtifacts artifacts: 'artifacts/logs/salt-runtests.log'
|
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}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,73 +1,80 @@
|
|||||||
pipeline {
|
timeout(time: 6, unit: 'HOURS') {
|
||||||
agent { label 'kitchen-slave' }
|
node('kitchen-slave') {
|
||||||
options {
|
timestamps {
|
||||||
timestamps()
|
ansiColor('xterm') {
|
||||||
ansiColor('xterm')
|
withEnv([
|
||||||
}
|
'SALT_KITCHEN_PLATFORMS=/var/jenkins/workspace/platforms.yml',
|
||||||
environment {
|
'SALT_KITCHEN_DRIVER=/var/jenkins/workspace/driver.yml',
|
||||||
SALT_KITCHEN_PLATFORMS = "/var/jenkins/workspace/platforms.yml"
|
'PATH=/usr/local/rbenv/shims/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin',
|
||||||
SALT_KITCHEN_DRIVER = "/var/jenkins/workspace/driver.yml"
|
'RBENV_VERSION=2.4.2',
|
||||||
PATH = "/usr/local/rbenv/shims/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin"
|
'TEST_SUITE=py3',
|
||||||
RBENV_VERSION = "2.4.2"
|
'TEST_PLATFORM=ubuntu-1604',
|
||||||
TEST_SUITE = "py3"
|
'PY_COLORS=1',
|
||||||
TEST_PLATFORM = "ubuntu-1604"
|
]) {
|
||||||
PY_COLORS = 1
|
stage('checkout-scm') {
|
||||||
}
|
cleanWs notFailBuild: true
|
||||||
stages {
|
checkout scm
|
||||||
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'
|
|
||||||
}
|
}
|
||||||
}}
|
try {
|
||||||
}
|
stage('github-pending') {
|
||||||
post {
|
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||||
always {
|
description: "running ${TEST_SUITE}-${TEST_PLATFORM}...",
|
||||||
script { withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) {
|
status: 'PENDING',
|
||||||
sshagent(credentials: ['jenkins-testing-ssh-key']) {
|
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
|
||||||
sh 'ssh-add ~/.ssh/jenkins-testing.pem'
|
|
||||||
sh 'bundle exec kitchen destroy $TEST_SUITE-$TEST_PLATFORM'
|
|
||||||
}
|
}
|
||||||
}}
|
stage('setup-bundle') {
|
||||||
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
|
sh 'bundle install --with ec2 windows --without opennebula docker'
|
||||||
archiveArtifacts artifacts: 'artifacts/logs/minion'
|
}
|
||||||
archiveArtifacts artifacts: 'artifacts/logs/salt-runtests.log'
|
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}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,73 +1,80 @@
|
|||||||
pipeline {
|
timeout(time: 6, unit: 'HOURS') {
|
||||||
agent { label 'kitchen-slave' }
|
node('kitchen-slave') {
|
||||||
options {
|
timestamps {
|
||||||
timestamps()
|
ansiColor('xterm') {
|
||||||
ansiColor('xterm')
|
withEnv([
|
||||||
}
|
'SALT_KITCHEN_PLATFORMS=/var/jenkins/workspace/platforms.yml',
|
||||||
environment {
|
'SALT_KITCHEN_DRIVER=/var/jenkins/workspace/driver.yml',
|
||||||
SALT_KITCHEN_PLATFORMS = "/var/jenkins/workspace/platforms.yml"
|
'PATH=/usr/local/rbenv/shims/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin',
|
||||||
SALT_KITCHEN_DRIVER = "/var/jenkins/workspace/driver.yml"
|
'RBENV_VERSION=2.4.2',
|
||||||
PATH = "/usr/local/rbenv/shims/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin"
|
'TEST_SUITE=py2',
|
||||||
RBENV_VERSION = "2.4.2"
|
'TEST_PLATFORM=windows-2016',
|
||||||
TEST_SUITE = "py2"
|
'PY_COLORS=1',
|
||||||
TEST_PLATFORM = "windows-2016"
|
]) {
|
||||||
PY_COLORS = 1
|
stage('checkout-scm') {
|
||||||
}
|
cleanWs notFailBuild: true
|
||||||
stages {
|
checkout scm
|
||||||
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'
|
|
||||||
}
|
}
|
||||||
}}
|
try {
|
||||||
}
|
stage('github-pending') {
|
||||||
post {
|
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||||
always {
|
description: "running ${TEST_SUITE}-${TEST_PLATFORM}...",
|
||||||
script { withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) {
|
status: 'PENDING',
|
||||||
sshagent(credentials: ['jenkins-testing-ssh-key']) {
|
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
|
||||||
sh 'ssh-add ~/.ssh/jenkins-testing.pem'
|
|
||||||
sh 'bundle exec kitchen destroy $TEST_SUITE-$TEST_PLATFORM'
|
|
||||||
}
|
}
|
||||||
}}
|
stage('setup-bundle') {
|
||||||
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
|
sh 'bundle install --with ec2 windows --without opennebula docker'
|
||||||
archiveArtifacts artifacts: 'artifacts/logs/minion'
|
}
|
||||||
archiveArtifacts artifacts: 'artifacts/logs/salt-runtests.log'
|
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}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,73 +1,80 @@
|
|||||||
pipeline {
|
timeout(time: 6, unit: 'HOURS') {
|
||||||
agent { label 'kitchen-slave' }
|
node('kitchen-slave') {
|
||||||
options {
|
timestamps {
|
||||||
timestamps()
|
ansiColor('xterm') {
|
||||||
ansiColor('xterm')
|
withEnv([
|
||||||
}
|
'SALT_KITCHEN_PLATFORMS=/var/jenkins/workspace/platforms.yml',
|
||||||
environment {
|
'SALT_KITCHEN_DRIVER=/var/jenkins/workspace/driver.yml',
|
||||||
SALT_KITCHEN_PLATFORMS = "/var/jenkins/workspace/platforms.yml"
|
'PATH=/usr/local/rbenv/shims/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin',
|
||||||
SALT_KITCHEN_DRIVER = "/var/jenkins/workspace/driver.yml"
|
'RBENV_VERSION=2.4.2',
|
||||||
PATH = "/usr/local/rbenv/shims/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin"
|
'TEST_SUITE=py3',
|
||||||
RBENV_VERSION = "2.4.2"
|
'TEST_PLATFORM=windows-2016',
|
||||||
TEST_SUITE = "py3"
|
'PY_COLORS=1',
|
||||||
TEST_PLATFORM = "windows-2016"
|
]) {
|
||||||
PY_COLORS = 1
|
stage('checkout-scm') {
|
||||||
}
|
cleanWs notFailBuild: true
|
||||||
stages {
|
checkout scm
|
||||||
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'
|
|
||||||
}
|
}
|
||||||
}}
|
try {
|
||||||
}
|
stage('github-pending') {
|
||||||
post {
|
githubNotify credentialsId: 'test-jenkins-credentials',
|
||||||
always {
|
description: "running ${TEST_SUITE}-${TEST_PLATFORM}...",
|
||||||
script { withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) {
|
status: 'PENDING',
|
||||||
sshagent(credentials: ['jenkins-testing-ssh-key']) {
|
context: "jenkins/pr/${TEST_SUITE}-${TEST_PLATFORM}"
|
||||||
sh 'ssh-add ~/.ssh/jenkins-testing.pem'
|
|
||||||
sh 'bundle exec kitchen destroy $TEST_SUITE-$TEST_PLATFORM'
|
|
||||||
}
|
}
|
||||||
}}
|
stage('setup-bundle') {
|
||||||
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
|
sh 'bundle install --with ec2 windows --without opennebula docker'
|
||||||
archiveArtifacts artifacts: 'artifacts/logs/minion'
|
}
|
||||||
archiveArtifacts artifacts: 'artifacts/logs/salt-runtests.log'
|
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}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
1
.ci/lint
1
.ci/lint
@ -3,6 +3,7 @@ pipeline {
|
|||||||
options {
|
options {
|
||||||
timestamps()
|
timestamps()
|
||||||
ansiColor('xterm')
|
ansiColor('xterm')
|
||||||
|
timeout(time: 1, unit: 'HOURS')
|
||||||
}
|
}
|
||||||
environment {
|
environment {
|
||||||
PYENV_ROOT = "/usr/local/pyenv"
|
PYENV_ROOT = "/usr/local/pyenv"
|
||||||
|
293
salt/_compat.py
293
salt/_compat.py
@ -2,18 +2,21 @@
|
|||||||
'''
|
'''
|
||||||
Salt compatibility code
|
Salt compatibility code
|
||||||
'''
|
'''
|
||||||
# pylint: disable=import-error,unused-import,invalid-name
|
# pylint: disable=import-error,unused-import,invalid-name,W0231,W0233
|
||||||
|
|
||||||
# Import python libs
|
# Import python libs
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import, unicode_literals, print_function
|
||||||
import sys
|
import sys
|
||||||
import types
|
import types
|
||||||
|
import logging
|
||||||
|
|
||||||
# Import 3rd-party libs
|
# Import 3rd-party libs
|
||||||
from salt.ext.six import binary_type, string_types, text_type
|
from salt.exceptions import SaltException
|
||||||
|
from salt.ext.six import binary_type, string_types, text_type, integer_types
|
||||||
from salt.ext.six.moves import cStringIO, StringIO
|
from salt.ext.six.moves import cStringIO, StringIO
|
||||||
|
|
||||||
HAS_XML = True
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Python >2.5
|
# Python >2.5
|
||||||
import xml.etree.cElementTree as ElementTree
|
import xml.etree.cElementTree as ElementTree
|
||||||
@ -31,11 +34,10 @@ except Exception:
|
|||||||
import elementtree.ElementTree as ElementTree
|
import elementtree.ElementTree as ElementTree
|
||||||
except Exception:
|
except Exception:
|
||||||
ElementTree = None
|
ElementTree = None
|
||||||
HAS_XML = False
|
|
||||||
|
|
||||||
|
|
||||||
# True if we are running on Python 3.
|
# True if we are running on Python 3.
|
||||||
PY3 = sys.version_info[0] == 3
|
PY3 = sys.version_info.major == 3
|
||||||
|
|
||||||
|
|
||||||
if PY3:
|
if PY3:
|
||||||
@ -45,13 +47,12 @@ else:
|
|||||||
import exceptions
|
import exceptions
|
||||||
|
|
||||||
|
|
||||||
if HAS_XML:
|
if ElementTree is not None:
|
||||||
if not hasattr(ElementTree, 'ParseError'):
|
if not hasattr(ElementTree, 'ParseError'):
|
||||||
class ParseError(Exception):
|
class ParseError(Exception):
|
||||||
'''
|
'''
|
||||||
older versions of ElementTree do not have ParseError
|
older versions of ElementTree do not have ParseError
|
||||||
'''
|
'''
|
||||||
pass
|
|
||||||
|
|
||||||
ElementTree.ParseError = ParseError
|
ElementTree.ParseError = ParseError
|
||||||
|
|
||||||
@ -61,9 +62,7 @@ def text_(s, encoding='latin-1', errors='strict'):
|
|||||||
If ``s`` is an instance of ``binary_type``, return
|
If ``s`` is an instance of ``binary_type``, return
|
||||||
``s.decode(encoding, errors)``, otherwise return ``s``
|
``s.decode(encoding, errors)``, otherwise return ``s``
|
||||||
'''
|
'''
|
||||||
if isinstance(s, binary_type):
|
return s.decode(encoding, errors) if isinstance(s, binary_type) else s
|
||||||
return s.decode(encoding, errors)
|
|
||||||
return s
|
|
||||||
|
|
||||||
|
|
||||||
def bytes_(s, encoding='latin-1', errors='strict'):
|
def bytes_(s, encoding='latin-1', errors='strict'):
|
||||||
@ -71,57 +70,37 @@ def bytes_(s, encoding='latin-1', errors='strict'):
|
|||||||
If ``s`` is an instance of ``text_type``, return
|
If ``s`` is an instance of ``text_type``, return
|
||||||
``s.encode(encoding, errors)``, otherwise return ``s``
|
``s.encode(encoding, errors)``, otherwise return ``s``
|
||||||
'''
|
'''
|
||||||
|
return s.encode(encoding, errors) if isinstance(s, text_type) else s
|
||||||
|
|
||||||
|
|
||||||
|
def ascii_native_(s):
|
||||||
|
'''
|
||||||
|
Python 3: If ``s`` is an instance of ``text_type``, return
|
||||||
|
``s.encode('ascii')``, otherwise return ``str(s, 'ascii', 'strict')``
|
||||||
|
|
||||||
|
Python 2: If ``s`` is an instance of ``text_type``, return
|
||||||
|
``s.encode('ascii')``, otherwise return ``str(s)``
|
||||||
|
'''
|
||||||
if isinstance(s, text_type):
|
if isinstance(s, text_type):
|
||||||
return s.encode(encoding, errors)
|
s = s.encode('ascii')
|
||||||
return s
|
|
||||||
|
return str(s, 'ascii', 'strict') if PY3 else s
|
||||||
|
|
||||||
|
|
||||||
if PY3:
|
def native_(s, encoding='latin-1', errors='strict'):
|
||||||
def ascii_native_(s):
|
'''
|
||||||
if isinstance(s, text_type):
|
Python 3: If ``s`` is an instance of ``text_type``, return ``s``, otherwise
|
||||||
s = s.encode('ascii')
|
return ``str(s, encoding, errors)``
|
||||||
return str(s, 'ascii', 'strict')
|
|
||||||
else:
|
|
||||||
def ascii_native_(s):
|
|
||||||
if isinstance(s, text_type):
|
|
||||||
s = s.encode('ascii')
|
|
||||||
return str(s)
|
|
||||||
|
|
||||||
ascii_native_.__doc__ = '''
|
Python 2: If ``s`` is an instance of ``text_type``, return
|
||||||
Python 3: If ``s`` is an instance of ``text_type``, return
|
``s.encode(encoding, errors)``, otherwise return ``str(s)``
|
||||||
``s.encode('ascii')``, otherwise return ``str(s, 'ascii', 'strict')``
|
'''
|
||||||
|
if PY3:
|
||||||
|
out = s if isinstance(s, text_type) else str(s, encoding, errors)
|
||||||
|
else:
|
||||||
|
out = s.encode(encoding, errors) if isinstance(s, text_type) else str(s)
|
||||||
|
|
||||||
Python 2: If ``s`` is an instance of ``text_type``, return
|
return out
|
||||||
``s.encode('ascii')``, otherwise return ``str(s)``
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
if PY3:
|
|
||||||
def native_(s, encoding='latin-1', errors='strict'):
|
|
||||||
'''
|
|
||||||
If ``s`` is an instance of ``text_type``, return
|
|
||||||
``s``, otherwise return ``str(s, encoding, errors)``
|
|
||||||
'''
|
|
||||||
if isinstance(s, text_type):
|
|
||||||
return s
|
|
||||||
return str(s, encoding, errors)
|
|
||||||
else:
|
|
||||||
def native_(s, encoding='latin-1', errors='strict'):
|
|
||||||
'''
|
|
||||||
If ``s`` is an instance of ``text_type``, return
|
|
||||||
``s.encode(encoding, errors)``, otherwise return ``str(s)``
|
|
||||||
'''
|
|
||||||
if isinstance(s, text_type):
|
|
||||||
return s.encode(encoding, errors)
|
|
||||||
return str(s)
|
|
||||||
|
|
||||||
native_.__doc__ = '''
|
|
||||||
Python 3: If ``s`` is an instance of ``text_type``, return ``s``, otherwise
|
|
||||||
return ``str(s, encoding, errors)``
|
|
||||||
|
|
||||||
Python 2: If ``s`` is an instance of ``text_type``, return
|
|
||||||
``s.encode(encoding, errors)``, otherwise return ``str(s)``
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
def string_io(data=None): # cStringIO can't handle unicode
|
def string_io(data=None): # cStringIO can't handle unicode
|
||||||
@ -133,7 +112,199 @@ def string_io(data=None): # cStringIO can't handle unicode
|
|||||||
except (UnicodeEncodeError, TypeError):
|
except (UnicodeEncodeError, TypeError):
|
||||||
return StringIO(data)
|
return StringIO(data)
|
||||||
|
|
||||||
if PY3:
|
|
||||||
import ipaddress
|
try:
|
||||||
else:
|
if PY3:
|
||||||
import salt.ext.ipaddress as ipaddress
|
import ipaddress
|
||||||
|
else:
|
||||||
|
import salt.ext.ipaddress as ipaddress
|
||||||
|
except ImportError:
|
||||||
|
ipaddress = None
|
||||||
|
|
||||||
|
|
||||||
|
class IPv6AddressScoped(ipaddress.IPv6Address):
|
||||||
|
'''
|
||||||
|
Represent and manipulate single IPv6 Addresses.
|
||||||
|
Scope-aware version
|
||||||
|
'''
|
||||||
|
def __init__(self, address):
|
||||||
|
'''
|
||||||
|
Instantiate a new IPv6 address object. Scope is moved to an attribute 'scope'.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
address: A string or integer representing the IP
|
||||||
|
|
||||||
|
Additionally, an integer can be passed, so
|
||||||
|
IPv6Address('2001:db8::') == IPv6Address(42540766411282592856903984951653826560)
|
||||||
|
or, more generally
|
||||||
|
IPv6Address(int(IPv6Address('2001:db8::'))) == IPv6Address('2001:db8::')
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
AddressValueError: If address isn't a valid IPv6 address.
|
||||||
|
|
||||||
|
:param address:
|
||||||
|
'''
|
||||||
|
# pylint: disable-all
|
||||||
|
if not hasattr(self, '_is_packed_binary'):
|
||||||
|
# This method (below) won't be around for some Python 3 versions
|
||||||
|
# and we need check this differently anyway
|
||||||
|
self._is_packed_binary = lambda p: isinstance(p, bytes)
|
||||||
|
# pylint: enable-all
|
||||||
|
|
||||||
|
if isinstance(address, string_types) and '%' in address:
|
||||||
|
buff = address.split('%')
|
||||||
|
if len(buff) != 2:
|
||||||
|
raise SaltException('Invalid IPv6 address: "{}"'.format(address))
|
||||||
|
address, self.__scope = buff
|
||||||
|
else:
|
||||||
|
self.__scope = None
|
||||||
|
|
||||||
|
if sys.version_info.major == 2:
|
||||||
|
ipaddress._BaseAddress.__init__(self, address)
|
||||||
|
ipaddress._BaseV6.__init__(self, address)
|
||||||
|
else:
|
||||||
|
# Python 3.4 fix. Versions higher are simply not affected
|
||||||
|
# https://github.com/python/cpython/blob/3.4/Lib/ipaddress.py#L543-L544
|
||||||
|
self._version = 6
|
||||||
|
self._max_prefixlen = ipaddress.IPV6LENGTH
|
||||||
|
|
||||||
|
# Efficient constructor from integer.
|
||||||
|
if isinstance(address, integer_types):
|
||||||
|
self._check_int_address(address)
|
||||||
|
self._ip = address
|
||||||
|
elif self._is_packed_binary(address):
|
||||||
|
self._check_packed_address(address, 16)
|
||||||
|
self._ip = ipaddress._int_from_bytes(address, 'big')
|
||||||
|
else:
|
||||||
|
address = str(address)
|
||||||
|
if '/' in address:
|
||||||
|
raise ipaddress.AddressValueError("Unexpected '/' in {}".format(address))
|
||||||
|
self._ip = self._ip_int_from_string(address)
|
||||||
|
|
||||||
|
def _is_packed_binary(self, data):
|
||||||
|
'''
|
||||||
|
Check if data is hexadecimal packed
|
||||||
|
|
||||||
|
:param data:
|
||||||
|
:return:
|
||||||
|
'''
|
||||||
|
packed = False
|
||||||
|
if len(data) == 16 and ':' not in data:
|
||||||
|
try:
|
||||||
|
packed = bool(int(str(bytearray(data)).encode('hex'), 16))
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return packed
|
||||||
|
|
||||||
|
@property
|
||||||
|
def scope(self):
|
||||||
|
'''
|
||||||
|
Return scope of IPv6 address.
|
||||||
|
|
||||||
|
:return:
|
||||||
|
'''
|
||||||
|
return self.__scope
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return text_type(self._string_from_ip_int(self._ip) +
|
||||||
|
('%' + self.scope if self.scope is not None else ''))
|
||||||
|
|
||||||
|
|
||||||
|
class IPv6InterfaceScoped(ipaddress.IPv6Interface, IPv6AddressScoped):
|
||||||
|
'''
|
||||||
|
Update
|
||||||
|
'''
|
||||||
|
def __init__(self, address):
|
||||||
|
if isinstance(address, (bytes, int)):
|
||||||
|
IPv6AddressScoped.__init__(self, address)
|
||||||
|
self.network = ipaddress.IPv6Network(self._ip)
|
||||||
|
self._prefixlen = self._max_prefixlen
|
||||||
|
return
|
||||||
|
|
||||||
|
addr = ipaddress._split_optional_netmask(address)
|
||||||
|
IPv6AddressScoped.__init__(self, addr[0])
|
||||||
|
self.network = ipaddress.IPv6Network(address, strict=False)
|
||||||
|
self.netmask = self.network.netmask
|
||||||
|
self._prefixlen = self.network._prefixlen
|
||||||
|
self.hostmask = self.network.hostmask
|
||||||
|
|
||||||
|
|
||||||
|
def ip_address(address):
|
||||||
|
"""Take an IP string/int and return an object of the correct type.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
address: A string or integer, the IP address. Either IPv4 or
|
||||||
|
IPv6 addresses may be supplied; integers less than 2**32 will
|
||||||
|
be considered to be IPv4 by default.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
An IPv4Address or IPv6Address object.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: if the *address* passed isn't either a v4 or a v6
|
||||||
|
address
|
||||||
|
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return ipaddress.IPv4Address(address)
|
||||||
|
except (ipaddress.AddressValueError, ipaddress.NetmaskValueError) as err:
|
||||||
|
log.debug('Error while parsing IPv4 address: %s', address)
|
||||||
|
log.debug(err)
|
||||||
|
|
||||||
|
try:
|
||||||
|
return IPv6AddressScoped(address)
|
||||||
|
except (ipaddress.AddressValueError, ipaddress.NetmaskValueError) as err:
|
||||||
|
log.debug('Error while parsing IPv6 address: %s', address)
|
||||||
|
log.debug(err)
|
||||||
|
|
||||||
|
if isinstance(address, bytes):
|
||||||
|
raise ipaddress.AddressValueError('{} does not appear to be an IPv4 or IPv6 address. '
|
||||||
|
'Did you pass in a bytes (str in Python 2) instead '
|
||||||
|
'of a unicode object?'.format(repr(address)))
|
||||||
|
|
||||||
|
raise ValueError('{} does not appear to be an IPv4 or IPv6 address'.format(repr(address)))
|
||||||
|
|
||||||
|
|
||||||
|
def ip_interface(address):
|
||||||
|
"""Take an IP string/int and return an object of the correct type.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
address: A string or integer, the IP address. Either IPv4 or
|
||||||
|
IPv6 addresses may be supplied; integers less than 2**32 will
|
||||||
|
be considered to be IPv4 by default.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
An IPv4Interface or IPv6Interface object.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: if the string passed isn't either a v4 or a v6
|
||||||
|
address.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
The IPv?Interface classes describe an Address on a particular
|
||||||
|
Network, so they're basically a combination of both the Address
|
||||||
|
and Network classes.
|
||||||
|
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return ipaddress.IPv4Interface(address)
|
||||||
|
except (ipaddress.AddressValueError, ipaddress.NetmaskValueError) as err:
|
||||||
|
log.debug('Error while getting IPv4 interface for address %s', address)
|
||||||
|
log.debug(err)
|
||||||
|
|
||||||
|
try:
|
||||||
|
return ipaddress.IPv6Interface(address)
|
||||||
|
except (ipaddress.AddressValueError, ipaddress.NetmaskValueError) as err:
|
||||||
|
log.debug('Error while getting IPv6 interface for address %s', address)
|
||||||
|
log.debug(err)
|
||||||
|
|
||||||
|
raise ValueError('{} does not appear to be an IPv4 or IPv6 interface'.format(address))
|
||||||
|
|
||||||
|
|
||||||
|
if ipaddress:
|
||||||
|
ipaddress.IPv6Address = IPv6AddressScoped
|
||||||
|
if sys.version_info.major == 2:
|
||||||
|
ipaddress.IPv6Interface = IPv6InterfaceScoped
|
||||||
|
ipaddress.ip_address = ip_address
|
||||||
|
ipaddress.ip_interface = ip_interface
|
||||||
|
@ -27,10 +27,7 @@ import salt.utils.cloud
|
|||||||
import salt.config as config
|
import salt.config as config
|
||||||
import salt.client
|
import salt.client
|
||||||
import salt.ext.six as six
|
import salt.ext.six as six
|
||||||
if six.PY3:
|
from salt._compat import ipaddress
|
||||||
import ipaddress
|
|
||||||
else:
|
|
||||||
import salt.ext.ipaddress as ipaddress
|
|
||||||
|
|
||||||
from salt.exceptions import SaltCloudException, SaltCloudSystemExit
|
from salt.exceptions import SaltCloudException, SaltCloudSystemExit
|
||||||
|
|
||||||
|
@ -25,13 +25,8 @@ import tempfile
|
|||||||
import salt.utils
|
import salt.utils
|
||||||
import salt.config as config
|
import salt.config as config
|
||||||
import salt.client
|
import salt.client
|
||||||
import salt.ext.six as six
|
from salt._compat import ipaddress
|
||||||
if six.PY3:
|
from salt.exceptions import SaltCloudException, SaltCloudSystemExit, SaltInvocationError
|
||||||
import ipaddress
|
|
||||||
else:
|
|
||||||
import salt.ext.ipaddress as ipaddress
|
|
||||||
from salt.exceptions import SaltCloudException, SaltCloudSystemExit, \
|
|
||||||
SaltInvocationError
|
|
||||||
|
|
||||||
# Get logging started
|
# Get logging started
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
@ -9,7 +9,7 @@ from __future__ import absolute_import
|
|||||||
import socket
|
import socket
|
||||||
import ctypes
|
import ctypes
|
||||||
import os
|
import os
|
||||||
import ipaddress
|
from salt._compat import ipaddress
|
||||||
import salt.ext.six as six
|
import salt.ext.six as six
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,9 +5,11 @@ Generate chronos proxy minion grains.
|
|||||||
.. versionadded:: 2015.8.2
|
.. versionadded:: 2015.8.2
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
# Import Python libs
|
||||||
from __future__ import absolute_import, print_function, unicode_literals
|
from __future__ import absolute_import, print_function, unicode_literals
|
||||||
|
|
||||||
|
|
||||||
|
# Import Salt libs
|
||||||
import salt.utils.http
|
import salt.utils.http
|
||||||
import salt.utils.platform
|
import salt.utils.platform
|
||||||
__proxyenabled__ = ['chronos']
|
__proxyenabled__ = ['chronos']
|
||||||
|
@ -113,13 +113,16 @@ __virtualname__ = 'sentry'
|
|||||||
|
|
||||||
def __virtual__():
|
def __virtual__():
|
||||||
if HAS_RAVEN is True:
|
if HAS_RAVEN is True:
|
||||||
__grains__ = salt.loader.grains(__opts__)
|
|
||||||
__salt__ = salt.loader.minion_mods(__opts__)
|
|
||||||
return __virtualname__
|
return __virtualname__
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def setup_handlers():
|
def setup_handlers():
|
||||||
|
'''
|
||||||
|
sets up the sentry handler
|
||||||
|
'''
|
||||||
|
__grains__ = salt.loader.grains(__opts__)
|
||||||
|
__salt__ = salt.loader.minion_mods(__opts__)
|
||||||
if 'sentry_handler' not in __opts__:
|
if 'sentry_handler' not in __opts__:
|
||||||
log.debug('No \'sentry_handler\' key was found in the configuration')
|
log.debug('No \'sentry_handler\' key was found in the configuration')
|
||||||
return False
|
return False
|
||||||
@ -133,7 +136,9 @@ def setup_handlers():
|
|||||||
transport_registry = TransportRegistry(default_transports)
|
transport_registry = TransportRegistry(default_transports)
|
||||||
url = urlparse(dsn)
|
url = urlparse(dsn)
|
||||||
if not transport_registry.supported_scheme(url.scheme):
|
if not transport_registry.supported_scheme(url.scheme):
|
||||||
raise ValueError('Unsupported Sentry DSN scheme: {0}'.format(url.scheme))
|
raise ValueError(
|
||||||
|
'Unsupported Sentry DSN scheme: %s', url.scheme
|
||||||
|
)
|
||||||
except ValueError as exc:
|
except ValueError as exc:
|
||||||
log.info(
|
log.info(
|
||||||
'Raven failed to parse the configuration provided DSN: %s', exc
|
'Raven failed to parse the configuration provided DSN: %s', exc
|
||||||
@ -202,7 +207,11 @@ def setup_handlers():
|
|||||||
context_dict = {}
|
context_dict = {}
|
||||||
if context is not None:
|
if context is not None:
|
||||||
for tag in context:
|
for tag in context:
|
||||||
tag_value = __salt__['grains.get'](tag)
|
try:
|
||||||
|
tag_value = __grains__[tag]
|
||||||
|
except KeyError:
|
||||||
|
log.debug('Sentry tag \'%s\' not found in grains.', tag)
|
||||||
|
continue
|
||||||
if len(tag_value) > 0:
|
if len(tag_value) > 0:
|
||||||
context_dict[tag] = tag_value
|
context_dict[tag] = tag_value
|
||||||
if len(context_dict) > 0:
|
if len(context_dict) > 0:
|
||||||
@ -229,4 +238,7 @@ def setup_handlers():
|
|||||||
|
|
||||||
|
|
||||||
def get_config_value(name, default=None):
|
def get_config_value(name, default=None):
|
||||||
|
'''
|
||||||
|
returns a configuration option for the sentry_handler
|
||||||
|
'''
|
||||||
return __opts__['sentry_handler'].get(name, default)
|
return __opts__['sentry_handler'].get(name, default)
|
||||||
|
@ -13,10 +13,7 @@ from salt.ext.six.moves import map, range
|
|||||||
import salt.utils.path
|
import salt.utils.path
|
||||||
|
|
||||||
# Import third-party libs
|
# Import third-party libs
|
||||||
if six.PY3:
|
from salt._compat import ipaddress
|
||||||
import ipaddress
|
|
||||||
else:
|
|
||||||
import salt.ext.ipaddress as ipaddress
|
|
||||||
|
|
||||||
# Set up logging
|
# Set up logging
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
@ -26,10 +26,7 @@ from salt.exceptions import CommandExecutionError
|
|||||||
# Import 3rd-party libs
|
# Import 3rd-party libs
|
||||||
from salt.ext import six
|
from salt.ext import six
|
||||||
from salt.ext.six.moves import range # pylint: disable=import-error,no-name-in-module,redefined-builtin
|
from salt.ext.six.moves import range # pylint: disable=import-error,no-name-in-module,redefined-builtin
|
||||||
if six.PY3:
|
from salt._compat import ipaddress
|
||||||
import ipaddress
|
|
||||||
else:
|
|
||||||
import salt.ext.ipaddress as ipaddress
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
@ -39,11 +39,7 @@ import salt.utils.path
|
|||||||
import salt.utils.stringutils
|
import salt.utils.stringutils
|
||||||
from salt.exceptions import CommandExecutionError, SaltInvocationError
|
from salt.exceptions import CommandExecutionError, SaltInvocationError
|
||||||
import salt.ext.six as six
|
import salt.ext.six as six
|
||||||
|
from salt._compat import ipaddress
|
||||||
if six.PY3:
|
|
||||||
import ipaddress
|
|
||||||
else:
|
|
||||||
import salt.ext.ipaddress as ipaddress
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -76,7 +76,25 @@ class _Zypper(object):
|
|||||||
Allows serial zypper calls (first came, first won).
|
Allows serial zypper calls (first came, first won).
|
||||||
'''
|
'''
|
||||||
|
|
||||||
SUCCESS_EXIT_CODES = [0, 100, 101, 102, 103]
|
SUCCESS_EXIT_CODES = {
|
||||||
|
0: 'Successful run of zypper with no special info.',
|
||||||
|
100: 'Patches are available for installation.',
|
||||||
|
101: 'Security patches are available for installation.',
|
||||||
|
102: 'Installation successful, reboot required.',
|
||||||
|
103: 'Installation succesful, restart of the package manager itself required.',
|
||||||
|
}
|
||||||
|
|
||||||
|
WARNING_EXIT_CODES = {
|
||||||
|
6: 'No repositories are defined.',
|
||||||
|
7: 'The ZYPP library is locked.',
|
||||||
|
106: 'Some repository had to be disabled temporarily because it failed to refresh. '
|
||||||
|
'You should check your repository configuration (e.g. zypper ref -f).',
|
||||||
|
107: 'Installation basically succeeded, but some of the packages %post install scripts returned an error. '
|
||||||
|
'These packages were successfully unpacked to disk and are registered in the rpm database, '
|
||||||
|
'but due to the failed install script they may not work as expected. The failed scripts output might '
|
||||||
|
'reveal what actually went wrong. Any scripts output is also logged to /var/log/zypp/history.'
|
||||||
|
}
|
||||||
|
|
||||||
LOCK_EXIT_CODE = 7
|
LOCK_EXIT_CODE = 7
|
||||||
XML_DIRECTIVES = ['-x', '--xmlout']
|
XML_DIRECTIVES = ['-x', '--xmlout']
|
||||||
ZYPPER_LOCK = '/var/run/zypp.pid'
|
ZYPPER_LOCK = '/var/run/zypp.pid'
|
||||||
@ -189,7 +207,15 @@ class _Zypper(object):
|
|||||||
|
|
||||||
:return:
|
:return:
|
||||||
'''
|
'''
|
||||||
return self.exit_code not in self.SUCCESS_EXIT_CODES
|
if self.exit_code:
|
||||||
|
msg = self.SUCCESS_EXIT_CODES.get(self.exit_code)
|
||||||
|
if msg:
|
||||||
|
log.info(msg)
|
||||||
|
msg = self.WARNING_EXIT_CODES.get(self.exit_code)
|
||||||
|
if msg:
|
||||||
|
log.warning(msg)
|
||||||
|
|
||||||
|
return self.exit_code not in self.SUCCESS_EXIT_CODES and self.exit_code not in self.WARNING_EXIT_CODES
|
||||||
|
|
||||||
def _is_lock(self):
|
def _is_lock(self):
|
||||||
'''
|
'''
|
||||||
|
@ -10,6 +10,7 @@ import logging
|
|||||||
import salt.loader
|
import salt.loader
|
||||||
import salt.utils.event
|
import salt.utils.event
|
||||||
import salt.utils.functools
|
import salt.utils.functools
|
||||||
|
import salt.utils.jid
|
||||||
from salt.exceptions import SaltInvocationError
|
from salt.exceptions import SaltInvocationError
|
||||||
|
|
||||||
LOGGER = logging.getLogger(__name__)
|
LOGGER = logging.getLogger(__name__)
|
||||||
@ -110,6 +111,8 @@ def orchestrate(mods,
|
|||||||
pillarenv = __opts__['pillarenv']
|
pillarenv = __opts__['pillarenv']
|
||||||
if saltenv is None and 'saltenv' in __opts__:
|
if saltenv is None and 'saltenv' in __opts__:
|
||||||
saltenv = __opts__['saltenv']
|
saltenv = __opts__['saltenv']
|
||||||
|
if orchestration_jid is None:
|
||||||
|
orchestration_jid = salt.utils.jid.gen_jid(__opts__)
|
||||||
|
|
||||||
running = minion.functions['state.sls'](
|
running = minion.functions['state.sls'](
|
||||||
mods,
|
mods,
|
||||||
|
@ -5215,7 +5215,9 @@ def append(name,
|
|||||||
check_res, check_msg = _check_file(name)
|
check_res, check_msg = _check_file(name)
|
||||||
if not check_res:
|
if not check_res:
|
||||||
# Try to create the file
|
# 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)
|
retry_res, retry_msg = _check_file(name)
|
||||||
if not retry_res:
|
if not retry_res:
|
||||||
return _error(ret, check_msg)
|
return _error(ret, check_msg)
|
||||||
@ -5496,7 +5498,9 @@ def prepend(name,
|
|||||||
check_res, check_msg = _check_file(name)
|
check_res, check_msg = _check_file(name)
|
||||||
if not check_res:
|
if not check_res:
|
||||||
# Try to create the file
|
# 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)
|
retry_res, retry_msg = _check_file(name)
|
||||||
if not retry_res:
|
if not retry_res:
|
||||||
return _error(ret, check_msg)
|
return _error(ret, check_msg)
|
||||||
|
@ -455,13 +455,14 @@ def traverse_dict(data, key, default=None, delimiter=DEFAULT_TARGET_DELIM):
|
|||||||
data['foo']['bar']['baz'] if this value exists, and will otherwise return
|
data['foo']['bar']['baz'] if this value exists, and will otherwise return
|
||||||
the dict in the default argument.
|
the dict in the default argument.
|
||||||
'''
|
'''
|
||||||
|
ptr = data
|
||||||
try:
|
try:
|
||||||
for each in key.split(delimiter):
|
for each in key.split(delimiter):
|
||||||
data = data[each]
|
ptr = ptr[each]
|
||||||
except (KeyError, IndexError, TypeError):
|
except (KeyError, IndexError, TypeError):
|
||||||
# Encountered a non-indexable value in the middle of traversing
|
# Encountered a non-indexable value in the middle of traversing
|
||||||
return default
|
return default
|
||||||
return data
|
return ptr
|
||||||
|
|
||||||
|
|
||||||
@jinja_filter('traverse')
|
@jinja_filter('traverse')
|
||||||
@ -476,16 +477,17 @@ def traverse_dict_and_list(data, key, default=None, delimiter=DEFAULT_TARGET_DEL
|
|||||||
{'foo':{'bar':['baz']}} , if data like {'foo':{'bar':{'0':'baz'}}}
|
{'foo':{'bar':['baz']}} , if data like {'foo':{'bar':{'0':'baz'}}}
|
||||||
then return data['foo']['bar']['0']
|
then return data['foo']['bar']['0']
|
||||||
'''
|
'''
|
||||||
|
ptr = data
|
||||||
for each in key.split(delimiter):
|
for each in key.split(delimiter):
|
||||||
if isinstance(data, list):
|
if isinstance(ptr, list):
|
||||||
try:
|
try:
|
||||||
idx = int(each)
|
idx = int(each)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
embed_match = False
|
embed_match = False
|
||||||
# Index was not numeric, lets look at any embedded dicts
|
# Index was not numeric, lets look at any embedded dicts
|
||||||
for embedded in (x for x in data if isinstance(x, dict)):
|
for embedded in (x for x in ptr if isinstance(x, dict)):
|
||||||
try:
|
try:
|
||||||
data = embedded[each]
|
ptr = embedded[each]
|
||||||
embed_match = True
|
embed_match = True
|
||||||
break
|
break
|
||||||
except KeyError:
|
except KeyError:
|
||||||
@ -495,15 +497,15 @@ def traverse_dict_and_list(data, key, default=None, delimiter=DEFAULT_TARGET_DEL
|
|||||||
return default
|
return default
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
data = data[idx]
|
ptr = ptr[idx]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
return default
|
return default
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
data = data[each]
|
ptr = ptr[each]
|
||||||
except (KeyError, TypeError):
|
except (KeyError, TypeError):
|
||||||
return default
|
return default
|
||||||
return data
|
return ptr
|
||||||
|
|
||||||
|
|
||||||
def subdict_match(data,
|
def subdict_match(data,
|
||||||
@ -519,16 +521,33 @@ def subdict_match(data,
|
|||||||
former, as more deeply-nested matches are tried first.
|
former, as more deeply-nested matches are tried first.
|
||||||
'''
|
'''
|
||||||
def _match(target, pattern, regex_match=False, exact_match=False):
|
def _match(target, pattern, regex_match=False, exact_match=False):
|
||||||
|
# The reason for using six.text_type first and _then_ using
|
||||||
|
# to_unicode as a fallback is because we want to eventually have
|
||||||
|
# unicode types for comparison below. If either value is numeric then
|
||||||
|
# six.text_type will turn it into a unicode string. However, if the
|
||||||
|
# value is a PY2 str type with non-ascii chars, then the result will be
|
||||||
|
# a UnicodeDecodeError. In those cases, we simply use to_unicode to
|
||||||
|
# decode it to unicode. The reason we can't simply use to_unicode to
|
||||||
|
# begin with is that (by design) to_unicode will raise a TypeError if a
|
||||||
|
# non-string/bytestring/bytearray value is passed.
|
||||||
|
try:
|
||||||
|
target = six.text_type(target).lower()
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
target = salt.utils.stringutils.to_unicode(target).lower()
|
||||||
|
try:
|
||||||
|
pattern = six.text_type(pattern).lower()
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
pattern = salt.utils.stringutils.to_unicode(pattern).lower()
|
||||||
|
|
||||||
if regex_match:
|
if regex_match:
|
||||||
try:
|
try:
|
||||||
return re.match(pattern.lower(), six.text_type(target).lower())
|
return re.match(pattern, target)
|
||||||
except Exception:
|
except Exception:
|
||||||
log.error('Invalid regex \'%s\' in match', pattern)
|
log.error('Invalid regex \'%s\' in match', pattern)
|
||||||
return False
|
return False
|
||||||
elif exact_match:
|
|
||||||
return six.text_type(target).lower() == pattern.lower()
|
|
||||||
else:
|
else:
|
||||||
return fnmatch.fnmatch(six.text_type(target).lower(), pattern.lower())
|
return target == pattern if exact_match \
|
||||||
|
else fnmatch.fnmatch(target, pattern)
|
||||||
|
|
||||||
def _dict_match(target, pattern, regex_match=False, exact_match=False):
|
def _dict_match(target, pattern, regex_match=False, exact_match=False):
|
||||||
wildcard = pattern.startswith('*:')
|
wildcard = pattern.startswith('*:')
|
||||||
@ -548,11 +567,6 @@ def subdict_match(data,
|
|||||||
return True
|
return True
|
||||||
if wildcard:
|
if wildcard:
|
||||||
for key in target:
|
for key in target:
|
||||||
if _match(key,
|
|
||||||
pattern,
|
|
||||||
regex_match=regex_match,
|
|
||||||
exact_match=exact_match):
|
|
||||||
return True
|
|
||||||
if isinstance(target[key], dict):
|
if isinstance(target[key], dict):
|
||||||
if _dict_match(target[key],
|
if _dict_match(target[key],
|
||||||
pattern,
|
pattern,
|
||||||
@ -566,6 +580,17 @@ def subdict_match(data,
|
|||||||
regex_match=regex_match,
|
regex_match=regex_match,
|
||||||
exact_match=exact_match):
|
exact_match=exact_match):
|
||||||
return True
|
return True
|
||||||
|
elif _match(target[key],
|
||||||
|
pattern,
|
||||||
|
regex_match=regex_match,
|
||||||
|
exact_match=exact_match):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
splits = expr.split(delimiter)
|
||||||
|
num_splits = len(splits)
|
||||||
|
if num_splits == 1:
|
||||||
|
# Delimiter not present, this can't possibly be a match
|
||||||
return False
|
return False
|
||||||
|
|
||||||
splits = expr.split(delimiter)
|
splits = expr.split(delimiter)
|
||||||
@ -578,10 +603,16 @@ def subdict_match(data,
|
|||||||
# want to use are 3, 2, and 1, in that order.
|
# want to use are 3, 2, and 1, in that order.
|
||||||
for idx in range(num_splits - 1, 0, -1):
|
for idx in range(num_splits - 1, 0, -1):
|
||||||
key = delimiter.join(splits[:idx])
|
key = delimiter.join(splits[:idx])
|
||||||
matchstr = delimiter.join(splits[idx:])
|
if key == '*':
|
||||||
|
# We are matching on everything under the top level, so we need to
|
||||||
|
# treat the match as the entire data being passed in
|
||||||
|
matchstr = expr
|
||||||
|
match = data
|
||||||
|
else:
|
||||||
|
matchstr = delimiter.join(splits[idx:])
|
||||||
|
match = traverse_dict_and_list(data, key, {}, delimiter=delimiter)
|
||||||
log.debug("Attempting to match '%s' in '%s' using delimiter '%s'",
|
log.debug("Attempting to match '%s' in '%s' using delimiter '%s'",
|
||||||
matchstr, key, delimiter)
|
matchstr, key, delimiter)
|
||||||
match = traverse_dict_and_list(data, key, {}, delimiter=delimiter)
|
|
||||||
if match == {}:
|
if match == {}:
|
||||||
continue
|
continue
|
||||||
if isinstance(match, dict):
|
if isinstance(match, dict):
|
||||||
|
@ -1139,18 +1139,13 @@ def parse_resolv(src='/etc/resolv.conf'):
|
|||||||
try:
|
try:
|
||||||
(directive, arg) = (line[0].lower(), line[1:])
|
(directive, arg) = (line[0].lower(), line[1:])
|
||||||
# Drop everything after # or ; (comments)
|
# Drop everything after # or ; (comments)
|
||||||
arg = list(itertools.takewhile(
|
arg = list(itertools.takewhile(lambda x: x[0] not in ('#', ';'), arg))
|
||||||
lambda x: x[0] not in ('#', ';'), arg))
|
|
||||||
|
|
||||||
if directive == 'nameserver':
|
if directive == 'nameserver':
|
||||||
# Split the scope (interface) if it is present
|
addr = arg[0]
|
||||||
addr, scope = arg[0].split('%', 1) if '%' in arg[0] else (arg[0], '')
|
|
||||||
try:
|
try:
|
||||||
ip_addr = ipaddress.ip_address(addr)
|
ip_addr = ipaddress.ip_address(addr)
|
||||||
version = ip_addr.version
|
version = ip_addr.version
|
||||||
# Rejoin scope after address validation
|
ip_addr = str(ip_addr)
|
||||||
if scope:
|
|
||||||
ip_addr = '%'.join((str(ip_addr), scope))
|
|
||||||
if ip_addr not in nameservers:
|
if ip_addr not in nameservers:
|
||||||
nameservers.append(ip_addr)
|
nameservers.append(ip_addr)
|
||||||
if version == 4 and ip_addr not in ip4_nameservers:
|
if version == 4 and ip_addr not in ip4_nameservers:
|
||||||
|
@ -26,10 +26,7 @@ import salt.cache
|
|||||||
from salt.ext import six
|
from salt.ext import six
|
||||||
|
|
||||||
# Import 3rd-party libs
|
# Import 3rd-party libs
|
||||||
if six.PY3:
|
from salt._compat import ipaddress
|
||||||
import ipaddress
|
|
||||||
else:
|
|
||||||
import salt.ext.ipaddress as ipaddress
|
|
||||||
HAS_RANGE = False
|
HAS_RANGE = False
|
||||||
try:
|
try:
|
||||||
import seco.range # pylint: disable=import-error
|
import seco.range # pylint: disable=import-error
|
||||||
|
@ -25,6 +25,7 @@ integration.test: True
|
|||||||
# Grains addons
|
# Grains addons
|
||||||
grains:
|
grains:
|
||||||
test_grain: cheese
|
test_grain: cheese
|
||||||
|
grain_path: /tmp/salt-tests-tmpdir/file-grain-test
|
||||||
script: grail
|
script: grail
|
||||||
alot: many
|
alot: many
|
||||||
planets:
|
planets:
|
||||||
|
@ -77,6 +77,7 @@ class CallTest(ShellCase, testprogram.TestProgramCase, ShellCaseCommonTestsMixin
|
|||||||
self.assertIn('hello', ''.join(out))
|
self.assertIn('hello', ''.join(out))
|
||||||
self.assertIn('Succeeded: 1', ''.join(out))
|
self.assertIn('Succeeded: 1', ''.join(out))
|
||||||
|
|
||||||
|
@skipIf(True, 'This test causes the test to hang. Skipping until further investigation can occur.')
|
||||||
@destructiveTest
|
@destructiveTest
|
||||||
@skip_if_not_root
|
@skip_if_not_root
|
||||||
@skipIf(salt.utils.platform.is_windows(), 'This test does not apply on Windows')
|
@skipIf(salt.utils.platform.is_windows(), 'This test does not apply on Windows')
|
||||||
|
@ -357,7 +357,6 @@ class FileTest(ModuleCase, SaltReturnAssertsMixin):
|
|||||||
file.
|
file.
|
||||||
'''
|
'''
|
||||||
grain_path = os.path.join(TMP, 'file-grain-test')
|
grain_path = os.path.join(TMP, 'file-grain-test')
|
||||||
self.run_function('grains.set', ['grain_path', grain_path])
|
|
||||||
state_file = 'file-grainget'
|
state_file = 'file-grainget'
|
||||||
|
|
||||||
self.run_function('state.sls', [state_file])
|
self.run_function('state.sls', [state_file])
|
||||||
|
@ -36,10 +36,7 @@ import salt.grains.core as core
|
|||||||
|
|
||||||
# Import 3rd-party libs
|
# Import 3rd-party libs
|
||||||
from salt.ext import six
|
from salt.ext import six
|
||||||
if six.PY3:
|
from salt._compat import ipaddress
|
||||||
import ipaddress
|
|
||||||
else:
|
|
||||||
import salt.ext.ipaddress as ipaddress
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -20,20 +20,11 @@ from tests.support.mock import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Import Salt Libs
|
# Import Salt Libs
|
||||||
from salt.ext import six
|
|
||||||
import salt.utils.network
|
import salt.utils.network
|
||||||
import salt.utils.path
|
import salt.utils.path
|
||||||
import salt.modules.network as network
|
import salt.modules.network as network
|
||||||
from salt.exceptions import CommandExecutionError
|
from salt.exceptions import CommandExecutionError
|
||||||
if six.PY2:
|
from salt._compat import ipaddress
|
||||||
import salt.ext.ipaddress as ipaddress
|
|
||||||
HAS_IPADDRESS = True
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
import ipaddress
|
|
||||||
HAS_IPADDRESS = True
|
|
||||||
except ImportError:
|
|
||||||
HAS_IPADDRESS = False
|
|
||||||
|
|
||||||
|
|
||||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||||
@ -276,7 +267,7 @@ class NetworkTestCase(TestCase, LoaderModuleMockMixin):
|
|||||||
self.assertDictEqual(network.connect('host', 'port'),
|
self.assertDictEqual(network.connect('host', 'port'),
|
||||||
{'comment': ret, 'result': True})
|
{'comment': ret, 'result': True})
|
||||||
|
|
||||||
@skipIf(HAS_IPADDRESS is False, 'unable to import \'ipaddress\'')
|
@skipIf(not bool(ipaddress), 'unable to import \'ipaddress\'')
|
||||||
def test_is_private(self):
|
def test_is_private(self):
|
||||||
'''
|
'''
|
||||||
Test for Check if the given IP address is a private address
|
Test for Check if the given IP address is a private address
|
||||||
@ -288,7 +279,7 @@ class NetworkTestCase(TestCase, LoaderModuleMockMixin):
|
|||||||
return_value=True):
|
return_value=True):
|
||||||
self.assertTrue(network.is_private('::1'))
|
self.assertTrue(network.is_private('::1'))
|
||||||
|
|
||||||
@skipIf(HAS_IPADDRESS is False, 'unable to import \'ipaddress\'')
|
@skipIf(not bool(ipaddress), 'unable to import \'ipaddress\'')
|
||||||
def test_is_loopback(self):
|
def test_is_loopback(self):
|
||||||
'''
|
'''
|
||||||
Test for Check if the given IP address is a loopback address
|
Test for Check if the given IP address is a loopback address
|
||||||
|
@ -144,6 +144,36 @@ class DataTestCase(TestCase):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_subdict_match_with_wildcards(self):
|
||||||
|
'''
|
||||||
|
Tests subdict matching when wildcards are used in the expression
|
||||||
|
'''
|
||||||
|
data = {
|
||||||
|
'a': {
|
||||||
|
'b': {
|
||||||
|
'ç': 'd',
|
||||||
|
'é': ['eff', 'gee', '8ch'],
|
||||||
|
'ĩ': {'j': 'k'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert salt.utils.data.subdict_match(data, '*:*:*:*')
|
||||||
|
assert salt.utils.data.subdict_match(data, 'a:*:*:*')
|
||||||
|
assert salt.utils.data.subdict_match(data, 'a:b:*:*')
|
||||||
|
assert salt.utils.data.subdict_match(data, 'a:b:ç:*')
|
||||||
|
assert salt.utils.data.subdict_match(data, 'a:b:*:d')
|
||||||
|
assert salt.utils.data.subdict_match(data, 'a:*:ç:d')
|
||||||
|
assert salt.utils.data.subdict_match(data, '*:b:ç:d')
|
||||||
|
assert salt.utils.data.subdict_match(data, '*:*:ç:d')
|
||||||
|
assert salt.utils.data.subdict_match(data, '*:*:*:d')
|
||||||
|
assert salt.utils.data.subdict_match(data, 'a:*:*:d')
|
||||||
|
assert salt.utils.data.subdict_match(data, 'a:b:*:ef*')
|
||||||
|
assert salt.utils.data.subdict_match(data, 'a:b:*:g*')
|
||||||
|
assert salt.utils.data.subdict_match(data, 'a:b:*:j:*')
|
||||||
|
assert salt.utils.data.subdict_match(data, 'a:b:*:j:k')
|
||||||
|
assert salt.utils.data.subdict_match(data, 'a:b:*:*:k')
|
||||||
|
assert salt.utils.data.subdict_match(data, 'a:b:*:*:*')
|
||||||
|
|
||||||
def test_traverse_dict(self):
|
def test_traverse_dict(self):
|
||||||
test_two_level_dict = {'foo': {'bar': 'baz'}}
|
test_two_level_dict = {'foo': {'bar': 'baz'}}
|
||||||
|
|
||||||
|
@ -984,6 +984,10 @@ class TestCustomExtensions(TestCase):
|
|||||||
dict(opts=self.local_opts, saltenv='test', salt=self.local_salt))
|
dict(opts=self.local_opts, saltenv='test', salt=self.local_salt))
|
||||||
self.assertEqual(rendered, 'False')
|
self.assertEqual(rendered, 'False')
|
||||||
|
|
||||||
|
rendered = render_jinja_tmpl("{{ 'fe80::20d:b9ff:fe01:ea8%eth0' | is_ipv6 }}",
|
||||||
|
dict(opts=self.local_opts, saltenv='test', salt=self.local_salt))
|
||||||
|
self.assertEqual(rendered, 'True')
|
||||||
|
|
||||||
rendered = render_jinja_tmpl("{{ 'FE80::' | is_ipv6 }}",
|
rendered = render_jinja_tmpl("{{ 'FE80::' | is_ipv6 }}",
|
||||||
dict(opts=self.local_opts, saltenv='test', salt=self.local_salt))
|
dict(opts=self.local_opts, saltenv='test', salt=self.local_salt))
|
||||||
self.assertEqual(rendered, 'True')
|
self.assertEqual(rendered, 'True')
|
||||||
@ -996,6 +1000,10 @@ class TestCustomExtensions(TestCase):
|
|||||||
'''
|
'''
|
||||||
Test the `ipaddr` Jinja filter.
|
Test the `ipaddr` Jinja filter.
|
||||||
'''
|
'''
|
||||||
|
rendered = render_jinja_tmpl("{{ '::' | ipaddr }}",
|
||||||
|
dict(opts=self.local_opts, saltenv='test', salt=self.local_salt))
|
||||||
|
self.assertEqual(rendered, '::')
|
||||||
|
|
||||||
rendered = render_jinja_tmpl("{{ '192.168.0.1' | ipaddr }}",
|
rendered = render_jinja_tmpl("{{ '192.168.0.1' | ipaddr }}",
|
||||||
dict(opts=self.local_opts, saltenv='test', salt=self.local_salt))
|
dict(opts=self.local_opts, saltenv='test', salt=self.local_salt))
|
||||||
self.assertEqual(rendered, '192.168.0.1')
|
self.assertEqual(rendered, '192.168.0.1')
|
||||||
|
Loading…
Reference in New Issue
Block a user