update: add new async task to check for updates via scheduler.
- save the data into DB for later evaluation - show in system info that we know the system is outdated
This commit is contained in:
parent
baaeb9a462
commit
a368564cba
5 changed files with 105 additions and 33 deletions
|
|
@ -31,8 +31,7 @@ from rhodecode.tests import assert_session_flash
|
|||
from rhodecode.tests.utils import AssertResponse
|
||||
|
||||
|
||||
UPDATE_DATA_QUALNAME = (
|
||||
'rhodecode.apps.admin.views.system_info.AdminSystemInfoSettingsView.get_update_data')
|
||||
UPDATE_DATA_QUALNAME = 'rhodecode.model.update.UpdateModel.get_update_data'
|
||||
|
||||
|
||||
def route_path(name, params=None, **kwargs):
|
||||
|
|
@ -586,7 +585,7 @@ class TestAdminSystemInfo(object):
|
|||
with mock.patch(UPDATE_DATA_QUALNAME, return_value=update_data):
|
||||
response = self.app.get(route_path('admin_settings_system_update'))
|
||||
response.mustcontain(
|
||||
'You already have the <b>latest</b> stable version.')
|
||||
'This instance is already running the <b>latest</b> stable version')
|
||||
|
||||
def test_system_update_bad_response(self, autologin_user):
|
||||
with mock.patch(UPDATE_DATA_QUALNAME, side_effect=ValueError('foo')):
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
import logging
|
||||
import urllib2
|
||||
import packaging.version
|
||||
|
||||
from pyramid.view import view_config
|
||||
|
||||
|
|
@ -31,8 +30,7 @@ from rhodecode.lib import helpers as h
|
|||
from rhodecode.lib.auth import (LoginRequired, HasPermissionAllDecorator)
|
||||
from rhodecode.lib.utils2 import str2bool
|
||||
from rhodecode.lib import system_info
|
||||
from rhodecode.lib.ext_json import json
|
||||
from rhodecode.model.settings import SettingsModel
|
||||
from rhodecode.model.update import UpdateModel
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -40,26 +38,8 @@ log = logging.getLogger(__name__)
|
|||
class AdminSystemInfoSettingsView(BaseAppView):
|
||||
def load_default_context(self):
|
||||
c = self._get_local_tmpl_context()
|
||||
|
||||
return c
|
||||
|
||||
@staticmethod
|
||||
def get_update_data(update_url):
|
||||
"""Return the JSON update data."""
|
||||
ver = rhodecode.__version__
|
||||
log.debug('Checking for upgrade on `%s` server', update_url)
|
||||
opener = urllib2.build_opener()
|
||||
opener.addheaders = [('User-agent', 'RhodeCode-SCM/%s' % ver)]
|
||||
response = opener.open(update_url)
|
||||
response_data = response.read()
|
||||
data = json.loads(response_data)
|
||||
|
||||
return data
|
||||
|
||||
def get_update_url(self):
|
||||
settings = SettingsModel().get_all_settings()
|
||||
return settings.get('rhodecode_update_url')
|
||||
|
||||
@LoginRequired()
|
||||
@HasPermissionAllDecorator('hg.admin')
|
||||
@view_config(
|
||||
|
|
@ -77,7 +57,7 @@ class AdminSystemInfoSettingsView(BaseAppView):
|
|||
|
||||
snapshot = str2bool(self.request.params.get('snapshot'))
|
||||
|
||||
c.rhodecode_update_url = self.get_update_url()
|
||||
c.rhodecode_update_url = UpdateModel().get_update_url()
|
||||
server_info = system_info.get_system_info(self.request.environ)
|
||||
|
||||
for key, val in server_info.items():
|
||||
|
|
@ -97,6 +77,14 @@ class AdminSystemInfoSettingsView(BaseAppView):
|
|||
update_info_msg = _('Note: please make sure this server can '
|
||||
'access `${url}` for the update link to work',
|
||||
mapping=dict(url=c.rhodecode_update_url))
|
||||
version = UpdateModel().get_stored_version()
|
||||
is_outdated = UpdateModel().is_outdated(
|
||||
rhodecode.__version__, version)
|
||||
update_state = {
|
||||
'type': 'warning',
|
||||
'message': 'New version available: {}'.format(version)
|
||||
} \
|
||||
if is_outdated else {}
|
||||
c.data_items = [
|
||||
# update info
|
||||
(_('Update info'), h.literal(
|
||||
|
|
@ -107,6 +95,7 @@ class AdminSystemInfoSettingsView(BaseAppView):
|
|||
|
||||
# RhodeCode specific
|
||||
(_('RhodeCode Version'), val('rhodecode_app')['text'], state('rhodecode_app')),
|
||||
(_('Latest version'), version, update_state),
|
||||
(_('RhodeCode Server IP'), val('server')['server_ip'], state('server')),
|
||||
(_('RhodeCode Server ID'), val('server')['server_id'], state('server')),
|
||||
(_('RhodeCode Configuration'), val('rhodecode_config')['path'], state('rhodecode_config')),
|
||||
|
|
@ -178,11 +167,11 @@ class AdminSystemInfoSettingsView(BaseAppView):
|
|||
_ = self.request.translate
|
||||
c = self.load_default_context()
|
||||
|
||||
update_url = self.get_update_url()
|
||||
update_url = UpdateModel().get_update_url()
|
||||
|
||||
_err = lambda s: '<div style="color:#ff8888; padding:4px 0px">{}</div>'.format(s)
|
||||
try:
|
||||
data = self.get_update_data(update_url)
|
||||
data = UpdateModel().get_update_data(update_url)
|
||||
except urllib2.URLError as e:
|
||||
log.exception("Exception contacting upgrade server")
|
||||
self.request.override_renderer = 'string'
|
||||
|
|
@ -200,9 +189,9 @@ class AdminSystemInfoSettingsView(BaseAppView):
|
|||
c.cur_ver = rhodecode.__version__
|
||||
c.should_upgrade = False
|
||||
|
||||
if (packaging.version.Version(c.latest_ver) >
|
||||
packaging.version.Version(c.cur_ver)):
|
||||
is_oudated = UpdateModel().is_outdated(c.cur_ver, c.latest_ver)
|
||||
if is_oudated:
|
||||
c.should_upgrade = True
|
||||
c.important_notices = latest['general']
|
||||
|
||||
UpdateModel().store_version(latest['version'])
|
||||
return self._get_template_context(c)
|
||||
|
|
|
|||
|
|
@ -278,6 +278,20 @@ def sync_repo(*args, **kwargs):
|
|||
log.debug('Repo `%s` not found or without a clone_url', repo_name)
|
||||
|
||||
|
||||
@async_task(ignore_result=True)
|
||||
def check_for_update():
|
||||
from rhodecode.model.update import UpdateModel
|
||||
update_url = UpdateModel().get_update_url()
|
||||
cur_ver = rhodecode.__version__
|
||||
|
||||
try:
|
||||
data = UpdateModel().get_update_data(update_url)
|
||||
latest = data['versions'][0]
|
||||
UpdateModel().store_version(latest['version'])
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
@async_task(ignore_result=False)
|
||||
def beat_check(*args, **kwargs):
|
||||
log = get_logger(beat_check)
|
||||
|
|
|
|||
71
rhodecode/model/update.py
Normal file
71
rhodecode/model/update.py
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (C) 2013-2017 RhodeCode GmbH
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License, version 3
|
||||
# (only), as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# This program is dual-licensed. If you wish to learn more about the
|
||||
# RhodeCode Enterprise Edition, including its added features, Support services,
|
||||
# and proprietary license terms, please see https://rhodecode.com/licenses/
|
||||
|
||||
import logging
|
||||
import urllib2
|
||||
from packaging import version
|
||||
|
||||
import rhodecode
|
||||
from rhodecode.lib.ext_json import json
|
||||
from rhodecode.model import BaseModel
|
||||
from rhodecode.model.meta import Session
|
||||
from rhodecode.model.settings import SettingsModel
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class UpdateModel(BaseModel):
|
||||
UPDATE_SETTINGS_KEY = 'update_version'
|
||||
UPDATE_URL_SETTINGS_KEY = 'rhodecode_update_url'
|
||||
|
||||
@staticmethod
|
||||
def get_update_data(update_url):
|
||||
"""Return the JSON update data."""
|
||||
ver = rhodecode.__version__
|
||||
log.debug('Checking for upgrade on `%s` server', update_url)
|
||||
opener = urllib2.build_opener()
|
||||
opener.addheaders = [('User-agent', 'RhodeCode-SCM/%s' % ver)]
|
||||
response = opener.open(update_url)
|
||||
response_data = response.read()
|
||||
data = json.loads(response_data)
|
||||
log.debug('update server returned data')
|
||||
return data
|
||||
|
||||
def get_update_url(self):
|
||||
settings = SettingsModel().get_all_settings()
|
||||
return settings.get(self.UPDATE_URL_SETTINGS_KEY)
|
||||
|
||||
def store_version(self, version):
|
||||
log.debug('Storing version %s into settings', version)
|
||||
setting = SettingsModel().create_or_update_setting(
|
||||
self.UPDATE_SETTINGS_KEY, version)
|
||||
Session().add(setting)
|
||||
Session().commit()
|
||||
|
||||
def get_stored_version(self):
|
||||
obj = SettingsModel().get_setting_by_name(self.UPDATE_SETTINGS_KEY)
|
||||
if obj:
|
||||
return obj.app_settings_value
|
||||
return '0.0.0'
|
||||
|
||||
def is_outdated(self, cur_version, latest_version=None):
|
||||
latest_version = latest_version or self.get_stored_version()
|
||||
return version.Version(latest_version) > version.Version(cur_version)
|
||||
|
|
@ -2,8 +2,7 @@
|
|||
## upgrade block rendered afte on-click check
|
||||
|
||||
<div class="alert ${'alert-warning' if c.should_upgrade else 'alert-success'}">
|
||||
<p >
|
||||
|
||||
<p>
|
||||
%if c.should_upgrade:
|
||||
A <b>new version</b> is available:
|
||||
%if c.latest_data.get('title'):
|
||||
|
|
@ -12,7 +11,7 @@
|
|||
<b>${c.latest_ver}</b>
|
||||
%endif
|
||||
%else:
|
||||
You already have the <b>latest</b> stable version.
|
||||
This instance is already running the <b>latest</b> stable version ${c.latest_ver}.
|
||||
%endif
|
||||
</p>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue