Show More
@@ -0,0 +1,71 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | ||
|
3 | # Copyright (C) 2013-2017 RhodeCode GmbH | |
|
4 | # | |
|
5 | # This program is free software: you can redistribute it and/or modify | |
|
6 | # it under the terms of the GNU Affero General Public License, version 3 | |
|
7 | # (only), as published by the Free Software Foundation. | |
|
8 | # | |
|
9 | # This program is distributed in the hope that it will be useful, | |
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
|
12 | # GNU General Public License for more details. | |
|
13 | # | |
|
14 | # You should have received a copy of the GNU Affero General Public License | |
|
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
|
16 | # | |
|
17 | # This program is dual-licensed. If you wish to learn more about the | |
|
18 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
|
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
|
20 | ||
|
21 | import logging | |
|
22 | import urllib2 | |
|
23 | from packaging import version | |
|
24 | ||
|
25 | import rhodecode | |
|
26 | from rhodecode.lib.ext_json import json | |
|
27 | from rhodecode.model import BaseModel | |
|
28 | from rhodecode.model.meta import Session | |
|
29 | from rhodecode.model.settings import SettingsModel | |
|
30 | ||
|
31 | ||
|
32 | log = logging.getLogger(__name__) | |
|
33 | ||
|
34 | ||
|
35 | class UpdateModel(BaseModel): | |
|
36 | UPDATE_SETTINGS_KEY = 'update_version' | |
|
37 | UPDATE_URL_SETTINGS_KEY = 'rhodecode_update_url' | |
|
38 | ||
|
39 | @staticmethod | |
|
40 | def get_update_data(update_url): | |
|
41 | """Return the JSON update data.""" | |
|
42 | ver = rhodecode.__version__ | |
|
43 | log.debug('Checking for upgrade on `%s` server', update_url) | |
|
44 | opener = urllib2.build_opener() | |
|
45 | opener.addheaders = [('User-agent', 'RhodeCode-SCM/%s' % ver)] | |
|
46 | response = opener.open(update_url) | |
|
47 | response_data = response.read() | |
|
48 | data = json.loads(response_data) | |
|
49 | log.debug('update server returned data') | |
|
50 | return data | |
|
51 | ||
|
52 | def get_update_url(self): | |
|
53 | settings = SettingsModel().get_all_settings() | |
|
54 | return settings.get(self.UPDATE_URL_SETTINGS_KEY) | |
|
55 | ||
|
56 | def store_version(self, version): | |
|
57 | log.debug('Storing version %s into settings', version) | |
|
58 | setting = SettingsModel().create_or_update_setting( | |
|
59 | self.UPDATE_SETTINGS_KEY, version) | |
|
60 | Session().add(setting) | |
|
61 | Session().commit() | |
|
62 | ||
|
63 | def get_stored_version(self): | |
|
64 | obj = SettingsModel().get_setting_by_name(self.UPDATE_SETTINGS_KEY) | |
|
65 | if obj: | |
|
66 | return obj.app_settings_value | |
|
67 | return '0.0.0' | |
|
68 | ||
|
69 | def is_outdated(self, cur_version, latest_version=None): | |
|
70 | latest_version = latest_version or self.get_stored_version() | |
|
71 | return version.Version(latest_version) > version.Version(cur_version) |
@@ -31,8 +31,7 b' from rhodecode.tests import assert_sessi' | |||
|
31 | 31 | from rhodecode.tests.utils import AssertResponse |
|
32 | 32 | |
|
33 | 33 | |
|
34 | UPDATE_DATA_QUALNAME = ( | |
|
35 | 'rhodecode.apps.admin.views.system_info.AdminSystemInfoSettingsView.get_update_data') | |
|
34 | UPDATE_DATA_QUALNAME = 'rhodecode.model.update.UpdateModel.get_update_data' | |
|
36 | 35 | |
|
37 | 36 | |
|
38 | 37 | def route_path(name, params=None, **kwargs): |
@@ -586,7 +585,7 b' class TestAdminSystemInfo(object):' | |||
|
586 | 585 | with mock.patch(UPDATE_DATA_QUALNAME, return_value=update_data): |
|
587 | 586 | response = self.app.get(route_path('admin_settings_system_update')) |
|
588 | 587 | response.mustcontain( |
|
589 |
' |
|
|
588 | 'This instance is already running the <b>latest</b> stable version') | |
|
590 | 589 | |
|
591 | 590 | def test_system_update_bad_response(self, autologin_user): |
|
592 | 591 | with mock.patch(UPDATE_DATA_QUALNAME, side_effect=ValueError('foo')): |
@@ -20,7 +20,6 b'' | |||
|
20 | 20 | |
|
21 | 21 | import logging |
|
22 | 22 | import urllib2 |
|
23 | import packaging.version | |
|
24 | 23 | |
|
25 | 24 | from pyramid.view import view_config |
|
26 | 25 | |
@@ -31,8 +30,7 b' from rhodecode.lib import helpers as h' | |||
|
31 | 30 | from rhodecode.lib.auth import (LoginRequired, HasPermissionAllDecorator) |
|
32 | 31 | from rhodecode.lib.utils2 import str2bool |
|
33 | 32 | from rhodecode.lib import system_info |
|
34 |
from rhodecode.l |
|
|
35 | from rhodecode.model.settings import SettingsModel | |
|
33 | from rhodecode.model.update import UpdateModel | |
|
36 | 34 | |
|
37 | 35 | log = logging.getLogger(__name__) |
|
38 | 36 | |
@@ -40,26 +38,8 b' log = logging.getLogger(__name__)' | |||
|
40 | 38 | class AdminSystemInfoSettingsView(BaseAppView): |
|
41 | 39 | def load_default_context(self): |
|
42 | 40 | c = self._get_local_tmpl_context() |
|
43 | ||
|
44 | 41 | return c |
|
45 | 42 | |
|
46 | @staticmethod | |
|
47 | def get_update_data(update_url): | |
|
48 | """Return the JSON update data.""" | |
|
49 | ver = rhodecode.__version__ | |
|
50 | log.debug('Checking for upgrade on `%s` server', update_url) | |
|
51 | opener = urllib2.build_opener() | |
|
52 | opener.addheaders = [('User-agent', 'RhodeCode-SCM/%s' % ver)] | |
|
53 | response = opener.open(update_url) | |
|
54 | response_data = response.read() | |
|
55 | data = json.loads(response_data) | |
|
56 | ||
|
57 | return data | |
|
58 | ||
|
59 | def get_update_url(self): | |
|
60 | settings = SettingsModel().get_all_settings() | |
|
61 | return settings.get('rhodecode_update_url') | |
|
62 | ||
|
63 | 43 | @LoginRequired() |
|
64 | 44 | @HasPermissionAllDecorator('hg.admin') |
|
65 | 45 | @view_config( |
@@ -77,7 +57,7 b' class AdminSystemInfoSettingsView(BaseAp' | |||
|
77 | 57 | |
|
78 | 58 | snapshot = str2bool(self.request.params.get('snapshot')) |
|
79 | 59 | |
|
80 |
c.rhodecode_update_url = |
|
|
60 | c.rhodecode_update_url = UpdateModel().get_update_url() | |
|
81 | 61 | server_info = system_info.get_system_info(self.request.environ) |
|
82 | 62 | |
|
83 | 63 | for key, val in server_info.items(): |
@@ -97,6 +77,14 b' class AdminSystemInfoSettingsView(BaseAp' | |||
|
97 | 77 | update_info_msg = _('Note: please make sure this server can ' |
|
98 | 78 | 'access `${url}` for the update link to work', |
|
99 | 79 | mapping=dict(url=c.rhodecode_update_url)) |
|
80 | version = UpdateModel().get_stored_version() | |
|
81 | is_outdated = UpdateModel().is_outdated( | |
|
82 | rhodecode.__version__, version) | |
|
83 | update_state = { | |
|
84 | 'type': 'warning', | |
|
85 | 'message': 'New version available: {}'.format(version) | |
|
86 | } \ | |
|
87 | if is_outdated else {} | |
|
100 | 88 | c.data_items = [ |
|
101 | 89 | # update info |
|
102 | 90 | (_('Update info'), h.literal( |
@@ -107,6 +95,7 b' class AdminSystemInfoSettingsView(BaseAp' | |||
|
107 | 95 | |
|
108 | 96 | # RhodeCode specific |
|
109 | 97 | (_('RhodeCode Version'), val('rhodecode_app')['text'], state('rhodecode_app')), |
|
98 | (_('Latest version'), version, update_state), | |
|
110 | 99 | (_('RhodeCode Server IP'), val('server')['server_ip'], state('server')), |
|
111 | 100 | (_('RhodeCode Server ID'), val('server')['server_id'], state('server')), |
|
112 | 101 | (_('RhodeCode Configuration'), val('rhodecode_config')['path'], state('rhodecode_config')), |
@@ -178,11 +167,11 b' class AdminSystemInfoSettingsView(BaseAp' | |||
|
178 | 167 | _ = self.request.translate |
|
179 | 168 | c = self.load_default_context() |
|
180 | 169 | |
|
181 |
update_url = |
|
|
170 | update_url = UpdateModel().get_update_url() | |
|
182 | 171 | |
|
183 | 172 | _err = lambda s: '<div style="color:#ff8888; padding:4px 0px">{}</div>'.format(s) |
|
184 | 173 | try: |
|
185 |
data = |
|
|
174 | data = UpdateModel().get_update_data(update_url) | |
|
186 | 175 | except urllib2.URLError as e: |
|
187 | 176 | log.exception("Exception contacting upgrade server") |
|
188 | 177 | self.request.override_renderer = 'string' |
@@ -200,9 +189,9 b' class AdminSystemInfoSettingsView(BaseAp' | |||
|
200 | 189 | c.cur_ver = rhodecode.__version__ |
|
201 | 190 | c.should_upgrade = False |
|
202 | 191 | |
|
203 | if (packaging.version.Version(c.latest_ver) > | |
|
204 | packaging.version.Version(c.cur_ver)): | |
|
192 | is_oudated = UpdateModel().is_outdated(c.cur_ver, c.latest_ver) | |
|
193 | if is_oudated: | |
|
205 | 194 | c.should_upgrade = True |
|
206 | 195 | c.important_notices = latest['general'] |
|
207 | ||
|
196 | UpdateModel().store_version(latest['version']) | |
|
208 | 197 | return self._get_template_context(c) |
@@ -278,6 +278,20 b' def sync_repo(*args, **kwargs):' | |||
|
278 | 278 | log.debug('Repo `%s` not found or without a clone_url', repo_name) |
|
279 | 279 | |
|
280 | 280 | |
|
281 | @async_task(ignore_result=True) | |
|
282 | def check_for_update(): | |
|
283 | from rhodecode.model.update import UpdateModel | |
|
284 | update_url = UpdateModel().get_update_url() | |
|
285 | cur_ver = rhodecode.__version__ | |
|
286 | ||
|
287 | try: | |
|
288 | data = UpdateModel().get_update_data(update_url) | |
|
289 | latest = data['versions'][0] | |
|
290 | UpdateModel().store_version(latest['version']) | |
|
291 | except Exception: | |
|
292 | pass | |
|
293 | ||
|
294 | ||
|
281 | 295 | @async_task(ignore_result=False) |
|
282 | 296 | def beat_check(*args, **kwargs): |
|
283 | 297 | log = get_logger(beat_check) |
@@ -2,8 +2,7 b'' | |||
|
2 | 2 | ## upgrade block rendered afte on-click check |
|
3 | 3 | |
|
4 | 4 | <div class="alert ${'alert-warning' if c.should_upgrade else 'alert-success'}"> |
|
5 |
<p |
|
|
6 | ||
|
5 | <p> | |
|
7 | 6 | %if c.should_upgrade: |
|
8 | 7 | A <b>new version</b> is available: |
|
9 | 8 | %if c.latest_data.get('title'): |
@@ -12,7 +11,7 b'' | |||
|
12 | 11 | <b>${c.latest_ver}</b> |
|
13 | 12 | %endif |
|
14 | 13 | %else: |
|
15 |
|
|
|
14 | This instance is already running the <b>latest</b> stable version ${c.latest_ver}. | |
|
16 | 15 | %endif |
|
17 | 16 | </p> |
|
18 | 17 |
General Comments 0
You need to be logged in to leave comments.
Login now