mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge remote-tracking branch 'upstream/2015.5' into merge-forward-2015.8
Conflicts: doc/topics/installation/windows.rst doc/topics/tutorials/pillar.rst pkg/windows/installer/Salt-Minion-Setup.nsi salt/modules/file.py salt/modules/schedule.py salt/pillar/git_pillar.py salt/states/boto_route53.py salt/states/pkg.py tests/integration/modules/pillar.py
This commit is contained in:
commit
3286a5250f
20 changed files with 348 additions and 180 deletions
|
@ -414,13 +414,17 @@ from the Salt Master. For example:
|
|||
|
||||
{% set some_data = salt.pillar.get('some_data', {'sane default': True}) %}
|
||||
|
||||
{# or #}
|
||||
|
||||
{% import_yaml 'path/to/file.yaml' as some_data %}
|
||||
|
||||
{# or #}
|
||||
|
||||
{% load_json 'path/to/file.json' as some_data %}
|
||||
{% import_json 'path/to/file.json' as some_data %}
|
||||
|
||||
{# or #}
|
||||
|
||||
{% load_text 'path/to/ssh_key.pub' as ssh_pub_key %}
|
||||
{% import_text 'path/to/ssh_key.pub' as ssh_pub_key %}
|
||||
|
||||
{# or #}
|
||||
|
||||
|
|
|
@ -55,13 +55,18 @@ Silent Installer Options
|
|||
========================
|
||||
|
||||
The installer can be run silently by providing the `/S` option at the command
|
||||
line. The options `/master` and `/minion-name` allow for configuring the master
|
||||
hostname and minion name, respectively. Here's an example of using the silent
|
||||
installer:
|
||||
line. The installer also accepts the following options for configuring the Salt
|
||||
Minion silently:
|
||||
|
||||
- `/master=` A string value to set the IP address or host name of the master. Default value is 'salt'
|
||||
- `/minion-name=` A string value to set the minion name. Default is 'hostname'
|
||||
- `/start-service=` Either a 1 or 0. '1' will start the service, '0' will not. Default is to start the service after installation.
|
||||
|
||||
Here's an example of using the silent installer:
|
||||
|
||||
.. code-block:: bat
|
||||
|
||||
Salt-Minion-0.17.0-Setup-amd64.exe /S /master=yoursaltmaster /minion-name=yourminionname
|
||||
Salt-Minion-2015.5.6-Setup-amd64.exe /S /master=yoursaltmaster /minion-name=yourminionname /start-service=0
|
||||
|
||||
|
||||
Running the Salt Minion on Windows as an Unprivileged User
|
||||
|
|
|
@ -4,10 +4,26 @@
|
|||
MinionFS Backend Walkthrough
|
||||
============================
|
||||
|
||||
Propagating Files
|
||||
=================
|
||||
|
||||
.. versionadded:: 2014.1.0
|
||||
|
||||
Sometimes, you might need to propagate files that are generated on a minion.
|
||||
Salt already has a feature to send files from a minion to the master:
|
||||
Sometimes, one might need to propagate files that are generated on a minion.
|
||||
Salt already has a feature to send files from a minion to the master.
|
||||
|
||||
Enabling File Propagation
|
||||
=========================
|
||||
|
||||
To enable propagation, the :conf_master:`file_recv` option needs to be set to ``True``.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
file_recv: True
|
||||
|
||||
These changes require a restart of the master, then new requests for the
|
||||
``salt://minion-id/`` protocol will send files that are pushed by ``cp.push``
|
||||
from ``minion-id`` to the master.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
|
@ -24,6 +40,9 @@ This command will store the file, including its full path, under
|
|||
<salt.modules.cp.push>`. To get up to speed, check out the
|
||||
:doc:`walkthrough </topics/tutorials/walkthrough>`.
|
||||
|
||||
MinionFS Backend
|
||||
================
|
||||
|
||||
Since it is not a good idea to expose the whole :conf_master:`cachedir`, MinionFS
|
||||
should be used to send these files to other minions.
|
||||
|
||||
|
@ -136,4 +155,4 @@ Or we can use a more elegant and salty way to add an SSH key:
|
|||
|
||||
|
||||
|
||||
.. [*] Yes, that was the actual key on my server, but the server is already destroyed.
|
||||
.. [*] Yes, that was the actual key on my server, but the server is already destroyed.
|
||||
|
|
|
@ -315,6 +315,19 @@ line:
|
|||
the key that is passed in will overwrite the entire value of that key,
|
||||
rather than merging only the specified value set via the command line.
|
||||
|
||||
The example below will swap the value for vim with telnet in the previously
|
||||
specified list, notice the nested pillar dict:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' state.sls edit.vim pillar='{"pkgs": {"vim": "telnet"}}'
|
||||
|
||||
.. note::
|
||||
|
||||
This will attempt to install telnet on your minions, feel free to
|
||||
uninstall the package or replace telnet value with anything else.
|
||||
|
||||
|
||||
More On Pillar
|
||||
==============
|
||||
|
||||
|
|
|
@ -31,6 +31,14 @@ You can specify multiple :ref:`state-declaration` under an
|
|||
Try stopping Apache before running ``state.highstate`` once again and observe
|
||||
the output.
|
||||
|
||||
.. note::
|
||||
|
||||
For those running RedhatOS derivatives (Centos, AWS), you will want to specify the
|
||||
service name to be httpd. More on state service here, :mod:`service state
|
||||
<salt.states.service>`. With the example above, just add "- name: httpd"
|
||||
above the require line and with the same spacing.
|
||||
|
||||
|
||||
Require other states
|
||||
====================
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
|
||||
|
||||
; MUI 1.67 compatible ------
|
||||
!include "MUI.nsh"
|
||||
!include "MUI2.nsh"
|
||||
|
||||
!include "nsDialogs.nsh"
|
||||
!include "LogicLib.nsh"
|
||||
|
@ -36,6 +36,7 @@ Var MasterHost
|
|||
Var MasterHost_State
|
||||
Var MinionName
|
||||
Var MinionName_State
|
||||
Var StartService
|
||||
|
||||
; MUI Settings
|
||||
!define MUI_ABORTWARNING
|
||||
|
@ -54,6 +55,7 @@ Page custom nsDialogsPage nsDialogsPageLeave
|
|||
!insertmacro MUI_PAGE_INSTFILES
|
||||
|
||||
; Finish page
|
||||
!define MUI_PAGE_CUSTOMFUNCTION_SHOW FinishPage.Show
|
||||
!define MUI_FINISHPAGE_RUN "$INSTDIR\nssm"
|
||||
!define MUI_FINISHPAGE_RUN_PARAMETERS "start salt-minion"
|
||||
!insertmacro MUI_PAGE_FINISH
|
||||
|
@ -76,6 +78,7 @@ Page custom nsDialogsPage nsDialogsPageLeave
|
|||
|
||||
|
||||
Function nsDialogsPage
|
||||
|
||||
nsDialogs::Create 1018
|
||||
Pop $Dialog
|
||||
|
||||
|
@ -110,6 +113,68 @@ Function nsDialogsPageLeave
|
|||
FunctionEnd
|
||||
|
||||
|
||||
Function getMinionConfig
|
||||
|
||||
confFind:
|
||||
IfFileExists "$INSTDIR\conf\minion" confFound confNotFound
|
||||
|
||||
confNotFound:
|
||||
${If} $INSTDIR == "c:\salt\bin\Scripts"
|
||||
StrCpy $INSTDIR "C:\salt"
|
||||
goto confFind
|
||||
${Else}
|
||||
goto confReallyNotFound
|
||||
${EndIf}
|
||||
|
||||
confFound:
|
||||
FileOpen $0 "$INSTDIR\conf\minion" r
|
||||
|
||||
confLoop:
|
||||
FileRead $0 $1
|
||||
IfErrors EndOfFile
|
||||
${StrLoc} $2 $1 "master:" ">"
|
||||
${If} $2 == 0
|
||||
${StrStrAdv} $2 $1 "master: " ">" ">" "0" "0" "0"
|
||||
${Trim} $2 $2
|
||||
StrCpy $MasterHost_State $2
|
||||
${EndIf}
|
||||
|
||||
${StrLoc} $2 $1 "id:" ">"
|
||||
${If} $2 == 0
|
||||
${StrStrAdv} $2 $1 "id: " ">" ">" "0" "0" "0"
|
||||
${Trim} $2 $2
|
||||
StrCpy $MinionName_State $2
|
||||
${EndIf}
|
||||
|
||||
Goto confLoop
|
||||
|
||||
EndOfFile:
|
||||
FileClose $0
|
||||
|
||||
confReallyNotFound:
|
||||
Push $R0
|
||||
Push $R1
|
||||
Push $R2
|
||||
${GetParameters} $R0
|
||||
${GetOptions} $R0 "/master=" $R1
|
||||
${GetOptions} $R0 "/minion-name=" $R2
|
||||
${IfNot} $R1 == ""
|
||||
StrCpy $MasterHost_State $R1
|
||||
${ElseIf} $MasterHost_State == ""
|
||||
StrCpy $MasterHost_State "salt"
|
||||
${EndIf}
|
||||
${IfNot} $R2 == ""
|
||||
StrCpy $MinionName_State $R2
|
||||
${ElseIf} $MinionName_State == ""
|
||||
StrCpy $MinionName_State "hostname"
|
||||
${EndIf}
|
||||
Pop $R2
|
||||
Pop $R1
|
||||
Pop $R0
|
||||
|
||||
FunctionEnd
|
||||
|
||||
|
||||
Function updateMinionConfig
|
||||
|
||||
ClearErrors
|
||||
|
@ -181,13 +246,54 @@ Section -Post
|
|||
RMDir /R "$INSTDIR\var\cache\salt" ; removing cache from old version
|
||||
|
||||
Call updateMinionConfig
|
||||
|
||||
Call checkStartService
|
||||
|
||||
SectionEnd
|
||||
|
||||
|
||||
Function FinishPage.Show
|
||||
|
||||
${IfNot} $StartService == 1
|
||||
SendMessage $mui.FinishPage.Run ${BM_SETCHECK} ${BST_UNCHECKED} 0
|
||||
${EndIf}
|
||||
|
||||
FunctionEnd
|
||||
|
||||
|
||||
Function checkStartService
|
||||
|
||||
; Check if the start-service option was passed
|
||||
Push $R0
|
||||
Push $R1
|
||||
${GetParameters} $R0
|
||||
${GetOptions} $R0 "/start-service=" $R1
|
||||
; If start-service was passed something, then set it
|
||||
${IfNot} $R1 == ""
|
||||
StrCpy $StartService $R1
|
||||
; Otherwise default to 1
|
||||
${Else}
|
||||
StrCpy $StartService 1
|
||||
${EndIf}
|
||||
Pop $R0
|
||||
Pop $R1
|
||||
|
||||
FunctionEnd
|
||||
|
||||
|
||||
Function .onInstSuccess
|
||||
; If the installer is running Silently, start the service
|
||||
IfSilent 0 +2
|
||||
Exec 'net start salt-minion'
|
||||
; If the installer is running Silently, start the service
|
||||
IfSilent silentOption notSilent
|
||||
|
||||
silentOption:
|
||||
|
||||
; If start-service is 1, then start the service
|
||||
${If} $StartService == 1
|
||||
Exec 'net start salt-minion'
|
||||
${EndIf}
|
||||
|
||||
notSilent:
|
||||
|
||||
FunctionEnd
|
||||
|
||||
|
||||
|
@ -233,62 +339,37 @@ Function .onInit
|
|||
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
|
||||
DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"
|
||||
|
||||
confFind:
|
||||
IfFileExists "$INSTDIR\conf\minion" confFound confNotFound
|
||||
Call getMinionConfig
|
||||
|
||||
confNotFound:
|
||||
; Check for existing installation
|
||||
ReadRegStr $R0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "UninstallString"
|
||||
StrCmp $R0 "" skipUninstall
|
||||
|
||||
; Found existing installation, prompt to uninstall
|
||||
MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "${PRODUCT_NAME} is already installed. $\n$\nClick `OK` to remove the existing installation." /SD IDOK IDOK uninst
|
||||
Abort
|
||||
|
||||
uninst:
|
||||
; Make sure we're in the right directory
|
||||
${If} $INSTDIR == "c:\salt\bin\Scripts"
|
||||
StrCpy $INSTDIR "C:\salt"
|
||||
goto confFind
|
||||
${Else}
|
||||
goto confReallyNotFound
|
||||
${EndIf}
|
||||
|
||||
confFound:
|
||||
FileOpen $0 "$INSTDIR\conf\minion" r
|
||||
; Stop and remove the salt-minion service
|
||||
ExecWait "net stop salt-minion"
|
||||
ExecWait "sc delete salt-minion"
|
||||
|
||||
confLoop:
|
||||
FileRead $0 $1
|
||||
IfErrors EndOfFile
|
||||
${StrLoc} $2 $1 "master:" ">"
|
||||
${If} $2 == 0
|
||||
${StrStrAdv} $2 $1 "master: " ">" ">" "0" "0" "0"
|
||||
${Trim} $2 $2
|
||||
StrCpy $MasterHost_State $2
|
||||
${EndIf}
|
||||
; Remove salt binaries and batch files
|
||||
Delete "$INSTDIR\uninst.exe"
|
||||
Delete "$INSTDIR\nssm.exe"
|
||||
Delete "$INSTDIR\salt*"
|
||||
RMDir /r "$INSTDIR\bin"
|
||||
|
||||
${StrLoc} $2 $1 "id:" ">"
|
||||
${If} $2 == 0
|
||||
${StrStrAdv} $2 $1 "id: " ">" ">" "0" "0" "0"
|
||||
${Trim} $2 $2
|
||||
StrCpy $MinionName_State $2
|
||||
${EndIf}
|
||||
; Remove registry entries
|
||||
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
|
||||
DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"
|
||||
|
||||
Goto confLoop
|
||||
|
||||
EndOfFile:
|
||||
FileClose $0
|
||||
|
||||
confReallyNotFound:
|
||||
Push $R0
|
||||
Push $R1
|
||||
Push $R2
|
||||
${GetParameters} $R0
|
||||
${GetOptions} $R0 "/master=" $R1
|
||||
${GetOptions} $R0 "/minion-name=" $R2
|
||||
${IfNot} $R1 == ""
|
||||
StrCpy $MasterHost_State $R1
|
||||
${ElseIf} $MasterHost_State == ""
|
||||
StrCpy $MasterHost_State "salt"
|
||||
${EndIf}
|
||||
${IfNot} $R2 == ""
|
||||
StrCpy $MinionName_State $R2
|
||||
${ElseIf} $MinionName_State == ""
|
||||
StrCpy $MinionName_State "hostname"
|
||||
${EndIf}
|
||||
Pop $R2
|
||||
Pop $R1
|
||||
Pop $R0
|
||||
skipUninstall:
|
||||
|
||||
FunctionEnd
|
||||
|
||||
|
|
|
@ -2704,6 +2704,8 @@ def apply_minion_config(overrides=None,
|
|||
if overrides:
|
||||
opts.update(overrides)
|
||||
|
||||
opts['__cli'] = os.path.basename(sys.argv[0])
|
||||
|
||||
if len(opts['sock_dir']) > len(opts['cachedir']) + 10:
|
||||
opts['sock_dir'] = os.path.join(opts['cachedir'], '.salt-unix')
|
||||
|
||||
|
|
|
@ -732,6 +732,8 @@ def _virtual(osdata):
|
|||
)
|
||||
if product.startswith('VMware'):
|
||||
grains['virtual'] = 'VMware'
|
||||
if product.startswith('VirtualBox'):
|
||||
grains['virtual'] = 'VirtualBox'
|
||||
if maker.startswith('Xen'):
|
||||
grains['virtual_subtype'] = '{0} {1}'.format(maker, product)
|
||||
grains['virtual'] = 'xen'
|
||||
|
|
|
@ -879,9 +879,9 @@ def _parse_settings_bond_1(opts, iface, bond_def):
|
|||
|
||||
if 'use_carrier' in opts:
|
||||
if opts['use_carrier'] in _CONFIG_TRUE:
|
||||
bond.update({'use_carrier': 'on'})
|
||||
bond.update({'use_carrier': '1'})
|
||||
elif opts['use_carrier'] in _CONFIG_FALSE:
|
||||
bond.update({'use_carrier': 'off'})
|
||||
bond.update({'use_carrier': '0'})
|
||||
else:
|
||||
valid = _CONFIG_TRUE + _CONFIG_FALSE
|
||||
_raise_error_iface(iface, 'use_carrier', valid)
|
||||
|
@ -962,9 +962,9 @@ def _parse_settings_bond_3(opts, iface, bond_def):
|
|||
|
||||
if 'use_carrier' in opts:
|
||||
if opts['use_carrier'] in _CONFIG_TRUE:
|
||||
bond.update({'use_carrier': 'on'})
|
||||
bond.update({'use_carrier': '1'})
|
||||
elif opts['use_carrier'] in _CONFIG_FALSE:
|
||||
bond.update({'use_carrier': 'off'})
|
||||
bond.update({'use_carrier': '0'})
|
||||
else:
|
||||
valid = _CONFIG_TRUE + _CONFIG_FALSE
|
||||
_raise_error_iface(iface, 'use_carrier', valid)
|
||||
|
@ -1006,9 +1006,9 @@ def _parse_settings_bond_4(opts, iface, bond_def):
|
|||
|
||||
if 'use_carrier' in opts:
|
||||
if opts['use_carrier'] in _CONFIG_TRUE:
|
||||
bond.update({'use_carrier': 'on'})
|
||||
bond.update({'use_carrier': '1'})
|
||||
elif opts['use_carrier'] in _CONFIG_FALSE:
|
||||
bond.update({'use_carrier': 'off'})
|
||||
bond.update({'use_carrier': '0'})
|
||||
else:
|
||||
valid = _CONFIG_TRUE + _CONFIG_FALSE
|
||||
_raise_error_iface(iface, 'use_carrier', valid)
|
||||
|
@ -1049,9 +1049,9 @@ def _parse_settings_bond_5(opts, iface, bond_def):
|
|||
|
||||
if 'use_carrier' in opts:
|
||||
if opts['use_carrier'] in _CONFIG_TRUE:
|
||||
bond.update({'use_carrier': 'on'})
|
||||
bond.update({'use_carrier': '1'})
|
||||
elif opts['use_carrier'] in _CONFIG_FALSE:
|
||||
bond.update({'use_carrier': 'off'})
|
||||
bond.update({'use_carrier': '0'})
|
||||
else:
|
||||
valid = _CONFIG_TRUE + _CONFIG_FALSE
|
||||
_raise_error_iface(iface, 'use_carrier', valid)
|
||||
|
@ -1085,9 +1085,9 @@ def _parse_settings_bond_6(opts, iface, bond_def):
|
|||
|
||||
if 'use_carrier' in opts:
|
||||
if opts['use_carrier'] in _CONFIG_TRUE:
|
||||
bond.update({'use_carrier': 'on'})
|
||||
bond.update({'use_carrier': '1'})
|
||||
elif opts['use_carrier'] in _CONFIG_FALSE:
|
||||
bond.update({'use_carrier': 'off'})
|
||||
bond.update({'use_carrier': '0'})
|
||||
else:
|
||||
valid = _CONFIG_TRUE + _CONFIG_FALSE
|
||||
_raise_error_iface(iface, 'use_carrier', valid)
|
||||
|
|
|
@ -51,16 +51,23 @@ def fire_master(data, tag, preload=None):
|
|||
pass
|
||||
return True
|
||||
|
||||
if preload:
|
||||
if preload or __opts__.get('__cli') == 'salt-call':
|
||||
# If preload is specified, we must send a raw event (this is
|
||||
# slower because it has to independently authenticate)
|
||||
load = preload
|
||||
if 'master_uri' not in __opts__:
|
||||
__opts__['master_uri'] = 'tcp://{ip}:{port}'.format(
|
||||
ip=salt.utils.ip_bracket(__opts__['interface']),
|
||||
port=__opts__.get('ret_port', '4506') # TODO, no fallback
|
||||
)
|
||||
auth = salt.crypt.SAuth(__opts__)
|
||||
load.update({'id': __opts__['id'],
|
||||
load = {'id': __opts__['id'],
|
||||
'tag': tag,
|
||||
'data': data,
|
||||
'tok': auth.gen_token('salt'),
|
||||
'cmd': '_minion_event'})
|
||||
'cmd': '_minion_event'}
|
||||
|
||||
if isinstance(preload, dict):
|
||||
load.update(preload)
|
||||
|
||||
channel = salt.transport.Channel.factory(__opts__)
|
||||
try:
|
||||
|
|
|
@ -29,6 +29,7 @@ import tempfile
|
|||
import time
|
||||
import glob
|
||||
import hashlib
|
||||
import mmap
|
||||
from functools import reduce # pylint: disable=redefined-builtin
|
||||
from collections import Iterable, Mapping
|
||||
|
||||
|
@ -1631,7 +1632,7 @@ def replace(path,
|
|||
pattern,
|
||||
repl,
|
||||
count=0,
|
||||
flags=0,
|
||||
flags=8,
|
||||
bufsize=1,
|
||||
append_if_not_found=False,
|
||||
prepend_if_not_found=False,
|
||||
|
@ -1665,14 +1666,14 @@ def replace(path,
|
|||
A list of flags defined in the :ref:`re module documentation
|
||||
<contents-of-module-re>`. Each list item should be a string that will
|
||||
correlate to the human-friendly flag name. E.g., ``['IGNORECASE',
|
||||
'MULTILINE']``. Note: multiline searches must specify ``file`` as the
|
||||
``bufsize`` argument below.
|
||||
'MULTILINE']``. Optionally, ``flags`` may be an int, with a value
|
||||
corresponding to the XOR (``|``) of all the desired flags. Defaults to
|
||||
8 (which supports 'MULTILINE').
|
||||
bufsize (int or str)
|
||||
How much of the file to buffer into memory at once. The
|
||||
default value ``1`` processes one line at a time. The special value
|
||||
``file`` may be specified which will read the entire file into memory
|
||||
before processing. Note: multiline searches must specify ``file``
|
||||
buffering.
|
||||
before processing.
|
||||
append_if_not_found
|
||||
.. versionadded:: 2014.7.0
|
||||
|
||||
|
@ -1773,8 +1774,9 @@ def replace(path,
|
|||
|
||||
flags_num = _get_flags(flags)
|
||||
cpattern = re.compile(str(pattern), flags_num)
|
||||
filesize = os.path.getsize(path)
|
||||
if bufsize == 'file':
|
||||
bufsize = os.path.getsize(path)
|
||||
bufsize = filesize
|
||||
|
||||
# Search the file; track if any changes have been made for the return val
|
||||
has_changes = False
|
||||
|
@ -1795,55 +1797,57 @@ def replace(path,
|
|||
append_if_not_found) \
|
||||
else repl
|
||||
|
||||
if search_only:
|
||||
# mmap throws a ValueError if the file is empty, but if it is empty we
|
||||
# should be able to skip the search anyway. NOTE: Is there a use case for
|
||||
# searching an empty file with an empty pattern?
|
||||
if filesize is not 0:
|
||||
# First check the whole file, determine whether to make the replacement
|
||||
# Searching first avoids modifying the time stamp if there are no changes
|
||||
try:
|
||||
# allow multiline searching
|
||||
with salt.utils.filebuffer.BufferedReader(path) as breader:
|
||||
for chunk in breader:
|
||||
if re.search(cpattern, chunk):
|
||||
return True
|
||||
return False
|
||||
# Use a read-only handle to open the file
|
||||
with salt.utils.fopen(path,
|
||||
mode='rb',
|
||||
buffering=bufsize) as r_file:
|
||||
r_data = mmap.mmap(r_file.fileno(),
|
||||
0,
|
||||
access=mmap.ACCESS_READ)
|
||||
if search_only:
|
||||
# Just search; bail as early as a match is found
|
||||
if re.search(cpattern, r_data):
|
||||
return True # `with` block handles file closure
|
||||
else:
|
||||
result, nrepl = re.subn(cpattern, repl, r_data, count)
|
||||
|
||||
# found anything? (even if no change)
|
||||
if nrepl > 0:
|
||||
found = True
|
||||
# Identity check the potential change
|
||||
has_changes = True if pattern != repl else has_changes
|
||||
|
||||
if prepend_if_not_found or append_if_not_found:
|
||||
# Search for content, to avoid pre/appending the
|
||||
# content if it was pre/appended in a previous run.
|
||||
if re.search('^{0}$'.format(re.escape(content)),
|
||||
r_data,
|
||||
flags=flags_num):
|
||||
# Content was found, so set found.
|
||||
found = True
|
||||
|
||||
# Keep track of show_changes here, in case the file isn't
|
||||
# modified
|
||||
if show_changes or append_if_not_found or \
|
||||
prepend_if_not_found:
|
||||
orig_file = r_data.read(filesize).splitlines(True)
|
||||
new_file = result.splitlines(True)
|
||||
|
||||
except (OSError, IOError) as exc:
|
||||
raise CommandExecutionError(
|
||||
"Unable to read file '{0}'. Exception: {1}".format(path, exc)
|
||||
"Unable to open file '{0}'. "
|
||||
"Exception: {1}".format(path, exc)
|
||||
)
|
||||
|
||||
# First check the whole file, determine whether to make the replacement
|
||||
# Searching first avoids modifying the time stamp if there are no changes
|
||||
try:
|
||||
# Use a read-only handle to open the file
|
||||
with salt.utils.fopen(path,
|
||||
mode='r',
|
||||
buffering=bufsize) as r_file:
|
||||
for line in r_file:
|
||||
result, nrepl = re.subn(cpattern, repl, line, count)
|
||||
|
||||
# found anything? (even if no change)
|
||||
if nrepl > 0:
|
||||
found = True
|
||||
|
||||
if prepend_if_not_found or append_if_not_found:
|
||||
# Search for content, so we don't continue pre/appending
|
||||
# the content if it's been pre/appended in a previous run.
|
||||
if re.search('^{0}$'.format(re.escape(content)), line):
|
||||
# Content was found, so set found.
|
||||
found = True
|
||||
|
||||
# Identity check each potential change until one change is made
|
||||
if has_changes is False and result != line:
|
||||
has_changes = True
|
||||
|
||||
# Keep track of show_changes here, in case the file isn't
|
||||
# modified
|
||||
if show_changes or append_if_not_found or \
|
||||
prepend_if_not_found:
|
||||
orig_file.append(line)
|
||||
new_file.append(result)
|
||||
|
||||
except (OSError, IOError) as exc:
|
||||
raise CommandExecutionError(
|
||||
"Unable to open file '{0}'. Exception: {1}".format(path, exc)
|
||||
)
|
||||
finally:
|
||||
if r_data and isinstance(r_data, mmap.mmap):
|
||||
r_data.close()
|
||||
|
||||
if has_changes and not dry_run:
|
||||
# Write the replacement text in this block.
|
||||
|
@ -1864,20 +1868,25 @@ def replace(path,
|
|||
with salt.utils.fopen(temp_file,
|
||||
mode='r',
|
||||
buffering=bufsize) as r_file:
|
||||
for line in r_file:
|
||||
result, nrepl = re.subn(cpattern, repl,
|
||||
line, count)
|
||||
try:
|
||||
w_file.write(result)
|
||||
except (OSError, IOError) as exc:
|
||||
raise CommandExecutionError(
|
||||
"Unable to write file '{0}'. Contents may "
|
||||
"be truncated. Temporary file contains copy "
|
||||
"at '{1}'. "
|
||||
"Exception: {2}".format(path, temp_file, exc)
|
||||
)
|
||||
r_data = mmap.mmap(r_file.fileno(),
|
||||
0,
|
||||
access=mmap.ACCESS_READ)
|
||||
result, nrepl = re.subn(cpattern, repl,
|
||||
r_data, count)
|
||||
try:
|
||||
w_file.write(result)
|
||||
except (OSError, IOError) as exc:
|
||||
raise CommandExecutionError(
|
||||
"Unable to write file '{0}'. Contents may "
|
||||
"be truncated. Temporary file contains copy "
|
||||
"at '{1}'. "
|
||||
"Exception: {2}".format(path, temp_file, exc)
|
||||
)
|
||||
except (OSError, IOError) as exc:
|
||||
raise CommandExecutionError("Exception: {0}".format(exc))
|
||||
finally:
|
||||
if r_data and isinstance(r_data, mmap.mmap):
|
||||
r_data.close()
|
||||
except (OSError, IOError) as exc:
|
||||
raise CommandExecutionError("Exception: {0}".format(exc))
|
||||
|
||||
|
@ -2162,7 +2171,7 @@ def blockreplace(path,
|
|||
|
||||
def search(path,
|
||||
pattern,
|
||||
flags=0,
|
||||
flags=8,
|
||||
bufsize=1,
|
||||
ignore_if_missing=False,
|
||||
multiline=False
|
||||
|
|
|
@ -443,7 +443,7 @@ def mkpart(device, part_type, fs_type=None, start=None, end=None):
|
|||
'''
|
||||
_validate_device(device)
|
||||
|
||||
if not start or not end:
|
||||
if start in [None, ''] or end in [None, '']:
|
||||
raise CommandExecutionError(
|
||||
'partition.mkpart requires a start and an end'
|
||||
)
|
||||
|
|
|
@ -322,9 +322,9 @@ def _parse_settings_bond_1(opts, iface, bond_def):
|
|||
|
||||
if 'use_carrier' in opts:
|
||||
if opts['use_carrier'] in _CONFIG_TRUE:
|
||||
bond.update({'use_carrier': 'on'})
|
||||
bond.update({'use_carrier': '1'})
|
||||
elif opts['use_carrier'] in _CONFIG_FALSE:
|
||||
bond.update({'use_carrier': 'off'})
|
||||
bond.update({'use_carrier': '0'})
|
||||
else:
|
||||
valid = _CONFIG_TRUE + _CONFIG_FALSE
|
||||
_raise_error_iface(iface, 'use_carrier', valid)
|
||||
|
@ -405,9 +405,9 @@ def _parse_settings_bond_3(opts, iface, bond_def):
|
|||
|
||||
if 'use_carrier' in opts:
|
||||
if opts['use_carrier'] in _CONFIG_TRUE:
|
||||
bond.update({'use_carrier': 'on'})
|
||||
bond.update({'use_carrier': '1'})
|
||||
elif opts['use_carrier'] in _CONFIG_FALSE:
|
||||
bond.update({'use_carrier': 'off'})
|
||||
bond.update({'use_carrier': '0'})
|
||||
else:
|
||||
valid = _CONFIG_TRUE + _CONFIG_FALSE
|
||||
_raise_error_iface(iface, 'use_carrier', valid)
|
||||
|
@ -449,9 +449,9 @@ def _parse_settings_bond_4(opts, iface, bond_def):
|
|||
|
||||
if 'use_carrier' in opts:
|
||||
if opts['use_carrier'] in _CONFIG_TRUE:
|
||||
bond.update({'use_carrier': 'on'})
|
||||
bond.update({'use_carrier': '1'})
|
||||
elif opts['use_carrier'] in _CONFIG_FALSE:
|
||||
bond.update({'use_carrier': 'off'})
|
||||
bond.update({'use_carrier': '0'})
|
||||
else:
|
||||
valid = _CONFIG_TRUE + _CONFIG_FALSE
|
||||
_raise_error_iface(iface, 'use_carrier', valid)
|
||||
|
@ -492,9 +492,9 @@ def _parse_settings_bond_5(opts, iface, bond_def):
|
|||
|
||||
if 'use_carrier' in opts:
|
||||
if opts['use_carrier'] in _CONFIG_TRUE:
|
||||
bond.update({'use_carrier': 'on'})
|
||||
bond.update({'use_carrier': '1'})
|
||||
elif opts['use_carrier'] in _CONFIG_FALSE:
|
||||
bond.update({'use_carrier': 'off'})
|
||||
bond.update({'use_carrier': '0'})
|
||||
else:
|
||||
valid = _CONFIG_TRUE + _CONFIG_FALSE
|
||||
_raise_error_iface(iface, 'use_carrier', valid)
|
||||
|
@ -528,9 +528,9 @@ def _parse_settings_bond_6(opts, iface, bond_def):
|
|||
|
||||
if 'use_carrier' in opts:
|
||||
if opts['use_carrier'] in _CONFIG_TRUE:
|
||||
bond.update({'use_carrier': 'on'})
|
||||
bond.update({'use_carrier': '1'})
|
||||
elif opts['use_carrier'] in _CONFIG_FALSE:
|
||||
bond.update({'use_carrier': 'off'})
|
||||
bond.update({'use_carrier': '0'})
|
||||
else:
|
||||
valid = _CONFIG_TRUE + _CONFIG_FALSE
|
||||
_raise_error_iface(iface, 'use_carrier', valid)
|
||||
|
|
|
@ -335,7 +335,7 @@ def build_schedule_item(name, **kwargs):
|
|||
schedule[name]['splay'] = kwargs['splay']
|
||||
|
||||
for item in ['range', 'when', 'once', 'once_fmt', 'cron', 'returner',
|
||||
'return_config', 'until']:
|
||||
'return_config', 'until', 'enabled']:
|
||||
if item in kwargs:
|
||||
schedule[name][item] = kwargs[item]
|
||||
|
||||
|
|
|
@ -714,7 +714,7 @@ def list_runner_functions(*args, **kwargs): # pylint: disable=unused-argument
|
|||
|
||||
def list_returners(*args):
|
||||
'''
|
||||
List the runners loaded on the minion
|
||||
List the returners loaded on the minion
|
||||
|
||||
.. versionadded:: 2014.7.0
|
||||
|
||||
|
|
|
@ -1914,6 +1914,14 @@ def mod_repo(repo, basedir=None, **kwargs):
|
|||
del repo_opts[key]
|
||||
todelete.append(key)
|
||||
|
||||
# convert disabled=True to enabled=0 from pkgrepo state
|
||||
if 'disabled' in repo_opts:
|
||||
kw_disabled = repo_opts['disabled']
|
||||
if kw_disabled is True or str(kw_disabled).lower() == 'true':
|
||||
repo_opts['enabled'] = 0
|
||||
del repo_opts['disabled']
|
||||
todelete.append('disabled')
|
||||
|
||||
# Add baseurl or mirrorlist to the 'todelete' list if the other was
|
||||
# specified in the repo_opts
|
||||
if 'mirrorlist' in repo_opts:
|
||||
|
|
|
@ -2453,7 +2453,7 @@ def replace(name,
|
|||
pattern,
|
||||
repl,
|
||||
count=0,
|
||||
flags=0,
|
||||
flags=8,
|
||||
bufsize=1,
|
||||
append_if_not_found=False,
|
||||
prepend_if_not_found=False,
|
||||
|
@ -2480,16 +2480,18 @@ def replace(name,
|
|||
replaced, otherwise all occurrences will be replaced.
|
||||
|
||||
flags
|
||||
A list of flags defined in the :ref:`re module documentation <contents-of-module-re>`.
|
||||
Each list item should be a string that will correlate to the human-friendly flag name.
|
||||
E.g., ``['IGNORECASE', 'MULTILINE']``. Note: multiline searches must specify ``file``
|
||||
as the ``bufsize`` argument below. Defaults to 0 and can be a list or an int.
|
||||
A list of flags defined in the :ref:`re module documentation
|
||||
<contents-of-module-re>`. Each list item should be a string that will
|
||||
correlate to the human-friendly flag name. E.g., ``['IGNORECASE',
|
||||
'MULTILINE']``. Optionally, ``flags`` may be an int, with a value
|
||||
corresponding to the XOR (``|``) of all the desired flags. Defaults to
|
||||
8 (which supports 'MULTILINE').
|
||||
|
||||
bufsize
|
||||
How much of the file to buffer into memory at once. The default value ``1`` processes
|
||||
one line at a time. The special value ``file`` may be specified which will read the
|
||||
entire file into memory before processing. Note: multiline searches must specify ``file``
|
||||
buffering. Can be an int or a str.
|
||||
How much of the file to buffer into memory at once. The default value
|
||||
``1`` processes one line at a time. The special value ``file`` may be
|
||||
specified which will read the entire file into memory before
|
||||
processing.
|
||||
|
||||
append_if_not_found
|
||||
If pattern is not found and set to ``True`` then, the content will be appended to the file.
|
||||
|
|
|
@ -368,27 +368,28 @@ def _find_install_targets(name=None,
|
|||
for name, version in desired.items()
|
||||
if not (name in cur_pkgs and version in (None, cur_pkgs[name]))
|
||||
])
|
||||
problems = _preflight_check(not_installed, **kwargs)
|
||||
comments = []
|
||||
if problems.get('no_suggest'):
|
||||
comments.append(
|
||||
'The following package(s) were not found, and no possible '
|
||||
'matches were found in the package db: '
|
||||
'{0}'.format(', '.join(sorted(problems['no_suggest'])))
|
||||
)
|
||||
if problems.get('suggest'):
|
||||
for pkgname, suggestions in six.iteritems(problems['suggest']):
|
||||
if not_installed:
|
||||
problems = _preflight_check(not_installed, **kwargs)
|
||||
comments = []
|
||||
if problems.get('no_suggest'):
|
||||
comments.append(
|
||||
'Package \'{0}\' not found (possible matches: {1})'
|
||||
.format(pkgname, ', '.join(suggestions))
|
||||
'The following package(s) were not found, and no possible '
|
||||
'matches were found in the package db: '
|
||||
'{0}'.format(', '.join(sorted(problems['no_suggest'])))
|
||||
)
|
||||
if comments:
|
||||
if len(comments) > 1:
|
||||
comments.append('')
|
||||
return {'name': name,
|
||||
'changes': {},
|
||||
'result': False,
|
||||
'comment': '. '.join(comments).rstrip()}
|
||||
if problems.get('suggest'):
|
||||
for pkgname, suggestions in six.iteritems(problems['suggest']):
|
||||
comments.append(
|
||||
'Package \'{0}\' not found (possible matches: {1})'
|
||||
.format(pkgname, ', '.join(suggestions))
|
||||
)
|
||||
if comments:
|
||||
if len(comments) > 1:
|
||||
comments.append('')
|
||||
return {'name': name,
|
||||
'changes': {},
|
||||
'result': False,
|
||||
'comment': '. '.join(comments).rstrip()}
|
||||
|
||||
# Find out which packages will be targeted in the call to pkg.install
|
||||
targets = {}
|
||||
|
|
|
@ -187,6 +187,12 @@ def present(name,
|
|||
ret['comment'] = new_item['comment']
|
||||
return ret
|
||||
|
||||
# The schedule.list gives us an item that is guaranteed to have an
|
||||
# 'enabled' argument. Before comparing, add 'enabled' if it's not
|
||||
# available (assume True, like schedule.list does)
|
||||
if 'enabled' not in new_item:
|
||||
new_item['enabled'] = True
|
||||
|
||||
if new_item == current_schedule[name]:
|
||||
ret['comment'].append('Job {0} in correct state'.format(name))
|
||||
else:
|
||||
|
|
|
@ -113,6 +113,7 @@ class PillarModuleTest(integration.ModuleCase):
|
|||
|
||||
self.assertEqual(grepo.rp_location, repo.remotes.origin.url)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from integration import run_tests
|
||||
run_tests(PillarModuleTest)
|
||||
|
|
Loading…
Add table
Reference in a new issue