##// END OF EJS Templates
update: add new async task to check for updates via scheduler....
marcink -
r2431:61a0f874 default
parent child
Show More
@@ -0,0 +1,71
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 from rhodecode.tests import assert_sessi
31 from rhodecode.tests.utils import AssertResponse
31 from rhodecode.tests.utils import AssertResponse
32
32
33
33
34 UPDATE_DATA_QUALNAME = (
34 UPDATE_DATA_QUALNAME = 'rhodecode.model.update.UpdateModel.get_update_data'
35 'rhodecode.apps.admin.views.system_info.AdminSystemInfoSettingsView.get_update_data')
36
35
37
36
38 def route_path(name, params=None, **kwargs):
37 def route_path(name, params=None, **kwargs):
@@ -586,7 +585,7 class TestAdminSystemInfo(object):
586 with mock.patch(UPDATE_DATA_QUALNAME, return_value=update_data):
585 with mock.patch(UPDATE_DATA_QUALNAME, return_value=update_data):
587 response = self.app.get(route_path('admin_settings_system_update'))
586 response = self.app.get(route_path('admin_settings_system_update'))
588 response.mustcontain(
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 def test_system_update_bad_response(self, autologin_user):
590 def test_system_update_bad_response(self, autologin_user):
592 with mock.patch(UPDATE_DATA_QUALNAME, side_effect=ValueError('foo')):
591 with mock.patch(UPDATE_DATA_QUALNAME, side_effect=ValueError('foo')):
@@ -20,7 +20,6
20
20
21 import logging
21 import logging
22 import urllib2
22 import urllib2
23 import packaging.version
24
23
25 from pyramid.view import view_config
24 from pyramid.view import view_config
26
25
@@ -31,8 +30,7 from rhodecode.lib import helpers as h
31 from rhodecode.lib.auth import (LoginRequired, HasPermissionAllDecorator)
30 from rhodecode.lib.auth import (LoginRequired, HasPermissionAllDecorator)
32 from rhodecode.lib.utils2 import str2bool
31 from rhodecode.lib.utils2 import str2bool
33 from rhodecode.lib import system_info
32 from rhodecode.lib import system_info
34 from rhodecode.lib.ext_json import json
33 from rhodecode.model.update import UpdateModel
35 from rhodecode.model.settings import SettingsModel
36
34
37 log = logging.getLogger(__name__)
35 log = logging.getLogger(__name__)
38
36
@@ -40,26 +38,8 log = logging.getLogger(__name__)
40 class AdminSystemInfoSettingsView(BaseAppView):
38 class AdminSystemInfoSettingsView(BaseAppView):
41 def load_default_context(self):
39 def load_default_context(self):
42 c = self._get_local_tmpl_context()
40 c = self._get_local_tmpl_context()
43
44 return c
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 @LoginRequired()
43 @LoginRequired()
64 @HasPermissionAllDecorator('hg.admin')
44 @HasPermissionAllDecorator('hg.admin')
65 @view_config(
45 @view_config(
@@ -77,7 +57,7 class AdminSystemInfoSettingsView(BaseAp
77
57
78 snapshot = str2bool(self.request.params.get('snapshot'))
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 server_info = system_info.get_system_info(self.request.environ)
61 server_info = system_info.get_system_info(self.request.environ)
82
62
83 for key, val in server_info.items():
63 for key, val in server_info.items():
@@ -97,6 +77,14 class AdminSystemInfoSettingsView(BaseAp
97 update_info_msg = _('Note: please make sure this server can '
77 update_info_msg = _('Note: please make sure this server can '
98 'access `${url}` for the update link to work',
78 'access `${url}` for the update link to work',
99 mapping=dict(url=c.rhodecode_update_url))
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 c.data_items = [
88 c.data_items = [
101 # update info
89 # update info
102 (_('Update info'), h.literal(
90 (_('Update info'), h.literal(
@@ -107,6 +95,7 class AdminSystemInfoSettingsView(BaseAp
107
95
108 # RhodeCode specific
96 # RhodeCode specific
109 (_('RhodeCode Version'), val('rhodecode_app')['text'], state('rhodecode_app')),
97 (_('RhodeCode Version'), val('rhodecode_app')['text'], state('rhodecode_app')),
98 (_('Latest version'), version, update_state),
110 (_('RhodeCode Server IP'), val('server')['server_ip'], state('server')),
99 (_('RhodeCode Server IP'), val('server')['server_ip'], state('server')),
111 (_('RhodeCode Server ID'), val('server')['server_id'], state('server')),
100 (_('RhodeCode Server ID'), val('server')['server_id'], state('server')),
112 (_('RhodeCode Configuration'), val('rhodecode_config')['path'], state('rhodecode_config')),
101 (_('RhodeCode Configuration'), val('rhodecode_config')['path'], state('rhodecode_config')),
@@ -178,11 +167,11 class AdminSystemInfoSettingsView(BaseAp
178 _ = self.request.translate
167 _ = self.request.translate
179 c = self.load_default_context()
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 _err = lambda s: '<div style="color:#ff8888; padding:4px 0px">{}</div>'.format(s)
172 _err = lambda s: '<div style="color:#ff8888; padding:4px 0px">{}</div>'.format(s)
184 try:
173 try:
185 data = self.get_update_data(update_url)
174 data = UpdateModel().get_update_data(update_url)
186 except urllib2.URLError as e:
175 except urllib2.URLError as e:
187 log.exception("Exception contacting upgrade server")
176 log.exception("Exception contacting upgrade server")
188 self.request.override_renderer = 'string'
177 self.request.override_renderer = 'string'
@@ -200,9 +189,9 class AdminSystemInfoSettingsView(BaseAp
200 c.cur_ver = rhodecode.__version__
189 c.cur_ver = rhodecode.__version__
201 c.should_upgrade = False
190 c.should_upgrade = False
202
191
203 if (packaging.version.Version(c.latest_ver) >
192 is_oudated = UpdateModel().is_outdated(c.cur_ver, c.latest_ver)
204 packaging.version.Version(c.cur_ver)):
193 if is_oudated:
205 c.should_upgrade = True
194 c.should_upgrade = True
206 c.important_notices = latest['general']
195 c.important_notices = latest['general']
207
196 UpdateModel().store_version(latest['version'])
208 return self._get_template_context(c)
197 return self._get_template_context(c)
@@ -278,6 +278,20 def sync_repo(*args, **kwargs):
278 log.debug('Repo `%s` not found or without a clone_url', repo_name)
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 @async_task(ignore_result=False)
295 @async_task(ignore_result=False)
282 def beat_check(*args, **kwargs):
296 def beat_check(*args, **kwargs):
283 log = get_logger(beat_check)
297 log = get_logger(beat_check)
@@ -2,8 +2,7
2 ## upgrade block rendered afte on-click check
2 ## upgrade block rendered afte on-click check
3
3
4 <div class="alert ${'alert-warning' if c.should_upgrade else 'alert-success'}">
4 <div class="alert ${'alert-warning' if c.should_upgrade else 'alert-success'}">
5 <p >
5 <p>
6
7 %if c.should_upgrade:
6 %if c.should_upgrade:
8 A <b>new version</b> is available:
7 A <b>new version</b> is available:
9 %if c.latest_data.get('title'):
8 %if c.latest_data.get('title'):
@@ -12,7 +11,7
12 <b>${c.latest_ver}</b>
11 <b>${c.latest_ver}</b>
13 %endif
12 %endif
14 %else:
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 %endif
15 %endif
17 </p>
16 </p>
18
17
General Comments 0
You need to be logged in to leave comments. Login now