mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 17:09:03 +00:00
Merge remote branch 'upstream/develop' into develop
This commit is contained in:
commit
32a3d82595
135
COPYING
Normal file
135
COPYING
Normal file
@ -0,0 +1,135 @@
|
||||
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: salt
|
||||
Upstream-Contact: salt-users@googlegroups.com
|
||||
Source: https://github.com/saltstack/salt
|
||||
|
||||
Files: *
|
||||
Copyright: 2013 SaltStack Team
|
||||
License: Apache-2.0
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
.
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
.
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
.
|
||||
On Debian systems, the full text of the Apache License, Version 2.0 can be
|
||||
found in the file
|
||||
`/usr/share/common-licenses/Apache-2.0'.
|
||||
|
||||
Files: debian/*
|
||||
Copyright: 2013 Joe Healy <joehealy@gmail.com>
|
||||
2012 Michael Prokop <mika@debian.org>
|
||||
2012 Christian Hofstaedtler <christian@hofstaedtler.name>
|
||||
2012 Ulrich Dangel <mru@spamt.net>
|
||||
2012 Corey Quinn <corey@sequestered.net>
|
||||
2011 Aaron Toponce <aaron.toponce@gmail.com>
|
||||
License: Apache-2.0
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
.
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
.
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
.
|
||||
On Debian systems, the full text of the Apache License, Version 2.0 can be
|
||||
found in the file
|
||||
`/usr/share/common-licenses/Apache-2.0'.
|
||||
|
||||
Files: salt/auth/pam.py
|
||||
Copyright: 2007 Chris AtLee <chris@atlee.ca>
|
||||
License: MIT License
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
.
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
Files: salt/utils/ipaddr.py
|
||||
Copyright: 2007 Google Inc.
|
||||
License: Apache-2.0
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
.
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
.
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
.
|
||||
On Debian systems, the full text of the Apache License, Version 2.0 can be
|
||||
found in the file
|
||||
`/usr/share/common-licenses/Apache-2.0'.
|
||||
|
||||
Files: doc/_ext/youtube.py
|
||||
Copyright: 2009 Chris Pickel <sfiera@gmail.com>
|
||||
License: BSD-2-clause
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
.
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
Files: doc/_ext/images
|
||||
Copyright: 2013 SaltStack Team
|
||||
License: Apache-2.0
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
.
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
.
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
.
|
||||
On Debian systems, the full text of the Apache License, Version 2.0 can be
|
||||
found in the file
|
||||
`/usr/share/common-licenses/Apache-2.0'.
|
||||
.
|
||||
Files in this directory were created in-house.
|
@ -383,7 +383,14 @@ Finally you use setup.py to run the tests with the following command:
|
||||
|
||||
./setup.py test
|
||||
|
||||
For greater control while running the tests, please try:
|
||||
For greater control while running the tests, please try something like:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
./tests/runtests.py -n integration.modules.virt -vv
|
||||
./tests/runtests.py -n unit.modules.virt_test -vv
|
||||
|
||||
Also see the help for all options:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
|
@ -193,6 +193,8 @@ and run NSIS.
|
||||
|
||||
The NSIS installer can be found here: http://nsis.sourceforge.net/Main_Page
|
||||
|
||||
You also need the nsProcess plugin for NSIS. It can be found here: http://nsis.sourceforge.net/NsProcess_plugin
|
||||
|
||||
|
||||
Testing the Salt minion
|
||||
=======================
|
||||
|
@ -2,6 +2,13 @@
|
||||
Salt 0.17.1 Release Notes
|
||||
=========================
|
||||
|
||||
.. note::
|
||||
|
||||
THIS RELEASE IS NOT COMPATIBLE WITH PREVIOUS VERSIONS. If you update your
|
||||
master to 0.17.1, you must update your minions as well. Sorry for the
|
||||
inconvenience -- this is a result of one of the security fixes listed
|
||||
below.
|
||||
|
||||
The 0.17.1 release comes with a number of improvements to salt-ssh, many
|
||||
bugfixes, and a number of security updates.
|
||||
|
||||
|
@ -26,16 +26,6 @@
|
||||
# processname: /usr/bin/salt-master
|
||||
|
||||
|
||||
if [ -f /etc/default/salt ]; then
|
||||
. /etc/default/salt
|
||||
else
|
||||
SALTMASTER=/usr/bin/salt-master
|
||||
PYTHON=/usr/bin/python
|
||||
fi
|
||||
|
||||
# Sanity checks.
|
||||
[ -x $SALTMASTER ] || exit 0
|
||||
|
||||
DEBIAN_VERSION=/etc/debian_version
|
||||
SUSE_RELEASE=/etc/SuSE-release
|
||||
# Source function library.
|
||||
@ -47,27 +37,35 @@ else
|
||||
. /etc/rc.d/init.d/functions
|
||||
fi
|
||||
|
||||
# Default values (can be overridden below)
|
||||
SALTMASTER=/usr/bin/salt-master
|
||||
PYTHON=/usr/bin/python
|
||||
MASTER_ARGS=""
|
||||
|
||||
if [ -f /etc/default/salt ]; then
|
||||
. /etc/default/salt
|
||||
fi
|
||||
|
||||
SERVICE=salt-master
|
||||
PROCESS=salt-master
|
||||
CONFIG_ARGS=" "
|
||||
|
||||
RETVAL=0
|
||||
|
||||
start() {
|
||||
echo -n $"Starting salt-master daemon: "
|
||||
if [ -f $SUSE_RELEASE ]; then
|
||||
startproc -f -p /var/run/$SERVICE.pid $SALTMASTER -d $CONFIG_ARGS
|
||||
startproc -f -p /var/run/$SERVICE.pid $SALTMASTER -d $MASTER_ARGS
|
||||
rc_status -v
|
||||
elif [ -e $DEBIAN_VERSION ]; then
|
||||
if [ -f $LOCKFILE ]; then
|
||||
echo -n "already started, lock file found"
|
||||
RETVAL=1
|
||||
elif $PYTHON $SALTMASTER -d >& /dev/null; then
|
||||
elif $PYTHON $SALTMASTER -d $MASTER_ARGS >& /dev/null; then
|
||||
echo -n "OK"
|
||||
RETVAL=0
|
||||
fi
|
||||
else
|
||||
daemon --check $SERVICE $SALTMASTER -d $CONFIG_ARGS
|
||||
daemon --check $SERVICE $SALTMASTER -d $MASTER_ARGS
|
||||
fi
|
||||
RETVAL=$?
|
||||
echo
|
||||
@ -100,7 +98,6 @@ restart() {
|
||||
start
|
||||
}
|
||||
|
||||
|
||||
# See how we were called.
|
||||
case "$1" in
|
||||
start|stop|restart)
|
||||
@ -129,11 +126,7 @@ case "$1" in
|
||||
;;
|
||||
reload)
|
||||
echo "can't reload configuration, you have to restart it"
|
||||
if [ -f $SUSE_RELEASE ]; then
|
||||
rc_status -v
|
||||
else
|
||||
RETVAL=$?
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo $"Usage: $0 {start|stop|status|restart|condrestart|reload}"
|
||||
@ -141,4 +134,3 @@ case "$1" in
|
||||
;;
|
||||
esac
|
||||
exit $RETVAL
|
||||
|
||||
|
@ -14,7 +14,8 @@
|
||||
# Default-Start: 3 5
|
||||
# Default-Stop: 0 1 2 6
|
||||
# Short-Description: Salt minion daemon
|
||||
# Description: This is the Salt minion daemon that can be controlled by the Salt master.
|
||||
# Description: This is the Salt minion daemon that can be controlled by the
|
||||
# Salt master.
|
||||
### END INIT INFO
|
||||
|
||||
|
||||
@ -26,16 +27,6 @@
|
||||
# processname: /usr/bin/salt-minion
|
||||
|
||||
|
||||
if [ -f /etc/default/salt ]; then
|
||||
. /etc/default/salt
|
||||
else
|
||||
SALTMINION=/usr/bin/salt-minion
|
||||
PYTHON=/usr/bin/python
|
||||
fi
|
||||
|
||||
# Sanity checks.
|
||||
[ -x $SALTMINION ] || exit 0
|
||||
|
||||
DEBIAN_VERSION=/etc/debian_version
|
||||
SUSE_RELEASE=/etc/SuSE-release
|
||||
# Source function library.
|
||||
@ -47,22 +38,30 @@ else
|
||||
. /etc/rc.d/init.d/functions
|
||||
fi
|
||||
|
||||
# Default values (can be overridden below)
|
||||
SALTMINION=/usr/bin/salt-minion
|
||||
PYTHON=/usr/bin/python
|
||||
MINION_ARGS=""
|
||||
|
||||
if [ -f /etc/default/salt ]; then
|
||||
. /etc/default/salt
|
||||
fi
|
||||
|
||||
SERVICE=salt-minion
|
||||
PROCESS=salt-minion
|
||||
CONFIG_ARGS=" "
|
||||
|
||||
RETVAL=0
|
||||
|
||||
start() {
|
||||
echo -n $"Starting salt-minion daemon: "
|
||||
if [ -f $SUSE_RELEASE ]; then
|
||||
startproc -f -p /var/run/$SERVICE.pid $SALTMINION -d $CONFIG_ARGS
|
||||
startproc -f -p /var/run/$SERVICE.pid $SALTMINION -d $MINION_ARGS
|
||||
rc_status -v
|
||||
elif [ -e $DEBIAN_VERSION ]; then
|
||||
if [ -f $LOCKFILE ]; then
|
||||
echo -n "already started, lock file found"
|
||||
RETVAL=1
|
||||
elif $PYTHON $SALTMINION -d >& /dev/null; then
|
||||
elif $PYTHON $SALTMINION -d $MINION_ARGS >& /dev/null; then
|
||||
echo -n "OK"
|
||||
RETVAL=0
|
||||
fi
|
||||
@ -71,7 +70,7 @@ start() {
|
||||
RETVAL=$?
|
||||
echo -n "already running"
|
||||
else
|
||||
daemon --check $SERVICE $SALTMINION -d $CONFIG_ARGS
|
||||
daemon --check $SERVICE $SALTMINION -d $MINION_ARGS
|
||||
RETVAL=$?
|
||||
fi
|
||||
fi
|
||||
@ -133,11 +132,7 @@ case "$1" in
|
||||
;;
|
||||
reload)
|
||||
echo "can't reload configuration, you have to restart it"
|
||||
if [ -f $SUSE_RELEASE ]; then
|
||||
rc_status -v
|
||||
else
|
||||
RETVAL=$?
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo $"Usage: $0 {start|stop|status|restart|condrestart|reload}"
|
||||
|
@ -14,28 +14,19 @@
|
||||
# Default-Start: 3 5
|
||||
# Default-Stop: 0 1 2 6
|
||||
# Short-Description: Salt syndic master-minion passthrough daemon
|
||||
# Description: This is a the Salt syndic daemon that enables Salt master-minion remote control passthrough.
|
||||
# Description: This is a the Salt syndic daemon that enables Salt master-minion
|
||||
# remote control passthrough.
|
||||
### END INIT INFO
|
||||
|
||||
|
||||
# chkconfig header
|
||||
|
||||
# chkconfig: 345 99 99
|
||||
# chkconfig: - 99 99
|
||||
# description: This is a the Salt syndic daemon that enables Salt master-minion remote control passthrough.
|
||||
#
|
||||
# processname: /usr/bin/salt-syndic
|
||||
|
||||
|
||||
if [ -f /etc/default/salt ]; then
|
||||
. /etc/default/salt
|
||||
else
|
||||
SALTSYNDIC=/usr/bin/salt-syndic
|
||||
PYTHON=/usr/bin/python
|
||||
fi
|
||||
|
||||
# Sanity checks.
|
||||
[ -x $SALTSYNDIC ] || exit 0
|
||||
|
||||
DEBIAN_VERSION=/etc/debian_version
|
||||
SUSE_RELEASE=/etc/SuSE-release
|
||||
# Source function library.
|
||||
@ -47,27 +38,35 @@ else
|
||||
. /etc/rc.d/init.d/functions
|
||||
fi
|
||||
|
||||
# Default values (can be overridden below)
|
||||
SALTSYNDIC=/usr/bin/salt-syndic
|
||||
PYTHON=/usr/bin/python
|
||||
SYNDIC_ARGS=""
|
||||
|
||||
if [ -f /etc/default/salt ]; then
|
||||
. /etc/default/salt
|
||||
fi
|
||||
|
||||
SERVICE=salt-syndic
|
||||
PROCESS=salt-syndic
|
||||
CONFIG_ARGS=" "
|
||||
|
||||
RETVAL=0
|
||||
|
||||
start() {
|
||||
echo -n $"Starting salt-syndic daemon: "
|
||||
if [ -f $SUSE_RELEASE ]; then
|
||||
startproc -f -p /var/run/$SERVICE.pid $SALTSYNDIC -d $CONFIG_ARGS
|
||||
startproc -f -p /var/run/$SERVICE.pid $SALTSYNDIC -d $SYNDIC_ARGS
|
||||
rc_status -v
|
||||
elif [ -e $DEBIAN_VERSION ]; then
|
||||
if [ -f $LOCKFILE ]; then
|
||||
echo -n "already started, lock file found"
|
||||
RETVAL=1
|
||||
elif $PYTHON $SALTSYNDIC -d >& /dev/null; then
|
||||
elif $PYTHON $SALTSYNDIC -d $SYNDIC_ARGS >& /dev/null; then
|
||||
echo -n "OK"
|
||||
RETVAL=0
|
||||
fi
|
||||
else
|
||||
daemon --check $SERVICE $SALTSYNDIC -d $CONFIG_ARGS
|
||||
daemon --check $SERVICE $SALTSYNDIC -d $SYNDIC_ARGS
|
||||
fi
|
||||
RETVAL=$?
|
||||
echo
|
||||
@ -123,18 +122,16 @@ case "$1" in
|
||||
RETVAL=$?
|
||||
fi
|
||||
;;
|
||||
condrestart)
|
||||
[ -f $LOCKFILE ] && restart || :
|
||||
;;
|
||||
reload)
|
||||
echo "can't reload configuration, you have to restart it"
|
||||
if [ -f $SUSE_RELEASE ]; then
|
||||
rc_status -v
|
||||
else
|
||||
RETVAL=$?
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo $"Usage: $0 {start|stop|status|restart|reload}"
|
||||
echo $"Usage: $0 {start|stop|status|restart|condrestart|reload}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
exit $RETVAL
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
#
|
||||
|
||||
Name: salt
|
||||
Version: 0.17.0
|
||||
Version: 0.17.1
|
||||
Release: 0
|
||||
Summary: A parallel remote execution system
|
||||
License: Apache-2.0
|
||||
@ -31,10 +31,8 @@ Source5: %{name}-syndic.service
|
||||
Source6: %{name}-minion.service
|
||||
Source7: %{name}.logrotate
|
||||
Source8: %{name}.SuSEfirewall2
|
||||
%if 0%{?sles_version}
|
||||
BuildRequires: python
|
||||
Requires: python
|
||||
%endif
|
||||
|
||||
#for building
|
||||
BuildRequires: python-devel
|
||||
BuildRequires: logrotate
|
||||
BuildRequires: python-Jinja2
|
||||
@ -42,18 +40,32 @@ BuildRequires: python-M2Crypto
|
||||
BuildRequires: python-PyYAML
|
||||
BuildRequires: python-msgpack-python
|
||||
BuildRequires: python-pycrypto
|
||||
BuildRequires: python-pyzmq >= 2.1.9
|
||||
BuildRequires: unzip
|
||||
Requires: logrotate
|
||||
Requires: python-Jinja2
|
||||
Requires: python-PyYAML
|
||||
Requires: python-Sphinx
|
||||
Requires(pre): %fillup_prereq
|
||||
Requires(pre): %insserv_prereq
|
||||
BuildRequires: python-pyzmq
|
||||
%if 0%{?sles_version}
|
||||
BuildRequires: python
|
||||
Requires: python
|
||||
%endif
|
||||
%if 0%{?suse_version} >= 1210
|
||||
BuildRequires: systemd
|
||||
%{?systemd_requires}
|
||||
%endif
|
||||
|
||||
#for testing
|
||||
BuildRequires: python-xml
|
||||
BuildRequires: python-unittest2
|
||||
BuildRequires: python-salt-testing
|
||||
BuildRequires: python-mock
|
||||
BuildRequires: python-pip
|
||||
|
||||
Requires: logrotate
|
||||
Requires: python-Jinja2
|
||||
Requires: python-PyYAML
|
||||
Requires: python-xml
|
||||
Requires(pre): %fillup_prereq
|
||||
%if 0%{?suse_version} < 1210
|
||||
Requires(pre): %insserv_prereq
|
||||
%endif
|
||||
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
%if 0%{?suse_version} && 0%{?suse_version} <= 1110
|
||||
%{!?python_sitelib: %global python_sitelib %(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
|
||||
@ -61,16 +73,6 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
BuildArch: noarch
|
||||
%endif
|
||||
|
||||
## Disabled for now python-mock issues
|
||||
%if 0%{?suse_version} != 1220 && 0%{?suse_version} != 1230
|
||||
BuildRequires: python-unittest2
|
||||
BuildRequires: python-salt-testing
|
||||
BuildRequires: python-xml
|
||||
BuildRequires: python-mock
|
||||
BuildRequires: python-pip
|
||||
BuildRequires: git
|
||||
%endif
|
||||
|
||||
%description
|
||||
Salt is a distributed remote execution system used to execute commands and
|
||||
query data. It was developed in order to bring the best solutions found in
|
||||
@ -83,8 +85,7 @@ servers, handle them quickly and through a simple and manageable interface.
|
||||
Summary: Management component for salt, a parallel remote execution system
|
||||
Group: System/Monitoring
|
||||
Requires: %{name} = %{version}
|
||||
Requires: zeromq >= 3.2
|
||||
Requires: python-pyzmq >= 2.10
|
||||
Requires: python-pyzmq
|
||||
Requires: python-M2Crypto
|
||||
Requires: python-msgpack-python
|
||||
Requires: python-pycrypto
|
||||
@ -96,8 +97,11 @@ Requires: dmidecode
|
||||
%endif
|
||||
%endif
|
||||
Recommends: python-halite
|
||||
Requires(pre): %fillup_prereq
|
||||
%if 0%{?suse_version} < 1210
|
||||
Requires(pre): %insserv_prereq
|
||||
%endif
|
||||
Requires(pre): %fillup_prereq
|
||||
|
||||
|
||||
%description master
|
||||
The Salt master is the central server to which all minions connect.
|
||||
@ -108,13 +112,14 @@ than serially.
|
||||
Summary: Client component for salt, a parallel remote execution system
|
||||
Group: System/Monitoring
|
||||
Requires: %{name} = %{version}
|
||||
Requires: zeromq >= 3.2
|
||||
Requires: python-pyzmq >= 2.10
|
||||
Requires: python-pyzmq
|
||||
Requires: python-M2Crypto
|
||||
Requires: python-msgpack-python
|
||||
Requires: python-pycrypto
|
||||
Requires(pre): %fillup_prereq
|
||||
%if 0%{?suse_version} < 1210
|
||||
Requires(pre): %insserv_prereq
|
||||
%endif
|
||||
Requires(pre): %fillup_prereq
|
||||
|
||||
%description minion
|
||||
Salt minion is queried and controlled from the master.
|
||||
@ -125,8 +130,10 @@ Summary: Syndic component for salt, a parallel remote execution system
|
||||
Group: System/Monitoring
|
||||
Requires: %{name} = %{version}
|
||||
Requires: %{name}-master = %{version}
|
||||
Requires(pre): %fillup_prereq
|
||||
%if 0%{?suse_version} < 1210
|
||||
Requires(pre): %insserv_prereq
|
||||
%endif
|
||||
Requires(pre): %fillup_prereq
|
||||
|
||||
%description syndic
|
||||
Salt syndic is the master-of-masters for salt
|
||||
@ -137,9 +144,13 @@ the management of multiple masters at a time..
|
||||
Summary: Ssh component for salt, a parallel remote execution system
|
||||
Group: System/Monitoring
|
||||
Requires: %{name} = %{version}
|
||||
Requires: sshpass
|
||||
Requires(pre): %fillup_prereq
|
||||
BuildRequires: python-markupsafe
|
||||
Requires: python-markupsafe
|
||||
Recommends: sshpass
|
||||
%if 0%{?suse_version} < 1210
|
||||
Requires(pre): %insserv_prereq
|
||||
%endif
|
||||
Requires(pre): %fillup_prereq
|
||||
|
||||
%description ssh
|
||||
Salt ssh is a master running without zmq.
|
||||
@ -154,10 +165,12 @@ python setup.py build
|
||||
%install
|
||||
python setup.py install --prefix=%{_prefix} --root=%{buildroot}
|
||||
|
||||
##missing directories
|
||||
## create missing directories
|
||||
mkdir -p %{buildroot}%{_sysconfdir}/salt/master.d
|
||||
mkdir -p %{buildroot}%{_sysconfdir}/salt/minion.d
|
||||
%if 0%{?suse_version} < 1210
|
||||
mkdir -p %{buildroot}%{_sysconfdir}/init.d
|
||||
%endif
|
||||
mkdir -p %{buildroot}%{_localstatedir}/log/salt
|
||||
mkdir -p %{buildroot}/%{_sysconfdir}/logrotate.d/
|
||||
mkdir -p %{buildroot}/%{_sbindir}
|
||||
@ -165,92 +178,102 @@ mkdir -p %{buildroot}/var/log/salt
|
||||
mkdir -p %{buildroot}/srv/salt
|
||||
mkdir -p %{buildroot}/srv/pillar
|
||||
#
|
||||
##init scripts
|
||||
## install init scripts
|
||||
%if 0%{?_unitdir:1}
|
||||
install -Dpm 0644 %{SOURCE4} %{buildroot}%_unitdir/salt-master.service
|
||||
install -Dpm 0644 %{SOURCE5} %{buildroot}%_unitdir/salt-syndic.service
|
||||
install -Dpm 0644 %{SOURCE6} %{buildroot}%_unitdir/salt-minion.service
|
||||
%else
|
||||
install -Dpm 0755 %{SOURCE1} %{buildroot}%{_initddir}/salt-master
|
||||
install -Dpm 0755 %{SOURCE2} %{buildroot}%{_initddir}/salt-syndic
|
||||
install -Dpm 0755 %{SOURCE3} %{buildroot}%{_initddir}/salt-minion
|
||||
ln -sf %{_initddir}/salt-master %{buildroot}%{_sbindir}/rcsalt-master
|
||||
ln -sf %{_initddir}/salt-syndic %{buildroot}%{_sbindir}/rcsalt-syndic
|
||||
ln -sf %{_initddir}/salt-minion %{buildroot}%{_sbindir}/rcsalt-minion
|
||||
|
||||
%if 0%{?_unitdir:1}
|
||||
install -Dpm 0644 %{SOURCE4} %{buildroot}%_unitdir/salt-master.service
|
||||
install -Dpm 0644 %{SOURCE5} %{buildroot}%_unitdir/salt-syndic.service
|
||||
install -Dpm 0644 %{SOURCE6} %{buildroot}%_unitdir/salt-minion.service
|
||||
%endif
|
||||
|
||||
#
|
||||
##config files
|
||||
## install config files
|
||||
install -Dpm 0644 conf/minion %{buildroot}%{_sysconfdir}/salt/minion
|
||||
install -Dpm 0644 conf/master %{buildroot}%{_sysconfdir}/salt/master
|
||||
#
|
||||
##logrotate file
|
||||
## install logrotate file
|
||||
install -Dpm 0644 %{SOURCE7} %{buildroot}%{_sysconfdir}/logrotate.d/salt
|
||||
#
|
||||
##SuSEfirewall2 file
|
||||
## install SuSEfirewall2 rules
|
||||
install -Dpm 0644 %{SOURCE8} %{buildroot}%{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/salt
|
||||
|
||||
%if 0%{?suse_version} != 1220 && 0%{?suse_version} != 1230
|
||||
%check
|
||||
#export only_local_network=False
|
||||
%{__python} setup.py test --runtests-opts=-u
|
||||
%endif
|
||||
|
||||
%preun -n salt-syndic
|
||||
%stop_on_removal salt-syndic
|
||||
%if 0%{?_unitdir:1}
|
||||
%service_del_preun salt-syndic.service
|
||||
%else
|
||||
%stop_on_removal salt-syndic
|
||||
%endif
|
||||
|
||||
%post -n salt-syndic
|
||||
%fillup_and_insserv
|
||||
%if 0%{?_unitdir:1}
|
||||
%service_add_post salt-syndic.service
|
||||
%fillup_only
|
||||
%else
|
||||
%fillup_and_insserv
|
||||
%endif
|
||||
|
||||
%postun -n salt-syndic
|
||||
%restart_on_update salt-syndic
|
||||
%if 0%{?_unitdir:1}
|
||||
%service_del_postun salt-syndic.service
|
||||
%endif
|
||||
%else
|
||||
%insserv_cleanup
|
||||
%restart_on_update salt-syndic
|
||||
%endif
|
||||
|
||||
%preun -n salt-master
|
||||
%stop_on_removal salt-master
|
||||
%if 0%{?_unitdir:1}
|
||||
%service_del_preun salt-master.service
|
||||
%else
|
||||
%stop_on_removal salt-master
|
||||
%endif
|
||||
|
||||
%post -n salt-master
|
||||
%fillup_and_insserv
|
||||
%if 0%{?_unitdir:1}
|
||||
%service_add_post salt-master.service
|
||||
%fillup_only
|
||||
%else
|
||||
%fillup_and_insserv
|
||||
%endif
|
||||
|
||||
%postun -n salt-master
|
||||
%restart_on_update salt-master
|
||||
%if 0%{?_unitdir:1}
|
||||
%service_del_postun salt-master.service
|
||||
%endif
|
||||
%else
|
||||
%restart_on_update salt-master
|
||||
%insserv_cleanup
|
||||
%endif
|
||||
|
||||
%preun -n salt-minion
|
||||
%stop_on_removal salt-minion
|
||||
%if 0%{?_unitdir:1}
|
||||
%service_del_preun salt-minion.service
|
||||
%else
|
||||
%stop_on_removal salt-minion
|
||||
%endif
|
||||
|
||||
%post -n salt-minion
|
||||
%fillup_and_insserv
|
||||
%if 0%{?_unitdir:1}
|
||||
%service_add_post salt-minion.service
|
||||
%fillup_only
|
||||
%else
|
||||
%fillup_and_insserv
|
||||
%endif
|
||||
|
||||
%postun -n salt-minion
|
||||
%restart_on_update salt-minion
|
||||
%if 0%{?_unitdir:1}
|
||||
%service_del_postun salt-minion.service
|
||||
%endif
|
||||
%else
|
||||
%insserv_cleanup
|
||||
%restart_on_update salt-minion
|
||||
%endif
|
||||
|
||||
%files -n salt-ssh
|
||||
%defattr(-,root,root)
|
||||
@ -261,22 +284,24 @@ install -Dpm 0644 %{SOURCE8} %{buildroot}%{_sysconfdir}/sysconfig/SuSEfirewall2
|
||||
%defattr(-,root,root)
|
||||
%{_bindir}/salt-syndic
|
||||
%{_mandir}/man1/salt-syndic.1.gz
|
||||
%{_sbindir}/rcsalt-syndic
|
||||
%{_sysconfdir}/init.d/salt-syndic
|
||||
%if 0%{?_unitdir:1}
|
||||
%_unitdir/salt-syndic.service
|
||||
%else
|
||||
%{_sbindir}/rcsalt-syndic
|
||||
%{_sysconfdir}/init.d/salt-syndic
|
||||
%endif
|
||||
|
||||
%files -n salt-minion
|
||||
%defattr(-,root,root)
|
||||
%{_bindir}/salt-minion
|
||||
%{_mandir}/man1/salt-minion.1.gz
|
||||
%{_sbindir}/rcsalt-minion
|
||||
%config(noreplace) %{_sysconfdir}/init.d/salt-minion
|
||||
%attr(0644, root, root) %config(noreplace) %{_sysconfdir}/salt/minion
|
||||
%{_sysconfdir}/salt/minion.d
|
||||
%if 0%{?_unitdir:1}
|
||||
%_unitdir/salt-minion.service
|
||||
%else
|
||||
%{_sbindir}/rcsalt-minion
|
||||
%config(noreplace) %{_sysconfdir}/init.d/salt-minion
|
||||
%endif
|
||||
|
||||
%files -n salt-master
|
||||
@ -291,8 +316,6 @@ install -Dpm 0644 %{SOURCE8} %{buildroot}%{_sysconfdir}/sysconfig/SuSEfirewall2
|
||||
%{_mandir}/man1/salt-cp.1.gz
|
||||
%{_mandir}/man1/salt-key.1.gz
|
||||
%{_mandir}/man1/salt-run.1.gz
|
||||
%{_sbindir}/rcsalt-master
|
||||
%config(noreplace) %{_sysconfdir}/init.d/salt-master
|
||||
%config(noreplace) %{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/salt
|
||||
%attr(0644, root, root) %config(noreplace) %{_sysconfdir}/salt/master
|
||||
%{_sysconfdir}/salt/master.d
|
||||
@ -300,6 +323,9 @@ install -Dpm 0644 %{SOURCE8} %{buildroot}%{_sysconfdir}/sysconfig/SuSEfirewall2
|
||||
%dir /srv/pillar
|
||||
%if 0%{?_unitdir:1}
|
||||
%_unitdir/salt-master.service
|
||||
%else
|
||||
%{_sbindir}/rcsalt-master
|
||||
%config(noreplace) %{_sysconfdir}/init.d/salt-master
|
||||
%endif
|
||||
|
||||
%files
|
||||
|
@ -170,7 +170,7 @@ class SSH(object):
|
||||
if deploy.startswith(('n', 'N')):
|
||||
return ret
|
||||
target['passwd'] = getpass.getpass(
|
||||
'Password for {0}@{1}:'.format(host, target['user'])
|
||||
'Password for {0}@{1}:'.format(target['user'], host)
|
||||
)
|
||||
return self._key_deploy_run(host, target, True)
|
||||
return ret
|
||||
|
@ -664,7 +664,7 @@ def syndic_config(master_config_path,
|
||||
return opts
|
||||
|
||||
|
||||
def get_id(root_dir=None):
|
||||
def get_id(root_dir=None, minion_id=False):
|
||||
'''
|
||||
Guess the id of the minion.
|
||||
|
||||
@ -704,6 +704,7 @@ def get_id(root_dir=None):
|
||||
fqdn = socket.getfqdn()
|
||||
if fqdn != 'localhost':
|
||||
log.info('Found minion id from getfqdn(): {0}'.format(fqdn))
|
||||
if minion_id:
|
||||
try:
|
||||
with salt.utils.fopen(id_cache, 'w') as idf:
|
||||
idf.write(fqdn)
|
||||
@ -720,6 +721,7 @@ def get_id(root_dir=None):
|
||||
'This file should not contain any whitespace.')
|
||||
else:
|
||||
if name != 'localhost':
|
||||
if minion_id:
|
||||
try:
|
||||
with salt.utils.fopen(id_cache, 'w') as idf:
|
||||
idf.write(name)
|
||||
@ -740,6 +742,7 @@ def get_id(root_dir=None):
|
||||
if name != 'localhost':
|
||||
log.info('Found minion id in hosts file: {0}'
|
||||
.format(name))
|
||||
if minion_id:
|
||||
try:
|
||||
with salt.utils.fopen(id_cache, 'w') as idf:
|
||||
idf.write(name)
|
||||
@ -766,6 +769,7 @@ def get_id(root_dir=None):
|
||||
if name != 'localhost':
|
||||
log.info('Found minion id in hosts file: {0}'
|
||||
.format(name))
|
||||
if minion_id:
|
||||
try:
|
||||
with salt.utils.fopen(id_cache, 'w') as idf:
|
||||
idf.write(name)
|
||||
@ -830,8 +834,9 @@ def apply_minion_config(overrides=None,
|
||||
|
||||
# No ID provided. Will getfqdn save us?
|
||||
using_ip_for_id = False
|
||||
if opts['id'] is None and minion_id:
|
||||
opts['id'], using_ip_for_id = get_id(opts['root_dir'])
|
||||
if opts['id'] is None:
|
||||
opts['id'], using_ip_for_id = get_id(opts['root_dir'],
|
||||
minion_id=minion_id)
|
||||
|
||||
# it does not make sense to append a domain to an IP based id
|
||||
if not using_ip_for_id and 'append_domain' in opts:
|
||||
|
@ -142,3 +142,42 @@ def inodeusage(args=None):
|
||||
log.warn("Problem parsing inode usage information")
|
||||
ret = {}
|
||||
return ret
|
||||
|
||||
|
||||
def percent(args=None):
|
||||
'''
|
||||
Return partion information for volumes mounted on this minion
|
||||
|
||||
CLI Example::
|
||||
|
||||
salt '*' disk.percent /var
|
||||
'''
|
||||
if __grains__['kernel'] == 'Linux':
|
||||
cmd = 'df -P'
|
||||
elif __grains__['kernel'] == 'OpenBSD':
|
||||
cmd = 'df -kP'
|
||||
else:
|
||||
cmd = 'df'
|
||||
ret = {}
|
||||
out = __salt__['cmd.run'](cmd).splitlines()
|
||||
for line in out:
|
||||
if not line:
|
||||
continue
|
||||
if line.startswith('Filesystem'):
|
||||
continue
|
||||
comps = line.split()
|
||||
while not comps[1].isdigit():
|
||||
comps[0] = '{0} {1}'.format(comps[0], comps[1])
|
||||
comps.pop(1)
|
||||
try:
|
||||
if __grains__['kernel'] == 'Darwin':
|
||||
ret[comps[8]] = comps[4]
|
||||
else:
|
||||
ret[comps[5]] = comps[4]
|
||||
except IndexError:
|
||||
log.warn("Problem parsing disk usage information")
|
||||
ret = {}
|
||||
if args:
|
||||
return ret[args]
|
||||
else:
|
||||
return ret
|
||||
|
@ -40,6 +40,7 @@ except ImportError:
|
||||
import salt.utils
|
||||
import salt.utils.find
|
||||
import salt.utils.filebuffer
|
||||
import salt.utils.atomicfile
|
||||
from salt.exceptions import CommandExecutionError, SaltInvocationError
|
||||
import salt._compat
|
||||
|
||||
@ -989,6 +990,154 @@ def replace(path,
|
||||
return has_changes
|
||||
|
||||
|
||||
def blockreplace(path,
|
||||
marker_start='#-- start managed zone --',
|
||||
marker_end='#-- end managed zone --',
|
||||
content='',
|
||||
append_if_not_found=False,
|
||||
backup='.bak',
|
||||
dry_run=False,
|
||||
show_changes=True,
|
||||
):
|
||||
'''
|
||||
Replace content of a text block in a file, delimited by line markers
|
||||
|
||||
.. versionadded:: 0.18.0
|
||||
|
||||
A block of content delimited by comments can help you manage several lines entries without
|
||||
worrying about old entries removal.
|
||||
Note: this function will store two copies of the file in-memory
|
||||
(the original version and the edited version) in order to detect changes
|
||||
and only edit the targeted file if necessary.
|
||||
|
||||
:param path: Filesystem path to the file to be edited
|
||||
:param marker_start: The line content identifying a line as the start of
|
||||
the content block. Note that the whole line containing this marker will
|
||||
be considered, so whitespaces or extra content before or after the
|
||||
marker is included in final output
|
||||
:param marker_end: The line content identifying a line as the end of
|
||||
the content block. Note that the whole line containing this marker will
|
||||
be considered, so whitespaces or extra content before or after the
|
||||
marker is included in final output
|
||||
:param content: The content to be used between the two lines identified by
|
||||
marker_start and marker_stop.
|
||||
:param append_if_not_found: False by default, if markers are not found and
|
||||
set to True then the markers and content will be appended to the file
|
||||
:param backup: The file extension to use for a backup of the file if any
|
||||
edit is made. Set to ``False`` to skip making a backup.
|
||||
:param dry_run: Don't make any edits to the file
|
||||
:param show_changes: Output a unified diff of the old file and the new
|
||||
file. If ``False`` return a boolean if any changes were made.
|
||||
|
||||
:rtype: bool or str
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' file.blockreplace /etc/hosts '#-- start managed zone foobar : DO NOT EDIT --' \
|
||||
'#-- end managed zone foobar --' $'10.0.1.1 foo.foobar\n10.0.1.2 bar.foobar' True
|
||||
'''
|
||||
if not os.path.exists(path):
|
||||
raise SaltInvocationError("File not found: %s", path)
|
||||
|
||||
if not salt.utils.istextfile(path):
|
||||
raise SaltInvocationError(
|
||||
"Cannot perform string replacements on a binary file: %s", path)
|
||||
|
||||
# Search the file; track if any changes have been made for the return val
|
||||
has_changes = False
|
||||
orig_file = []
|
||||
new_file = []
|
||||
in_block = False
|
||||
old_content = ''
|
||||
done = False
|
||||
# we do not use in_place editing to avoid file attrs modifications when
|
||||
# no changes are required and to avoid any file access on a partially
|
||||
# written file.
|
||||
# we could also use salt.utils.filebuffer.BufferedReader
|
||||
for line in fileinput.input(path,
|
||||
inplace=False, backup=False,
|
||||
bufsize=1, mode='rb'):
|
||||
|
||||
result = line
|
||||
|
||||
if marker_start in line:
|
||||
# managed block start found, start recording
|
||||
in_block = True
|
||||
|
||||
else:
|
||||
if in_block:
|
||||
if marker_end in line:
|
||||
# end of block detected
|
||||
in_block = False
|
||||
|
||||
# push new block content in file
|
||||
for cline in content.split("\n"):
|
||||
new_file.append(cline+"\n")
|
||||
|
||||
done = True
|
||||
|
||||
else:
|
||||
# remove old content, but keep a trace
|
||||
old_content += line
|
||||
result = None
|
||||
# else: we are not in the marked block, keep saving things
|
||||
|
||||
orig_file.append(line)
|
||||
if result is not None:
|
||||
new_file.append(result)
|
||||
# end for. If we are here without block managment we maybe have some problems,
|
||||
# or we need to initialise the marked block
|
||||
|
||||
if in_block:
|
||||
# unterminated block => bad, always fail
|
||||
raise CommandExecutionError("Unterminated marked block. End of file reached before marker_end.")
|
||||
|
||||
if not done:
|
||||
if append_if_not_found:
|
||||
# add the markers and content at the end of file
|
||||
new_file.append(marker_start + '\n')
|
||||
new_file.append(content + '\n')
|
||||
new_file.append(marker_end + '\n')
|
||||
done = True
|
||||
else:
|
||||
raise CommandExecutionError("Cannot edit marked block. Markers were not found in file.")
|
||||
|
||||
if done:
|
||||
diff = ''.join(difflib.unified_diff(orig_file, new_file))
|
||||
has_changes = diff is not ''
|
||||
if has_changes and not dry_run:
|
||||
# changes detected
|
||||
# backup old content
|
||||
if backup is not False:
|
||||
shutil.copy2(path, '{0}{1}'.format(path, backup))
|
||||
|
||||
# backup file attrs
|
||||
perms = {}
|
||||
perms['user'] = get_user(path)
|
||||
perms['group'] = get_group(path)
|
||||
perms['mode'] = __salt__['config.manage_mode'](get_mode(path))
|
||||
|
||||
# write new content in the file while avoiding partial reads
|
||||
f = salt.utils.atomicfile.atomic_open(path, 'wb')
|
||||
for line in new_file:
|
||||
f.write(line)
|
||||
f.close()
|
||||
|
||||
# this may have overwritten file attrs
|
||||
check_perms(path,
|
||||
None,
|
||||
perms['user'],
|
||||
perms['group'],
|
||||
perms['mode'])
|
||||
|
||||
if show_changes:
|
||||
return diff
|
||||
|
||||
return has_changes
|
||||
|
||||
|
||||
def search(path,
|
||||
pattern,
|
||||
flags=0,
|
||||
|
@ -34,13 +34,11 @@ import time
|
||||
import logging
|
||||
import re
|
||||
import sys
|
||||
import shlex
|
||||
|
||||
# Import salt libs
|
||||
import salt.utils
|
||||
|
||||
#import shlex which should be distributed with Python
|
||||
import shlex
|
||||
|
||||
# Import third party libs
|
||||
try:
|
||||
import MySQLdb
|
||||
|
@ -428,7 +428,7 @@ def list_(profile=None):
|
||||
|
||||
def server_list(profile=None):
|
||||
'''
|
||||
Return detailed information for an active server
|
||||
Return list of active servers
|
||||
|
||||
CLI Example:
|
||||
|
||||
@ -443,6 +443,12 @@ def server_list(profile=None):
|
||||
'id': item.id,
|
||||
'name': item.name,
|
||||
'status': item.status,
|
||||
'accessIPv4': item.accessIPv4,
|
||||
'accessIPv6': item.accessIPv6,
|
||||
'flavor': {'id': item.flavor['id'],
|
||||
'links': item.flavor['links']},
|
||||
'image': {'id': item.image['id'],
|
||||
'links': item.image['links']},
|
||||
}
|
||||
return ret
|
||||
|
||||
@ -455,20 +461,19 @@ def show(server_id, profile=None):
|
||||
return server_show(server_id, profile)
|
||||
|
||||
|
||||
def server_show(server_id, profile=None):
|
||||
def server_list_detailed(profile=None):
|
||||
'''
|
||||
Return detailed information for an active server
|
||||
Return detailed list of active servers
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' nova.show
|
||||
salt '*' nova.server_list_detailed
|
||||
'''
|
||||
nt_ks = _auth(profile)
|
||||
ret = {}
|
||||
for item in nt_ks.servers.list():
|
||||
if item.id == server_id:
|
||||
ret[item.name] = {
|
||||
'OS-EXT-SRV-ATTR': {},
|
||||
'OS-EXT-STS': {},
|
||||
@ -488,7 +493,6 @@ def server_show(server_id, profile=None):
|
||||
'metadata': item.metadata,
|
||||
'name': item.name,
|
||||
'progress': item.progress,
|
||||
'security_groups': item.security_groups,
|
||||
'status': item.status,
|
||||
'tenant_id': item.tenant_id,
|
||||
'updated': item.updated,
|
||||
@ -510,6 +514,27 @@ def server_show(server_id, profile=None):
|
||||
ret[item.name]['OS-EXT-STS']['task_state'] = item.__dict__['OS-EXT-STS:task_state']
|
||||
if hasattr(item.__dict__, 'OS-EXT-STS:vm_state'):
|
||||
ret[item.name]['OS-EXT-STS']['vm_state'] = item.__dict__['OS-EXT-STS:vm_state']
|
||||
if hasattr(item.__dict__, 'security_groups'):
|
||||
ret[item.name]['security_groups'] = item.__dict__['security_groups']
|
||||
return ret
|
||||
|
||||
|
||||
def server_show(server_id, profile=None):
|
||||
'''
|
||||
Return detailed information for an active server
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' nova.server_show <server_id>
|
||||
'''
|
||||
ret = {}
|
||||
server_list = server_list_detailed(profile)
|
||||
for item in server_list:
|
||||
id_ = server_list[item]['id']
|
||||
if str(id_) == server_id:
|
||||
ret[server_list[item]['name']] = server_list[item]
|
||||
return ret
|
||||
|
||||
|
||||
|
@ -267,13 +267,13 @@ def do(cmdline=None, runas=None):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' rbenv.do "gem list bundler"
|
||||
salt '*' rbenv.do "gem list bundler" deploy
|
||||
salt '*' rbenv.do 'gem list bundler'
|
||||
salt '*' rbenv.do 'gem list bundler' deploy
|
||||
'''
|
||||
|
||||
path = _rbenv_path(runas)
|
||||
result = __salt__['cmd.run_all'](
|
||||
"env PATH={0}/shims:$PATH {1}".format(path, cmdline),
|
||||
'env PATH={0}/shims:$PATH {1}'.format(path, cmdline),
|
||||
runas=runas
|
||||
)
|
||||
|
||||
|
@ -60,6 +60,12 @@ def __virtual__():
|
||||
# Disable on these platforms, specific service modules exist:
|
||||
if __grains__['os'] in ('Ubuntu', 'Linaro', 'elementary OS'):
|
||||
return __virtualname__
|
||||
elif __grains__['os'] in ('Debian', 'Raspbian'):
|
||||
debian_initctl = '/sbin/initctl'
|
||||
if os.path.isfile(debian_initctl):
|
||||
initctl_version = salt.modules.cmdmod._run_quiet(debian_initctl + ' version')
|
||||
if 'upstart' in initctl_version:
|
||||
return 'service'
|
||||
return False
|
||||
|
||||
|
||||
|
@ -129,8 +129,11 @@ def ext_pillar(pillar,
|
||||
if not os.path.isdir(path):
|
||||
log.error('Virtualenv {} not a directory!'.format(path))
|
||||
return {}
|
||||
# load the virtualenv
|
||||
sys.path[0:0] = (virtualenv.path_locations(env)[1] + '/site-packages/',)
|
||||
# load the virtualenv first
|
||||
sys.path.insert(0,
|
||||
os.path.join(
|
||||
virtualenv.path_locations(env)[1],
|
||||
'site-packages'))
|
||||
|
||||
# load the django project
|
||||
sys.path.append(project_path)
|
||||
|
@ -18,7 +18,7 @@ import salt.key
|
||||
import salt.client
|
||||
import salt.output
|
||||
|
||||
FINGERPRINT_REGEX = re.compile(r"[a-f0-9]{2}:"*15 + r"[a-f0-9]{2}")
|
||||
FINGERPRINT_REGEX = re.compile(r'^([a-f0-9]{2}:){15}([a-f0-9]{2})$')
|
||||
|
||||
|
||||
def status(output=True):
|
||||
|
@ -1776,6 +1776,121 @@ def replace(name,
|
||||
return ret
|
||||
|
||||
|
||||
def blockreplace(name,
|
||||
marker_start='#-- start managed zone --',
|
||||
marker_end='#-- end managed zone --',
|
||||
content='',
|
||||
append_if_not_found=False,
|
||||
backup='.bak',
|
||||
show_changes=True):
|
||||
'''
|
||||
Maintain an edit in a file in a zone delimited by two line markers
|
||||
|
||||
.. versionadded:: 0.18.0
|
||||
|
||||
A block of content delimited by comments can help you manage several lines
|
||||
entries without worrying about old entries removal. This can help you maintaining
|
||||
an unmanaged file containing manual edits.
|
||||
Note: this function will store two copies of the file in-memory
|
||||
(the original version and the edited version) in order to detect changes
|
||||
and only edit the targeted file if necessary.
|
||||
|
||||
:param name: Filesystem path to the file to be edited
|
||||
:param marker_start: The line content identifying a line as the start of
|
||||
the content block. Note that the whole line containing this marker will
|
||||
be considered, so whitespaces or extra content before or after the
|
||||
marker is included in final output
|
||||
:param marker_end: The line content identifying a line as the end of
|
||||
the content block. Note that the whole line containing this marker will
|
||||
be considered, so whitespaces or extra content before or after the
|
||||
marker is included in final output.
|
||||
Note: you can use file.accumulated and target this state. All accumulated
|
||||
datas dictionnaries content will be added as new lines in the content.
|
||||
:param content: The content to be used between the two lines identified by
|
||||
marker_start and marker_stop.
|
||||
:param append_if_not_found: False by default, if markers are not found and
|
||||
set to True then the markers and content will be appended to the file
|
||||
:param backup: The file extension to use for a backup of the file if any
|
||||
edit is made. Set to ``False`` to skip making a backup.
|
||||
:param dry_run: Don't make any edits to the file
|
||||
:param show_changes: Output a unified diff of the old file and the new
|
||||
file. If ``False`` return a boolean if any changes were made.
|
||||
|
||||
:rtype: bool or str
|
||||
|
||||
Exemple of usage with an accumulator and with a variable::
|
||||
|
||||
{% set myvar = 42 %}
|
||||
hosts-config-block-{{ myvar }}:
|
||||
file.blockreplace:
|
||||
- name: /etc/hosts
|
||||
- marker_start: "# START managed zone {{ myvar }} -DO-NOT-EDIT-"
|
||||
- marker_end: "# END managed zone {{ myvar }} --"
|
||||
- content: 'First line of content'
|
||||
- append_if_not_found: True
|
||||
- backup: '.bak'
|
||||
- show_changes: True
|
||||
|
||||
hosts-config-block-{{ myvar }}-accumulated1:
|
||||
file.accumulated:
|
||||
- filename: /etc/hosts
|
||||
- name: my-accumulator-{{ myvar }}
|
||||
- text: "text 2"
|
||||
- require_in:
|
||||
- file: foobar-config-block-{{ myvar }}
|
||||
|
||||
hosts-config-block-{{ myvar }}-accumulated2:
|
||||
file.accumulated:
|
||||
- filename: /etc/hosts
|
||||
- name: my-accumulator-{{ myvar }}
|
||||
- text: |
|
||||
text 3
|
||||
text 4
|
||||
- require_in:
|
||||
- file: foobar-config-block-{{ myvar }}
|
||||
|
||||
will generate and maintain a block of content in ``/etc/hosts``::
|
||||
|
||||
# START managed zone 42 -DO-NOT-EDIT-
|
||||
First line of content
|
||||
text 2
|
||||
text 3
|
||||
text 4
|
||||
# END managed zone 42 --
|
||||
'''
|
||||
ret = {'name': name, 'changes': {}, 'result': False, 'comment': ''}
|
||||
|
||||
check_res, check_msg = _check_file(name)
|
||||
if not check_res:
|
||||
return _error(ret, check_msg)
|
||||
|
||||
if name in _ACCUMULATORS:
|
||||
accumulator = _ACCUMULATORS[name]
|
||||
for acc, acc_content in accumulator.iteritems():
|
||||
for line in acc_content:
|
||||
if content == '':
|
||||
content = line
|
||||
else:
|
||||
content += "\n" + line
|
||||
changes = __salt__['file.blockreplace'](name,
|
||||
marker_start,
|
||||
marker_end,
|
||||
content=content,
|
||||
append_if_not_found=append_if_not_found,
|
||||
backup=backup,
|
||||
dry_run=__opts__['test'],
|
||||
show_changes=show_changes)
|
||||
|
||||
if changes:
|
||||
ret['changes'] = changes
|
||||
ret['comment'] = 'Changes were made'
|
||||
else:
|
||||
ret['comment'] = 'No changes were made'
|
||||
|
||||
ret['result'] = True
|
||||
return ret
|
||||
|
||||
|
||||
def sed(name,
|
||||
before,
|
||||
after,
|
||||
@ -2548,7 +2663,8 @@ def rename(name, source, force=False, makedirs=False):
|
||||
def accumulated(name, filename, text, **kwargs):
|
||||
'''
|
||||
Prepare accumulator which can be used in template in file.managed state.
|
||||
Accumulator dictionary becomes available in template.
|
||||
Accumulator dictionary becomes available in template. It can also be used
|
||||
in file.blockreplace.
|
||||
|
||||
name
|
||||
Accumulator name
|
||||
|
@ -3,7 +3,7 @@
|
||||
Control of entries in SSH authorized_key files.
|
||||
===============================================
|
||||
|
||||
The information stored in a user's ssh authorized key file can be easily
|
||||
The information stored in a user's SSH authorized key file can be easily
|
||||
controlled via the ssh_auth state. Defaults can be set by the enc, options,
|
||||
and comment keys. These defaults can be overridden by including them in the
|
||||
name.
|
||||
@ -116,19 +116,19 @@ def present(
|
||||
config='.ssh/authorized_keys',
|
||||
**kwargs):
|
||||
'''
|
||||
Verifies that the specified ssh key is present for the specified user
|
||||
Verifies that the specified SSH key is present for the specified user
|
||||
|
||||
name
|
||||
The ssh key to manage
|
||||
The SSH key to manage
|
||||
|
||||
user
|
||||
The user who owns the ssh authorized keys file to modify
|
||||
The user who owns the SSH authorized keys file to modify
|
||||
|
||||
enc
|
||||
Defines what type of key is being used, can be ecdsa ssh-rsa, ssh-dss
|
||||
Defines what type of key is being used; can be ecdsa, ssh-rsa or ssh-dss
|
||||
|
||||
comment
|
||||
The comment to be placed with the ssh public key
|
||||
The comment to be placed with the SSH public key
|
||||
|
||||
source
|
||||
The source file for the key(s). Can contain any number of public keys,
|
||||
@ -237,15 +237,29 @@ def present(
|
||||
return ret
|
||||
|
||||
|
||||
def absent(name, user, config='.ssh/authorized_keys'):
|
||||
def absent(name,
|
||||
user,
|
||||
enc='ssh-rsa',
|
||||
comment='',
|
||||
options=None,
|
||||
config='.ssh/authorized_keys'):
|
||||
'''
|
||||
Verifies that the specified ssh key is absent
|
||||
Verifies that the specified SSH key is absent
|
||||
|
||||
name
|
||||
The ssh key to manage
|
||||
The SSH key to manage
|
||||
|
||||
user
|
||||
The user who owns the ssh authorized keys file to modify
|
||||
The user who owns the SSH authorized keys file to modify
|
||||
|
||||
enc
|
||||
Defines what type of key is being used; can be ecdsa, ssh-rsa or ssh-dss
|
||||
|
||||
comment
|
||||
The comment to be placed with the SSH public key
|
||||
|
||||
options
|
||||
The options passed to the key, pass a list object
|
||||
|
||||
config
|
||||
The location of the authorized keys file relative to the user's home
|
||||
@ -263,9 +277,9 @@ def absent(name, user, config='.ssh/authorized_keys'):
|
||||
check = __salt__['ssh.check_key'](
|
||||
user,
|
||||
name,
|
||||
'',
|
||||
'',
|
||||
[],
|
||||
enc,
|
||||
comment,
|
||||
options or [],
|
||||
config)
|
||||
if check == 'update' or check == 'exists':
|
||||
ret['result'] = None
|
||||
|
@ -13,7 +13,8 @@ def mac(addr):
|
||||
'''
|
||||
valid = re.compile(r'''
|
||||
(^([0-9A-F]{1,2}[-]){5}([0-9A-F]{1,2})$
|
||||
|^([0-9A-F]{1,2}[:]){5}([0-9A-F]{1,2})$)
|
||||
|^([0-9A-F]{1,2}[:]){5}([0-9A-F]{1,2})$
|
||||
|^([0-9A-F]{1,2}[.]){5}([0-9A-F]{1,2})$)
|
||||
''',
|
||||
re.VERBOSE | re.IGNORECASE)
|
||||
return valid.match(addr) is not None
|
||||
|
@ -6,17 +6,20 @@ import textwrap
|
||||
# Import Salt Testing libs
|
||||
from salttesting import TestCase
|
||||
from salttesting.helpers import ensure_in_syspath
|
||||
from salttesting.mock import MagicMock
|
||||
|
||||
ensure_in_syspath('../../')
|
||||
|
||||
# Import Salt libs
|
||||
from salt.modules import file as filemod
|
||||
from salt.modules import cmdmod
|
||||
from salt.exceptions import CommandExecutionError, SaltInvocationError
|
||||
|
||||
filemod.__salt__ = {
|
||||
'cmd.run': cmdmod.run,
|
||||
'cmd.run_all': cmdmod.run_all
|
||||
}
|
||||
filemod.__opts__ = {'test': False}
|
||||
|
||||
SED_CONTENT = """test
|
||||
some
|
||||
@ -101,6 +104,140 @@ class FileReplaceTestCase(TestCase):
|
||||
def test_re_int_flags(self):
|
||||
filemod.replace(self.tfile.name, r'Etiam', 'Salticus', flags=10)
|
||||
|
||||
class FileBlockReplaceTestCase(TestCase):
|
||||
MULTILINE_STRING = textwrap.dedent('''\
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam rhoncus
|
||||
enim ac bibendum vulputate. Etiam nibh velit, placerat ac auctor in,
|
||||
lacinia a turpis. Nulla elit elit, ornare in sodales eu, aliquam sit
|
||||
amet nisl.
|
||||
|
||||
Fusce ac vehicula lectus. Vivamus justo nunc, pulvinar in ornare nec,
|
||||
sollicitudin id sem. Pellentesque sed ipsum dapibus, dapibus elit id,
|
||||
malesuada nisi.
|
||||
|
||||
first part of start line // START BLOCK : part of start line not removed
|
||||
to be removed
|
||||
first part of end line // END BLOCK : part of end line not removed
|
||||
|
||||
#-- START BLOCK UNFINISHED
|
||||
|
||||
#-- START BLOCK 1
|
||||
old content part 1
|
||||
old content part 2
|
||||
#-- END BLOCK 1
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec
|
||||
venenatis tellus eget massa facilisis, in auctor ante aliquet. Sed nec
|
||||
cursus metus. Curabitur massa urna, vehicula id porttitor sed, lobortis
|
||||
quis leo.
|
||||
''')
|
||||
|
||||
def setUp(self):
|
||||
self.tfile = tempfile.NamedTemporaryFile(delete=False,prefix='blockrepltmp')
|
||||
self.tfile.write(self.MULTILINE_STRING)
|
||||
self.tfile.close()
|
||||
manage_mode_mock = MagicMock()
|
||||
filemod.__salt__['config.manage_mode'] = manage_mode_mock
|
||||
|
||||
def tearDown(self):
|
||||
os.remove(self.tfile.name)
|
||||
|
||||
def test_replace_multiline(self):
|
||||
new_multiline_content = "Who's that then?\nWell, how'd you become king, then?\nWe found them. I'm not a witch.\nWe shall say 'Ni' again to you, if you do not appease us."
|
||||
filemod.blockreplace(self.tfile.name, '#-- START BLOCK 1', '#-- END BLOCK 1', new_multiline_content, backup=False)
|
||||
|
||||
with open(self.tfile.name, 'rb') as fp:
|
||||
filecontent=fp.read()
|
||||
self.assertIn('#-- START BLOCK 1'+"\n"+new_multiline_content+"\n"+'#-- END BLOCK 1', filecontent)
|
||||
self.assertNotIn('old content part 1', filecontent)
|
||||
self.assertNotIn('old content part 2', filecontent)
|
||||
|
||||
def test_replace_append(self):
|
||||
new_content = "Well, I didn't vote for you."
|
||||
|
||||
self.assertRaises(
|
||||
CommandExecutionError,
|
||||
filemod.blockreplace,
|
||||
self.tfile.name,
|
||||
'#-- START BLOCK 2',
|
||||
'#-- END BLOCK 2',
|
||||
new_content,
|
||||
append_if_not_found=False,
|
||||
backup=False
|
||||
)
|
||||
with open(self.tfile.name, 'rb') as fp:
|
||||
self.assertNotIn('#-- START BLOCK 2'+"\n"+new_content+"\n"+'#-- END BLOCK 2', fp.read())
|
||||
|
||||
filemod.blockreplace(self.tfile.name, '#-- START BLOCK 2', '#-- END BLOCK 2', new_content, backup=False,append_if_not_found=True)
|
||||
|
||||
with open(self.tfile.name, 'rb') as fp:
|
||||
self.assertIn('#-- START BLOCK 2'+"\n"+new_content+"\n"+'#-- END BLOCK 2', fp.read())
|
||||
|
||||
|
||||
def test_replace_partial_marked_lines(self):
|
||||
filemod.blockreplace(self.tfile.name, '// START BLOCK', '// END BLOCK', 'new content 1', backup=False)
|
||||
|
||||
with open(self.tfile.name, 'rb') as fp:
|
||||
filecontent=fp.read()
|
||||
self.assertIn('new content 1', filecontent)
|
||||
self.assertNotIn('to be removed', filecontent)
|
||||
self.assertIn('first part of start line', filecontent)
|
||||
self.assertIn('first part of end line', filecontent)
|
||||
self.assertIn('part of start line not removed', filecontent)
|
||||
self.assertIn('part of end line not removed', filecontent)
|
||||
|
||||
def test_backup(self):
|
||||
fext = '.bak'
|
||||
bak_file = '{0}{1}'.format(self.tfile.name, fext)
|
||||
|
||||
filemod.blockreplace(self.tfile.name, '// START BLOCK', '// END BLOCK', 'new content 2', backup=fext)
|
||||
|
||||
self.assertTrue(os.path.exists(bak_file))
|
||||
os.unlink(bak_file)
|
||||
self.assertFalse(os.path.exists(bak_file))
|
||||
|
||||
fext = '.bak'
|
||||
bak_file = '{0}{1}'.format(self.tfile.name, fext)
|
||||
|
||||
filemod.blockreplace(self.tfile.name, '// START BLOCK', '// END BLOCK', 'new content 3', backup=False)
|
||||
|
||||
self.assertFalse(os.path.exists(bak_file))
|
||||
|
||||
def test_no_modifications(self):
|
||||
filemod.blockreplace(self.tfile.name, '// START BLOCK', '// END BLOCK', 'new content 4', backup=False)
|
||||
before_ctime = os.stat(self.tfile.name).st_mtime
|
||||
filemod.blockreplace(self.tfile.name, '// START BLOCK', '// END BLOCK', 'new content 4', backup=False)
|
||||
after_ctime = os.stat(self.tfile.name).st_mtime
|
||||
|
||||
self.assertEqual(before_ctime, after_ctime)
|
||||
|
||||
def test_dry_run(self):
|
||||
before_ctime = os.stat(self.tfile.name).st_mtime
|
||||
filemod.blockreplace(self.tfile.name, '// START BLOCK', '// END BLOCK', 'new content 5', dry_run=True)
|
||||
after_ctime = os.stat(self.tfile.name).st_mtime
|
||||
|
||||
self.assertEqual(before_ctime, after_ctime)
|
||||
|
||||
def test_show_changes(self):
|
||||
ret = filemod.blockreplace(self.tfile.name, '// START BLOCK', '// END BLOCK', 'new content 6', backup=False, show_changes=True)
|
||||
|
||||
self.assertTrue(ret.startswith('---')) # looks like a diff
|
||||
|
||||
ret = filemod.blockreplace(self.tfile.name, '// START BLOCK', '// END BLOCK', 'new content 7', backup=False, show_changes=False)
|
||||
|
||||
self.assertIsInstance(ret, bool)
|
||||
|
||||
def test_unfinished_block_exception(self):
|
||||
self.assertRaises(
|
||||
CommandExecutionError,
|
||||
filemod.blockreplace,
|
||||
self.tfile.name,
|
||||
'#-- START BLOCK UNFINISHED',
|
||||
'#-- END BLOCK UNFINISHED',
|
||||
'foobar',
|
||||
backup=False
|
||||
)
|
||||
|
||||
|
||||
class FileModuleTestCase(TestCase):
|
||||
def test_sed_limit_escaped(self):
|
||||
@ -149,4 +286,4 @@ class FileModuleTestCase(TestCase):
|
||||
|
||||
if __name__ == '__main__':
|
||||
from integration import run_tests
|
||||
run_tests(FileModuleTestCase, FileReplaceTestCase, needs_daemon=False)
|
||||
run_tests(FileModuleTestCase, FileReplaceTestCase, FileBlockReplaceTestCase, needs_daemon=False)
|
||||
|
Loading…
Reference in New Issue
Block a user