salt/tests/support/win_installer.py
2018-05-27 14:09:50 -07:00

98 lines
2.6 KiB
Python

# -*- coding: utf-8 -*-
'''
:copyright: Copyright 2013-2017 by the SaltStack Team, see AUTHORS for more details.
:license: Apache 2.0, see LICENSE for more details.
tests.support.win_installer
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Fetches the binary Windows installer
'''
from __future__ import absolute_import
import hashlib
import requests
import re
PREFIX = 'Salt-Minion-'
REPO = "https://repo.saltstack.com/windows"
def iter_installers(content):
'''
Parse a list of windows installer links and their corresponding md5
checksum links.
'''
HREF_RE = "<a href=\"(.*?)\">"
installer, md5 = None, None
for m in re.finditer(HREF_RE, content):
x = m.groups()[0]
if not x.startswith(PREFIX):
continue
if x.endswith('zip'):
continue
if installer:
if x != installer + '.md5':
raise Exception("Unable to parse response")
md5 = x
yield installer, md5
installer, md5 = None, None
else:
installer = x
def split_installer(name):
'''
Return a tuple of the salt version, python verison and architecture from an
installer name.
'''
x = name[len(PREFIX):]
return x.split('-')[:3]
def latest_version(repo=REPO):
'''
Return the latest version found on the salt repository webpage.
'''
content = requests.get(repo).content.decode('utf-8')
for name, md5 in iter_installers(content):
pass
return split_installer(name)[0]
def installer_name(salt_ver, py_ver='Py2', arch='AMD64'):
'''
Create an installer file name
'''
return "Salt-Minion-{}-{}-{}-Setup.exe".format(salt_ver, py_ver, arch)
def latest_installer_name(repo=REPO, **kwargs):
'''
Fetch the latest installer name
'''
return installer_name(latest_version(repo), **kwargs)
def download_and_verify(fp, name, repo=REPO):
'''
Download an installer and verify it's contents.
'''
md5 = "{}.md5".format(name)
url = lambda x: "{}/{}".format(repo, x)
resp = requests.get(url(md5))
if resp.status_code != 200:
raise Exception("Unable to fetch installer md5")
installer_md5 = resp.text.strip().split()[0].lower()
resp = requests.get(url(name), stream=True)
if resp.status_code != 200:
raise Exception("Unable to fetch installer")
md5hsh = hashlib.md5()
for chunk in resp.iter_content(chunk_size=1024):
md5hsh.update(chunk)
fp.write(chunk)
if md5hsh.hexdigest() != installer_md5:
raise Exception("Installer's hash does not match {} != {}".format(
md5hsh.hexdigest(), installer_md5
))