diff --git a/rhodecode/apps/admin/__init__.py b/rhodecode/apps/admin/__init__.py
index d43e1077..2e4d7aa2 100644
--- a/rhodecode/apps/admin/__init__.py
+++ b/rhodecode/apps/admin/__init__.py
@@ -209,6 +209,15 @@ def admin_routes(config):
renderer="rhodecode:templates/admin/settings/settings_system_update.mako",
)
+ config.add_route(name="settings_system_info_rcstack_update", pattern="/settings/system/rcstack/update")
+ config.add_view(
+ AdminSystemInfoSettingsView,
+ attr="settings_system_info_rcstack_update",
+ route_name="settings_system_info_rcstack_update",
+ request_method="GET",
+ renderer="rhodecode:templates/admin/settings/settings_system_update.mako",
+ )
+
config.add_route(name="admin_settings_exception_tracker", pattern="/settings/exceptions")
config.add_view(
ExceptionsTrackerView,
diff --git a/rhodecode/apps/admin/update_service.py b/rhodecode/apps/admin/update_service.py
new file mode 100644
index 00000000..8aee9cd0
--- /dev/null
+++ b/rhodecode/apps/admin/update_service.py
@@ -0,0 +1,38 @@
+import logging
+import os
+
+import requests
+
+from rhodecode.lib.type_utils import str2bool
+
+
+class RcStackUpdateService:
+ class State:
+ READY = "ready"
+ PROCESSING = "processing"
+
+ def __init__(self, server_host: str, server_port: int):
+ self.host = server_host
+ self.port = server_port
+ self.log = logging.getLogger(__name__)
+
+ def feature_available(self):
+ if str2bool(os.environ.get("DISABLE_RC_UPDATE_SERVICE", "false")) or self.host is None:
+ return False
+
+ try:
+ self.get_state()
+ return True
+ except Exception as e:
+ self.log.error(f"Server on host machine not available, error: {e}")
+ return False
+
+ def get_state(self):
+ url_base = f"http://{self.host}:{self.port}"
+ url = f"{url_base}/state"
+ return requests.get(url).json().get("state", None)
+
+ def rcstack_update(self):
+ url_base = f"http://{self.host}:{self.port}"
+ url = f"{url_base}/rcstack/update"
+ return requests.get(url).json()
diff --git a/rhodecode/apps/admin/views/system_info.py b/rhodecode/apps/admin/views/system_info.py
index ce75a584..fd68e1cd 100644
--- a/rhodecode/apps/admin/views/system_info.py
+++ b/rhodecode/apps/admin/views/system_info.py
@@ -22,9 +22,12 @@ import urllib.error
import urllib.parse
import os
+from pyramid.httpexceptions import HTTPFound
+
import rhodecode
from rhodecode.apps._base import BaseAppView
from rhodecode.apps._base.navigation import navigation_list
+from rhodecode.apps.admin.update_service import RcStackUpdateService
from rhodecode.lib import helpers as h
from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
from rhodecode.lib.utils2 import str2bool
@@ -112,6 +115,20 @@ class AdminSystemInfoSettingsView(BaseAppView):
update_state = (
{"type": "warning", "message": "New version available: {}".format(version)} if is_outdated else {}
)
+
+ update_service = self._get_rc_update_service()
+ update_feature_available = update_service.feature_available()
+
+ update_literal = ""
+ if update_feature_available:
+ update_service_state = update_service.get_state()
+ if update_service_state == RcStackUpdateService.State.READY:
+ update_literal = '
%s.' % (_("Update RcStack"))
+ else:
+ update_literal = "
%s." % (
+ _("Update in progress, please wait. You can check logs on the host machine.")
+ )
+
c.data_items = [
# update info
(
@@ -119,6 +136,7 @@ class AdminSystemInfoSettingsView(BaseAppView):
h.literal(
'%s.' % (_("Check for updates"))
+ "
%s." % (update_info_msg)
+ + update_literal
),
"",
),
@@ -206,6 +224,22 @@ class AdminSystemInfoSettingsView(BaseAppView):
h.flash("You are not allowed to do this", category="warning")
return self._get_template_context(c)
+ @LoginRequired()
+ @HasPermissionAllDecorator("hg.admin")
+ def settings_system_info_rcstack_update(self):
+ update_service = self._get_rc_update_service()
+ update_feature_available = update_service.feature_available()
+
+ if update_feature_available:
+ response = update_service.rcstack_update()
+ log.debug(f"update server response: {response}")
+ return HTTPFound(h.route_path("admin_settings_system"))
+
+ def _get_rc_update_service(self) -> RcStackUpdateService:
+ host = os.environ.get("RC_UPDATE_HOST", None)
+ port = os.environ.get("RC_UPDATE_PORT", 10025)
+ return RcStackUpdateService(server_host=host, server_port=port)
+
@LoginRequired()
@HasPermissionAllDecorator("hg.admin")
def settings_system_info_check_update(self):
diff --git a/rhodecode/templates/admin/settings/settings_system.mako b/rhodecode/templates/admin/settings/settings_system.mako
index edaf81c0..5c359ab0 100644
--- a/rhodecode/templates/admin/settings/settings_system.mako
+++ b/rhodecode/templates/admin/settings/settings_system.mako
@@ -100,4 +100,7 @@
$('#update_notice').show();
$('#update_notice').load("${h.route_path('admin_settings_system_update', _query={'ver': request.GET.get('ver')})}");
})
+ $('#rcstack_update').on('click', function(e){
+ window.location.href = "${h.route_path('settings_system_info_rcstack_update')}";
+ })
diff --git a/update_server.py b/update_server.py
index feeed1fe..e0d31b2c 100644
--- a/update_server.py
+++ b/update_server.py
@@ -61,17 +61,11 @@ class RcstackUpdater(BaseHTTPRequestHandler):
self.end_headers()
self.wfile.write(body)
- def _send_json_ok(self):
- return self._send_json({"status": "ok"})
-
def do_GET(self):
- if self.path == "/health":
- return self._send_json_ok()
-
- elif self.path == "/state":
+ if self.path == "/state":
return self._send_json({"state": STATUS["state"]})
- elif self.path == "/update-rcstack":
+ elif self.path == "/rcstack/update":
# If already processing, return ok and do not spawn a new process.
if STATUS["state"] != "ready":
return self._send_json({"status": "ok", "state": STATUS["state"]})
@@ -139,16 +133,10 @@ class RcstackUpdater(BaseHTTPRequestHandler):
self.wfile.write(msg)
-def main():
- logging.basicConfig(
- level=logging.INFO,
- format="%(asctime)s %(levelname)s %(name)s: %(message)s",
- )
- host = "127.0.0.1"
- port = 10025
+def main(host="127.0.0.1", port=10025):
httpd = HTTPServer((host, port), RcstackUpdater)
- log = logging.getLogger("mini-server")
- log.info("listening on http://%s:%d", host, port)
+ stamp = time.strftime("%Y-%m-%d %H:%M:%S")
+ print("[%s] listening on http://%s:%d" % (stamp, host, port))
httpd.serve_forever()