# -*- 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 = "" 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', 'sha256')): 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 ))