Merge branch 'develop' of https://github.com/saltstack/salt into disable_lspci
* 'develop' of https://github.com/saltstack/salt: (57 commits) fixed a typo in the halite docs, reworded a sentence to clarify how halite is obtained Using the same technique as the python path checker to determine the correct md5 command. This improves the previous technique. OS X doesn't call md5sum by its full name. Instead, it is installed as simple 'md5'. Because we don't know what OS we're deploying to ahead of time, we need to check that condition for that in the shim script and account for it. Remove stale files in the docs dir. Refs #7984. Tested against a build and walk-through of the HTML docs. pip freeze output has comments sometimes: ignore Removing nsProcess plugin. Using ExecWait and a sleep 3s to stop salt-minion. Fix my typo Change assertEquals to assertEqual Use versionadded instead of note Reworked part of the halite docs to clarify the running of halite itself, created sections in prep for nginx/apache work. Reformatted according to Debian spec. Also added note to declare that images in doc/_ext/images were created in-house, by Salt Stack. Forgot to add youtube.py. Initial commit of a top-level COPYING file to assist package maintainers. Stop shipping fonts in the docset. Start using free-fonts from Google and then fall-back to system fonts if those are not available. Fix for swapped vars in ssh-client auth. Still guess an ID always, but only cache if it's a proper minion Add note about upgrading minions for 0.17.1 fix bad indent Kill some whitespace Lint fixes for execution module file.block ... Conflicts: salt/grains/core.py
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.
|
2
doc/_themes/saltstack/layout.html
vendored
@ -161,7 +161,7 @@
|
||||
{%- endblock %}
|
||||
|
||||
{%- block extrahead %} {% endblock %}
|
||||
|
||||
<link href='http://fonts.googleapis.com/css?family=Open+Sans:300italic,800italic,300,800' rel='stylesheet' type='text/css'>
|
||||
<script src="{{ pathto('_static/js/vendor/modernizr-2.6.2-respond-1.1.0.min.js', 1) }}"></script>
|
||||
|
||||
{%- block analytics %}
|
||||
|
145
doc/_themes/saltstack/static/css/main.css
vendored
@ -1,115 +1,3 @@
|
||||
/* ==========================================================================
|
||||
WEBFONTS
|
||||
========================================================================== */
|
||||
/*
|
||||
Font: Nexa Light
|
||||
Style: Regular
|
||||
URL: http://www.youworkforthem.com/product.php?sku=T3972
|
||||
Foundry: Fontfabric
|
||||
Foundry: http://www.youworkforthem.com/designer/105/fontfabric
|
||||
Copyright: Copyright (c) 2010 by Svetoslav Simov. All rights reserved.
|
||||
Version: 1.1
|
||||
Created: October 11, 2012
|
||||
License: http://www.youworkforthem.com/font-license
|
||||
License: The WebFont(s) listed in this document must follow the YouWorkForThem
|
||||
WebFont license rules. All other parties are strictly restricted
|
||||
from using the WebFonts(s) listed without a purchased license.
|
||||
All details above must always remain unaltered and visible in your CSS.
|
||||
*/
|
||||
|
||||
@font-face {
|
||||
font-family: 'Nexa Light';
|
||||
src: url('../fonts/nexa-light.eot');
|
||||
src: url('../fonts/nexa-light.eot?#iefix') format('embedded-opentype'),
|
||||
url('../fonts/nexa-light.woff') format('woff'),
|
||||
url('../fonts/nexa-light.ttf') format('truetype'),
|
||||
url('../fonts/nexa-light.svg#ywftsvg') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Font: Nexa Light Italic
|
||||
Style: Italic
|
||||
URL: http://www.youworkforthem.com/product.php?sku=T3972
|
||||
Foundry: Fontfabric
|
||||
Foundry: http://www.youworkforthem.com/designer/105/fontfabric
|
||||
Copyright: Copyright (c) 2012 by Svetoslav Simov. All rights reserved.
|
||||
Version: 1.1
|
||||
Created: October 11, 2012
|
||||
License: http://www.youworkforthem.com/font-license
|
||||
License: The WebFont(s) listed in this document must follow the YouWorkForThem
|
||||
WebFont license rules. All other parties are strictly restricted
|
||||
from using the WebFonts(s) listed without a purchased license.
|
||||
All details above must always remain unaltered and visible in your CSS.
|
||||
*/
|
||||
|
||||
@font-face {
|
||||
font-family: 'Nexa Light Italic';
|
||||
src: url('../fonts/nexa-light-italic.eot');
|
||||
src: url('../fonts/nexa-light-italic.eot?#iefix') format('embedded-opentype'),
|
||||
url('../fonts/nexa-light-italic.woff') format('woff'),
|
||||
url('../fonts/nexa-light-italic.ttf') format('truetype'),
|
||||
url('../fonts/nexa-light-italic.svg#ywftsvg') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Font: Nexa XBold
|
||||
Style: Regular
|
||||
URL: http://www.youworkforthem.com/product.php?sku=T3972
|
||||
Foundry: Fontfabric
|
||||
Foundry: http://www.youworkforthem.com/designer/105/fontfabric
|
||||
Copyright: Copyright (c) 2010 by Svetoslav Simov. All rights reserved.
|
||||
Version: 1.1
|
||||
Created: October 11, 2012
|
||||
License: http://www.youworkforthem.com/font-license
|
||||
License: The WebFont(s) listed in this document must follow the YouWorkForThem
|
||||
WebFont license rules. All other parties are strictly restricted
|
||||
from using the WebFonts(s) listed without a purchased license.
|
||||
All details above must always remain unaltered and visible in your CSS.
|
||||
*/
|
||||
|
||||
@font-face {
|
||||
font-family: 'Nexa XBold';
|
||||
src: url('../fonts/nexa-xbold.eot');
|
||||
src: url('../fonts/nexa-xbold.eot?#iefix') format('embedded-opentype'),
|
||||
url('../fonts/nexa-xbold.woff') format('woff'),
|
||||
url('../fonts/nexa-xbold.ttf') format('truetype'),
|
||||
url('../fonts/nexa-xbold.svg#ywftsvg') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/*
|
||||
Font: Nexa XBold Italic
|
||||
Style: Regular
|
||||
URL: http://www.youworkforthem.com/product.php?sku=T3972
|
||||
Foundry: Fontfabric
|
||||
Foundry: http://www.youworkforthem.com/designer/105/fontfabric
|
||||
Copyright: Copyright (c) 2012 by Svetoslav Simov. All rights reserved.
|
||||
Version: 1.1
|
||||
Created: October 11, 2012
|
||||
License: http://www.youworkforthem.com/font-license
|
||||
License: The WebFont(s) listed in this document must follow the YouWorkForThem
|
||||
WebFont license rules. All other parties are strictly restricted
|
||||
from using the WebFonts(s) listed without a purchased license.
|
||||
All details above must always remain unaltered and visible in your CSS.
|
||||
*/
|
||||
|
||||
@font-face {
|
||||
font-family: 'Nexa XBold Italic';
|
||||
src: url('../fonts/nexa-xbold-italic.eot');
|
||||
src: url('../fonts/nexa-xbold-italic.eot?#iefix') format('embedded-opentype'),
|
||||
url('../fonts/nexa-xbold-italic.woff') format('woff'),
|
||||
url('../fonts/nexa-xbold-italic.ttf') format('truetype'),
|
||||
url('../fonts/nexa-xbold-italic.svg#ywftsvg') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
|
||||
/* ==========================================================================
|
||||
@ -129,7 +17,7 @@ html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockq
|
||||
}
|
||||
.navbar-inverse .brand, .navbar-inverse .nav > li > a {
|
||||
color: #484c51;
|
||||
font: 14px/24px 'Nexa Light';
|
||||
font: 14px/24px 'Open Sans Light';
|
||||
}
|
||||
.navbar .nav li.currentNav {
|
||||
background: url(../img/navCurrentArrow.png) center 32px no-repeat;
|
||||
@ -145,7 +33,7 @@ html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockq
|
||||
}
|
||||
.articleCredits {
|
||||
padding-left: 12px;
|
||||
font: 12px/24px 'Nexa Light';
|
||||
font: 12px/24px 'Open Sans Light';
|
||||
white-space: pre;
|
||||
}
|
||||
.fullwidth {
|
||||
@ -167,7 +55,7 @@ body.index .success, body.index .clients {
|
||||
.testimonialAuthor {
|
||||
display: block;
|
||||
margin-bottom: 30px;
|
||||
font: 12px/24px 'Nexa XBold';
|
||||
font: 12px/24px 'Open Sans Extrabold';
|
||||
color: #aa2b39;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
@ -185,12 +73,12 @@ body.index .success, body.index .clients {
|
||||
}
|
||||
h2.homeSecTitles {
|
||||
color: #8d9caa;
|
||||
font-family: 'Nexa XBold Italic';
|
||||
font-family: 'Open Sans Extrabold Italic';
|
||||
text-transform: capitalize;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.success h3 {
|
||||
font: 18px/30px 'Nexa Light Italic'; color: #4f575b; margin: 25px 0;
|
||||
font: 18px/30px 'Open Sans Light Italic'; color: #4f575b; margin: 25px 0;
|
||||
}
|
||||
.success img {
|
||||
margin: 30px 10px 10px 80px;
|
||||
@ -214,7 +102,7 @@ h2.homeSecTitles {
|
||||
}
|
||||
.carousel-caption p {
|
||||
margin-top: 25px;
|
||||
font: 16px/24px 'Nexa Light';
|
||||
font: 16px/24px 'Open Sans Light';
|
||||
color: #000;
|
||||
display: none;
|
||||
}
|
||||
@ -230,11 +118,12 @@ h2.homeSecTitles {
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: 'Nexa Light';
|
||||
font-family: 'Open Sans Light';
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font: 18px/28px 'Nexa XBold';
|
||||
font: 18px/28px 'Open Sans Extrabold';
|
||||
text-transform: uppercase;
|
||||
color: #373e4b;
|
||||
margin-bottom: 0;
|
||||
@ -260,11 +149,11 @@ body.products .lede {
|
||||
margin-top: 30px;
|
||||
}
|
||||
.lede h3 {
|
||||
font: 24px/30px 'Nexa Light';
|
||||
font: 24px/30px 'Open Sans Light';
|
||||
color: #aa2b39;
|
||||
}
|
||||
.lede h4 {
|
||||
font: 20px/30px 'Nexa Light Italic';
|
||||
font: 20px/30px 'Open Sans Light Italic';
|
||||
color: #373e4b;
|
||||
}
|
||||
body.services .lede h4 {
|
||||
@ -275,7 +164,7 @@ body.services .lede {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
body.about h1, body.services h1, body.contact h1 {
|
||||
font: 20px/30px 'Nexa XBold Italic';
|
||||
font: 20px/30px 'Open Sans Extrabold Italic';
|
||||
color: #4f575b;
|
||||
margin-top: 0;
|
||||
}
|
||||
@ -284,7 +173,7 @@ body.about h1, body.services h1, body.contact h1 {
|
||||
}
|
||||
body.about h6 {
|
||||
margin: 0;
|
||||
font-family: 'Nexa Light Italic';
|
||||
font-family: 'Open Sans Light Italic';
|
||||
text-transform: uppercase;
|
||||
line-height: 80%;
|
||||
margin-bottom: 10px;
|
||||
@ -301,7 +190,7 @@ body.services table th, body.services table td {
|
||||
}
|
||||
body.services table td {
|
||||
color: #373e4b;
|
||||
font-family: 'Nexa Light Italic';
|
||||
font-family: 'Open Sans Light Italic';
|
||||
width: 206px;
|
||||
}
|
||||
body.services table tr:last-child th, body.services table tr:last-child td {
|
||||
@ -327,7 +216,7 @@ body.services table td.tableCenter {
|
||||
padding: 5px 0;
|
||||
background: #aa2b39;
|
||||
color: #FFF;
|
||||
font-family: 'Nexa Light';
|
||||
font-family: 'Open Sans Light';
|
||||
text-shadow: none;
|
||||
font-weight: normal;
|
||||
border: none;
|
||||
@ -378,7 +267,7 @@ footer {
|
||||
}
|
||||
footer p, footer a {
|
||||
color: #FFF;
|
||||
font: 12px 'Nexa Light';
|
||||
font: 12px 'Open Sans Light';
|
||||
}
|
||||
footer a {
|
||||
display:block;
|
||||
@ -395,7 +284,7 @@ footer .row-fluid {
|
||||
}
|
||||
.footerCol h4 {
|
||||
color: #FFF;
|
||||
font: 14px/24px 'Nexa XBold';
|
||||
font: 14px/24px 'Open Sans Extrabold';
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
@ -1,26 +0,0 @@
|
||||
/*
|
||||
Font: Nexa Light Italic
|
||||
Style: Italic
|
||||
URL: http://www.youworkforthem.com/product.php?sku=T3972
|
||||
Foundry: Fontfabric
|
||||
Foundry: http://www.youworkforthem.com/designer/105/fontfabric
|
||||
Copyright: Copyright (c) 2012 by Svetoslav Simov. All rights reserved.
|
||||
Version: 1.1
|
||||
Created: October 11, 2012
|
||||
License: http://www.youworkforthem.com/font-license
|
||||
License: The WebFont(s) listed in this document must follow the YouWorkForThem
|
||||
WebFont license rules. All other parties are strictly restricted
|
||||
from using the WebFonts(s) listed without a purchased license.
|
||||
All details above must always remain unaltered and visible in your CSS.
|
||||
*/
|
||||
|
||||
@font-face {
|
||||
font-family: 'Nexa Light Italic';
|
||||
src: url('nexa-light-italic.eot');
|
||||
src: url('nexa-light-italic.eot?#iefix') format('embedded-opentype'),
|
||||
url('nexa-light-italic.woff') format('woff'),
|
||||
url('nexa-light-italic.ttf') format('truetype'),
|
||||
url('nexa-light-italic.svg#ywftsvg') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
Before Width: | Height: | Size: 137 KiB |
@ -1,26 +0,0 @@
|
||||
/*
|
||||
Font: Nexa Light
|
||||
Style: Regular
|
||||
URL: http://www.youworkforthem.com/product.php?sku=T3972
|
||||
Foundry: Fontfabric
|
||||
Foundry: http://www.youworkforthem.com/designer/105/fontfabric
|
||||
Copyright: Copyright (c) 2010 by Svetoslav Simov. All rights reserved.
|
||||
Version: 1.1
|
||||
Created: October 11, 2012
|
||||
License: http://www.youworkforthem.com/font-license
|
||||
License: The WebFont(s) listed in this document must follow the YouWorkForThem
|
||||
WebFont license rules. All other parties are strictly restricted
|
||||
from using the WebFonts(s) listed without a purchased license.
|
||||
All details above must always remain unaltered and visible in your CSS.
|
||||
*/
|
||||
|
||||
@font-face {
|
||||
font-family: 'Nexa Light';
|
||||
src: url('nexa-light.eot');
|
||||
src: url('nexa-light.eot?#iefix') format('embedded-opentype'),
|
||||
url('nexa-light.woff') format('woff'),
|
||||
url('nexa-light.ttf') format('truetype'),
|
||||
url('nexa-light.svg#ywftsvg') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
BIN
doc/_themes/saltstack/static/fonts/nexa-light.eot
vendored
Before Width: | Height: | Size: 131 KiB |
BIN
doc/_themes/saltstack/static/fonts/nexa-light.ttf
vendored
BIN
doc/_themes/saltstack/static/fonts/nexa-light.woff
vendored
@ -1,26 +0,0 @@
|
||||
/*
|
||||
Font: Nexa XBold Italic
|
||||
Style: Regular
|
||||
URL: http://www.youworkforthem.com/product.php?sku=T3972
|
||||
Foundry: Fontfabric
|
||||
Foundry: http://www.youworkforthem.com/designer/105/fontfabric
|
||||
Copyright: Copyright (c) 2012 by Svetoslav Simov. All rights reserved.
|
||||
Version: 1.1
|
||||
Created: October 11, 2012
|
||||
License: http://www.youworkforthem.com/font-license
|
||||
License: The WebFont(s) listed in this document must follow the YouWorkForThem
|
||||
WebFont license rules. All other parties are strictly restricted
|
||||
from using the WebFonts(s) listed without a purchased license.
|
||||
All details above must always remain unaltered and visible in your CSS.
|
||||
*/
|
||||
|
||||
@font-face {
|
||||
font-family: 'Nexa XBold Italic';
|
||||
src: url('nexa-xbold-italic.eot');
|
||||
src: url('nexa-xbold-italic.eot?#iefix') format('embedded-opentype'),
|
||||
url('nexa-xbold-italic.woff') format('woff'),
|
||||
url('nexa-xbold-italic.ttf') format('truetype'),
|
||||
url('nexa-xbold-italic.svg#ywftsvg') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
Before Width: | Height: | Size: 137 KiB |
@ -1,26 +0,0 @@
|
||||
/*
|
||||
Font: Nexa XBold
|
||||
Style: Regular
|
||||
URL: http://www.youworkforthem.com/product.php?sku=T3972
|
||||
Foundry: Fontfabric
|
||||
Foundry: http://www.youworkforthem.com/designer/105/fontfabric
|
||||
Copyright: Copyright (c) 2010 by Svetoslav Simov. All rights reserved.
|
||||
Version: 1.1
|
||||
Created: October 11, 2012
|
||||
License: http://www.youworkforthem.com/font-license
|
||||
License: The WebFont(s) listed in this document must follow the YouWorkForThem
|
||||
WebFont license rules. All other parties are strictly restricted
|
||||
from using the WebFonts(s) listed without a purchased license.
|
||||
All details above must always remain unaltered and visible in your CSS.
|
||||
*/
|
||||
|
||||
@font-face {
|
||||
font-family: 'Nexa XBold';
|
||||
src: url('nexa-xbold.eot');
|
||||
src: url('nexa-xbold.eot?#iefix') format('embedded-opentype'),
|
||||
url('nexa-xbold.woff') format('woff'),
|
||||
url('nexa-xbold.ttf') format('truetype'),
|
||||
url('nexa-xbold.svg#ywftsvg') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
BIN
doc/_themes/saltstack/static/fonts/nexa-xbold.eot
vendored
Before Width: | Height: | Size: 129 KiB |
BIN
doc/_themes/saltstack/static/fonts/nexa-xbold.ttf
vendored
BIN
doc/_themes/saltstack/static/fonts/nexa-xbold.woff
vendored
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 167 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.6 KiB |
BIN
doc/_themes/saltstack/static/images/heroImages.jpg
vendored
Before Width: | Height: | Size: 161 KiB |
BIN
doc/_themes/saltstack/static/images/heroScale.jpg
vendored
Before Width: | Height: | Size: 173 KiB |
BIN
doc/_themes/saltstack/static/images/heroSpeed.jpg
vendored
Before Width: | Height: | Size: 129 KiB |
Before Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 686 B |
BIN
doc/_themes/saltstack/static/images/socialG-dark.png
vendored
Before Width: | Height: | Size: 751 B |
Before Width: | Height: | Size: 749 B |
Before Width: | Height: | Size: 707 B |
Before Width: | Height: | Size: 677 B |
Before Width: | Height: | Size: 9.2 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 8.4 KiB |
BIN
doc/_themes/saltstack/static/images/ssWeAreHere.jpg
vendored
Before Width: | Height: | Size: 41 KiB |
BIN
doc/_themes/saltstack/static/images/theRegister.jpg
vendored
Before Width: | Height: | Size: 34 KiB |
@ -1,8 +1,8 @@
|
||||
Developing Salt
|
||||
===============
|
||||
|
||||
There is a great need for contributions to salt and patches are welcome! The goal
|
||||
here is to make contributions clear, make sure there is a trail for where the code
|
||||
There is a great need for contributions to salt and patches are welcome! The goal
|
||||
here is to make contributions clear, make sure there is a trail for where the code
|
||||
has come from, and most importantly, to give credit where credit is due!
|
||||
|
||||
There are a number of ways to contribute to salt development.
|
||||
@ -14,8 +14,8 @@ Sending a GitHub pull request
|
||||
This is the preferred method for contributions. Simply create a GitHub
|
||||
fork, commit changes to the fork, and then open up a pull request.
|
||||
|
||||
The following is an example (from `Open Comparison Contributing Docs`_ )
|
||||
of an efficient workflow for forking, cloning, branching, committing, and
|
||||
The following is an example (from `Open Comparison Contributing Docs`_ )
|
||||
of an efficient workflow for forking, cloning, branching, committing, and
|
||||
sending a pull request for a GitHub repository.
|
||||
|
||||
First, make a local clone of your GitHub fork of the salt GitHub repo and make
|
||||
@ -29,7 +29,7 @@ Then, create a new branch on your clone by entering the following commands:
|
||||
|
||||
Switched to a new branch 'fixed-broken-thing'
|
||||
|
||||
Choose a name for your branch that describes its purpose.
|
||||
Choose a name for your branch that describes its purpose.
|
||||
|
||||
Now commit your changes to this new branch with the following command:
|
||||
|
||||
@ -51,8 +51,8 @@ Push your locally-committed changes back up to GitHub:
|
||||
.. code-block:: bash
|
||||
|
||||
git push --set-upstream origin fixed-broken-thing
|
||||
|
||||
Now go look at your fork of the salt repo on the GitHub website. The new
|
||||
|
||||
Now go look at your fork of the salt repo on the GitHub website. The new
|
||||
branch will now be listed under the "Source" tab where it says "Switch Branches".
|
||||
Select the new branch from this list, and then click the "Pull request" button.
|
||||
|
||||
@ -62,7 +62,7 @@ to the pull request.
|
||||
The repo managers will be notified of your pull request and it will be
|
||||
reviewed. If a reviewer asks for changes, just make the changes locally in the
|
||||
same local feature branch, push them to GitHub, then add a comment to the
|
||||
discussion section of the pull request.
|
||||
discussion section of the pull request.
|
||||
|
||||
|
||||
.. _enable-travis-ci:
|
||||
@ -81,7 +81,7 @@ Keeping Salt Forks in Sync
|
||||
Salt is advancing quickly. It is therefore critical to pull upstream changes
|
||||
from master into forks on a regular basis. Nothing is worse than putting in a
|
||||
days of hard work into a pull request only to have it rejected because it has
|
||||
diverged too far from master.
|
||||
diverged too far from master.
|
||||
|
||||
To pull in upstream changes:
|
||||
|
||||
@ -187,7 +187,7 @@ Install Salt (and dependencies) into the virtualenv:
|
||||
.. note:: Installing M2Crypto
|
||||
|
||||
``swig`` and ``libssl-dev`` are required to build M2Crypto. To fix
|
||||
the error ``command 'swig' failed with exit status 1`` while installing M2Crypto,
|
||||
the error ``command 'swig' failed with exit status 1`` while installing M2Crypto,
|
||||
try installing it with the following command:
|
||||
|
||||
.. code-block:: bash
|
||||
@ -226,7 +226,7 @@ Install Salt (and dependencies) into the virtualenv:
|
||||
* `Fedora Linux`_ releases 11 and later
|
||||
* `Amazon Linux`_
|
||||
|
||||
Developers using one of these systems should create the salt virtualenv using the
|
||||
Developers using one of these systems should create the salt virtualenv using the
|
||||
``--system-site-packages`` option to ensure that the correct modules are available.
|
||||
|
||||
.. _`RHEL`: https://www.redhat.com/products/enterprise-linux/
|
||||
@ -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
|
||||
|
||||
@ -431,3 +438,10 @@ Change to salt documentation directory, then:
|
||||
.. code-block:: bash
|
||||
|
||||
make SPHINXBUILD=sphinx-1.0-build html
|
||||
|
||||
Once you've updated the documentation, you can run the following command to
|
||||
launch a simple Python http server to see your changes:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd _build/html; python -m SimpleHTTPServer
|
||||
|
@ -23,15 +23,20 @@ Major Features
|
||||
Halite
|
||||
------
|
||||
|
||||
The new Halite web GUI is now available, a great deal of work has been put into
|
||||
Halite to make it fully event driven and amazingly fast. The Halite UI can be
|
||||
started from within the Salt Master, or standalone, and does not require an
|
||||
external database to run, it is very lightweight!
|
||||
The new Halite web GUI is now available on PyPi, a great deal of work has
|
||||
been put into Halite to make it fully event driven and amazingly fast. The
|
||||
Halite UI can be started from within the Salt Master (after being installed
|
||||
from PyPi), or standalone, and does not require an external database to run,
|
||||
it is very lightweight!
|
||||
|
||||
This initial release of Halite is primarily the framework for the UI and the
|
||||
communication systems making it easy to extend and build the UI up. It
|
||||
presently supports watching the event bus and firing commands over Salt.
|
||||
|
||||
At this time Halite is not available as a package, but installation
|
||||
documentation is available at:
|
||||
http://docs.saltstack.com/topics/tutorials/halite.html
|
||||
|
||||
Halite is, like the rest of Salt, Open Source!
|
||||
|
||||
Much more will be coming in the future of Halite!
|
||||
|
@ -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.
|
||||
|
||||
|
224
doc/topics/tutorials/halite.rst
Normal file
@ -0,0 +1,224 @@
|
||||
=================================
|
||||
Installing and Configuring Halite
|
||||
=================================
|
||||
|
||||
In this tutorial we'll walk through installing and setting up Halite. As of
|
||||
2013-10-12 a packaged version of Halite is not available, in addition the
|
||||
current version of Halite is considered pre-alpha and is supported only in
|
||||
Salt 0.17 or greater. Additional information is available on GitHub:
|
||||
https://github.com/saltstack/halite
|
||||
|
||||
Installing Halite
|
||||
=================
|
||||
|
||||
Before beginning this tutorial ensure that the salt-master is installed. To
|
||||
install the salt-master please review the installation documentation:
|
||||
http://docs.saltstack.com/topics/installation/index.html
|
||||
|
||||
.. note::
|
||||
|
||||
Halite only works with Salt versions greater than 0.17.
|
||||
|
||||
|
||||
To begin the installation of Halite you'll need to install pip. The
|
||||
Salt package, as well as the bootstrap do not install pip by default.
|
||||
|
||||
On CentOS:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ yum install python-pip
|
||||
|
||||
|
||||
On Debian:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ apt-get install python-pip
|
||||
|
||||
|
||||
Once you have pip installed, use it to install halite:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install -U halite
|
||||
|
||||
|
||||
Depending on the webserver you want to run halite through, you'll need to
|
||||
install that piece as well. On RHEL based distros use one of the following:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install cherrypy
|
||||
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install paste
|
||||
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ yum install python-devel
|
||||
$ yum install gcc
|
||||
$ pip install gevent
|
||||
|
||||
|
||||
On Debian based distributions:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install CherryPy
|
||||
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install paste
|
||||
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ apt-get install gcc
|
||||
$ apt-get install python-dev
|
||||
$ pip install gevent
|
||||
|
||||
|
||||
Configuring Halite Permissions
|
||||
==============================
|
||||
|
||||
Configuring Halite access permissions is easy. By default you only need to
|
||||
ensure that the @runner group is configured. In the /etc/salt/master file
|
||||
uncomment and modify the following lines:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
external_auth:
|
||||
pam:
|
||||
testuser:
|
||||
- .*
|
||||
- '@runner'
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
You cannot use the root user for pam login, it will fail to authenticate.
|
||||
|
||||
Halite uses the runner manage.status to get the status of minions so runner
|
||||
permissions are required. As you can see in this example the root user has
|
||||
been configured, if you aren't running Halite as the root user, you'll need
|
||||
to modify this value. For example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
external_auth:
|
||||
pam:
|
||||
mytestuser:
|
||||
- .*
|
||||
- '@runner'
|
||||
- '@wheel'
|
||||
|
||||
|
||||
Currently Halite allows, but does not require any wheel modules.
|
||||
|
||||
|
||||
Configuring Halite settings
|
||||
===========================
|
||||
|
||||
Once you've configured the permissions for Halite, you'll need to set up the
|
||||
Halite settings in the /etc/salt/master file. Halite supports CherryPy, Paste
|
||||
and Gevent out of the box.
|
||||
|
||||
To configure cherrypy add the following to the bottom of your /etc/salt/master file:
|
||||
|
||||
.. code-block: yaml
|
||||
|
||||
halite:
|
||||
level: 'debug'
|
||||
server: 'cherrypy'
|
||||
host: '0.0.0.0'
|
||||
port: '8080'
|
||||
cors: False
|
||||
tls: True
|
||||
certpath: '/etc/pki/tls/certs/localhost.crt'
|
||||
keypath: '/etc/pki/tls/certs/localhost.key'
|
||||
pempath: '/etc/pki/tls/certs/localhost.pem'
|
||||
|
||||
|
||||
If you wish to use paste:
|
||||
|
||||
.. code-block: yaml
|
||||
|
||||
halite:
|
||||
level: 'debug'
|
||||
server: 'paste'
|
||||
host: '0.0.0.0'
|
||||
port: '8080'
|
||||
cors: False
|
||||
tls: True
|
||||
certpath: '/etc/pki/tls/certs/localhost.crt'
|
||||
keypath: '/etc/pki/tls/certs/localhost.key'
|
||||
pempath: '/etc/pki/tls/certs/localhost.pem'
|
||||
|
||||
|
||||
To use gevent:
|
||||
|
||||
.. code-block: yaml
|
||||
|
||||
halite:
|
||||
level: 'debug'
|
||||
server: 'gevent'
|
||||
host: '0.0.0.0'
|
||||
port: '8080'
|
||||
cors: False
|
||||
tls: True
|
||||
certpath: '/etc/pki/tls/certs/localhost.crt'
|
||||
keypath: '/etc/pki/tls/certs/localhost.key'
|
||||
pempath: '/etc/pki/tls/certs/localhost.pem'
|
||||
|
||||
|
||||
The "cherrypy" and "gevent" servers require the certpath and keypath files
|
||||
to run tls/ssl. The .crt file holds the public cert and the .key file holds
|
||||
the private key. Whereas the "paste" server requires a single .pem file that
|
||||
contains both the cert and key. This can be created simply by concatenating
|
||||
the .crt and .key files.
|
||||
|
||||
If you want to use a self signed cert you can create one using the Salt.tls
|
||||
module:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' tls.create_ca_signed_cert test localhost
|
||||
|
||||
|
||||
When using self signed certs, browsers will need approval before accepting the
|
||||
cert. If the web application page has been cached with a non https version of
|
||||
the app then the browser cache will have to be cleared before it will
|
||||
recognize and prompt to accept the self signed certificate.
|
||||
|
||||
|
||||
Starting halite
|
||||
===============
|
||||
|
||||
Once you've configured the halite section of your /etc/salt/master, you can
|
||||
restart the salt-master service, and your halite instance will be available.
|
||||
Depending on your configuration the instance will be available either at
|
||||
http://localhost:8080/app, http://domain:8080/app, or
|
||||
http://123.456.789.012:8080/app depending on how your system is configured.
|
||||
|
||||
.. note::
|
||||
|
||||
halite requires an HTML 5 compliant browser.
|
||||
|
||||
|
||||
All logs relating to halite are logged to the default /var/log/salt/master file.
|
||||
|
||||
|
||||
Running your halite instance through nginx
|
||||
==========================================
|
||||
|
||||
|
||||
|
||||
Running your halite instance through apache
|
||||
===========================================
|
||||
|
||||
|
@ -6,15 +6,15 @@
|
||||
# LSB header
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: salt-master
|
||||
# Required-Start: $local_fs $remote_fs $network $named $time
|
||||
# Should-Start: $time ypbind smtp
|
||||
# Required-Stop: $local_fs $remote_fs $network $named $time
|
||||
# Should-Stop: ypbind smtp
|
||||
# Default-Start: 3 5
|
||||
# Default-Stop: 0 1 2 6
|
||||
# Short-Description: Salt master control daemon
|
||||
# Description: This is a daemon that controls the Salt minions.
|
||||
# Provides: salt-master
|
||||
# Required-Start: $local_fs $remote_fs $network $named $time
|
||||
# Should-Start: $time ypbind smtp
|
||||
# Required-Stop: $local_fs $remote_fs $network $named $time
|
||||
# Should-Stop: ypbind smtp
|
||||
# Default-Start: 3 5
|
||||
# Default-Stop: 0 1 2 6
|
||||
# Short-Description: Salt master control daemon
|
||||
# Description: This is a daemon that controls the Salt minions.
|
||||
### END INIT INFO
|
||||
|
||||
|
||||
@ -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
|
||||
RETVAL=$?
|
||||
;;
|
||||
*)
|
||||
echo $"Usage: $0 {start|stop|status|restart|condrestart|reload}"
|
||||
@ -141,4 +134,3 @@ case "$1" in
|
||||
;;
|
||||
esac
|
||||
exit $RETVAL
|
||||
|
||||
|
@ -6,15 +6,16 @@
|
||||
# LSB header
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: salt-minion
|
||||
# Required-Start: $local_fs $remote_fs $network $named $time
|
||||
# Should-Start: $time ypbind smtp
|
||||
# Required-Stop: $local_fs $remote_fs $network $named $time
|
||||
# Should-Stop: ypbind smtp
|
||||
# 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.
|
||||
# Provides: salt-minion
|
||||
# Required-Start: $local_fs $remote_fs $network $named $time
|
||||
# Should-Start: $time ypbind smtp
|
||||
# Required-Stop: $local_fs $remote_fs $network $named $time
|
||||
# Should-Stop: ypbind smtp
|
||||
# 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.
|
||||
### 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
|
||||
RETVAL=$?
|
||||
;;
|
||||
*)
|
||||
echo $"Usage: $0 {start|stop|status|restart|condrestart|reload}"
|
||||
|
@ -6,36 +6,27 @@
|
||||
# LSB header
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: salt-syndic
|
||||
# Required-Start: $local_fs $remote_fs $network $named $time
|
||||
# Should-Start: $time ypbind smtp
|
||||
# Required-Stop: $local_fs $remote_fs $network $named $time
|
||||
# Should-Stop: ypbind smtp
|
||||
# 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.
|
||||
# Provides: salt-syndic
|
||||
# Required-Start: $local_fs $remote_fs $network $named $time
|
||||
# Should-Start: $time ypbind smtp
|
||||
# Required-Stop: $local_fs $remote_fs $network $named $time
|
||||
# Should-Stop: ypbind smtp
|
||||
# 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.
|
||||
### 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
|
||||
;;
|
||||
reload)
|
||||
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
|
||||
RETVAL=$?
|
||||
;;
|
||||
*)
|
||||
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
|
||||
|
@ -12,7 +12,6 @@
|
||||
!include "nsDialogs.nsh"
|
||||
!include "LogicLib.nsh"
|
||||
!include "FileFunc.nsh"
|
||||
!include "nsProcess.nsh"; using plugin nsProcess
|
||||
|
||||
Var Dialog
|
||||
Var Label
|
||||
@ -127,9 +126,8 @@ ShowUnInstDetails show
|
||||
|
||||
Section "MainSection" SEC01
|
||||
|
||||
Exec "sc stop salt-minion" ;stopping service before upgrading
|
||||
${nsProcess::CloseProcess} "salt-minion.exe" $R0
|
||||
${nsProcess::Unload}
|
||||
ExecWait "net stop salt-minion" ;stopping service before upgrading
|
||||
Sleep 3000
|
||||
SetOutPath "$INSTDIR\"
|
||||
SetOverwrite try
|
||||
CreateDirectory $INSTDIR\conf\pki\minion
|
||||
@ -155,7 +153,7 @@ SectionEnd
|
||||
Function .onInstSuccess
|
||||
Exec "nssm.exe install salt-minion $INSTDIR\salt-minion.exe -c $INSTDIR\conf -l quiet"
|
||||
RMDir /R "$INSTDIR\var\cache\salt" ; removing cache from old version
|
||||
Exec "sc start salt-minion"
|
||||
ExecWait "net start salt-minion"
|
||||
FunctionEnd
|
||||
|
||||
Function un.onUninstSuccess
|
||||
@ -191,8 +189,8 @@ Function .onInit
|
||||
FunctionEnd
|
||||
|
||||
Section Uninstall
|
||||
Exec "sc stop salt-minion"
|
||||
Exec "sc delete salt-minion"
|
||||
ExecWait "net stop salt-minion"
|
||||
ExecWait "sc delete salt-minion"
|
||||
Delete "$INSTDIR\uninst.exe"
|
||||
Delete "$INSTDIR\nssm.exe"
|
||||
Delete "$INSTDIR\python*"
|
||||
|
@ -59,6 +59,23 @@ SSH_SHIM = '''/bin/sh << 'EOF'
|
||||
fi
|
||||
done
|
||||
SALT=/tmp/.salt/salt-call
|
||||
|
||||
if [ {{2}} == 'md5' ]
|
||||
then
|
||||
for md5_candidate in \\
|
||||
md5sum \\
|
||||
md5 ;
|
||||
do
|
||||
if [ $(which $md5_candidate 2>/dev/null) ]
|
||||
then
|
||||
SUMCHECK=$(which $md5_candidate)
|
||||
break
|
||||
fi
|
||||
done
|
||||
else
|
||||
SUMCHECK={{2}}
|
||||
fi
|
||||
|
||||
if [ -f $SALT ]
|
||||
then
|
||||
if [ $(cat /tmp/.salt/version) != {0} ]
|
||||
@ -80,7 +97,7 @@ SSH_SHIM = '''/bin/sh << 'EOF'
|
||||
fi
|
||||
if [ -f /tmp/.salt/salt-thin.tgz ]
|
||||
then
|
||||
[ $({{2}}sum /tmp/.salt/salt-thin.tgz | cut -f1 -d' ') = {{3}} ] && {{0}} tar xzvf /tmp/.salt/salt-thin.tgz -C /tmp/.salt
|
||||
[ $($SUMCHECK /tmp/.salt/salt-thin.tgz | cut -f1 -d' ') = {{3}} ] && {{0}} tar xzvf /tmp/.salt/salt-thin.tgz -C /tmp/.salt
|
||||
else
|
||||
install -m 0700 -d /tmp/.salt
|
||||
echo "{1}"
|
||||
@ -170,7 +187,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,11 +704,12 @@ def get_id(root_dir=None):
|
||||
fqdn = socket.getfqdn()
|
||||
if fqdn != 'localhost':
|
||||
log.info('Found minion id from getfqdn(): {0}'.format(fqdn))
|
||||
try:
|
||||
with salt.utils.fopen(id_cache, 'w') as idf:
|
||||
idf.write(fqdn)
|
||||
except (IOError, OSError) as exc:
|
||||
log.error('Could not cache minion ID: {0}'.format(exc))
|
||||
if minion_id:
|
||||
try:
|
||||
with salt.utils.fopen(id_cache, 'w') as idf:
|
||||
idf.write(fqdn)
|
||||
except (IOError, OSError) as exc:
|
||||
log.error('Could not cache minion ID: {0}'.format(exc))
|
||||
return fqdn, False
|
||||
|
||||
# Check /etc/hostname
|
||||
@ -720,11 +721,12 @@ def get_id(root_dir=None):
|
||||
'This file should not contain any whitespace.')
|
||||
else:
|
||||
if name != 'localhost':
|
||||
try:
|
||||
with salt.utils.fopen(id_cache, 'w') as idf:
|
||||
idf.write(name)
|
||||
except (IOError, OSError) as exc:
|
||||
log.error('Could not cache minion ID: {0}'.format(exc))
|
||||
if minion_id:
|
||||
try:
|
||||
with salt.utils.fopen(id_cache, 'w') as idf:
|
||||
idf.write(name)
|
||||
except (IOError, OSError) as exc:
|
||||
log.error('Could not cache minion ID: {0}'.format(exc))
|
||||
return name, False
|
||||
except (IOError, OSError):
|
||||
pass
|
||||
@ -740,12 +742,13 @@ def get_id(root_dir=None):
|
||||
if name != 'localhost':
|
||||
log.info('Found minion id in hosts file: {0}'
|
||||
.format(name))
|
||||
try:
|
||||
with salt.utils.fopen(id_cache, 'w') as idf:
|
||||
idf.write(name)
|
||||
except (IOError, OSError) as exc:
|
||||
log.error('Could not cache minion ID: {0}'
|
||||
.format(exc))
|
||||
if minion_id:
|
||||
try:
|
||||
with salt.utils.fopen(id_cache, 'w') as idf:
|
||||
idf.write(name)
|
||||
except (IOError, OSError) as exc:
|
||||
log.error('Could not cache minion ID: {0}'
|
||||
.format(exc))
|
||||
return name, False
|
||||
except (IOError, OSError):
|
||||
pass
|
||||
@ -766,12 +769,13 @@ def get_id(root_dir=None):
|
||||
if name != 'localhost':
|
||||
log.info('Found minion id in hosts file: {0}'
|
||||
.format(name))
|
||||
try:
|
||||
with salt.utils.fopen(id_cache, 'w') as idf:
|
||||
idf.write(name)
|
||||
except (IOError, OSError) as exc:
|
||||
log.error('Could not cache minion ID: {0}'
|
||||
.format(exc))
|
||||
if minion_id:
|
||||
try:
|
||||
with salt.utils.fopen(id_cache, 'w') as idf:
|
||||
idf.write(name)
|
||||
except (IOError, OSError) as exc:
|
||||
log.error('Could not cache minion ID: {0}'
|
||||
.format(exc))
|
||||
return name, False
|
||||
except IndexError:
|
||||
pass # could not split line (malformed entry?)
|
||||
@ -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:
|
||||
|
@ -141,14 +141,21 @@ def _linux_gpu_data():
|
||||
'The `lspci` binary is not available on the system. GPU grains '
|
||||
'will not be available.'
|
||||
)
|
||||
return {}
|
||||
return {}
|
||||
|
||||
<<<<<<< HEAD
|
||||
elif __opts__.get('enable_gpu_grains', None) is False:
|
||||
log.info(
|
||||
'Skipping lspci call because enable_gpu_grains was set to False in the config. '
|
||||
'GPU grains will not be available.'
|
||||
)
|
||||
return {}
|
||||
elif __opts__.get('enable_gpu_grains', None) is False:
|
||||
log.info(
|
||||
'Skipping lspci call because enable_gpu_grains was set to False in the config. '
|
||||
'GPU grains will not be available.'
|
||||
)
|
||||
return {}
|
||||
|
||||
# dominant gpu vendors to search for (MUST be lowercase for matching below)
|
||||
known_vendors = ['nvidia', 'amd', 'ati', 'intel']
|
||||
|
@ -276,7 +276,6 @@ class MasterMinion(object):
|
||||
self.mk_rend = rend
|
||||
self.mk_matcher = matcher
|
||||
self.gen_modules()
|
||||
self.grains_cache = self.opts['grains']
|
||||
|
||||
def gen_modules(self):
|
||||
'''
|
||||
@ -502,6 +501,7 @@ class Minion(object):
|
||||
self.opts,
|
||||
self.functions,
|
||||
self.returners)
|
||||
self.grains_cache = self.opts['grains']
|
||||
|
||||
def __prep_mod_opts(self):
|
||||
'''
|
||||
@ -930,7 +930,6 @@ class Minion(object):
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@property
|
||||
def master_pub(self):
|
||||
'''
|
||||
@ -1160,13 +1159,13 @@ class Minion(object):
|
||||
if self.opts['grains_refresh_every']: # If exists and is not zero. In minutes, not seconds!
|
||||
if self.opts['grains_refresh_every'] > 1:
|
||||
log.debug(
|
||||
"Enabling the grains refresher. Will run every {0} minutes.".format\
|
||||
(self.opts['grains_refresh_every'])
|
||||
'Enabling the grains refresher. Will run every {0} minutes.'.format(
|
||||
self.opts['grains_refresh_every'])
|
||||
)
|
||||
else: # Clean up minute vs. minutes in log message
|
||||
log.debug(
|
||||
"Enabling the grains refresher. Will run every {0} minute.".format\
|
||||
(self.opts['grains_refresh_every'])
|
||||
'Enabling the grains refresher. Will run every {0} minute.'.format(
|
||||
self.opts['grains_refresh_every'])
|
||||
|
||||
)
|
||||
self._refresh_grains_watcher(
|
||||
|
@ -384,11 +384,10 @@ def install(name=None,
|
||||
if pkg_params is None or len(pkg_params) == 0:
|
||||
return {}
|
||||
elif pkg_type == 'file':
|
||||
cmd = 'dpkg -i {confold} {verify} {pkg}'.format(
|
||||
confold='--force-confold',
|
||||
verify='--force-bad-verify' if skip_verify else '',
|
||||
pkg=' '.join(pkg_params),
|
||||
)
|
||||
cmd = ['dpkg', '-i', '--force-confold']
|
||||
if skip_verify:
|
||||
cmd.append('--force-bad-verify')
|
||||
cmd.extend(pkg_params)
|
||||
elif pkg_type == 'repository':
|
||||
if pkgs is None and kwargs.get('version') and len(pkg_params) == 1:
|
||||
# Only use the 'version' param if 'name' was not specified as a
|
||||
|
@ -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,
|
||||
@ -2523,12 +2672,11 @@ def mknod(name,
|
||||
|
||||
def list_backups(path, limit=None):
|
||||
'''
|
||||
.. note::
|
||||
This function will be available in version 0.17.0.
|
||||
|
||||
Lists the previous versions of a file backed up using Salt's :doc:`file
|
||||
state backup </ref/states/backup_mode>` system.
|
||||
|
||||
.. versionadded:: 0.17.0
|
||||
|
||||
path
|
||||
The path on the minion to check for backups
|
||||
limit
|
||||
@ -2579,12 +2727,11 @@ list_backup = list_backups
|
||||
|
||||
def restore_backup(path, backup_id):
|
||||
'''
|
||||
.. note::
|
||||
This function will be available in version 0.17.0.
|
||||
|
||||
Restore a previous version of a file that was backed up using Salt's
|
||||
:doc:`file state backup </ref/states/backup_mode>` system.
|
||||
|
||||
.. versionadded:: 0.17.0
|
||||
|
||||
path
|
||||
The path on the minion to check for backups
|
||||
backup_id
|
||||
@ -2639,12 +2786,11 @@ def restore_backup(path, backup_id):
|
||||
|
||||
def delete_backup(path, backup_id):
|
||||
'''
|
||||
.. note::
|
||||
This function will be available in version 0.17.0.
|
||||
|
||||
Restore a previous version of a file that was backed up using Salt's
|
||||
:doc:`file state backup </ref/states/backup_mode>` system.
|
||||
|
||||
.. versionadded:: 0.17.0
|
||||
|
||||
path
|
||||
The path on the minion to check for backups
|
||||
backup_id
|
||||
|
@ -3,6 +3,10 @@
|
||||
Module to provide MySQL compatibility to salt.
|
||||
|
||||
:depends: - MySQLdb Python module
|
||||
.. note::
|
||||
|
||||
On CentOS 5 (and possibly RHEL 5) both MySQL-python and python26-mysqldb need to be installed.
|
||||
|
||||
:configuration: In order to connect to MySQL, certain configuration is required
|
||||
in /etc/salt/minion on the relevant minions. Some sample configs might look
|
||||
like::
|
||||
@ -30,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
|
||||
@ -187,7 +189,7 @@ def _grant_to_tokens(grant):
|
||||
continue
|
||||
|
||||
if phrase == 'grants':
|
||||
if token[-1:] == ',' or exploded_grant[position_tracker+1] == 'ON': # Read-ahead
|
||||
if token.endswith(',') or exploded_grant[position_tracker+1] == 'ON': # Read-ahead
|
||||
cleaned_token = token.rstrip(',')
|
||||
if multiword_statement:
|
||||
multiword_statement.append(cleaned_token)
|
||||
@ -208,14 +210,10 @@ def _grant_to_tokens(grant):
|
||||
|
||||
position_tracker += 1
|
||||
|
||||
return {
|
||||
'user': user,
|
||||
'host': host,
|
||||
'grant': grant_tokens,
|
||||
'database': database,
|
||||
|
||||
}
|
||||
|
||||
return dict(user=user,
|
||||
host=host,
|
||||
grant=grant_tokens,
|
||||
database=database)
|
||||
|
||||
|
||||
def query(database, query, **connection_args):
|
||||
@ -968,6 +966,15 @@ def user_remove(user,
|
||||
return False
|
||||
|
||||
|
||||
def tokenize_grant(grant):
|
||||
'''
|
||||
External wrapper function
|
||||
:param grant:
|
||||
:return: dict
|
||||
'''
|
||||
return _grant_to_tokens(grant)
|
||||
|
||||
|
||||
# Maintenance
|
||||
def db_check(name,
|
||||
table=None,
|
||||
@ -1142,9 +1149,6 @@ def grant_exists(grant,
|
||||
|
||||
salt '*' mysql.grant_exists 'SELECT,INSERT,UPDATE,...' 'database.*' 'frank' 'localhost'
|
||||
'''
|
||||
# TODO: This function is a bit tricky, since it requires the ordering to
|
||||
# be exactly the same. Perhaps should be replaced/reworked with a
|
||||
# better/cleaner solution.
|
||||
target = __grant_generate(
|
||||
grant, database, user, host, grant_option, escape
|
||||
)
|
||||
@ -1154,17 +1158,18 @@ def grant_exists(grant,
|
||||
for grant in grants:
|
||||
try:
|
||||
target_tokens = None
|
||||
if not target_tokens: # Avoid the overhead of re-calc in loop
|
||||
if not target_tokens: # Avoid the overhead of re-calc in loop
|
||||
target_tokens = _grant_to_tokens(target)
|
||||
grant_tokens = _grant_to_tokens(grant)
|
||||
if grant_tokens['user'] == target_tokens['user'] and \
|
||||
grant_tokens['database'] == target_tokens['database'] and \
|
||||
grant_tokens['host'] == target_tokens['host']:
|
||||
if set(grant_tokens['grant']) == set(target_tokens['grant']):
|
||||
return True
|
||||
grant_tokens['database'] == target_tokens['database'] and \
|
||||
grant_tokens['host'] == target_tokens['host'] and \
|
||||
set(grant_tokens['grant']) == set(target_tokens['grant']):
|
||||
log.debug(grant_tokens)
|
||||
log.debug(target_tokens)
|
||||
return True
|
||||
|
||||
except Exception as exc: # Fallback to strict parsing
|
||||
log.debug("OH NO CAUGHT EXCEPTION: {0}".format(exc))
|
||||
if grants is not False and target in grants:
|
||||
log.debug('Grant exists.')
|
||||
return True
|
||||
@ -1173,7 +1178,6 @@ def grant_exists(grant,
|
||||
return False
|
||||
|
||||
|
||||
|
||||
def grant_add(grant,
|
||||
database,
|
||||
user,
|
||||
|
@ -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,45 +461,43 @@ 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': {},
|
||||
'accessIPv4': item.accessIPv4,
|
||||
'accessIPv6': item.accessIPv6,
|
||||
'addresses': item.addresses,
|
||||
'config_drive': item.config_drive,
|
||||
'created': item.created,
|
||||
'flavor': {'id': item.flavor['id'],
|
||||
'links': item.flavor['links']},
|
||||
'hostId': item.hostId,
|
||||
'id': item.id,
|
||||
'image': {'id': item.image['id'],
|
||||
'links': item.image['links']},
|
||||
'key_name': item.key_name,
|
||||
'links': item.links,
|
||||
'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,
|
||||
'user_id': item.user_id,
|
||||
}
|
||||
ret[item.name] = {
|
||||
'OS-EXT-SRV-ATTR': {},
|
||||
'OS-EXT-STS': {},
|
||||
'accessIPv4': item.accessIPv4,
|
||||
'accessIPv6': item.accessIPv6,
|
||||
'addresses': item.addresses,
|
||||
'config_drive': item.config_drive,
|
||||
'created': item.created,
|
||||
'flavor': {'id': item.flavor['id'],
|
||||
'links': item.flavor['links']},
|
||||
'hostId': item.hostId,
|
||||
'id': item.id,
|
||||
'image': {'id': item.image['id'],
|
||||
'links': item.image['links']},
|
||||
'key_name': item.key_name,
|
||||
'links': item.links,
|
||||
'metadata': item.metadata,
|
||||
'name': item.name,
|
||||
'progress': item.progress,
|
||||
'status': item.status,
|
||||
'tenant_id': item.tenant_id,
|
||||
'updated': item.updated,
|
||||
'user_id': item.user_id,
|
||||
}
|
||||
if hasattr(item.__dict__, 'OS-DCF:diskConfig'):
|
||||
ret[item.name]['OS-DCF'] = {
|
||||
'diskConfig': item.__dict__['OS-DCF:diskConfig']
|
||||
@ -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
|
||||
|
||||
|
||||
|
@ -767,8 +767,9 @@ def list_(prefix=None,
|
||||
raise CommandExecutionError(result['stderr'])
|
||||
|
||||
for line in result['stdout'].splitlines():
|
||||
if line.startswith('-f'):
|
||||
if line.startswith('-f') or line.startswith('#'):
|
||||
# ignore -f line as it contains --find-links directory
|
||||
# ignore comment lines
|
||||
continue
|
||||
elif line.startswith('-e'):
|
||||
line = line.split('-e ')[1]
|
||||
|
@ -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.append(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):
|
||||
|
@ -2214,7 +2214,7 @@ class BaseHighState(object):
|
||||
statefiles = fnmatch.filter(self.avail[env], sls_match)
|
||||
if not statefiles:
|
||||
# No matching sls file was found! Output an error
|
||||
log.error(
|
||||
all_errors.append(
|
||||
'No matching sls found for \'{0}\' in env \'{1}\''
|
||||
.format(sls_match, env)
|
||||
)
|
||||
|
@ -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
|
||||
|
@ -69,6 +69,7 @@ def present(name,
|
||||
host='localhost',
|
||||
grant_option=False,
|
||||
escape=True,
|
||||
revoke_first=False,
|
||||
**connection_args):
|
||||
'''
|
||||
Ensure that the grant is present with the specified properties
|
||||
@ -93,6 +94,22 @@ def present(name,
|
||||
|
||||
escape
|
||||
Defines if the database value gets escaped or not. default: True
|
||||
|
||||
revoke_first
|
||||
By default, MySQL will not do anything if you issue a command to grant
|
||||
privileges that are more restrictive than what's already in place. This
|
||||
effectively means that you cannot downgrade permissions without first
|
||||
revoking permissions applied to a db.table/user pair first.
|
||||
|
||||
To have Salt forcibly revoke perms before applying a new grant, enable
|
||||
the 'revoke_first options.
|
||||
|
||||
WARNING: This will *remove* permissions for a database before attempting to apply
|
||||
new permissions. There is no guarantee that new permissions will be applied correctly
|
||||
which can leave your database security in an unknown and potentially dangerous state.
|
||||
Use with caution!
|
||||
|
||||
default: False
|
||||
'''
|
||||
comment = 'Grant {0} on {1} to {2}@{3} is already present'
|
||||
ret = {'name': name,
|
||||
@ -111,6 +128,19 @@ def present(name,
|
||||
ret['comment'] = err
|
||||
ret['result'] = False
|
||||
return ret
|
||||
if revoke_first:
|
||||
# for each grant, break into tokens and see if its on the same user/db as ours. (there is probably only one)
|
||||
for user_grant in __salt__['mysql.user_grants'](user, host, **connection_args):
|
||||
if __salt__['mysql.tokenize_grant'](user_grant)['database'].replace('`', '')\
|
||||
== database.replace('`', ''):
|
||||
grant_to_revoke = ','.join(__salt__['mysql.tokenize_grant'](user_grant)['grant']).rstrip(',')
|
||||
__salt__['mysql.grant_revoke'](grant_to_revoke,
|
||||
database,
|
||||
user,
|
||||
host=host,
|
||||
grant_option=grant_option,
|
||||
escape=escape,
|
||||
connection_args=connection_args) # Probably needs some ordering love
|
||||
|
||||
# The grant is not present, make it!
|
||||
if __opts__['test']:
|
||||
|
@ -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
|
||||
|
@ -220,7 +220,7 @@ def daemonize(redirect_out=True):
|
||||
# not cleanly redirected and the parent process dies when the
|
||||
# multiprocessing process attempts to access stdout or err.
|
||||
if redirect_out:
|
||||
dev_null = open('/dev/null', 'rw')
|
||||
dev_null = open('/dev/null', 'w')
|
||||
os.dup2(dev_null.fileno(), sys.stdin.fileno())
|
||||
os.dup2(dev_null.fileno(), sys.stdout.fileno())
|
||||
os.dup2(dev_null.fileno(), sys.stderr.fileno())
|
||||
|
@ -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
|
||||
|
@ -69,7 +69,7 @@ class CMDModuleTest(integration.ModuleCase):
|
||||
|
||||
environment2 = os.environ.copy()
|
||||
|
||||
self.assertEquals(environment, environment2)
|
||||
self.assertEqual(environment, environment2)
|
||||
|
||||
getpwnam_mock.assert_called_with('foobar')
|
||||
loads_mock.assert_called_with('{}')
|
||||
|
@ -134,7 +134,7 @@ class FileTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
|
||||
)
|
||||
|
||||
changes = ret.values()[0]['changes']
|
||||
self.assertEquals('<show_diff=False>', changes['diff'])
|
||||
self.assertEqual('<show_diff=False>', changes['diff'])
|
||||
|
||||
def test_directory(self):
|
||||
'''
|
||||
|
@ -282,21 +282,21 @@ class ConfigTestCase(TestCase):
|
||||
)
|
||||
syndic_opts.update(salt.minion.resolve_dns(syndic_opts))
|
||||
# id & pki dir are shared & so configured on the minion side
|
||||
self.assertEquals(syndic_opts['id'], 'minion')
|
||||
self.assertEquals(syndic_opts['pki_dir'], '/tmp/salttest/pki')
|
||||
self.assertEqual(syndic_opts['id'], 'minion')
|
||||
self.assertEqual(syndic_opts['pki_dir'], '/tmp/salttest/pki')
|
||||
# the rest is configured master side
|
||||
self.assertEquals(syndic_opts['master_uri'], 'tcp://127.0.0.1:54506')
|
||||
self.assertEquals(syndic_opts['master_port'], 54506)
|
||||
self.assertEquals(syndic_opts['master_ip'], '127.0.0.1')
|
||||
self.assertEquals(syndic_opts['master'], 'localhost')
|
||||
self.assertEquals(syndic_opts['sock_dir'], '/tmp/salttest/minion_sock')
|
||||
self.assertEquals(syndic_opts['cachedir'], '/tmp/salttest/cachedir')
|
||||
self.assertEquals(syndic_opts['log_file'], '/tmp/salttest/osyndic.log')
|
||||
self.assertEquals(syndic_opts['pidfile'], '/tmp/salttest/osyndic.pid')
|
||||
self.assertEqual(syndic_opts['master_uri'], 'tcp://127.0.0.1:54506')
|
||||
self.assertEqual(syndic_opts['master_port'], 54506)
|
||||
self.assertEqual(syndic_opts['master_ip'], '127.0.0.1')
|
||||
self.assertEqual(syndic_opts['master'], 'localhost')
|
||||
self.assertEqual(syndic_opts['sock_dir'], '/tmp/salttest/minion_sock')
|
||||
self.assertEqual(syndic_opts['cachedir'], '/tmp/salttest/cachedir')
|
||||
self.assertEqual(syndic_opts['log_file'], '/tmp/salttest/osyndic.log')
|
||||
self.assertEqual(syndic_opts['pidfile'], '/tmp/salttest/osyndic.pid')
|
||||
# Show that the options of localclient that repub to local master
|
||||
# are not merged with syndic ones
|
||||
self.assertEquals(syndic_opts['_master_conf_file'], minion_config_path)
|
||||
self.assertEquals(syndic_opts['_minion_conf_file'], syndic_conf_path)
|
||||
self.assertEqual(syndic_opts['_master_conf_file'], minion_config_path)
|
||||
self.assertEqual(syndic_opts['_minion_conf_file'], syndic_conf_path)
|
||||
|
||||
def test_check_dns_deprecation_warning(self):
|
||||
helium_version = SaltStackVersion.from_name('Helium')
|
||||
|
@ -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):
|
||||
@ -116,7 +253,7 @@ class FileModuleTestCase(TestCase):
|
||||
filemod.sed(path, before, after, limit=limit)
|
||||
|
||||
with open(path, 'rb') as newfile:
|
||||
self.assertEquals(
|
||||
self.assertEqual(
|
||||
SED_CONTENT.replace(before, ''),
|
||||
newfile.read()
|
||||
)
|
||||
@ -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)
|
||||
|
@ -29,7 +29,7 @@ class PostgresTestCase(TestCase):
|
||||
postgres._run_psql('echo "hi"')
|
||||
cmd = SALT_STUB['cmd.run_all']
|
||||
|
||||
self.assertEquals('postgres', cmd.call_args[1]['runas'])
|
||||
self.assertEqual('postgres', cmd.call_args[1]['runas'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -39,16 +39,16 @@ class TestFileState(TestCase):
|
||||
}
|
||||
|
||||
filestate.serialize('/tmp', dataset)
|
||||
self.assertEquals(yaml.load(returner.returned), dataset)
|
||||
self.assertEqual(yaml.load(returner.returned), dataset)
|
||||
|
||||
filestate.serialize('/tmp', dataset, formatter="yaml")
|
||||
self.assertEquals(yaml.load(returner.returned), dataset)
|
||||
self.assertEqual(yaml.load(returner.returned), dataset)
|
||||
|
||||
filestate.serialize('/tmp', dataset, formatter="json")
|
||||
self.assertEquals(json.loads(returner.returned), dataset)
|
||||
self.assertEqual(json.loads(returner.returned), dataset)
|
||||
|
||||
filestate.serialize('/tmp', dataset, formatter="python")
|
||||
self.assertEquals(returner.returned, pprint.pformat(dataset))
|
||||
self.assertEqual(returner.returned, pprint.pformat(dataset))
|
||||
|
||||
def test_contents_and_contents_pillar(self):
|
||||
def returner(contents, *args, **kwargs):
|
||||
@ -63,7 +63,7 @@ class TestFileState(TestCase):
|
||||
filestate.__salt__['config.manage_mode'] = manage_mode_mock
|
||||
|
||||
ret = filestate.managed('/tmp/foo', contents='hi', contents_pillar='foo:bar')
|
||||
self.assertEquals(False, ret['result'])
|
||||
self.assertEqual(False, ret['result'])
|
||||
|
||||
def test_contents_pillar_adds_newline(self):
|
||||
# make sure the newline
|
||||
@ -105,10 +105,10 @@ class TestFileState(TestCase):
|
||||
pillar_mock.assert_called_once_with(pillar_path)
|
||||
|
||||
# make sure no errors are returned
|
||||
self.assertEquals(None, ret)
|
||||
self.assertEqual(None, ret)
|
||||
|
||||
# make sure the value is correct
|
||||
self.assertEquals(expected, returner.returned[1][-1])
|
||||
self.assertEqual(expected, returner.returned[1][-1])
|
||||
|
||||
if __name__ == '__main__':
|
||||
from integration import run_tests
|
||||
|
@ -292,7 +292,7 @@ class TestCustomExtensions(TestCase):
|
||||
}
|
||||
env = Environment(extensions=[SerializerExtension])
|
||||
rendered = env.from_string('{{ dataset|json }}').render(dataset=dataset)
|
||||
self.assertEquals(dataset, json.loads(rendered))
|
||||
self.assertEqual(dataset, json.loads(rendered))
|
||||
|
||||
def test_serialize_yaml(self):
|
||||
dataset = {
|
||||
@ -303,7 +303,7 @@ class TestCustomExtensions(TestCase):
|
||||
}
|
||||
env = Environment(extensions=[SerializerExtension])
|
||||
rendered = env.from_string('{{ dataset|yaml }}').render(dataset=dataset)
|
||||
self.assertEquals(dataset, yaml.load(rendered))
|
||||
self.assertEqual(dataset, yaml.load(rendered))
|
||||
|
||||
def test_serialize_python(self):
|
||||
dataset = {
|
||||
@ -314,16 +314,16 @@ class TestCustomExtensions(TestCase):
|
||||
}
|
||||
env = Environment(extensions=[SerializerExtension])
|
||||
rendered = env.from_string('{{ dataset|python }}').render(dataset=dataset)
|
||||
self.assertEquals(rendered, pprint.pformat(dataset))
|
||||
self.assertEqual(rendered, pprint.pformat(dataset))
|
||||
|
||||
def test_load_yaml(self):
|
||||
env = Environment(extensions=[SerializerExtension])
|
||||
rendered = env.from_string('{% set document = "{foo: it works}"|load_yaml %}{{ document.foo }}').render()
|
||||
self.assertEquals(rendered, u"it works")
|
||||
self.assertEqual(rendered, u"it works")
|
||||
|
||||
rendered = env.from_string('{% set document = document|load_yaml %}'
|
||||
'{{ document.foo }}').render(document="{foo: it works}")
|
||||
self.assertEquals(rendered, u"it works")
|
||||
self.assertEqual(rendered, u"it works")
|
||||
|
||||
with self.assertRaises(exceptions.TemplateRuntimeError):
|
||||
env.from_string('{% set document = document|load_yaml %}'
|
||||
@ -337,13 +337,13 @@ class TestCustomExtensions(TestCase):
|
||||
'{{ docu.foo }}'
|
||||
|
||||
rendered = env.from_string(source).render(bar="barred")
|
||||
self.assertEquals(rendered, u"barred, it works")
|
||||
self.assertEqual(rendered, u"barred, it works")
|
||||
|
||||
source = '{{ bar }}, {% load_json as docu %}{"foo": "it works", "{{ bar }}": "baz"}{% endload %}' + \
|
||||
'{{ docu.foo }}'
|
||||
|
||||
rendered = env.from_string(source).render(bar="barred")
|
||||
self.assertEquals(rendered, u"barred, it works")
|
||||
self.assertEqual(rendered, u"barred, it works")
|
||||
|
||||
with self.assertRaises(exceptions.TemplateSyntaxError):
|
||||
env.from_string('{% load_yamle as document %}{foo, bar: it works}{% endload %}').render()
|
||||
@ -356,11 +356,11 @@ class TestCustomExtensions(TestCase):
|
||||
env = Environment(extensions=[SerializerExtension])
|
||||
rendered = env.from_string('{% set document = \'{"foo": "it works"}\'|load_json %}'
|
||||
'{{ document.foo }}').render()
|
||||
self.assertEquals(rendered, u"it works")
|
||||
self.assertEqual(rendered, u"it works")
|
||||
|
||||
rendered = env.from_string('{% set document = document|load_json %}'
|
||||
'{{ document.foo }}').render(document='{"foo": "it works"}')
|
||||
self.assertEquals(rendered, u"it works")
|
||||
self.assertEqual(rendered, u"it works")
|
||||
|
||||
# bad quotes
|
||||
with self.assertRaises(exceptions.TemplateRuntimeError):
|
||||
@ -374,7 +374,7 @@ class TestCustomExtensions(TestCase):
|
||||
loader = DictLoader({'foo': '{bar: "my god is blue", foo: [1, 2, 3]}'})
|
||||
env = Environment(extensions=[SerializerExtension], loader=loader)
|
||||
rendered = env.from_string('{% import_yaml "foo" as doc %}{{ doc.bar }}').render()
|
||||
self.assertEquals(rendered, u"my god is blue")
|
||||
self.assertEqual(rendered, u"my god is blue")
|
||||
|
||||
with self.assertRaises(exceptions.TemplateNotFound):
|
||||
env.from_string('{% import_yaml "does not exists" as doc %}').render()
|
||||
@ -383,7 +383,7 @@ class TestCustomExtensions(TestCase):
|
||||
loader = DictLoader({'foo': '{"bar": "my god is blue", "foo": [1, 2, 3]}'})
|
||||
env = Environment(extensions=[SerializerExtension], loader=loader)
|
||||
rendered = env.from_string('{% import_json "foo" as doc %}{{ doc.bar }}').render()
|
||||
self.assertEquals(rendered, u"my god is blue")
|
||||
self.assertEqual(rendered, u"my god is blue")
|
||||
|
||||
with self.assertRaises(exceptions.TemplateNotFound):
|
||||
env.from_string('{% import_json "does not exists" as doc %}').render()
|
||||
@ -420,22 +420,22 @@ class TestCustomExtensions(TestCase):
|
||||
|
||||
env = Environment(extensions=[SerializerExtension], loader=loader)
|
||||
rendered = env.get_template('main1').render()
|
||||
self.assertEquals(rendered, u"my god is blue")
|
||||
self.assertEqual(rendered, u"my god is blue")
|
||||
|
||||
rendered = env.get_template('main2').render()
|
||||
self.assertEquals(rendered, u"it works")
|
||||
self.assertEqual(rendered, u"it works")
|
||||
|
||||
rendered = env.get_template('main3').render().strip()
|
||||
self.assertEquals(rendered, u"my god is blue")
|
||||
self.assertEqual(rendered, u"my god is blue")
|
||||
|
||||
rendered = env.get_template('main4').render().strip()
|
||||
self.assertEquals(rendered, u"it works")
|
||||
self.assertEqual(rendered, u"it works")
|
||||
|
||||
rendered = env.get_template('main5').render().strip()
|
||||
self.assertEquals(rendered, u"my god is blue")
|
||||
self.assertEqual(rendered, u"my god is blue")
|
||||
|
||||
rendered = env.get_template('main6').render().strip()
|
||||
self.assertEquals(rendered, u"it works")
|
||||
self.assertEqual(rendered, u"it works")
|
||||
|
||||
# def test_print(self):
|
||||
# env = Environment(extensions=[SerializerExtension])
|
||||
|