summaryrefslogtreecommitdiff
path: root/src/mongo/installer/compass/install_compass.in
blob: 87f99dafd489a6a1c1251988b4ddb74009654212 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
#!/usr/bin/env python
#!@python_interpreter@

# This script downloads the latest version of Compass and installs it on
# non-windows platforms.

import os
import os.path as path
import shutil
import subprocess
import sys
import tempfile
import platform


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'

    (_handle, filename) = tempfile.mkstemp(suffix=suf)
    try:
        subprocess.check_call(['curl', '--fail', '-L', '-o', filename, link],
                              stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    except subprocess.CalledProcessError as error:
        print 'Unable to download MongoDB Compass, please check your internet' \
            ' connection. If the issue persists go to' \
            ' https://www.mongodb.com/download-center?jmp=hero#compass' \
            ' to download the compass installer for your platform.'

    try:
        out = subprocess.check_output(['file', filename])
    except subprocess.CalledProcessError as error:
        print 'Got an unexpected error checking file type %s' % error
        sys.exit(1)

    if 'ASCII Text' in out:
        print 'Unknown package format downloaded. Appears there was an HTTP error.'
        sys.exit(1)

    return filename


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:
        try:
            subprocess.check_call(['hdiutil', 'attach', '-nobrowse', '-noautoopen',
                                    '-mountpoint', tmp, dmg], stdout=fnull, stderr=fnull)
        except subprocess.CalledProcessError as error:
            print 'Problem running hdiutil: %s' % error

        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 IOError:
            print 'Unknown error copying MongoDB Compass to /Applications/'
        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 float(version_number) >= 14.04):
        return True

    if ((distro_name == 'Red Hat Enterprise Linux Server' or
         'CentOS' in distro_name) and
            (float(version_number) >= 7.0)):
        return True

    return False


def is_supported_mac_version():
    v, _, _ = platform.mac_ver()
    # Get Mac OSX Major.Minor verson as a float
    ver_float = float('.'.join(v.split('.')[:2]))
    return ver_float >= 10.10


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 os_type == 'osx' and not is_supported_mac_version():
        print 'You are using an unsupported Mac OSX version. Please upgrade\n' \
            'to at least version 10.10 (Yosemite) to install Compass.'
        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_type@/stable/' + os_type
    print 'Downloading the package...'
    try:
        pkg = download_pkg(link, pkg_format=pkg_format)
    # This should not execute we are catching errors in all of these functions
    # but these are a catch all so we don't just dump Python stack traces to
    # the user in the case we have a new failure case we didn't think about.
    except Exception:
        print 'Unkown error downloading compass. Please open a ticket on the' \
            ' SERVER project at https://jira.mongodb.org/'

    print 'Installing the package...'
    try:
        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
    except Exception:
        print 'Unkown error downloading compass. Please open a ticket on the' \
            ' SERVER project at https://jira.mongodb.org/'

    print 'Cleaning up...'
    os.remove(pkg)
    print 'Done!'


if __name__ == '__main__':
    download_and_install_compass()