#!/usr/bin/env python2 # This script downloads the latest version of Compass and installs it on # non-windows platforms. import json import os import os.path as path import shutil import subprocess import sys import tempfile import platform import time import urllib def get_pkg_format(): """Determine the package manager for this Linux distro.""" with open(os.devnull, 'w') as fnull: try: subprocess.call(['apt-get', '--help'], stdout=fnull, stderr=fnull) return 'apt' except: pass try: subprocess.call(['dnf', '--help'], stdout=fnull, stderr=fnull) return 'dnf' except: pass try: subprocess.call(['yum', '--help'], stdout=fnull, stderr=fnull) return 'yum' except: pass return '' def download_progress(count, block_size, total_size): """Log the download progress.""" percent = int(count * block_size * 100 / total_size) sys.stdout.write("\rDownloading Compass... %d%%" % percent) sys.stdout.flush() def download_pkg(link, pkg_format=''): """Download the package from link, logging progress. Returns the filename.""" suf = '' if pkg_format == 'apt': suf = '.deb' elif pkg_format == 'yum' or pkg_format == 'dnf': suf = '.rpm' tmpf = tempfile.mkstemp(suffix=suf) res = urllib.urlretrieve(link, filename=tmpf[1], reporthook=download_progress) # Download progress doesn't end with a newline so add it here. print '' return res[0] def install_mac(dmg): """Use CLI tools to mount the dmg and extract all .apps into Applications.""" tmp = tempfile.mkdtemp() with open(os.devnull, 'w') as fnull: subprocess.check_call(['hdiutil', 'attach', '-nobrowse', '-noautoopen', '-mountpoint', tmp, dmg], stdout=fnull, stderr=fnull) try: apps = [f for f in os.listdir(tmp) if f.endswith('.app')] for app in apps: if path.isdir('/Applications/' + app): print 'Old version found removing...' shutil.rmtree('/Applications/' + app) print 'Copying %s to /Applications' % app shutil.copytree(path.join(tmp, app), '/Applications/' + app) # We don't really care about what errors come up here. Just log the failure # and use the finally to make sure we always unmount the dmg. except Exception as exception: print exception finally: subprocess.check_call(['hdiutil', 'detach', tmp], stdout=fnull, stderr=fnull) if path.isdir('/Applications/MongoDB Compass.app'): subprocess.check_call(['open', '/Applications/MongoDB Compass.app']) return if path.isdir('/Applications/MongoDB Compass Community.app'): subprocess.check_call(['open', '/Applications/MongoDB Compass Community.app']) return def install_linux(pkg_format, pkg_file): """Use the package manager indicated by pkg_format to install pkg_file.""" if pkg_format == 'yum': install = ['yum', 'localinstall', '--assumeyes', pkg_file] elif pkg_format == 'apt': # dpkg returns an error code when it fails to install dependencies # so just run it and let apt-get tell us if something went wrong subprocess.call(['dpkg', '--install', pkg_file]) install = ['apt-get', 'install', '-f', '--yes'] elif pkg_format == 'dnf': install = ['dnf', 'install', '--assumeyes', pkg_file] else: print 'No available installation methods.' sys.exit(1) subprocess.check_call(install) def is_supported_distro(): distro_name, version_number, extra = platform.linux_distribution() if (distro_name == 'Ubuntu' and (version_number == '14.04' or version_number == '16.04')): return True if (distro_name == 'Red Hat Enterprise Linux Server' and (float(version_number) >= 7.0)): return True return False def download_and_install_compass(): """Download and install compass for this platform.""" os_type = sys.platform pkg_format = get_pkg_format() # Sometimes sys.platform gives us 'linux2' and we only want 'linux' if os_type.startswith('linux'): os_type = 'linux' if pkg_format == 'apt': os_type += '_deb' elif pkg_format == 'yum' or pkg_format == 'dnf': os_type += '_rpm' elif os_type == 'darwin': os_type = 'osx' if os_type.startswith('linux') and os.getuid() != 0: print 'You must run this script as root.' sys.exit(1) if os_type.startswith('linux') and not is_supported_distro(): print 'You are using an unsupported Linux distribution.\n' \ 'Please visit: https://compass.mongodb.com/community-supported-platforms' \ ' to view available community supported packages.' sys.exit(1) if platform.machine() != 'x86_64': print 'Sorry, MongoDB Compass is only supported on 64 bit platforms.' \ ' If you believe you\'re seeing this message in error please open a' \ ' ticket on the SERVER project at https://jira.mongodb.org/' link = 'https://compass.mongodb.com/api/v2/download/latest/compass-community/stable/' + os_type pkg = download_pkg(link, pkg_format=pkg_format) print 'Installing the package...' if os_type == 'osx': install_mac(pkg) elif os_type.startswith('linux'): install_linux(pkg_format, pkg) else: print 'Unrecognized os_type: %s' % os_type print 'Cleaning up...' os.remove(pkg) print 'Done!' if __name__ == '__main__': download_and_install_compass()