vagrant-salt 0.3.2 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rst +131 -170
- data/example/complete/Vagrantfile +67 -0
- data/example/complete/salt/custom-bootstrap-salt.sh +2425 -0
- data/example/complete/salt/key/master.pem +30 -0
- data/example/complete/salt/key/master.pub +14 -0
- data/example/complete/salt/key/minion.pem +30 -0
- data/example/complete/salt/key/minion.pub +14 -0
- data/example/complete/salt/master +459 -0
- data/example/{salt/minion.conf → complete/salt/minion} +1 -2
- data/example/{salt → complete/salt}/roots/pillar/top.sls +0 -0
- data/example/complete/salt/roots/salt/nginx.sls +5 -0
- data/example/complete/salt/roots/salt/top.sls +3 -0
- data/example/masterless/Vagrantfile +18 -0
- data/example/masterless/salt/minion +219 -0
- data/example/{salt/roots/salt → masterless/salt/roots/pillar}/top.sls +0 -0
- data/example/masterless/salt/roots/salt/nginx.sls +5 -0
- data/example/masterless/salt/roots/salt/top.sls +3 -0
- data/lib/vagrant-salt.rb +16 -3
- data/lib/vagrant-salt/config.rb +103 -0
- data/lib/vagrant-salt/errors.rb +11 -0
- data/lib/vagrant-salt/plugin.rb +31 -0
- data/lib/vagrant-salt/provisioner.rb +211 -104
- data/lib/vagrant-salt/version.rb +5 -0
- data/scripts/.travis.yml +16 -0
- data/scripts/ChangeLog +39 -0
- data/scripts/LICENSE +16 -0
- data/scripts/README.rst +124 -35
- data/scripts/bootstrap-salt-minion.sh +1815 -381
- data/scripts/bootstrap-salt.sh +2425 -0
- data/scripts/salt-bootstrap.sh +2425 -0
- data/scripts/tests/README.rst +38 -0
- data/scripts/tests/bootstrap/__init__.py +11 -0
- data/{example/salt/key/KEYPAIR_GOES_HERE → scripts/tests/bootstrap/ext/__init__.py} +0 -0
- data/scripts/tests/bootstrap/ext/console.py +100 -0
- data/scripts/tests/bootstrap/ext/os_data.py +199 -0
- data/scripts/tests/bootstrap/test_install.py +586 -0
- data/scripts/tests/bootstrap/test_lint.py +27 -0
- data/scripts/tests/bootstrap/test_usage.py +28 -0
- data/scripts/tests/bootstrap/unittesting.py +216 -0
- data/scripts/tests/ext/checkbashisms +640 -0
- data/scripts/tests/install-testsuite-deps.py +99 -0
- data/scripts/tests/runtests.py +207 -0
- data/templates/locales/en.yml +14 -0
- data/vagrant-salt.gemspec +2 -2
- metadata +43 -10
- data/example/Vagrantfile +0 -26
- data/lib/vagrant_init.rb +0 -1
@@ -0,0 +1,38 @@
|
|
1
|
+
Salt Bootstrap Script - Integration Testing
|
2
|
+
===========================================
|
3
|
+
|
4
|
+
Testing ``salt-bootstrap`` requires both Python and Perl.
|
5
|
+
|
6
|
+
Yes, it's weird that a shell script uses either one of the above languages for testing itself, the
|
7
|
+
explanation though, is simple.
|
8
|
+
|
9
|
+
Perl is required because we use a script, `checkbashisms`_, which does exactly what it's name says.
|
10
|
+
In our case, it tries it's best to find non ``POSIX`` compliant code in our bootstrap script since
|
11
|
+
we require the script to be able to properly execute in any ``POSIX`` compliant shell.
|
12
|
+
|
13
|
+
Python is used in the integration tests. It greatly simplifies running these tests and can even
|
14
|
+
provide some JUnit compliant XML used to generate reports of those tests. Doing this job in shell
|
15
|
+
scripting would be too cumbersome and too complicated.
|
16
|
+
|
17
|
+
Running the tests suite
|
18
|
+
-----------------------
|
19
|
+
|
20
|
+
.. warning:: The test suite is **destructive**. It will install/un-install packages on your system.
|
21
|
+
You must run the suite using ``sudo`` or most / all of the tests will be skipped.
|
22
|
+
|
23
|
+
Running the tests suite is as simple as:
|
24
|
+
|
25
|
+
.. code:: console
|
26
|
+
|
27
|
+
sudo python tests/runtests.py
|
28
|
+
|
29
|
+
For additional information on the available options:
|
30
|
+
|
31
|
+
.. code:: console
|
32
|
+
|
33
|
+
python tests/runtests.py --help
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
.. _`checkbashisms`: http://sourceforge.net/projects/checkbaskisms/
|
38
|
+
.. vim: fenc=utf-8 spell spl=en cc=100 tw=99 fo=want sts=2 sw=2 et
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
"""
|
3
|
+
bootstrap
|
4
|
+
~~~~~~~~~
|
5
|
+
|
6
|
+
salt-bootstrap script unittesting
|
7
|
+
|
8
|
+
:codeauthor: :email:`Pedro Algarvio (pedro@algarvio.me)`
|
9
|
+
:copyright: © 2013 by the SaltStack Team, see AUTHORS for more details.
|
10
|
+
:license: Apache 2.0, see LICENSE for more details.
|
11
|
+
"""
|
File without changes
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# vim: sw=4 ts=4 fenc=utf-8
|
3
|
+
'''
|
4
|
+
getTerminalSize()
|
5
|
+
- get width and height of console
|
6
|
+
- works on linux,os x,windows,cygwin(windows)
|
7
|
+
- taken from http://stackoverflow.com/questions/566746/how-to-get-console-window-width-in-python
|
8
|
+
'''
|
9
|
+
|
10
|
+
# Import python libs
|
11
|
+
import os
|
12
|
+
import platform
|
13
|
+
import struct
|
14
|
+
import ctypes
|
15
|
+
import subprocess
|
16
|
+
import fcntl
|
17
|
+
import termios
|
18
|
+
|
19
|
+
__all__ = ['getTerminalSize']
|
20
|
+
|
21
|
+
|
22
|
+
def getTerminalSize():
|
23
|
+
current_os = platform.system()
|
24
|
+
tuple_xy=None
|
25
|
+
if current_os == 'Windows':
|
26
|
+
tuple_xy = _getTerminalSize_windows()
|
27
|
+
if tuple_xy is None:
|
28
|
+
tuple_xy = _getTerminalSize_tput()
|
29
|
+
# needed for window's python in cygwin's xterm!
|
30
|
+
if current_os == 'Linux' or current_os == 'Darwin' or current_os.startswith('CYGWIN'):
|
31
|
+
tuple_xy = _getTerminalSize_linux()
|
32
|
+
if tuple_xy is None:
|
33
|
+
print 'default'
|
34
|
+
tuple_xy = (80, 25) # default value
|
35
|
+
return tuple_xy
|
36
|
+
|
37
|
+
|
38
|
+
def _getTerminalSize_windows():
|
39
|
+
res=None
|
40
|
+
try:
|
41
|
+
# stdin handle is -10
|
42
|
+
# stdout handle is -11
|
43
|
+
# stderr handle is -12
|
44
|
+
|
45
|
+
h = ctypes.windll.kernel32.GetStdHandle(-12)
|
46
|
+
csbi = ctypes.create_string_buffer(22)
|
47
|
+
res = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
|
48
|
+
except Exception:
|
49
|
+
return None
|
50
|
+
if res:
|
51
|
+
(bufx, bufy, curx, cury, wattr,
|
52
|
+
left, top, right, bottom, maxx, maxy) = struct.unpack('hhhhHhhhhhh', csbi.raw)
|
53
|
+
sizex = right - left + 1
|
54
|
+
sizey = bottom - top + 1
|
55
|
+
return sizex, sizey
|
56
|
+
else:
|
57
|
+
return None
|
58
|
+
|
59
|
+
|
60
|
+
def _getTerminalSize_tput():
|
61
|
+
# get terminal width
|
62
|
+
# src: http://stackoverflow.com/questions/263890/how-do-i-find-the-width-height-of-a-terminal-window
|
63
|
+
try:
|
64
|
+
proc=subprocess.Popen(['tput', 'cols'],stdin=subprocess.PIPE,stdout=subprocess.PIPE)
|
65
|
+
output=proc.communicate(input=None)
|
66
|
+
cols=int(output[0])
|
67
|
+
proc=subprocess.Popen(['tput', 'lines'],stdin=subprocess.PIPE,stdout=subprocess.PIPE)
|
68
|
+
output=proc.communicate(input=None)
|
69
|
+
rows=int(output[0])
|
70
|
+
return (cols,rows)
|
71
|
+
except Exception:
|
72
|
+
return None
|
73
|
+
|
74
|
+
|
75
|
+
def _getTerminalSize_linux():
|
76
|
+
def ioctl_GWINSZ(fd):
|
77
|
+
try:
|
78
|
+
cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,'1234'))
|
79
|
+
except Exception:
|
80
|
+
return None
|
81
|
+
return cr
|
82
|
+
cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
|
83
|
+
if not cr:
|
84
|
+
try:
|
85
|
+
fd = os.open(os.ctermid(), os.O_RDONLY)
|
86
|
+
cr = ioctl_GWINSZ(fd)
|
87
|
+
os.close(fd)
|
88
|
+
except Exception:
|
89
|
+
pass
|
90
|
+
if not cr:
|
91
|
+
try:
|
92
|
+
cr = (os.environ['LINES'], os.environ['COLUMNS'])
|
93
|
+
except Exception:
|
94
|
+
return None
|
95
|
+
return int(cr[1]), int(cr[0])
|
96
|
+
|
97
|
+
|
98
|
+
if __name__ == '__main__':
|
99
|
+
sizex,sizey=getTerminalSize()
|
100
|
+
print 'width =',sizex,'height =',sizey
|
@@ -0,0 +1,199 @@
|
|
1
|
+
'''
|
2
|
+
This file was copied and adapted from salt's source code
|
3
|
+
'''
|
4
|
+
|
5
|
+
import os
|
6
|
+
import re
|
7
|
+
import sys
|
8
|
+
import platform
|
9
|
+
# Extend the default list of supported distros. This will be used for the
|
10
|
+
# /etc/DISTRO-release checking that is part of platform.linux_distribution()
|
11
|
+
from platform import _supported_dists
|
12
|
+
_supported_dists += ('arch', 'mageia', 'meego', 'vmware', 'bluewhite64',
|
13
|
+
'slamd64', 'ovs', 'system', 'mint', 'oracle')
|
14
|
+
|
15
|
+
_REPLACE_LINUX_RE = re.compile(r'linux', re.IGNORECASE)
|
16
|
+
|
17
|
+
# This maps (at most) the first ten characters (no spaces, lowercased) of
|
18
|
+
# 'osfullname' to the 'os' grain that Salt traditionally uses.
|
19
|
+
# Please see os_data() and _supported_dists.
|
20
|
+
# If your system is not detecting properly it likely needs an entry here.
|
21
|
+
_OS_NAME_MAP = {
|
22
|
+
'redhatente': 'RedHat',
|
23
|
+
'gentoobase': 'Gentoo',
|
24
|
+
'archarm': 'Arch ARM',
|
25
|
+
'arch': 'Arch',
|
26
|
+
'debian': 'Debian',
|
27
|
+
'debiangnu/': 'Debian',
|
28
|
+
'fedoraremi': 'Fedora',
|
29
|
+
'amazonami': 'Amazon',
|
30
|
+
'alt': 'ALT',
|
31
|
+
'oracleserv': 'OEL',
|
32
|
+
}
|
33
|
+
|
34
|
+
# Map the 'os' grain to the 'os_family' grain
|
35
|
+
# These should always be capitalized entries as the lookup comes
|
36
|
+
# post-_OS_NAME_MAP. If your system is having trouble with detection, please
|
37
|
+
# make sure that the 'os' grain is capitalized and working correctly first.
|
38
|
+
_OS_FAMILY_MAP = {
|
39
|
+
'Ubuntu': 'Debian',
|
40
|
+
'Fedora': 'RedHat',
|
41
|
+
'CentOS': 'RedHat',
|
42
|
+
'GoOSe': 'RedHat',
|
43
|
+
'Scientific': 'RedHat',
|
44
|
+
'Amazon': 'RedHat',
|
45
|
+
'CloudLinux': 'RedHat',
|
46
|
+
'OVS': 'RedHat',
|
47
|
+
'OEL': 'RedHat',
|
48
|
+
'Mandrake': 'Mandriva',
|
49
|
+
'ESXi': 'VMWare',
|
50
|
+
'Mint': 'Debian',
|
51
|
+
'VMWareESX': 'VMWare',
|
52
|
+
'Bluewhite64': 'Bluewhite',
|
53
|
+
'Slamd64': 'Slackware',
|
54
|
+
'SLES': 'Suse',
|
55
|
+
'SUSE Enterprise Server': 'Suse',
|
56
|
+
'SUSE Enterprise Server': 'Suse',
|
57
|
+
'SLED': 'Suse',
|
58
|
+
'openSUSE': 'Suse',
|
59
|
+
'SUSE': 'Suse',
|
60
|
+
'Solaris': 'Solaris',
|
61
|
+
'SmartOS': 'Solaris',
|
62
|
+
'Arch ARM': 'Arch',
|
63
|
+
'ALT': 'RedHat',
|
64
|
+
'Trisquel': 'Debian'
|
65
|
+
}
|
66
|
+
|
67
|
+
|
68
|
+
def os_data():
|
69
|
+
'''
|
70
|
+
Return grains pertaining to the operating system
|
71
|
+
'''
|
72
|
+
grains = {
|
73
|
+
'num_gpus': 0,
|
74
|
+
'gpus': [],
|
75
|
+
}
|
76
|
+
|
77
|
+
# Windows Server 2008 64-bit
|
78
|
+
# ('Windows', 'MINIONNAME', '2008ServerR2', '6.1.7601', 'AMD64', 'Intel64 Fam ily 6 Model 23 Stepping 6, GenuineIntel')
|
79
|
+
# Ubuntu 10.04
|
80
|
+
# ('Linux', 'MINIONNAME', '2.6.32-38-server', '#83-Ubuntu SMP Wed Jan 4 11:26:59 UTC 2012', 'x86_64', '')
|
81
|
+
(grains['kernel'], grains['nodename'],
|
82
|
+
grains['kernelrelease'], version, grains['cpuarch'], _) = platform.uname()
|
83
|
+
if sys.platform.startswith('win'):
|
84
|
+
grains['osrelease'] = grains['kernelrelease']
|
85
|
+
grains['osversion'] = grains['kernelrelease'] = version
|
86
|
+
grains['os'] = 'Windows'
|
87
|
+
grains['os_family'] = 'Windows'
|
88
|
+
return grains
|
89
|
+
elif sys.platform.startswith('linux'):
|
90
|
+
# Add lsb grains on any distro with lsb-release
|
91
|
+
try:
|
92
|
+
import lsb_release
|
93
|
+
release = lsb_release.get_distro_information()
|
94
|
+
for key, value in release.iteritems():
|
95
|
+
grains['lsb_{0}'.format(key.lower())] = value # override /etc/lsb-release
|
96
|
+
except ImportError:
|
97
|
+
# if the python library isn't available, default to regex
|
98
|
+
if os.path.isfile('/etc/lsb-release'):
|
99
|
+
with open('/etc/lsb-release') as ifile:
|
100
|
+
for line in ifile:
|
101
|
+
# Matches any possible format:
|
102
|
+
# DISTRIB_ID="Ubuntu"
|
103
|
+
# DISTRIB_ID='Mageia'
|
104
|
+
# DISTRIB_ID=Fedora
|
105
|
+
# DISTRIB_RELEASE='10.10'
|
106
|
+
# DISTRIB_CODENAME='squeeze'
|
107
|
+
# DISTRIB_DESCRIPTION='Ubuntu 10.10'
|
108
|
+
regex = re.compile('^(DISTRIB_(?:ID|RELEASE|CODENAME|DESCRIPTION))=(?:\'|")?([\w\s\.-_]+)(?:\'|")?')
|
109
|
+
match = regex.match(line.rstrip('\n'))
|
110
|
+
if match:
|
111
|
+
# Adds: lsb_distrib_{id,release,codename,description}
|
112
|
+
grains['lsb_{0}'.format(match.groups()[0].lower())] = match.groups()[1].rstrip()
|
113
|
+
elif os.path.isfile('/etc/os-release'):
|
114
|
+
# Arch ARM linux
|
115
|
+
with open('/etc/os-release') as ifile:
|
116
|
+
# Imitate lsb-release
|
117
|
+
for line in ifile:
|
118
|
+
# NAME="Arch Linux ARM"
|
119
|
+
# ID=archarm
|
120
|
+
# ID_LIKE=arch
|
121
|
+
# PRETTY_NAME="Arch Linux ARM"
|
122
|
+
# ANSI_COLOR="0;36"
|
123
|
+
# HOME_URL="http://archlinuxarm.org/"
|
124
|
+
# SUPPORT_URL="https://archlinuxarm.org/forum"
|
125
|
+
# BUG_REPORT_URL="https://github.com/archlinuxarm/PKGBUILDs/issues"
|
126
|
+
regex = re.compile('^([\w]+)=(?:\'|")?([\w\s\.-_]+)(?:\'|")?')
|
127
|
+
match = regex.match(line.rstrip('\n'))
|
128
|
+
if match:
|
129
|
+
name, value = match.groups()
|
130
|
+
if name.lower() == 'name':
|
131
|
+
grains['lsb_distrib_id'] = value.strip()
|
132
|
+
elif os.path.isfile('/etc/altlinux-release'):
|
133
|
+
# ALT Linux
|
134
|
+
grains['lsb_distrib_id'] = 'altlinux'
|
135
|
+
with open('/etc/altlinux-release') as ifile:
|
136
|
+
# This file is symlinked to from:
|
137
|
+
# /etc/fedora-release
|
138
|
+
# /etc/redhat-release
|
139
|
+
# /etc/system-release
|
140
|
+
for line in ifile:
|
141
|
+
# ALT Linux Sisyphus (unstable)
|
142
|
+
comps = line.split()
|
143
|
+
if comps[0] == 'ALT':
|
144
|
+
grains['lsb_distrib_release'] = comps[2]
|
145
|
+
grains['lsb_distrib_codename'] = \
|
146
|
+
comps[3].replace('(', '').replace(')', '')
|
147
|
+
# Use the already intelligent platform module to get distro info
|
148
|
+
(osname, osrelease, oscodename) = platform.linux_distribution(
|
149
|
+
supported_dists=_supported_dists)
|
150
|
+
# Try to assign these three names based on the lsb info, they tend to
|
151
|
+
# be more accurate than what python gets from /etc/DISTRO-release.
|
152
|
+
# It's worth noting that Ubuntu has patched their Python distribution
|
153
|
+
# so that platform.linux_distribution() does the /etc/lsb-release
|
154
|
+
# parsing, but we do it anyway here for the sake for full portability.
|
155
|
+
grains['osfullname'] = grains.get('lsb_distrib_id', osname).strip()
|
156
|
+
grains['osrelease'] = grains.get('lsb_distrib_release', osrelease).strip()
|
157
|
+
grains['oscodename'] = grains.get('lsb_distrib_codename', oscodename).strip()
|
158
|
+
distroname = _REPLACE_LINUX_RE.sub('', grains['osfullname']).strip()
|
159
|
+
# return the first ten characters with no spaces, lowercased
|
160
|
+
shortname = distroname.replace(' ', '').lower()[:10]
|
161
|
+
# this maps the long names from the /etc/DISTRO-release files to the
|
162
|
+
# traditional short names that Salt has used.
|
163
|
+
grains['os'] = _OS_NAME_MAP.get(shortname, distroname)
|
164
|
+
elif grains['kernel'] == 'SunOS':
|
165
|
+
grains['os'] = 'Solaris'
|
166
|
+
if os.path.isfile('/etc/release'):
|
167
|
+
with open('/etc/release', 'r') as fp_:
|
168
|
+
rel_data = fp_.read()
|
169
|
+
if 'SmartOS' in rel_data:
|
170
|
+
grains['os'] = 'SmartOS'
|
171
|
+
#grains.update(_sunos_cpudata(grains))
|
172
|
+
elif grains['kernel'] == 'VMkernel':
|
173
|
+
grains['os'] = 'ESXi'
|
174
|
+
elif grains['kernel'] == 'Darwin':
|
175
|
+
grains['os'] = 'MacOS'
|
176
|
+
# grains.update(_bsd_cpudata(grains))
|
177
|
+
else:
|
178
|
+
grains['os'] = grains['kernel']
|
179
|
+
if grains['kernel'] in ('FreeBSD', 'OpenBSD'):
|
180
|
+
grains['os'] = grains['kernel']
|
181
|
+
grains['os_family'] = grains['os']
|
182
|
+
grains['osfullname'] = "{0} {1}".format(grains['kernel'], grains['kernelrelease'])
|
183
|
+
grains['osrelease'] = grains['kernelrelease']
|
184
|
+
# grains.update(_bsd_cpudata(grains))
|
185
|
+
if not grains['os']:
|
186
|
+
grains['os'] = 'Unknown {0}'.format(grains['kernel'])
|
187
|
+
grains['os_family'] = 'Unknown'
|
188
|
+
else:
|
189
|
+
# this assigns family names based on the os name
|
190
|
+
# family defaults to the os name if not found
|
191
|
+
grains['os_family'] = _OS_FAMILY_MAP.get(grains['os'], grains['os'])
|
192
|
+
|
193
|
+
return grains
|
194
|
+
|
195
|
+
GRAINS = os_data()
|
196
|
+
|
197
|
+
if __name__ == '__main__':
|
198
|
+
import pprint
|
199
|
+
pprint.pprint(GRAINS)
|
@@ -0,0 +1,586 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
'''
|
3
|
+
bootstrap.test_install
|
4
|
+
~~~~~~~~~~~~~~~~~~~~~~
|
5
|
+
|
6
|
+
Run installation tests.
|
7
|
+
|
8
|
+
:codeauthor: :email:`Pedro Algarvio (pedro@algarvio.me)`
|
9
|
+
:copyright: © 2013 by the SaltStack Team, see AUTHORS for more details.
|
10
|
+
:license: Apache 2.0, see LICENSE for more details.
|
11
|
+
'''
|
12
|
+
|
13
|
+
import glob
|
14
|
+
import shutil
|
15
|
+
from bootstrap.unittesting import *
|
16
|
+
|
17
|
+
|
18
|
+
CLEANUP_COMMANDS_BY_OS_FAMILY = {
|
19
|
+
'Arch': [
|
20
|
+
'pacman -Qs python2-crypto && pacman -Rsc --noconfirm python2-crypto && exit $? || exit 0',
|
21
|
+
'pacman -Qs python2-distribute && pacman -Rsc --noconfirm python2-distribute && exit $? || exit 0',
|
22
|
+
'pacman -Qs python2-jinja && pacman -Rsc --noconfirm python2-jinja && exit $? || exit 0',
|
23
|
+
'pacman -Qs python2-m2crypto && pacman -Rsc --noconfirm python2-m2crypto && exit $? || exit 0',
|
24
|
+
'pacman -Qs python2-markupsafe && pacman -Rsc --noconfirm python2-markupsafe && exit $? || exit 0',
|
25
|
+
'pacman -Qs python2-msgpack && pacman -Rsc --noconfirm python2-msgpack && exit $? || exit 0',
|
26
|
+
'pacman -Qs python2-psutil && pacman -Rsc --noconfirm python2-psutil && exit $? || exit 0',
|
27
|
+
'pacman -Qs python2-pyzmq && pacman -Rsc --noconfirm python2-pyzmq && exit $? || exit 0',
|
28
|
+
'pacman -Qs zeromq && pacman -Rsc --noconfirm zeromq && exit $? || exit 0',
|
29
|
+
],
|
30
|
+
'Debian': [
|
31
|
+
'apt-get remove -y -o DPkg::Options::=--force-confold '
|
32
|
+
'--purge salt-master salt-minion salt-syndic python-crypto '
|
33
|
+
'python-jinja2 python-m2crypto python-yaml msgpack-python python-zmq',
|
34
|
+
'apt-get autoremove -y -o DPkg::Options::=--force-confold --purge',
|
35
|
+
'rm -rf /etc/apt/sources.list.d/saltstack-salt-*'
|
36
|
+
],
|
37
|
+
'RedHat': [
|
38
|
+
'yum -y remove salt-minion salt-master',
|
39
|
+
'yum -y remove python{0}-m2crypto m2crypto python{0}-crypto '
|
40
|
+
'python{0}-msgpack python{0}-zmq python{0}-jinja2'.format(
|
41
|
+
GRAINS['osrelease'].split('.')[0] == '5' and '26' or ''
|
42
|
+
),
|
43
|
+
],
|
44
|
+
'FreeBSD': [
|
45
|
+
'pkg delete -y swig sysutils/py-salt',
|
46
|
+
'pkg autoremove -y'
|
47
|
+
],
|
48
|
+
'Solaris': [
|
49
|
+
'pkgin -y rm libtool-base autoconf automake libuuid gcc-compiler '
|
50
|
+
'gmake py27-setuptools py27-yaml py27-crypto swig',
|
51
|
+
'svcs network/salt-minion >/dev/null 2>&1 && svcadm disable network/salt-minion >/dev/null 2>&1 || exit 0',
|
52
|
+
'svcs network/salt-minion >/dev/null 2>&1 && svccfg delete network/salt-minion >/dev/null 2>&1 || exit 0',
|
53
|
+
'svcs network/salt-master >/dev/null 2>&1 && svcadm disable network/salt-master >/dev/null 2>&1 || exit 0',
|
54
|
+
'svcs network/salt-master >/dev/null 2>&1 && svccfg delete network/salt-master >/dev/null 2>&1 || exit 0',
|
55
|
+
'svcs network/salt-syndic >/dev/null 2>&1 && svcadm disable network/salt-syndic >/dev/null 2>&1 || exit 0',
|
56
|
+
'svcs network/salt-syndic >/dev/null 2>&1 && svccfg delete network/salt-syndic >/dev/null 2>&1 || exit 0'
|
57
|
+
],
|
58
|
+
'Suse': [
|
59
|
+
'(zypper --non-interactive se -i salt-master || exit 0 && zypper --non-interactive remove salt-master && exit 0) || '
|
60
|
+
'(rpm -q salt-master && rpm -e --noscripts salt-master || exit 0)',
|
61
|
+
'(zypper --non-interactive se -i salt-minion || exit 0 && zypper --non-interactive remove salt-minion && exit 0) || '
|
62
|
+
'(rpm -q salt-minion && rpm -e --noscripts salt-minion || exit 0)',
|
63
|
+
'(zypper --non-interactive se -i salt-syndic || exit 0 && zypper --non-interactive remove salt-syndic && exit 0) || '
|
64
|
+
'(rpm -q salt-syndic && rpm -e --noscripts salt-syndic || exit 0)',
|
65
|
+
'(zypper --non-interactive se -i salt || exit 0 && zypper --non-interactive remove salt && exit 0) || '
|
66
|
+
'(rpm -q salt && rpm -e --noscripts salt || exit 0)',
|
67
|
+
'pip uninstall -y salt >/dev/null 2>&1 || exit 0',
|
68
|
+
'pip uninstall -y PyYaml >/dev/null 2>&1 || exit 0',
|
69
|
+
'zypper --non-interactive remove libzmq3 python-Jinja2 '
|
70
|
+
'python-M2Crypto python-PyYAML python-msgpack-python '
|
71
|
+
'python-pycrypto python-pyzmq',
|
72
|
+
]
|
73
|
+
}
|
74
|
+
|
75
|
+
OS_REQUIRES_PIP_ALLOWED = (
|
76
|
+
# Some distributions can only install salt or some of its dependencies
|
77
|
+
# passing -P to the bootstrap script.
|
78
|
+
# The GRAINS['os'] which are in this list, requires that extra argument.
|
79
|
+
'Debian',
|
80
|
+
'SmartOS',
|
81
|
+
'Suse' # Need to revisit openSUSE and SLES for the proper OS grain.
|
82
|
+
)
|
83
|
+
|
84
|
+
# SLES grains differ from openSUSE, let do a 1:1 direct mapping
|
85
|
+
CLEANUP_COMMANDS_BY_OS_FAMILY['SUSE Enterprise Server'] = CLEANUP_COMMANDS_BY_OS_FAMILY['Suse']
|
86
|
+
|
87
|
+
|
88
|
+
class InstallationTestCase(BootstrapTestCase):
|
89
|
+
|
90
|
+
def setUp(self):
|
91
|
+
if os.geteuid() is not 0:
|
92
|
+
self.skipTest('you must be root to run this test')
|
93
|
+
|
94
|
+
if GRAINS['os_family'] not in CLEANUP_COMMANDS_BY_OS_FAMILY:
|
95
|
+
self.skipTest(
|
96
|
+
'There is not `tearDown()` clean up support for {0!r} OS '
|
97
|
+
'family.'.format(
|
98
|
+
GRAINS['os_family']
|
99
|
+
)
|
100
|
+
)
|
101
|
+
|
102
|
+
def tearDown(self):
|
103
|
+
for cleanup in CLEANUP_COMMANDS_BY_OS_FAMILY[GRAINS['os_family']]:
|
104
|
+
print 'Running cleanup command {0!r}'.format(cleanup)
|
105
|
+
self.assert_script_result(
|
106
|
+
'Failed to execute cleanup command {0!r}'.format(cleanup),
|
107
|
+
(
|
108
|
+
0, # Proper exit code without errors.
|
109
|
+
|
110
|
+
4, # ZYPPER_EXIT_ERR_ZYPP: A problem reported by ZYPP
|
111
|
+
# library.
|
112
|
+
|
113
|
+
65, # FreeBSD throws this error code when the packages
|
114
|
+
# being un-installed were not installed in the first
|
115
|
+
# place.
|
116
|
+
|
117
|
+
100, # Same as above but on Ubuntu with a another errno
|
118
|
+
|
119
|
+
104, # ZYPPER_EXIT_INF_CAP_NOT_FOUND: Returned by the
|
120
|
+
# install and the remove command in case any of
|
121
|
+
# the arguments does not match any of the available
|
122
|
+
# (or installed) package names or other capabilities.
|
123
|
+
),
|
124
|
+
self.run_script(
|
125
|
+
script=None,
|
126
|
+
args=cleanup.split(),
|
127
|
+
timeout=15 * 60,
|
128
|
+
stream_stds=True
|
129
|
+
)
|
130
|
+
)
|
131
|
+
|
132
|
+
# As a last resort, by hand house cleaning...
|
133
|
+
for glob_rule in ('/tmp/git', '/usr/lib*/python*/site-packages/salt*',
|
134
|
+
'/usr/bin/salt*', '/usr/lib/systemd/system/salt*',
|
135
|
+
'/etc/init*/salt*', '/usr/share/doc/salt*',
|
136
|
+
'/usr/share/man/man*/salt*', '/var/*/salt*',
|
137
|
+
'/etc/salt'):
|
138
|
+
for entry in glob.glob(glob_rule):
|
139
|
+
if os.path.isfile(entry):
|
140
|
+
print 'Removing file {0!r}'.format(entry)
|
141
|
+
os.remove(entry)
|
142
|
+
elif os.path.isdir(entry):
|
143
|
+
print 'Removing directory {0!r}'.format(entry)
|
144
|
+
shutil.rmtree(entry)
|
145
|
+
|
146
|
+
def test_install_using_bash(self):
|
147
|
+
if not os.path.exists('/bin/bash'):
|
148
|
+
self.skipTest('\'/bin/bash\' was not found on this system')
|
149
|
+
|
150
|
+
args = []
|
151
|
+
if GRAINS['os'] in OS_REQUIRES_PIP_ALLOWED:
|
152
|
+
args.append('-P')
|
153
|
+
|
154
|
+
self.assert_script_result(
|
155
|
+
'Failed to install using bash',
|
156
|
+
0,
|
157
|
+
self.run_script(
|
158
|
+
args=args,
|
159
|
+
executable='/bin/bash',
|
160
|
+
timeout=15 * 60,
|
161
|
+
stream_stds=True
|
162
|
+
)
|
163
|
+
)
|
164
|
+
|
165
|
+
# Try to get the versions report
|
166
|
+
self.assert_script_result(
|
167
|
+
'Failed to get the versions report (\'--versions-report\')',
|
168
|
+
0,
|
169
|
+
self.run_script(
|
170
|
+
script=None,
|
171
|
+
args=('salt-minion', '--versions-report'),
|
172
|
+
timeout=15 * 60,
|
173
|
+
stream_stds=True
|
174
|
+
)
|
175
|
+
)
|
176
|
+
|
177
|
+
def test_install_using_sh(self):
|
178
|
+
args = []
|
179
|
+
if GRAINS['os'] in OS_REQUIRES_PIP_ALLOWED:
|
180
|
+
args.append('-P')
|
181
|
+
|
182
|
+
self.assert_script_result(
|
183
|
+
'Failed to install using sh',
|
184
|
+
0,
|
185
|
+
self.run_script(
|
186
|
+
args=args,
|
187
|
+
timeout=15 * 60,
|
188
|
+
stream_stds=True
|
189
|
+
)
|
190
|
+
)
|
191
|
+
|
192
|
+
# Try to get the versions report
|
193
|
+
self.assert_script_result(
|
194
|
+
'Failed to get the versions report (\'--versions-report\')',
|
195
|
+
0,
|
196
|
+
self.run_script(
|
197
|
+
script=None,
|
198
|
+
args=('salt-minion', '--versions-report'),
|
199
|
+
timeout=15 * 60,
|
200
|
+
stream_stds=True
|
201
|
+
)
|
202
|
+
)
|
203
|
+
|
204
|
+
def test_install_explicit_stable(self):
|
205
|
+
args = []
|
206
|
+
if GRAINS['os'] in OS_REQUIRES_PIP_ALLOWED:
|
207
|
+
args.append('-P')
|
208
|
+
|
209
|
+
args.append('stable')
|
210
|
+
|
211
|
+
self.assert_script_result(
|
212
|
+
'Failed to install explicit stable using sh',
|
213
|
+
0,
|
214
|
+
self.run_script(
|
215
|
+
args=args,
|
216
|
+
timeout=15 * 60,
|
217
|
+
stream_stds=True
|
218
|
+
)
|
219
|
+
)
|
220
|
+
|
221
|
+
# Try to get the versions report
|
222
|
+
self.assert_script_result(
|
223
|
+
'Failed to get the versions report (\'--versions-report\')',
|
224
|
+
0,
|
225
|
+
self.run_script(
|
226
|
+
script=None,
|
227
|
+
args=('salt-minion', '--versions-report'),
|
228
|
+
timeout=15 * 60,
|
229
|
+
stream_stds=True
|
230
|
+
)
|
231
|
+
)
|
232
|
+
|
233
|
+
def test_install_daily(self):
|
234
|
+
args = []
|
235
|
+
if GRAINS['os'] in OS_REQUIRES_PIP_ALLOWED:
|
236
|
+
args.append('-P')
|
237
|
+
|
238
|
+
args.append('daily')
|
239
|
+
|
240
|
+
rc, out, err = self.run_script(
|
241
|
+
args=args, timeout=15 * 60, stream_stds=True
|
242
|
+
)
|
243
|
+
if GRAINS['os'] in ('Ubuntu', 'Trisquel'):
|
244
|
+
self.assert_script_result(
|
245
|
+
'Failed to install daily',
|
246
|
+
0, (rc, out, err)
|
247
|
+
)
|
248
|
+
|
249
|
+
# Try to get the versions report
|
250
|
+
self.assert_script_result(
|
251
|
+
'Failed to get the versions report (\'--versions-report\')',
|
252
|
+
0,
|
253
|
+
self.run_script(
|
254
|
+
script=None,
|
255
|
+
args=('salt-minion', '--versions-report'),
|
256
|
+
timeout=15 * 60,
|
257
|
+
stream_stds=True
|
258
|
+
)
|
259
|
+
)
|
260
|
+
else:
|
261
|
+
self.assert_script_result(
|
262
|
+
'Although system is not Ubuntu, we managed to install',
|
263
|
+
1, (rc, out, err)
|
264
|
+
)
|
265
|
+
|
266
|
+
def test_install_stable_piped_through_sh(self):
|
267
|
+
args = 'cat {0} | sh '.format(BOOTSTRAP_SCRIPT_PATH).split()
|
268
|
+
if GRAINS['os'] in OS_REQUIRES_PIP_ALLOWED:
|
269
|
+
args.extend('-s -- -P'.split())
|
270
|
+
|
271
|
+
self.assert_script_result(
|
272
|
+
'Failed to install stable piped through sh',
|
273
|
+
0,
|
274
|
+
self.run_script(
|
275
|
+
script=None,
|
276
|
+
args=args,
|
277
|
+
timeout=15 * 60,
|
278
|
+
stream_stds=True
|
279
|
+
)
|
280
|
+
)
|
281
|
+
|
282
|
+
# Try to get the versions report
|
283
|
+
self.assert_script_result(
|
284
|
+
'Failed to get the versions report (\'--versions-report\')',
|
285
|
+
0,
|
286
|
+
self.run_script(
|
287
|
+
script=None,
|
288
|
+
args=('salt-minion', '--versions-report'),
|
289
|
+
timeout=15 * 60,
|
290
|
+
stream_stds=True
|
291
|
+
)
|
292
|
+
)
|
293
|
+
|
294
|
+
#def test_install_latest_from_git_develop(self):
|
295
|
+
# args = []
|
296
|
+
# if GRAINS['os'] in OS_REQUIRES_PIP_ALLOWED:
|
297
|
+
# args.append('-P')
|
298
|
+
#
|
299
|
+
# args.extend(['git', 'develop'])
|
300
|
+
#
|
301
|
+
# self.assert_script_result(
|
302
|
+
# 'Failed to install using latest git develop',
|
303
|
+
# 0,
|
304
|
+
# self.run_script(
|
305
|
+
# args=args,
|
306
|
+
# timeout=15 * 60,
|
307
|
+
# stream_stds=True
|
308
|
+
# )
|
309
|
+
# )
|
310
|
+
#
|
311
|
+
# # Try to get the versions report
|
312
|
+
# self.assert_script_result(
|
313
|
+
# 'Failed to get the versions report (\'--versions-report\')',
|
314
|
+
# 0,
|
315
|
+
# self.run_script(
|
316
|
+
# script=None,
|
317
|
+
# args=('salt', '--versions-report'),
|
318
|
+
# timeout=15 * 60,
|
319
|
+
# stream_stds=True
|
320
|
+
# )
|
321
|
+
# )
|
322
|
+
|
323
|
+
def test_install_specific_git_tag(self):
|
324
|
+
args = []
|
325
|
+
if GRAINS['os'] in OS_REQUIRES_PIP_ALLOWED:
|
326
|
+
args.append('-P')
|
327
|
+
|
328
|
+
args.extend(['git', 'v0.13.1'])
|
329
|
+
|
330
|
+
self.assert_script_result(
|
331
|
+
'Failed to install using specific git tag',
|
332
|
+
0,
|
333
|
+
self.run_script(
|
334
|
+
args=args,
|
335
|
+
timeout=15 * 60,
|
336
|
+
stream_stds=True
|
337
|
+
)
|
338
|
+
)
|
339
|
+
|
340
|
+
# Try to get the versions report
|
341
|
+
self.assert_script_result(
|
342
|
+
'Failed to get the versions report (\'--versions-report\')',
|
343
|
+
0,
|
344
|
+
self.run_script(
|
345
|
+
script=None,
|
346
|
+
args=('salt', '--versions-report'),
|
347
|
+
timeout=15 * 60,
|
348
|
+
stream_stds=True
|
349
|
+
)
|
350
|
+
)
|
351
|
+
|
352
|
+
def test_install_specific_git_sha(self):
|
353
|
+
args = []
|
354
|
+
if GRAINS['os'] in OS_REQUIRES_PIP_ALLOWED:
|
355
|
+
args.append('-P')
|
356
|
+
|
357
|
+
args.extend(['git', '2b6264de62bf2ea221bb2c0b8af36dfcfaafe7cf'])
|
358
|
+
|
359
|
+
self.assert_script_result(
|
360
|
+
'Failed to install using specific git sha',
|
361
|
+
0,
|
362
|
+
self.run_script(
|
363
|
+
args=args,
|
364
|
+
timeout=15 * 60,
|
365
|
+
stream_stds=True
|
366
|
+
)
|
367
|
+
)
|
368
|
+
|
369
|
+
# Try to get the versions report
|
370
|
+
self.assert_script_result(
|
371
|
+
'Failed to get the versions report (\'--versions-report\')',
|
372
|
+
0,
|
373
|
+
self.run_script(
|
374
|
+
script=None,
|
375
|
+
args=('salt', '--versions-report'),
|
376
|
+
timeout=15 * 60,
|
377
|
+
stream_stds=True
|
378
|
+
)
|
379
|
+
)
|
380
|
+
|
381
|
+
def test_config_only_without_config_dir_fails(self):
|
382
|
+
'''
|
383
|
+
Test running in configuration mode only without providing the necessary
|
384
|
+
configuration directory fails.
|
385
|
+
'''
|
386
|
+
self.assert_script_result(
|
387
|
+
'The script successfully executed even though no configuration '
|
388
|
+
'directory was provided.',
|
389
|
+
1,
|
390
|
+
self.run_script(args=('-C',))
|
391
|
+
)
|
392
|
+
|
393
|
+
def test_config_with_a_non_existing_configuration_dir_fails(self):
|
394
|
+
'''
|
395
|
+
Do we fail if the passed configuration directory passed does not exits?
|
396
|
+
'''
|
397
|
+
self.assert_script_result(
|
398
|
+
'The script successfully executed even though the configuration '
|
399
|
+
'directory provided does not exist.',
|
400
|
+
1,
|
401
|
+
self.run_script(
|
402
|
+
args=('-C', '-c', '/tmp/this-directory-must-not-exist')
|
403
|
+
)
|
404
|
+
)
|
405
|
+
|
406
|
+
def test_config_only_without_actually_configuring_anything_fails(self):
|
407
|
+
'''
|
408
|
+
Test running in configuration mode only without actually configuring
|
409
|
+
anything fails.
|
410
|
+
'''
|
411
|
+
rc, out, err = self.run_script(
|
412
|
+
args=('-C', '-n', '-c', '/tmp'),
|
413
|
+
)
|
414
|
+
|
415
|
+
self.assert_script_result(
|
416
|
+
'The script did not show a warning even though no configuration '
|
417
|
+
'was done.',
|
418
|
+
0, (rc, out, err)
|
419
|
+
)
|
420
|
+
self.assertIn(
|
421
|
+
'WARN: No configuration or keys were copied over. No '
|
422
|
+
'configuration was done!',
|
423
|
+
'\n'.join(out)
|
424
|
+
)
|
425
|
+
|
426
|
+
def test_install_salt_master(self):
|
427
|
+
'''
|
428
|
+
Test if installing a salt-master works
|
429
|
+
'''
|
430
|
+
args = []
|
431
|
+
if GRAINS['os'] in OS_REQUIRES_PIP_ALLOWED:
|
432
|
+
args.append('-P')
|
433
|
+
|
434
|
+
args.extend(['-N', '-M'])
|
435
|
+
|
436
|
+
self.assert_script_result(
|
437
|
+
'Failed to install salt-master',
|
438
|
+
0,
|
439
|
+
self.run_script(
|
440
|
+
args=args,
|
441
|
+
timeout=15 * 60,
|
442
|
+
stream_stds=True
|
443
|
+
)
|
444
|
+
)
|
445
|
+
|
446
|
+
# Try to get the versions report
|
447
|
+
self.assert_script_result(
|
448
|
+
'Failed to get the versions report from salt-master',
|
449
|
+
0,
|
450
|
+
self.run_script(
|
451
|
+
script=None,
|
452
|
+
args=('salt-master', '--versions-report'),
|
453
|
+
timeout=15 * 60,
|
454
|
+
stream_stds=True
|
455
|
+
)
|
456
|
+
)
|
457
|
+
|
458
|
+
def test_install_salt_syndic(self):
|
459
|
+
'''
|
460
|
+
Test if installing a salt-syndic works
|
461
|
+
'''
|
462
|
+
if GRAINS['os'] == 'Debian':
|
463
|
+
self.skipTest(
|
464
|
+
'Currently the debian stable package will have the syndic '
|
465
|
+
'waiting for a connection to a master.'
|
466
|
+
)
|
467
|
+
|
468
|
+
args = []
|
469
|
+
if GRAINS['os'] in OS_REQUIRES_PIP_ALLOWED:
|
470
|
+
args.append('-P')
|
471
|
+
|
472
|
+
args.extend(['-N', '-S'])
|
473
|
+
|
474
|
+
self.assert_script_result(
|
475
|
+
'Failed to install salt-syndic',
|
476
|
+
0,
|
477
|
+
self.run_script(
|
478
|
+
args=args,
|
479
|
+
timeout=15 * 60,
|
480
|
+
stream_stds=True
|
481
|
+
)
|
482
|
+
)
|
483
|
+
|
484
|
+
# Try to get the versions report
|
485
|
+
self.assert_script_result(
|
486
|
+
'Failed to get the versions report from salt-syndic',
|
487
|
+
0,
|
488
|
+
self.run_script(
|
489
|
+
script=None,
|
490
|
+
args=('salt-syndic', '--versions-report'),
|
491
|
+
timeout=15 * 60,
|
492
|
+
stream_stds=True
|
493
|
+
)
|
494
|
+
)
|
495
|
+
|
496
|
+
def test_install_pip_not_allowed(self):
|
497
|
+
'''
|
498
|
+
Check if distributions which require `-P` to allow pip to install
|
499
|
+
packages, fail if that flag is not passed.
|
500
|
+
'''
|
501
|
+
if GRAINS['os'] not in OS_REQUIRES_PIP_ALLOWED:
|
502
|
+
self.skipTest(
|
503
|
+
'Distribution {0} does not require the extra `-P` flag'.format(
|
504
|
+
GRAINS['os']
|
505
|
+
)
|
506
|
+
)
|
507
|
+
|
508
|
+
self.assert_script_result(
|
509
|
+
'Even though {0} is flagged as requiring the extra `-P` flag to '
|
510
|
+
'allow packages to be installed by pip, it did not fail when we '
|
511
|
+
'did not pass it'.format(GRAINS['os']),
|
512
|
+
1,
|
513
|
+
self.run_script(
|
514
|
+
timeout=15 * 60,
|
515
|
+
stream_stds=True
|
516
|
+
)
|
517
|
+
)
|
518
|
+
|
519
|
+
def test_install_from_git_on_checked_out_repository(self):
|
520
|
+
'''
|
521
|
+
Check if the script properly updates an already checked out repository.
|
522
|
+
'''
|
523
|
+
if not os.path.isdir('/tmp/git'):
|
524
|
+
os.makedirs('/tmp/git')
|
525
|
+
|
526
|
+
# Clone salt from git
|
527
|
+
self.assert_script_result(
|
528
|
+
'Failed to clone salt\'s git repository',
|
529
|
+
0,
|
530
|
+
self.run_script(
|
531
|
+
script=None,
|
532
|
+
args=('git', 'clone', 'https://github.com/saltstack/salt.git'),
|
533
|
+
cwd='/tmp/git',
|
534
|
+
timeout=15 * 60,
|
535
|
+
stream_stds=True
|
536
|
+
)
|
537
|
+
)
|
538
|
+
|
539
|
+
# Check-out a specific revision
|
540
|
+
self.assert_script_result(
|
541
|
+
'Failed to checkout v0.12.1 from salt\'s cloned git repository',
|
542
|
+
0,
|
543
|
+
self.run_script(
|
544
|
+
script=None,
|
545
|
+
args=('git', 'checkout', 'v0.12.1'),
|
546
|
+
cwd='/tmp/git/salt',
|
547
|
+
timeout=15 * 60,
|
548
|
+
stream_stds=True
|
549
|
+
)
|
550
|
+
)
|
551
|
+
|
552
|
+
# Now run the bootstrap script over an existing git checkout and see
|
553
|
+
# if it properly updates.
|
554
|
+
args = []
|
555
|
+
if GRAINS['os'] in OS_REQUIRES_PIP_ALLOWED:
|
556
|
+
args.append('-P')
|
557
|
+
|
558
|
+
args.extend(['git', 'v0.13.1'])
|
559
|
+
|
560
|
+
self.assert_script_result(
|
561
|
+
'Failed to install using specific git tag',
|
562
|
+
0,
|
563
|
+
self.run_script(
|
564
|
+
args=args,
|
565
|
+
timeout=15 * 60,
|
566
|
+
stream_stds=True
|
567
|
+
)
|
568
|
+
)
|
569
|
+
|
570
|
+
# Get the version from the salt binary just installed
|
571
|
+
# Do it as a two step so we can check the returning output.
|
572
|
+
rc, out, err = self.run_script(
|
573
|
+
script=None,
|
574
|
+
args=('salt', '--version'),
|
575
|
+
timeout=15 * 60,
|
576
|
+
stream_stds=True
|
577
|
+
)
|
578
|
+
|
579
|
+
self.assert_script_result(
|
580
|
+
'Failed to get the salt version',
|
581
|
+
0, (rc, out, err)
|
582
|
+
)
|
583
|
+
|
584
|
+
# Make sure the installation updated the git repository to the proper
|
585
|
+
# git tag before installing.
|
586
|
+
self.assertIn('0.13.1', '\n'.join(out))
|