##// 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 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 b' 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 b''
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 b' 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 b' 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 b' 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 b' 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 b' 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 b' 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 b' 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 b' 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 b''
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 b''
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