##// END OF EJS Templates
update: add new async task to check for updates via scheduler....
marcink -
r2431:61a0f874 default
parent child Browse files
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 'You already have the <b>latest</b> stable version.')
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.lib.ext_json import json
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 = self.get_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 = self.get_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 = self.get_update_data(update_url)
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 You already have the <b>latest</b> stable version.
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