Merge branch '2018.3' into mac_brew

This commit is contained in:
Nicole Thomas 2018-07-31 12:28:36 -04:00 committed by GitHub
commit e818c752b3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 168 additions and 86 deletions

View file

@ -29,13 +29,13 @@ pipeline {
parallel {
stage('salt linting') {
steps {
sh 'eval "$(pyenv init -)"; tox -e pylint-salt | tee pylint-report.xml'
sh 'eval "$(pyenv init -)"; tox -e pylint-salt $(find salt/ -name "*.py" -exec git diff --name-only "origin/$CHANGE_TARGET" "origin/$BRANCH_NAME" setup.py {} +) | tee pylint-report.xml'
archiveArtifacts artifacts: 'pylint-report.xml'
}
}
stage('test linting') {
steps {
sh 'eval "$(pyenv init -)"; tox -e pylint-tests | tee pylint-report-tests.xml'
sh 'eval "$(pyenv init -)"; tox -e pylint-tests $(find tests/ -name "*.py" -exec git diff --name-only "origin/$CHANGE_TARGET" "origin/$BRANCH_NAME" {} +) | tee pylint-report-tests.xml'
archiveArtifacts artifacts: 'pylint-report-tests.xml'
}
}
@ -49,7 +49,9 @@ pipeline {
parserName: 'PyLint',
pattern: 'pylint-report*.xml'
]],
failedTotalAll: '1',
failedTotalAll: '0',
useDeltaValues: false,
canRunOnFailed: true,
usePreviousBuildAsReference: true
])
cleanWs()

View file

@ -21,11 +21,21 @@ SaltStack has its own coding style guide that informs contributors on various co
approaches. Please review the :ref:`Salt Coding Style <coding-style>` documentation
for information about Salt's particular coding patterns.
Within the :ref:`Salt Coding Style <coding-style>` documentation, there is a section
about running Salt's ``.pylintrc`` file. SaltStack recommends running the ``.pylintrc``
file on any files you are changing with your code contribution before submitting a
pull request to Salt's repository. Please see the :ref:`Linting<pylint-instructions>`
documentation for more information.
Within the :ref:`Salt Coding Style <coding-style>` documentation, there is a
section about running Salt's ``.testing.pylintrc`` file. SaltStack recommends
running the ``.testing.pylintrc`` file on any files you are changing with your
code contribution before submitting a pull request to Salt's repository. Please
see the :ref:`Linting<pylint-instructions>` documentation for more information.
.. note::
There are two pylint files in the ``salt`` directory. One is the
``.pylintrc`` file and the other is the ``.testing.pylintrc`` file. The
tests that run in Jenkins against GitHub Pull Requests use
``.testing.pylintrc``. The ``testing.pylintrc`` file is a little less
strict than the ``.pylintrc`` and is used to make it easier for contributors
to submit changes. The ``.pylintrc`` file can be used for linting, but the
``testing.pylintrc`` is the source of truth when submitting pull requests.
.. _github-pull-request:

View file

@ -22,21 +22,31 @@ improve Salt)!!
Linting
=======
Most Salt style conventions are codified in Salt's ``.pylintrc`` file. Salt's
pylint file has two dependencies: pylint_ and saltpylint_. You can install
these dependencies with ``pip``:
Most Salt style conventions are codified in Salt's ``.testing.pylintrc`` file.
Salt's pylint file has two dependencies: pylint_ and saltpylint_. You can
install these dependencies with ``pip``:
.. code-block:: bash
pip install pylint
pip install saltpylint
The ``.pylintrc`` file is found in the root of the Salt project and can be passed
as an argument to the pylint_ program as follows:
The ``.testing.pylintrc`` file is found in the root of the Salt project and can
be passed as an argument to the pylint_ program as follows:
.. code-block:: bash
pylint --rcfile=/path/to/salt/.pylintrc salt/dir/to/lint
pylint --rcfile=/path/to/salt/.testing.pylintrc salt/dir/to/lint
.. note::
There are two pylint files in the ``salt`` directory. One is the
``.pylintrc`` file and the other is the ``.testing.pylintrc`` file. The
tests that run in Jenkins against GitHub Pull Requests use
``.testing.pylintrc``. The ``testing.pylintrc`` file is a little less
strict than the ``.pylintrc`` and is used to make it easier for contributors
to submit changes. The ``.pylintrc`` file can be used for linting, but the
``testing.pylintrc`` is the source of truth when submitting pull requests.
.. _pylint: http://www.pylint.org
.. _saltpylint: https://github.com/saltstack/salt-pylint

View file

@ -80,13 +80,13 @@ def _ssh_state(chunks, st_kwargs,
# Read in the JSON data and return the data structure
try:
return salt.utils.json.loads(stdout, object_hook=salt.utils.data.encode_dict)
return salt.utils.data.decode(salt.utils.json.loads(stdout, object_hook=salt.utils.data.encode_dict))
except Exception as e:
log.error("JSON Render failed for: %s\n%s", stdout, stderr)
log.error(str(e))
# If for some reason the json load fails, return the stdout
return stdout
return salt.utils.data.decode(stdout)
def _set_retcode(ret, highstate=None):

View file

@ -129,8 +129,6 @@ def serve_file(load, fnd):
with salt.utils.files.fopen(fpath, 'rb') as fp_:
fp_.seek(load['loc'])
data = fp_.read(__opts__['file_buffer_size'])
if data and six.PY3 and not salt.utils.files.is_binary(fpath):
data = data.decode(__salt_system_encoding__)
if gzip and data:
data = salt.utils.gzip_util.compress(data, gzip)
ret['gzip'] = gzip

View file

@ -200,7 +200,7 @@ def _walk(path, value, metrics, timestamp, skip):
to a float. Defaults to `False`.
'''
log.trace(
'Carbon return walking path: %s, value: %s, metrics: %s, ',
'Carbon return walking path: %s, value: %s, metrics: %s, '
'timestamp: %s', path, value, metrics, timestamp
)
if isinstance(value, collections.Mapping):

View file

@ -172,7 +172,9 @@ def init(
start=True,
disk='default',
saltenv='base',
enable_vnc=False):
enable_vnc=False,
seed_cmd='seed.apply',
enable_qcow=False):
'''
This routine is used to create a new virtual machine. This routines takes
a number of options to determine what the newly created virtual machine
@ -194,14 +196,14 @@ def init(
on the salt fileserver, but http, https and ftp can also be used.
hypervisor
The hypervisor to use for the new virtual machine. Default is 'kvm'.
The hypervisor to use for the new virtual machine. Default is `kvm`.
host
The host to use for the new virtual machine, if this is omitted
Salt will automatically detect what host to use.
seed
Set to False to prevent Salt from seeding the new virtual machine.
Set to `False` to prevent Salt from seeding the new virtual machine.
nic
The nic profile to use, defaults to the "default" nic profile which
@ -217,6 +219,17 @@ def init(
saltenv
The Salt environment to use
enable_vnc
Whether a VNC screen is attached to resulting VM. Default is `False`.
seed_cmd
If seed is `True`, use this execution module function to seed new VM.
Default is `seed.apply`.
enable_qcow
Clone disk image as a copy-on-write qcow2 image, using downloaded
`image` as backing file.
'''
__jid_event__.fire_event({'message': 'Searching for hosts'}, 'progress')
data = query(host, quiet=True)
@ -257,25 +270,29 @@ def init(
)
try:
cmd_ret = client.cmd_iter(
host,
'virt.init',
[
name,
cpu,
mem,
image,
nic,
hypervisor,
start,
disk,
saltenv,
seed,
install,
pub_key,
priv_key,
enable_vnc,
],
timeout=600)
host,
'virt.init',
[
name,
cpu,
mem
],
timeout=600,
kwarg={
'image': image,
'nic': nic,
'hypervisor': hypervisor,
'start': start,
'disk': disk,
'saltenv': saltenv,
'seed': seed,
'install': install,
'pub_key': pub_key,
'priv_key': priv_key,
'seed_cmd': seed_cmd,
'enable_vnc': enable_vnc,
'enable_qcow': enable_qcow,
})
except SaltClientError as client_error:
# Fall through to ret error handling below
print(client_error)

View file

@ -73,7 +73,7 @@ def _create_new_policy(name, rules):
payload = {'rules': rules}
url = "v1/sys/policy/{0}".format(name)
response = __utils__['vault.make_request']('PUT', url, json=payload)
if response.status_code != 204:
if response.status_code not in [200, 204]:
return {
'name': name,
'changes': {},
@ -108,7 +108,7 @@ def _handle_existing_policy(name, new_rules, existing_rules):
url = "v1/sys/policy/{0}".format(name)
response = __utils__['vault.make_request']('PUT', url, json=payload)
if response.status_code != 204:
if response.status_code not in [200, 204]:
return {
'name': name,
'changes': {},

View file

@ -1534,9 +1534,9 @@ class Pygit2(GitProvider):
elif tag_ref in refs:
tag_obj = self.repo.revparse_single(tag_ref)
if not isinstance(tag_obj, pygit2.Tag):
if not isinstance(tag_obj, pygit2.Commit):
log.error(
'%s does not correspond to pygit2.Tag object',
'%s does not correspond to pygit2.Commit object',
tag_ref
)
else:
@ -1556,9 +1556,10 @@ class Pygit2(GitProvider):
exc_info=True
)
return None
log.debug('SHA of tag %s: %s', tgt_ref, tag_sha)
if head_sha != target_sha:
if not _perform_checkout(local_ref, branch=False):
if head_sha != tag_sha:
if not _perform_checkout(tag_ref, branch=False):
return None
# Return the relative root, if present

View file

@ -0,0 +1,3 @@
echo1:
cmd.run:
- name: "echo 'This is Æ test!'"

View file

@ -1,6 +1,6 @@
Scene 24
OLD MAN: Ah, hee he he ha!
ARTHUR: And this enchanter of whom you speak, he has seen the grail?
OLD MAN: Ha ha he he he he!

View file

@ -1942,6 +1942,20 @@ class StateModuleTest(ModuleCase, SaltReturnAssertsMixin):
_expected = "cmd_|-echo1_|-echo 'This is Æ test!'_|-run"
self.assertIn(_expected, ret)
def test_state_sls_unicode_characters_cmd_output(self):
'''
test the output from running and echo command with non-ascii
characters.
'''
ret = self.run_function('state.sls', ['issue-46672-a'])
key = list(ret.keys())[0]
log.debug('== ret %s ==', type(ret))
_expected = 'This is Æ test!'
if salt.utils.platform.is_windows():
# Windows cmd.exe will mangle the output using cmd's codepage.
_expected = "'This is test!'"
self.assertEqual(_expected, ret[key]['changes']['stdout'])
def tearDown(self):
nonbase_file = os.path.join(TMP, 'nonbase_env')
if os.path.isfile(nonbase_file):

View file

@ -30,6 +30,7 @@ from tests.support.helpers import (
with_tempdir,
with_tempfile,
Webserver,
destructiveTest
)
from tests.support.mixins import SaltReturnAssertsMixin
@ -3653,3 +3654,54 @@ class RemoteFileTest(ModuleCase, SaltReturnAssertsMixin):
skip_verify=True)
log.debug('ret = %s', ret)
self.assertSaltTrueReturn(ret)
WIN_TEST_FILE = 'c:/testfile'
@destructiveTest
@skipIf(not IS_WINDOWS, 'windows test only')
class WinFileTest(ModuleCase):
'''
Test for the file state on Windows
'''
def setUp(self):
self.run_state('file.managed', name=WIN_TEST_FILE, makedirs=True, contents='Only a test')
def tearDown(self):
self.run_state('file.absent', name=WIN_TEST_FILE)
def test_file_managed(self):
'''
Test file.managed on Windows
'''
self.assertTrue(self.run_state('file.exists', name=WIN_TEST_FILE))
def test_file_copy(self):
'''
Test file.copy on Windows
'''
ret = self.run_state('file.copy', name='c:/testfile_copy', makedirs=True, source=WIN_TEST_FILE)
self.assertTrue(ret)
def test_file_comment(self):
'''
Test file.comment on Windows
'''
self.run_state('file.comment', name=WIN_TEST_FILE, regex='^Only')
with salt.utils.files.fopen(WIN_TEST_FILE, 'r') as fp_:
self.assertTrue(fp_.read().startswith('#Only'))
def test_file_replace(self):
'''
Test file.replace on Windows
'''
self.run_state('file.replace', name=WIN_TEST_FILE, pattern='test', repl='testing')
with salt.utils.files.fopen(WIN_TEST_FILE, 'r') as fp_:
self.assertIn('testing', fp_.read())
def test_file_absent(self):
'''
Test file.absent on Windows
'''
ret = self.run_state('file.absent', name=WIN_TEST_FILE)
self.assertTrue(ret)

View file

@ -598,7 +598,7 @@ class TestSaltProgram(six.with_metaclass(TestSaltProgramMeta, TestProgram)):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
connect = sock.bind(('localhost', port))
except:
except OSError:
# these ports are already in use, use different ones
pub_port = 4606
ret_port = 4607

View file

@ -12,7 +12,7 @@ import tempfile
# Import Salt Testing libs
from tests.integration import AdaptedConfigurationTestCaseMixin
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.paths import FILES, TMP, TMP_STATE_TREE
from tests.support.paths import BASE_FILES, TMP, TMP_STATE_TREE
from tests.support.unit import TestCase, skipIf
from tests.support.mock import patch, NO_MOCK, NO_MOCK_REASON
@ -20,6 +20,7 @@ from tests.support.mock import patch, NO_MOCK, NO_MOCK_REASON
import salt.fileserver.roots as roots
import salt.fileclient
import salt.utils.files
import salt.utils.hashutils
import salt.utils.platform
try:
@ -63,13 +64,11 @@ class RootsTest(TestCase, AdaptedConfigurationTestCaseMixin, LoaderModuleMockMix
else:
cls.test_symlink_list_file_roots = None
cls.tmp_dir = tempfile.mkdtemp(dir=TMP)
full_path_to_file = os.path.join(FILES, 'file', 'base', 'testfile')
full_path_to_file = os.path.join(BASE_FILES, 'testfile')
with salt.utils.files.fopen(full_path_to_file, 'rb') as s_fp:
with salt.utils.files.fopen(os.path.join(cls.tmp_dir, 'testfile'), 'wb') as d_fp:
for line in s_fp:
d_fp.write(
line.rstrip(b'\n').rstrip(b'\r') + os.linesep.encode('utf-8')
)
d_fp.write(line.rstrip(b'\n').rstrip(b'\r') + b'\n')
@classmethod
def tearDownClass(cls):
@ -95,7 +94,7 @@ class RootsTest(TestCase, AdaptedConfigurationTestCaseMixin, LoaderModuleMockMix
ret = roots.find_file('testfile')
self.assertEqual('testfile', ret['rel'])
full_path_to_file = os.path.join(FILES, 'file', 'base', 'testfile')
full_path_to_file = os.path.join(BASE_FILES, 'testfile')
self.assertEqual(full_path_to_file, ret['path'])
def test_serve_file(self):
@ -108,34 +107,9 @@ class RootsTest(TestCase, AdaptedConfigurationTestCaseMixin, LoaderModuleMockMix
'rel': 'testfile'}
ret = roots.serve_file(load, fnd)
data = 'Scene 24\n\n \n OLD MAN: Ah, hee he he ha!\n ' \
'ARTHUR: And this enchanter of whom you speak, he ' \
'has seen the grail?\n OLD MAN: Ha ha he he he ' \
'he!\n ARTHUR: Where does he live? Old man, where ' \
'does he live?\n OLD MAN: He knows of a cave, a ' \
'cave which no man has entered.\n ARTHUR: And the ' \
'Grail... The Grail is there?\n OLD MAN: Very much ' \
'danger, for beyond the cave lies the Gorge\n ' \
'of Eternal Peril, which no man has ever crossed.\n ' \
'ARTHUR: But the Grail! Where is the Grail!?\n ' \
'OLD MAN: Seek you the Bridge of Death.\n ARTHUR: ' \
'The Bridge of Death, which leads to the Grail?\n ' \
'OLD MAN: Hee hee ha ha!\n\n'
if salt.utils.platform.is_windows():
data = 'Scene 24\r\n\r\n \r\n OLD MAN: Ah, hee he he ' \
'ha!\r\n ARTHUR: And this enchanter of whom you ' \
'speak, he has seen the grail?\r\n OLD MAN: Ha ha ' \
'he he he he!\r\n ARTHUR: Where does he live? Old ' \
'man, where does he live?\r\n OLD MAN: He knows of ' \
'a cave, a cave which no man has entered.\r\n ' \
'ARTHUR: And the Grail... The Grail is there?\r\n ' \
'OLD MAN: Very much danger, for beyond the cave lies ' \
'the Gorge\r\n of Eternal Peril, which no man ' \
'has ever crossed.\r\n ARTHUR: But the Grail! ' \
'Where is the Grail!?\r\n OLD MAN: Seek you the ' \
'Bridge of Death.\r\n ARTHUR: The Bridge of Death, ' \
'which leads to the Grail?\r\n OLD MAN: Hee hee ha ' \
'ha!\r\n\r\n'
with salt.utils.files.fopen(
os.path.join(BASE_FILES, 'testfile'), 'rb') as fp_:
data = fp_.read()
self.assertDictEqual(
ret,
@ -163,9 +137,9 @@ class RootsTest(TestCase, AdaptedConfigurationTestCaseMixin, LoaderModuleMockMix
# Hashes are different in Windows. May be how git translates line
# endings
hsum = 'baba5791276eb99a7cc498fb1acfbc3b4bd96d24cfe984b4ed6b5be2418731df'
if salt.utils.platform.is_windows():
hsum = '754aa260e1f3e70f43aaf92149c7d1bad37f708c53304c37660e628d7553f687'
with salt.utils.files.fopen(
os.path.join(BASE_FILES, 'testfile'), 'rb') as fp_:
hsum = salt.utils.hashutils.sha256_digest(fp_.read())
self.assertDictEqual(
ret,

View file

@ -43,6 +43,7 @@ integration.states.test_pip_state
integration.states.test_pkg
integration.states.test_reg
integration.states.test_renderers
integration.states.test_file
integration.states.test_user
integration.utils.testprogram
integration.wheel.test_client