Merge branch '2017.7' into bugs/47901_future_done_exception

This commit is contained in:
Dmitry Kuzmenko 2018-06-19 15:34:33 +03:00 committed by GitHub
commit 5f63316311
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 376 additions and 11 deletions

29
.ci/docs Normal file
View file

@ -0,0 +1,29 @@
pipeline {
agent { label 'docs' }
environment {
PYENV_ROOT = "/usr/local/pyenv"
PATH = "$PYENV_ROOT/bin:$PATH"
}
stages {
stage('setup') {
steps {
sh 'eval "$(pyenv init -)"; pyenv install 2.7.14 || echo "We already have this python."; pyenv local 2.7.14; pyenv shell 2.7.14'
sh 'eval "$(pyenv init -)"; pip install sphinx -e .'
}
}
stage('build') {
steps {
sh 'eval "$(pyenv init -)"; make -C doc clean html'
archiveArtifacts artifacts: 'doc/_build/html'
}
}
}
post {
success {
githubNotify description: "The docs job has passed, artifacts have been saved", status: "SUCCESS"
}
failure {
githubNotify description: "The docs job has failed", status: "FAILURE"
}
}
}

48
.ci/kitchen-centos7-py2 Normal file
View file

@ -0,0 +1,48 @@
pipeline {
agent { label 'kitchen-slave' }
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"
}
stages {
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'
}
}}
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
}
post {
always {
script { withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) {
sshagent(credentials: ['jenkins-testing-ssh-key']) {
sh 'ssh-add ~/.ssh/jenkins/jenkins-testing.pem'
sh 'bundle exec kitchen destroy $TEST_SUITE-$TEST_PLATFORM'
}
}}
}
}
}
}
post {
success {
githubNotify description: "The centos7-py2 job has passed", status: "SUCCESS"
}
failure {
githubNotify description: "The centos7-py2 job has failed", status: "FAILURE"
}
}
}

48
.ci/kitchen-centos7-py3 Normal file
View file

@ -0,0 +1,48 @@
pipeline {
agent { label 'kitchen-slave' }
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"
}
stages {
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'
}
}}
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
}
post {
always {
script { withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) {
sshagent(credentials: ['jenkins-testing-ssh-key']) {
sh 'ssh-add ~/.ssh/jenkins/jenkins-testing.pem'
sh 'bundle exec kitchen destroy $TEST_SUITE-$TEST_PLATFORM'
}
}}
}
}
}
}
post {
success {
githubNotify description: "The centos7-py3 job has passed", status: "SUCCESS"
}
failure {
githubNotify description: "The centos7-py3 job has failed", status: "FAILURE"
}
}
}

View file

@ -0,0 +1,48 @@
pipeline {
agent { label 'kitchen-slave' }
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"
}
stages {
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'
}
}}
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
}
post {
always {
script { withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) {
sshagent(credentials: ['jenkins-testing-ssh-key']) {
sh 'ssh-add ~/.ssh/jenkins/jenkins-testing.pem'
sh 'bundle exec kitchen destroy $TEST_SUITE-$TEST_PLATFORM'
}
}}
}
}
}
}
post {
success {
githubNotify description: "The ubuntu-1604-py2 job has passed", status: "SUCCESS"
}
failure {
githubNotify description: "The ubuntu-1604-py2 job has failed", status: "FAILURE"
}
}
}

View file

@ -0,0 +1,48 @@
pipeline {
agent { label 'kitchen-slave' }
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"
}
stages {
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'
}
}}
archiveArtifacts artifacts: 'artifacts/xml-unittests-output/*.xml'
}
post {
always {
script { withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) {
sshagent(credentials: ['jenkins-testing-ssh-key']) {
sh 'ssh-add ~/.ssh/jenkins/jenkins-testing.pem'
sh 'bundle exec kitchen destroy $TEST_SUITE-$TEST_PLATFORM'
}
}}
}
}
}
}
post {
success {
githubNotify description: "The ubuntu-1604-py3 job has passed", status: "SUCCESS"
}
failure {
githubNotify description: "The ubuntu-1604-py3 job has failed", status: "FAILURE"
}
}
}

41
.ci/lint Normal file
View file

@ -0,0 +1,41 @@
pipeline {
agent { label 'pr-lint-slave' }
environment {
PYENV_ROOT = "/usr/local/pyenv"
PATH = "$PYENV_ROOT/bin:$PATH"
}
stages {
stage('setup') {
steps {
sh 'eval "$(pyenv init -)"; pyenv install 2.7.14 || echo "We already have this python."; pyenv local 2.7.14; pyenv shell 2.7.14'
sh 'eval "$(pyenv init -)"; pip install pylint SaltPyLint'
sh 'eval "$(pyenv init -)"; which pylint; pylint --version'
}
}
stage('linting') {
failFast false
parallel {
stage('salt linting') {
steps {
sh 'eval "$(pyenv init -)"; pylint --rcfile=.testing.pylintrc --disable=W1307,str-format-in-logging setup.py salt/ | tee pylint-report.xml'
archiveArtifacts artifacts: 'pylint-report.xml'
}
}
stage('test linting') {
steps {
sh 'eval "$(pyenv init -)"; pylint --rcfile=.testing.pylintrc --disable=W0232,E1002,W1307,str-format-in-logging tests/ | tee pylint-report-tests.xml'
archiveArtifacts artifacts: 'pylint-report-tests.xml'
}
}
}
}
}
post {
success {
githubNotify description: "The lint job has passed", status: "SUCCESS"
}
failure {
githubNotify description: "The lint job has failed", status: "FAILURE"
}
}
}

View file

@ -1162,6 +1162,40 @@ The password used for HTTP proxy access.
proxy_password: obolus
Docker Configuration
====================
.. conf_minion:: docker.update_mine
``docker.update_mine``
----------------------
.. versionadded:: 2017.7.8,2018.3.3
.. versionchanged:: Fluorine
The default value is now ``False``
Default: ``True``
If enabled, when containers are added, removed, stopped, started, etc., the
:ref:`mine <salt-mine>` will be updated with the results of :py:func:`docker.ps
verbose=True all=True host=True <salt.modules.dockermod.ps>`. This mine data is
used by :py:func:`mine.get_docker <salt.modules.mine.get_docker>`. Set this
option to ``False`` to keep Salt from updating the mine with this information.
.. note::
This option can also be set in Grains or Pillar data, with Grains
overriding Pillar and the minion config file overriding Grains.
.. note::
Disabling this will of course keep :py:func:`mine.get_docker
<salt.modules.mine.get_docker>` from returning any information for a given
minion.
.. code-block:: yaml
docker.update_mine: False
Minion Module Management
========================

View file

@ -16,3 +16,16 @@ New win_snmp behavior
- :py:func:`win_snmp.set_community_names
<salt.modules.win_snmp.set_community_names>` now raises an error when SNMP
settings are being managed by GroupPolicy.
Option Added to Disable Docker Mine Updates
===========================================
When a docker container is added, removed, started, stopped, etc., the results
of a :py:func:`docker.ps verbose=True all=True host=True
<salt.modules.dockermod.ps>` are sent to the :ref:`mine <salt-mine>`, to be
used by :py:func:`mine.get_docker <salt.modules.mine.get_docker>`.
A new config option (:conf_minion:`docker.update_mine`) has been added. When
set to ``False``, Salt will not send this information to the mine. This is
useful in cases where sensitive information is stored in the container's
environment.

View file

@ -436,11 +436,20 @@ def _refresh_mine_cache(wrapped):
refresh salt mine on exit.
'''
returned = wrapped(*args, **salt.utils.clean_kwargs(**kwargs))
__salt__['mine.send']('docker.ps', verbose=True, all=True, host=True)
if _check_update_mine():
__salt__['mine.send']('docker.ps', verbose=True, all=True, host=True)
return returned
return wrapper
def _check_update_mine():
try:
ret = __context__['docker.update_mine']
except KeyError:
ret = __context__['docker.update_mine'] = __salt__['config.get']('docker.update_mine', default=True)
return ret
# Helper functions
def _change_state(name, action, expected, *args, **kwargs):
'''

View file

@ -374,10 +374,18 @@ def flush():
def get_docker(interfaces=None, cidrs=None, with_container_id=False):
'''
Get all mine data for 'docker.get_containers' and run an aggregation
routine. The "interfaces" parameter allows for specifying which network
interfaces to select ip addresses from. The "cidrs" parameter allows for
specifying a list of cidrs which the ip address must match.
.. versionchanged:: 2017.7.8,2018.3.3
When :conf_minion:`docker.update_mine` is set to ``False`` for a given
minion, no mine data will be populated for that minion, and thus none
will be returned for it.
.. versionchanged:: Fluorine
:conf_minion:`docker.update_mine` now defaults to ``False``
Get all mine data for :py:func:`docker.ps <salt.modules.dockermod.ps_>` and
run an aggregation routine. The ``interfaces`` parameter allows for
specifying the network interfaces from which to select IP addresses. The
``cidrs`` parameter allows for specifying a list of subnets which the IP
address must match.
with_container_id
Boolean, to expose container_id in the list of results

View file

@ -136,6 +136,7 @@ class DockerTestCase(TestCase, LoaderModuleMockMixin):
with patch.dict(docker_mod.__salt__,
{'mine.send': mine_send,
'container_resource.run': MagicMock(),
'config.get': MagicMock(return_value=True),
'cp.cache_file': MagicMock(return_value=False)}):
with patch.dict(docker_mod.__utils__,
{'docker.get_client_args': client_args_mock}):
@ -144,6 +145,44 @@ class DockerTestCase(TestCase, LoaderModuleMockMixin):
mine_send.assert_called_with('docker.ps', verbose=True, all=True,
host=True)
def test_update_mine(self):
'''
Test the docker.update_mine config option
'''
def config_get_disabled(val, default):
return {'base_url': docker_mod.NOTSET,
'version': docker_mod.NOTSET,
'docker.url': docker_mod.NOTSET,
'docker.version': docker_mod.NOTSET,
'docker.machine': docker_mod.NOTSET,
'docker.update_mine': False}[val]
def config_get_enabled(val, default):
return {'base_url': docker_mod.NOTSET,
'version': docker_mod.NOTSET,
'docker.url': docker_mod.NOTSET,
'docker.version': docker_mod.NOTSET,
'docker.machine': docker_mod.NOTSET,
'docker.update_mine': True}[val]
mine_mock = Mock()
dunder_salt = {
'config.get': MagicMock(side_effect=config_get_disabled),
'mine.send': mine_mock,
}
with patch.dict(docker_mod.__salt__, dunder_salt), \
patch.dict(docker_mod.__context__, {'docker.client': Mock()}), \
patch.object(docker_mod, 'state', MagicMock(return_value='stopped')):
docker_mod.stop('foo', timeout=1)
mine_mock.assert_not_called()
with patch.dict(docker_mod.__salt__, dunder_salt), \
patch.dict(docker_mod.__context__, {'docker.client': Mock()}), \
patch.object(docker_mod, 'state', MagicMock(return_value='stopped')):
dunder_salt['config.get'].side_effect = config_get_enabled
docker_mod.stop('foo', timeout=1)
self.assert_called_once(mine_mock)
@skipIf(_docker_py_version() < (1, 5, 0),
'docker module must be installed to run this test or is too old. >=1.5.0')
def test_list_networks(self, *args):

View file

@ -117,12 +117,12 @@ class MountTestCase(TestCase, LoaderModuleMockMixin):
mock_open(read_data=file_data),
create=True) as m:
m.return_value.__iter__.return_value = file_data.splitlines()
self.assertEqual(mount.fstab(), {'/tmp': {'device': 'swap',
'device_fsck': '-',
'fstype': 'tmpfs',
'mount_at_boot': 'yes',
'opts': ['size=2048m'],
'pass_fsck': '-'}})
self.assertEqual(mount.vfstab(), {'/tmp': {'device': 'swap',
'device_fsck': '-',
'fstype': 'tmpfs',
'mount_at_boot': 'yes',
'opts': ['size=2048m'],
'pass_fsck': '-'}})
def test_rm_fstab(self):
'''