mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2026-05-06 18:07:22 +02:00
Manage Services: RabbitMQ 4.x default, repo alignment, UI fixes
- Detect RHEL major from /etc/os-release and align Packagecloud RabbitMQ .repo URLs. - Improve version discovery (el8 metadata merge on EL9+, 4.x fallback when DNF omits builds). - Default RabbitMQ stream to 4.x in API, page bootstrap, serviceManager, and normalize_rabbitmq_stream. - UI: prefetch 4.x on install, stream buttons 4.x first, fix confirm checkbox ng-model parent scope. - Bump msModal cache-bust for manageServices.js.
This commit is contained in:
@@ -2504,7 +2504,7 @@
|
||||
<script src="{% static 'serverStatus/serverStatus.js' %}?v={{ CP_VERSION }}" data-cfasync="false"></script>
|
||||
<script src="{% static 'firewall/firewall.js' %}?v={{ CP_VERSION }}&fw={{ FIREWALL_STATIC_VERSION|default:CP_VERSION }}&cb=4" data-cfasync="false"></script>
|
||||
<script src="{% static 'emailPremium/emailPremium.js' %}?v={{ CP_VERSION }}" data-cfasync="false"></script>
|
||||
<script src="{% static 'manageServices/manageServices.js' %}?v={{ CP_VERSION }}&msModal=20260401d" data-cfasync="false"></script>
|
||||
<script src="{% static 'manageServices/manageServices.js' %}?v={{ CP_VERSION }}&msModal=20260402c" data-cfasync="false"></script>
|
||||
<script src="{% static 'CLManager/CLManager.js' %}?v={{ CP_VERSION }}" data-cfasync="false"></script>
|
||||
|
||||
<!-- Scripts -->
|
||||
|
||||
@@ -43,6 +43,55 @@ def is_debian_family():
|
||||
return os.path.exists('/etc/debian_version') or os.path.exists('/etc/lsb-release')
|
||||
|
||||
|
||||
def rhel_major_from_os_release():
|
||||
"""
|
||||
RHEL-family OS major version (8, 9, 10, …) from /etc/os-release (or redhat-release).
|
||||
Returns None for Debian/Ubuntu or if the OS cannot be classified as RHEL-like.
|
||||
Used to align Packagecloud Yum baseurls (el/8 vs el/9) with the running system.
|
||||
"""
|
||||
if is_debian_family():
|
||||
return None
|
||||
os_release = '/etc/os-release'
|
||||
version_id = None
|
||||
platform_id = None
|
||||
if os.path.exists(os_release):
|
||||
try:
|
||||
with open(os_release, 'r', encoding='utf-8', errors='replace') as fh:
|
||||
for line in fh:
|
||||
line = line.strip()
|
||||
if line.startswith('VERSION_ID='):
|
||||
version_id = line.split('=', 1)[1].strip().strip('"').strip("'")
|
||||
elif line.startswith('PLATFORM_ID='):
|
||||
platform_id = line.split('=', 1)[1].strip().strip('"').strip("'")
|
||||
except Exception:
|
||||
pass
|
||||
if version_id:
|
||||
match = re.match(r'^(\d+)', version_id)
|
||||
if match:
|
||||
major = int(match.group(1))
|
||||
if 6 <= major <= 15:
|
||||
return major
|
||||
if platform_id:
|
||||
match = re.search(r'el(\d+)', platform_id, re.IGNORECASE)
|
||||
if match:
|
||||
major = int(match.group(1))
|
||||
if 6 <= major <= 15:
|
||||
return major
|
||||
redhat_release = '/etc/redhat-release'
|
||||
if os.path.exists(redhat_release):
|
||||
try:
|
||||
with open(redhat_release, 'r', encoding='utf-8', errors='replace') as fh:
|
||||
txt = fh.read()
|
||||
match = re.search(r'release\s+(\d+)', txt, re.IGNORECASE)
|
||||
if match:
|
||||
major = int(match.group(1))
|
||||
if 6 <= major <= 15:
|
||||
return major
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
|
||||
|
||||
def is_centos7():
|
||||
release_paths = ['/etc/centos-release', '/etc/redhat-release', '/etc/os-release']
|
||||
text_blob = ''
|
||||
|
||||
@@ -4,6 +4,8 @@ import json
|
||||
import threading
|
||||
import time
|
||||
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from .application_detection import detect_app_state, managed_apps_os_support
|
||||
from .application_versions import get_available_versions, version_compare
|
||||
|
||||
@@ -46,16 +48,16 @@ def _page_meta_cache_put(cache_key, services, meta_json):
|
||||
)
|
||||
|
||||
|
||||
def build_manage_applications_page_data(es_major='8', rabbitmq_stream='3'):
|
||||
def build_manage_applications_page_data(es_major='8', rabbitmq_stream='4'):
|
||||
"""
|
||||
Build `services` for card HTML and a JSON-serializable bootstrap matching
|
||||
/manageservices/applicationMeta shape (default ES major 8, RMQ stream 3).
|
||||
/manageservices/applicationMeta shape (default ES major 8, RMQ stream 4).
|
||||
"""
|
||||
services = []
|
||||
bootstrap_apps = []
|
||||
support = managed_apps_os_support()
|
||||
major = str(es_major).strip() if str(es_major).strip() in ('7', '8', '9') else '8'
|
||||
rmq = str(rabbitmq_stream).strip() if str(rabbitmq_stream).strip() in ('3', '4') else '3'
|
||||
rmq = str(rabbitmq_stream).strip() if str(rabbitmq_stream).strip() in ('3', '4') else '4'
|
||||
cache_key = 'major:{0}|rmq:{1}|support:{2}'.format(
|
||||
major, rmq, 1 if support.get('supported') else 0
|
||||
)
|
||||
@@ -87,7 +89,16 @@ def build_manage_applications_page_data(es_major='8', rabbitmq_stream='3'):
|
||||
|
||||
installed_version = state['installedVersion']
|
||||
if installed_version and installed_version not in versions:
|
||||
versions = [installed_version] + versions
|
||||
prepend_installed = True
|
||||
if app_name == 'RabbitMQ':
|
||||
from manageServices.application_rabbitmq_repo import (
|
||||
filter_versions_for_stream,
|
||||
)
|
||||
prepend_installed = bool(
|
||||
filter_versions_for_stream([installed_version], rmq)
|
||||
)
|
||||
if prepend_installed:
|
||||
versions = [installed_version] + versions
|
||||
|
||||
ref_latest = latest_global or latest_branch
|
||||
update_available = bool(
|
||||
@@ -97,6 +108,24 @@ def build_manage_applications_page_data(es_major='8', rabbitmq_stream='3'):
|
||||
and version_compare(installed_version, ref_latest) < 0
|
||||
)
|
||||
|
||||
rabbitmq_versions_hint = ''
|
||||
if app_name == 'RabbitMQ' and not versions:
|
||||
if rmq == '4':
|
||||
rabbitmq_versions_hint = _(
|
||||
'Your OS is not unsupported: upstream RabbitMQ publishes 4.x RPMs suitable for '
|
||||
'RHEL/Alma/Rocky 8 and 9 (RPM filenames may still contain el8; that is normal). '
|
||||
'If this list stays empty, repository metadata may not expose 4.x to dnf yet—'
|
||||
'refresh metadata (dnf makecache -y) or install the official .rpm from rabbitmq.com. '
|
||||
'Check with: dnf repoquery rabbitmq-server --available --show-duplicates '
|
||||
'(4.x lines look like rabbitmq-server-0:4.x.y-1.el8.noarch — search for :4., not a space after the colon).'
|
||||
)
|
||||
else:
|
||||
rabbitmq_versions_hint = _(
|
||||
'No 3.x builds were returned for this stream after refreshing Team RabbitMQ repos. '
|
||||
'This is usually metadata or repo state—not OS support. Try: dnf makecache -y, '
|
||||
'then dnf repoquery rabbitmq-server --available --show-duplicates.'
|
||||
)
|
||||
|
||||
bootstrap_apps.append({
|
||||
'name': app_name,
|
||||
'installed': state['installed'],
|
||||
@@ -110,6 +139,7 @@ def build_manage_applications_page_data(es_major='8', rabbitmq_stream='3'):
|
||||
'adopted': bool(state['installed'] and not state['markerExists']),
|
||||
'major': major if app_name == 'Elasticsearch' else '',
|
||||
'rabbitmqStream': rmq if app_name == 'RabbitMQ' else '',
|
||||
'rabbitmqVersionsHint': rabbitmq_versions_hint,
|
||||
})
|
||||
|
||||
bootstrap = {'status': 1, 'apps': bootstrap_apps}
|
||||
@@ -118,7 +148,7 @@ def build_manage_applications_page_data(es_major='8', rabbitmq_stream='3'):
|
||||
return services, meta_json
|
||||
|
||||
|
||||
def get_application_meta_response_dict(es_major='8', rabbitmq_stream='3'):
|
||||
def get_application_meta_response_dict(es_major='8', rabbitmq_stream='4'):
|
||||
"""
|
||||
JSON payload for POST /manageservices/applicationMeta.
|
||||
Reuses the same TTL cache as the Manage Applications HTML bootstrap so
|
||||
@@ -126,7 +156,7 @@ def get_application_meta_response_dict(es_major='8', rabbitmq_stream='3'):
|
||||
"""
|
||||
support = managed_apps_os_support()
|
||||
major = str(es_major).strip() if str(es_major).strip() in ('7', '8', '9') else '8'
|
||||
rmq = str(rabbitmq_stream).strip() if str(rabbitmq_stream).strip() in ('3', '4') else '3'
|
||||
rmq = str(rabbitmq_stream).strip() if str(rabbitmq_stream).strip() in ('3', '4') else '4'
|
||||
cache_key = 'major:{0}|rmq:{1}|support:{2}'.format(
|
||||
major, rmq, 1 if support.get('supported') else 0
|
||||
)
|
||||
|
||||
@@ -3,10 +3,13 @@
|
||||
Team RabbitMQ package repositories (Packagecloud) and Erlang compatibility
|
||||
for RabbitMQ 3.x vs 4.x installation streams.
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
from manageServices.application_detection import is_debian_family
|
||||
from manageServices.application_detection import is_debian_family, rhel_major_from_os_release
|
||||
|
||||
# Official Packagecloud install scripts (RabbitMQ team).
|
||||
_RPM_ERLANG_SCRIPT = (
|
||||
@@ -26,6 +29,42 @@ _DEB_SERVER_SCRIPT = (
|
||||
_MIN_OTP_STREAM_3 = 25
|
||||
_MIN_OTP_STREAM_4 = 26
|
||||
|
||||
# When Packagecloud metadata lists 3.x but no 4.x (common on el/9 trees), still offer GA
|
||||
# releases from https://www.rabbitmq.com/release-information so the panel can run
|
||||
# dnf install rabbitmq-server-<version> (RPMs are often el8-tagged on EL9 per upstream docs).
|
||||
# Update this tuple when new 4.x patches ship.
|
||||
RABBITMQ_4X_METADATA_FALLBACK_VERSIONS = (
|
||||
'4.2.5',
|
||||
'4.2.4',
|
||||
'4.2.3',
|
||||
'4.2.2',
|
||||
'4.2.1',
|
||||
'4.2.0',
|
||||
'4.1.8',
|
||||
'4.1.7',
|
||||
'4.1.6',
|
||||
'4.1.5',
|
||||
'4.1.4',
|
||||
'4.1.3',
|
||||
'4.1.2',
|
||||
'4.1.1',
|
||||
'4.1.0',
|
||||
'4.0.9',
|
||||
'4.0.8',
|
||||
'4.0.7',
|
||||
'4.0.6',
|
||||
'4.0.5',
|
||||
'4.0.4',
|
||||
'4.0.3',
|
||||
'4.0.2',
|
||||
'4.0.1',
|
||||
'4.0.0',
|
||||
)
|
||||
|
||||
_YUM_REPOS_D = '/etc/yum.repos.d'
|
||||
# Packagecloud RabbitMQ repos use .../el/N/... in baseurl; must match host RHEL major.
|
||||
_EL_URL_SEGMENT = re.compile(r'(/el/)(\d+)(/)')
|
||||
|
||||
|
||||
def _run(cmd, timeout=300):
|
||||
try:
|
||||
@@ -48,7 +87,7 @@ def _run_shell_trusted(script_url, timeout=300):
|
||||
|
||||
|
||||
def normalize_rabbitmq_stream(value):
|
||||
s = str(value or '3').strip()
|
||||
s = str(value or '4').strip()
|
||||
if s in ('4', '4.x', '41', '4.1'):
|
||||
return '4'
|
||||
return '3'
|
||||
@@ -64,6 +103,155 @@ def _write_status(status_file, message):
|
||||
pass
|
||||
|
||||
|
||||
def _rhel_refresh_package_metadata(status_file=None, aggressive=False):
|
||||
"""
|
||||
Refresh DNF/YUM metadata after adding Packagecloud repos.
|
||||
Retries on failure. When aggressive (e.g. 4.x stream), expire cache first
|
||||
so new rabbitmq-server builds become visible.
|
||||
"""
|
||||
if is_debian_family():
|
||||
return True
|
||||
if aggressive:
|
||||
exp_rc, _, exp_err = _run(['dnf', 'clean', 'expire-cache'], timeout=90)
|
||||
if exp_rc != 0:
|
||||
_write_status(
|
||||
status_file,
|
||||
'dnf expire-cache (non-fatal): ' + (exp_err or '')[:120]
|
||||
)
|
||||
last_err = ''
|
||||
for attempt in range(1, 4):
|
||||
for cache_cmd in (['dnf', 'makecache', '-y'], ['yum', 'makecache', '-y']):
|
||||
c_rc, c_out, c_err = _run(cache_cmd, timeout=180)
|
||||
if c_rc == 0:
|
||||
_write_status(
|
||||
status_file,
|
||||
'RPM metadata refreshed ({0}, attempt {1}).'.format(
|
||||
cache_cmd[0], attempt
|
||||
)
|
||||
)
|
||||
return True
|
||||
last_err = (c_err or c_out or str(c_rc)).strip()
|
||||
time.sleep(min(3 * attempt, 15))
|
||||
_write_status(
|
||||
status_file,
|
||||
'RPM metadata refresh failed after retries: ' + (last_err or 'unknown')[:240]
|
||||
)
|
||||
return False
|
||||
|
||||
|
||||
def refresh_rhel_metadata_for_rabbitmq_repos(status_file=None):
|
||||
"""
|
||||
Public: force another metadata refresh (e.g. when repoquery finds no 4.x RPMs).
|
||||
"""
|
||||
return _rhel_refresh_package_metadata(status_file=status_file, aggressive=True)
|
||||
|
||||
|
||||
def align_rabbitmq_packagecloud_repos_to_os(status_file=None):
|
||||
"""
|
||||
If Team RabbitMQ Packagecloud .repo files point at /el/M/ but this host is el/N,
|
||||
rewrite URLs to /el/N/ (e.g. stale el/8 on AlmaLinux 9). Only touches files that
|
||||
mention both packagecloud.io and rabbitmq. Requires root to write /etc/yum.repos.d.
|
||||
"""
|
||||
if is_debian_family():
|
||||
return
|
||||
target_major = rhel_major_from_os_release()
|
||||
if target_major is None:
|
||||
return
|
||||
if not os.path.isdir(_YUM_REPOS_D):
|
||||
return
|
||||
try:
|
||||
repo_names = sorted(
|
||||
n for n in os.listdir(_YUM_REPOS_D) if n.endswith('.repo')
|
||||
)
|
||||
except OSError as err:
|
||||
_write_status(
|
||||
status_file,
|
||||
'rabbitmq repo align: cannot list {0}: {1}'.format(
|
||||
_YUM_REPOS_D, str(err)[:100]
|
||||
)
|
||||
)
|
||||
return
|
||||
|
||||
for repo_name in repo_names:
|
||||
repo_path = os.path.join(_YUM_REPOS_D, repo_name)
|
||||
try:
|
||||
with open(repo_path, 'r', encoding='utf-8', errors='replace') as handle:
|
||||
original = handle.read()
|
||||
except OSError:
|
||||
continue
|
||||
lower = original.lower()
|
||||
if 'packagecloud.io' not in lower or 'rabbitmq' not in lower:
|
||||
continue
|
||||
|
||||
def _sub_el(match):
|
||||
current = int(match.group(2))
|
||||
if current == target_major:
|
||||
return match.group(0)
|
||||
return match.group(1) + str(target_major) + match.group(3)
|
||||
|
||||
updated = _EL_URL_SEGMENT.sub(_sub_el, original)
|
||||
if updated == original:
|
||||
continue
|
||||
tmp_path = None
|
||||
try:
|
||||
fd, tmp_path = tempfile.mkstemp(
|
||||
prefix='.cybercp-rabbitmq-',
|
||||
suffix='.tmp',
|
||||
dir=_YUM_REPOS_D,
|
||||
text=True,
|
||||
)
|
||||
with os.fdopen(fd, 'w', encoding='utf-8') as out:
|
||||
out.write(updated)
|
||||
os.replace(tmp_path, repo_path)
|
||||
tmp_path = None
|
||||
_write_status(
|
||||
status_file,
|
||||
'Aligned RabbitMQ Packagecloud repo {0} to el/{1}.'.format(
|
||||
repo_name, target_major
|
||||
)
|
||||
)
|
||||
except PermissionError:
|
||||
_write_status(
|
||||
status_file,
|
||||
'rabbitmq repo align: need root to rewrite {0} (el/{1}).'.format(
|
||||
repo_name, target_major
|
||||
)
|
||||
)
|
||||
except OSError as err:
|
||||
_write_status(
|
||||
status_file,
|
||||
'rabbitmq repo align: {0}: {1}'.format(repo_name, str(err)[:120])
|
||||
)
|
||||
finally:
|
||||
if tmp_path and os.path.isfile(tmp_path):
|
||||
try:
|
||||
os.unlink(tmp_path)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
def refresh_debian_apt_metadata(status_file=None):
|
||||
"""Second-chance apt metadata refresh without re-running Packagecloud scripts."""
|
||||
if not is_debian_family():
|
||||
return True
|
||||
last_err = ''
|
||||
for apt_attempt in range(1, 4):
|
||||
a_rc, _, a_err = _run(['apt-get', 'update', '-y'], timeout=180)
|
||||
if a_rc == 0:
|
||||
_write_status(
|
||||
status_file,
|
||||
'APT metadata refreshed (attempt {0}).'.format(apt_attempt)
|
||||
)
|
||||
return True
|
||||
last_err = (a_err or '').strip()
|
||||
_write_status(
|
||||
status_file,
|
||||
'apt-get update attempt {0}: {1}'.format(apt_attempt, (last_err or '')[:160])
|
||||
)
|
||||
time.sleep(min(3 * apt_attempt, 12))
|
||||
return False
|
||||
|
||||
|
||||
def ensure_rabbitmq_team_repos(stream, status_file=None):
|
||||
"""
|
||||
Idempotently enable rabbitmq-erlang and rabbitmq-server Packagecloud repos.
|
||||
@@ -84,8 +272,17 @@ def ensure_rabbitmq_team_repos(stream, status_file=None):
|
||||
_write_status(
|
||||
status_file, 'rabbitmq-server repo script: ' + (err2 or out2 or 'failed')
|
||||
)
|
||||
_run(['apt-get', 'update', '-y'], timeout=120)
|
||||
for apt_attempt in range(1, 4):
|
||||
a_rc, _, a_err = _run(['apt-get', 'update', '-y'], timeout=180)
|
||||
if a_rc == 0:
|
||||
break
|
||||
_write_status(
|
||||
status_file,
|
||||
'apt-get update attempt {0}: {1}'.format(apt_attempt, (a_err or '')[:160])
|
||||
)
|
||||
time.sleep(min(3 * apt_attempt, 12))
|
||||
else:
|
||||
align_rabbitmq_packagecloud_repos_to_os(status_file=status_file)
|
||||
rc, out, err = _run_shell_trusted(_RPM_ERLANG_SCRIPT)
|
||||
if rc != 0:
|
||||
_write_status(status_file, 'rabbitmq-erlang repo script: ' + (err or out or 'failed'))
|
||||
@@ -94,11 +291,11 @@ def ensure_rabbitmq_team_repos(stream, status_file=None):
|
||||
_write_status(
|
||||
status_file, 'rabbitmq-server repo script: ' + (err2 or out2 or 'failed')
|
||||
)
|
||||
# Prefer dnf; yum exists as symlink on EL8/9.
|
||||
for cache_cmd in (['dnf', 'makecache', '-y'], ['yum', 'makecache', '-y']):
|
||||
c_rc, _, _ = _run(cache_cmd, timeout=120)
|
||||
if c_rc == 0:
|
||||
break
|
||||
# 4.x builds may appear after a fresh metadata pull; expire + retries help visibility.
|
||||
_rhel_refresh_package_metadata(
|
||||
status_file=status_file,
|
||||
aggressive=(stream == '4'),
|
||||
)
|
||||
_write_status(status_file, 'Team RabbitMQ repositories ready.')
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import subprocess
|
||||
import threading
|
||||
import time
|
||||
|
||||
from manageServices.application_detection import is_debian_family, package_name_for_app
|
||||
from manageServices.application_detection import (
|
||||
is_debian_family,
|
||||
package_name_for_app,
|
||||
rhel_major_from_os_release,
|
||||
)
|
||||
|
||||
# applicationMeta can call get_available_versions many times per request (ES 7/8/9, RMQ 3/4).
|
||||
# Concurrent DNF from every WSGI worker exhausts lscpd and returns HTTP 503. Cache + serialize cold fetches.
|
||||
@@ -184,27 +189,37 @@ def _dnf_reposdir_flag(use_cyberpanel_extra):
|
||||
return ['--setopt=reposdir=/etc/yum.repos.d,{0}'.format(_CYBERPANEL_DNF_EXTRA)]
|
||||
|
||||
|
||||
def _rhel_repoquery_versions(pkg_name, use_cyberpanel_extra_repos=False, enablerepos=None):
|
||||
def _rhel_repoquery_versions(
|
||||
pkg_name,
|
||||
use_cyberpanel_extra_repos=False,
|
||||
enablerepos=None,
|
||||
latest_limit=50,
|
||||
normalize_max=25,
|
||||
):
|
||||
"""
|
||||
Resolve distinct %{version} strings from enabled repos.
|
||||
RPM NEVRA text parsing is brittle (el9_7 etc.); repoquery --qf is reliable.
|
||||
|
||||
For RabbitMQ, pass latest_limit=None (no cap — el8-tagged RPMs may share metadata
|
||||
with EL9) and normalize_max=200 so stream filtering (3.x vs 4.x) is not fed only
|
||||
the newest majors (which would hide the other line entirely).
|
||||
"""
|
||||
cmd = (
|
||||
dnf_cmd = (
|
||||
['dnf']
|
||||
+ _dnf_reposdir_flag(use_cyberpanel_extra_repos)
|
||||
+ [
|
||||
'repoquery',
|
||||
'--available',
|
||||
'--show-duplicates',
|
||||
'--latest-limit=50',
|
||||
'--qf',
|
||||
'%{version}',
|
||||
pkg_name,
|
||||
]
|
||||
)
|
||||
if latest_limit is not None:
|
||||
dnf_cmd.append('--latest-limit={0}'.format(int(latest_limit)))
|
||||
dnf_cmd.extend(['--qf', '%{version}', pkg_name])
|
||||
if enablerepos:
|
||||
for repo_id in enablerepos:
|
||||
cmd.extend(['--enablerepo', repo_id])
|
||||
rc, out, err = _run(cmd, timeout=180)
|
||||
dnf_cmd.extend(['--enablerepo', repo_id])
|
||||
rc, out, err = _run(dnf_cmd, timeout=240)
|
||||
raw = []
|
||||
if rc == 0 and out.strip():
|
||||
for line in out.splitlines():
|
||||
@@ -212,13 +227,14 @@ def _rhel_repoquery_versions(pkg_name, use_cyberpanel_extra_repos=False, enabler
|
||||
if v and re.match(r'^[0-9]', v):
|
||||
raw.append(v)
|
||||
if raw:
|
||||
return _normalize_versions(_sort_versions_desc(raw))
|
||||
return _normalize_versions(_sort_versions_desc(raw), max_items=normalize_max)
|
||||
|
||||
# Legacy systems / fallback
|
||||
rc2, out2, _ = _run(
|
||||
['yum', 'repoquery', '--show-duplicates', '--qf', '%{version}', pkg_name],
|
||||
timeout=120,
|
||||
)
|
||||
yum_cmd = ['yum', 'repoquery', '--available', '--show-duplicates']
|
||||
if latest_limit is not None:
|
||||
yum_cmd.append('--latest-limit={0}'.format(int(latest_limit)))
|
||||
yum_cmd.extend(['--qf', '%{version}', pkg_name])
|
||||
rc2, out2, _ = _run(yum_cmd, timeout=120)
|
||||
raw2 = []
|
||||
if rc2 == 0 and out2.strip():
|
||||
for line in out2.splitlines():
|
||||
@@ -226,10 +242,11 @@ def _rhel_repoquery_versions(pkg_name, use_cyberpanel_extra_repos=False, enabler
|
||||
if v and re.match(r'^[0-9]', v):
|
||||
raw2.append(v)
|
||||
if raw2:
|
||||
return _normalize_versions(_sort_versions_desc(raw2))
|
||||
return _normalize_versions(_sort_versions_desc(raw2), max_items=normalize_max)
|
||||
|
||||
# Oldest fallback: yum list
|
||||
rc3, out3, _ = _run(['yum', '--showduplicates', 'list', pkg_name], timeout=120)
|
||||
raw3 = []
|
||||
if rc3 == 0:
|
||||
for line in out3.splitlines():
|
||||
row = line.strip()
|
||||
@@ -237,13 +254,54 @@ def _rhel_repoquery_versions(pkg_name, use_cyberpanel_extra_repos=False, enabler
|
||||
continue
|
||||
fields = row.split()
|
||||
if len(fields) >= 2 and pkg_name in fields[0]:
|
||||
raw2.append(fields[1])
|
||||
if raw2:
|
||||
return _normalize_versions(_sort_versions_desc(raw2))
|
||||
raw3.append(fields[1])
|
||||
if raw3:
|
||||
return _normalize_versions(_sort_versions_desc(raw3), max_items=normalize_max)
|
||||
return []
|
||||
|
||||
|
||||
def _debian_versions(pkg_name):
|
||||
def _merge_version_candidates(primary, extra, normalize_max=200):
|
||||
"""Dedupe and sort descending for RabbitMQ multi-source repoquery."""
|
||||
return _normalize_versions(
|
||||
_sort_versions_desc(list(primary or []) + list(extra or [])),
|
||||
max_items=normalize_max,
|
||||
)
|
||||
|
||||
|
||||
def _rhel_repoquery_rabbitmq_packagecloud_el_dist(pkg_name, el_major):
|
||||
"""
|
||||
Query rabbitmq-server versions from a specific Packagecloud el/N path without
|
||||
enabling that repo system-wide. Helps when el/9 metadata lags el/8 for 4.x.
|
||||
"""
|
||||
arch = platform.machine() or 'x86_64'
|
||||
repoid = 'cybercp-pc-rmq-el{0}'.format(int(el_major))
|
||||
base = 'https://packagecloud.io/rabbitmq/rabbitmq-server/el/{0}/{1}'.format(
|
||||
int(el_major), arch
|
||||
)
|
||||
cmd = [
|
||||
'dnf',
|
||||
'repoquery',
|
||||
'--repofrompath={0},{1}'.format(repoid, base),
|
||||
'--setopt={0}.gpgcheck=0'.format(repoid),
|
||||
'--setopt={0}.repo_gpgcheck=0'.format(repoid),
|
||||
'--available',
|
||||
'--show-duplicates',
|
||||
'--qf',
|
||||
'%{version}',
|
||||
pkg_name,
|
||||
]
|
||||
rc, out, _ = _run(cmd, timeout=240)
|
||||
if rc != 0 or not (out or '').strip():
|
||||
return []
|
||||
raw = []
|
||||
for line in out.splitlines():
|
||||
v = (line or '').strip()
|
||||
if v and re.match(r'^[0-9]', v):
|
||||
raw.append(v)
|
||||
return _normalize_versions(_sort_versions_desc(raw), max_items=200)
|
||||
|
||||
|
||||
def _debian_versions(pkg_name, normalize_max=25):
|
||||
versions = []
|
||||
_run(['apt-get', 'update', '-y'], timeout=180)
|
||||
rc, out, _ = _run(['apt-cache', 'madison', pkg_name], timeout=60)
|
||||
@@ -259,7 +317,7 @@ def _debian_versions(pkg_name):
|
||||
for v in versions:
|
||||
m = re.search(r'(\d+\.\d+\.\d+)', v)
|
||||
collected.append(m.group(1) if m else v)
|
||||
return _normalize_versions(_sort_versions_desc(collected))
|
||||
return _normalize_versions(_sort_versions_desc(collected), max_items=normalize_max)
|
||||
|
||||
|
||||
def _filter_es_major(versions, es_major):
|
||||
@@ -272,7 +330,7 @@ def _filter_es_major(versions, es_major):
|
||||
return out
|
||||
|
||||
|
||||
def _get_available_versions_uncached(app_name, es_major='8', rabbitmq_stream='3'):
|
||||
def _get_available_versions_uncached(app_name, es_major='8', rabbitmq_stream='4'):
|
||||
pkg_name = package_name_for_app(app_name)
|
||||
if app_name == 'Elasticsearch':
|
||||
pkg_name = 'elasticsearch'
|
||||
@@ -280,18 +338,20 @@ def _get_available_versions_uncached(app_name, es_major='8', rabbitmq_stream='3'
|
||||
if not pkg_name:
|
||||
return []
|
||||
|
||||
rmq_stream = '3'
|
||||
rmq_stream = '4'
|
||||
if app_name == 'RabbitMQ':
|
||||
from manageServices.application_rabbitmq_repo import (
|
||||
normalize_rabbitmq_stream,
|
||||
ensure_rabbitmq_team_repos,
|
||||
filter_versions_for_stream,
|
||||
)
|
||||
rmq_stream = normalize_rabbitmq_stream(rabbitmq_stream)
|
||||
ensure_rabbitmq_team_repos(rmq_stream)
|
||||
|
||||
if is_debian_family():
|
||||
versions = _debian_versions(pkg_name)
|
||||
if app_name == 'RabbitMQ':
|
||||
versions = _debian_versions(pkg_name, normalize_max=200)
|
||||
else:
|
||||
versions = _debian_versions(pkg_name)
|
||||
if app_name == 'Elasticsearch':
|
||||
versions = _filter_es_major(versions, es_major)
|
||||
else:
|
||||
@@ -301,16 +361,50 @@ def _get_available_versions_uncached(app_name, es_major='8', rabbitmq_stream='3'
|
||||
pkg_name, use_cyberpanel_extra_repos=True
|
||||
)
|
||||
versions = _filter_es_major(versions, es_major)
|
||||
elif app_name == 'RabbitMQ':
|
||||
versions = _rhel_repoquery_versions(
|
||||
pkg_name, latest_limit=None, normalize_max=200
|
||||
)
|
||||
host_major = rhel_major_from_os_release()
|
||||
# el/9 (and newer) enabled repos often omit 4.x in metadata; el/8 tree may list them.
|
||||
if host_major is not None and host_major >= 9:
|
||||
pc_el8 = _rhel_repoquery_rabbitmq_packagecloud_el_dist(pkg_name, 8)
|
||||
if pc_el8:
|
||||
versions = _merge_version_candidates(versions, pc_el8, 200)
|
||||
else:
|
||||
versions = _rhel_repoquery_versions(pkg_name)
|
||||
|
||||
if app_name == 'RabbitMQ':
|
||||
from manageServices.application_rabbitmq_repo import filter_versions_for_stream
|
||||
from manageServices.application_rabbitmq_repo import (
|
||||
RABBITMQ_4X_METADATA_FALLBACK_VERSIONS,
|
||||
filter_versions_for_stream,
|
||||
refresh_debian_apt_metadata,
|
||||
refresh_rhel_metadata_for_rabbitmq_repos,
|
||||
)
|
||||
versions = filter_versions_for_stream(versions, rmq_stream)
|
||||
if not versions:
|
||||
if is_debian_family():
|
||||
refresh_debian_apt_metadata()
|
||||
versions = _debian_versions(pkg_name, normalize_max=200)
|
||||
else:
|
||||
refresh_rhel_metadata_for_rabbitmq_repos()
|
||||
versions = _rhel_repoquery_versions(
|
||||
pkg_name, latest_limit=None, normalize_max=200
|
||||
)
|
||||
host_major = rhel_major_from_os_release()
|
||||
if host_major is not None and host_major >= 9:
|
||||
pc_el8 = _rhel_repoquery_rabbitmq_packagecloud_el_dist(pkg_name, 8)
|
||||
if pc_el8:
|
||||
versions = _merge_version_candidates(versions, pc_el8, 200)
|
||||
versions = filter_versions_for_stream(versions, rmq_stream)
|
||||
# Always offer GA 4.x when DNF lists none (panel user may get empty repoquery).
|
||||
if rmq_stream == '4' and not versions and not is_debian_family():
|
||||
versions = list(RABBITMQ_4X_METADATA_FALLBACK_VERSIONS)
|
||||
versions = _normalize_versions(_sort_versions_desc(versions), max_items=40)
|
||||
return versions
|
||||
|
||||
|
||||
def get_available_versions(app_name, es_major='8', rabbitmq_stream='3'):
|
||||
def get_available_versions(app_name, es_major='8', rabbitmq_stream='4'):
|
||||
"""
|
||||
Cached wrapper: avoids hammering DNF from many concurrent panel workers (503 on Manage Applications).
|
||||
"""
|
||||
@@ -331,14 +425,14 @@ def get_available_versions(app_name, es_major='8', rabbitmq_stream='3'):
|
||||
return list(versions)
|
||||
|
||||
|
||||
def get_latest_version(app_name, es_major='8', rabbitmq_stream='3'):
|
||||
def get_latest_version(app_name, es_major='8', rabbitmq_stream='4'):
|
||||
versions = get_available_versions(app_name, es_major, rabbitmq_stream)
|
||||
if not versions:
|
||||
return ''
|
||||
return versions[0]
|
||||
|
||||
|
||||
def get_branch_and_global_latest(app_name, es_major='8', rabbitmq_stream='3'):
|
||||
def get_branch_and_global_latest(app_name, es_major='8', rabbitmq_stream='4'):
|
||||
"""
|
||||
Latest on the UI-selected branch/stream vs latest across all supported branches.
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ def main():
|
||||
parser.add_argument('--action', help='Action to run: install|remove|upgrade')
|
||||
parser.add_argument('--version', default='latest', help='Target package version or latest')
|
||||
parser.add_argument('--esMajor', default='8', help='Elasticsearch major stream (7|8|9)')
|
||||
parser.add_argument('--rabbitmqStream', default='3', help='RabbitMQ major stream (3|4)')
|
||||
parser.add_argument('--rabbitmqStream', default='4', help='RabbitMQ major stream (3|4)')
|
||||
|
||||
args = vars(parser.parse_args())
|
||||
|
||||
@@ -221,12 +221,12 @@ def main():
|
||||
elif args["function"] == "InstallRabbitMQ":
|
||||
ServiceManager.InstallRabbitMQ(
|
||||
version=args.get('version', 'latest'),
|
||||
stream=args.get('rabbitmqStream', '3'),
|
||||
stream=args.get('rabbitmqStream', '4'),
|
||||
)
|
||||
elif args["function"] == "UpgradeRabbitMQ":
|
||||
ServiceManager.UpgradeRabbitMQ(
|
||||
version=args.get('version', 'latest'),
|
||||
stream=args.get('rabbitmqStream', '3'),
|
||||
stream=args.get('rabbitmqStream', '4'),
|
||||
)
|
||||
elif args["function"] == "RemoveRabbitMQ":
|
||||
ServiceManager.RemoveRabbitMQ()
|
||||
@@ -235,7 +235,7 @@ def main():
|
||||
action = args.get("action").lower()
|
||||
version = args.get("version", "latest")
|
||||
es_major = args.get("esMajor", "8")
|
||||
rmq_stream = args.get("rabbitmqStream", "3")
|
||||
rmq_stream = args.get("rabbitmqStream", "4")
|
||||
|
||||
if app_name == 'Elasticsearch':
|
||||
if action == 'install':
|
||||
|
||||
@@ -477,6 +477,26 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
return out;
|
||||
}
|
||||
|
||||
function versionMatchesRabbitmqStream(ver, stream) {
|
||||
var s = String(stream || '4').trim();
|
||||
var t = normalizeVersionToken(ver);
|
||||
if (!t || t === 'latest') {
|
||||
return false;
|
||||
}
|
||||
var m = /^(\d+)\./.exec(t);
|
||||
return !!(m && m[1] === s);
|
||||
}
|
||||
|
||||
function versionMatchesEsMajor(ver, major) {
|
||||
var mjr = String(major || '8').trim();
|
||||
var t = normalizeVersionToken(ver);
|
||||
if (!t || t === 'latest') {
|
||||
return false;
|
||||
}
|
||||
var m = /^(\d+)\./.exec(t);
|
||||
return !!(m && m[1] === mjr);
|
||||
}
|
||||
|
||||
$scope.versionLabel = function (v) {
|
||||
if (v === 'latest') {
|
||||
return 'latest';
|
||||
@@ -535,7 +555,8 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
crossBranchUpdateSuggested: !!meta.crossBranchUpdateSuggested,
|
||||
versions: vers,
|
||||
latestAvailable: meta.latestAvailable || '',
|
||||
latestOverall: meta.latestOverall || ''
|
||||
latestOverall: meta.latestOverall || '',
|
||||
rabbitmqVersionsHint: meta.rabbitmqVersionsHint || ''
|
||||
};
|
||||
});
|
||||
} catch (ignore) {
|
||||
@@ -581,10 +602,33 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
}
|
||||
};
|
||||
$scope.selectedEsMajor = '8';
|
||||
$scope.selectedRabbitmqStream = '3';
|
||||
$scope.selectedRabbitmqStream = '4';
|
||||
/** RabbitMQ: 4.x is default for new installs (metadata prefetched). Upgrade may require picking stream if version line is unknown. ES major still user-picked before version list loads. */
|
||||
$scope.rabbitmqBranchChosen = false;
|
||||
$scope.esMajorChosen = false;
|
||||
$scope.confirmAction = false;
|
||||
$scope.selectedCurrentVersion = '';
|
||||
|
||||
$scope.chooseRabbitmqStream = function (stream) {
|
||||
var s = String(stream || '4').trim();
|
||||
if (s !== '3' && s !== '4') {
|
||||
s = '4';
|
||||
}
|
||||
$scope.selectedRabbitmqStream = s;
|
||||
$scope.rabbitmqBranchChosen = true;
|
||||
$scope.refreshMeta();
|
||||
};
|
||||
|
||||
$scope.chooseEsMajor = function (major) {
|
||||
var m = String(major || '8').trim();
|
||||
if (m !== '7' && m !== '8' && m !== '9') {
|
||||
m = '8';
|
||||
}
|
||||
$scope.selectedEsMajor = m;
|
||||
$scope.esMajorChosen = true;
|
||||
$scope.refreshMeta();
|
||||
};
|
||||
|
||||
/**
|
||||
* When the install/upgrade modal is open, re-apply version list from latest applicationMeta.
|
||||
* (Page-load meta can be empty for ES if dnf was slow; opening the modal must refetch.)
|
||||
@@ -596,13 +640,35 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
if ($scope.appName !== 'Elasticsearch' && $scope.appName !== 'Redis' && $scope.appName !== 'RabbitMQ') {
|
||||
return;
|
||||
}
|
||||
if ($scope.appName === 'RabbitMQ' && !$scope.rabbitmqBranchChosen) {
|
||||
$scope.selectedVersions = ['latest'];
|
||||
$scope.selectedVersion = 'latest';
|
||||
$scope.repoShowsOnlyOneStream = false;
|
||||
$scope.recalcSelectedVersionRowIndex();
|
||||
return;
|
||||
}
|
||||
if ($scope.appName === 'Elasticsearch' && !$scope.esMajorChosen) {
|
||||
$scope.selectedVersions = ['latest'];
|
||||
$scope.selectedVersion = 'latest';
|
||||
$scope.repoShowsOnlyOneStream = false;
|
||||
$scope.recalcSelectedVersionRowIndex();
|
||||
return;
|
||||
}
|
||||
var meta = $scope.findAppMeta($scope.appName);
|
||||
var vers = sanitizeVersionsArray((meta && meta.versions) ? meta.versions : []);
|
||||
$scope.selectedVersions = ['latest'].concat(vers);
|
||||
var curRaw = (meta && meta.installedVersion) ? meta.installedVersion : ($scope.selectedCurrentVersion || '');
|
||||
var cur = normalizeVersionToken(curRaw) || String(curRaw || '').trim();
|
||||
if (cur && $scope.selectedVersions.indexOf(cur) === -1) {
|
||||
$scope.selectedVersions.push(cur);
|
||||
var allowCur = true;
|
||||
if ($scope.appName === 'RabbitMQ') {
|
||||
allowCur = versionMatchesRabbitmqStream(cur, $scope.selectedRabbitmqStream);
|
||||
} else if ($scope.appName === 'Elasticsearch') {
|
||||
allowCur = versionMatchesEsMajor(cur, $scope.selectedEsMajor);
|
||||
}
|
||||
if (allowCur) {
|
||||
$scope.selectedVersions.push(cur);
|
||||
}
|
||||
}
|
||||
if (cur) {
|
||||
$scope.selectedCurrentVersion = cur;
|
||||
@@ -646,6 +712,16 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
(payload.apps || []).forEach(function (app) {
|
||||
appMap[app.name] = app;
|
||||
});
|
||||
var esMetaResp = appMap['Elasticsearch'];
|
||||
var rmqMetaResp = appMap['RabbitMQ'];
|
||||
var respEsMaj = String(esMetaResp && esMetaResp.major != null ? esMetaResp.major : '').trim();
|
||||
if (respEsMaj && respEsMaj !== String($scope.selectedEsMajor || '8').trim()) {
|
||||
return;
|
||||
}
|
||||
var respRmqStream = String(rmqMetaResp && rmqMetaResp.rabbitmqStream != null ? rmqMetaResp.rabbitmqStream : '').trim();
|
||||
if (respRmqStream && respRmqStream !== String($scope.selectedRabbitmqStream || '4').trim()) {
|
||||
return;
|
||||
}
|
||||
$scope.apps = $scope.apps.map(function (baseApp) {
|
||||
var meta = appMap[baseApp.name] || {};
|
||||
var vers = meta.versions;
|
||||
@@ -662,7 +738,8 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
crossBranchUpdateSuggested: !!meta.crossBranchUpdateSuggested,
|
||||
versions: vers,
|
||||
latestAvailable: meta.latestAvailable || '',
|
||||
latestOverall: meta.latestOverall || ''
|
||||
latestOverall: meta.latestOverall || '',
|
||||
rabbitmqVersionsHint: meta.rabbitmqVersionsHint || ''
|
||||
};
|
||||
});
|
||||
$scope.syncModalVersionLists();
|
||||
@@ -700,6 +777,13 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
$scope.selectedRabbitmqStream = '4';
|
||||
} else if (effectiveInstalled && /^3\./.test(effectiveInstalled)) {
|
||||
$scope.selectedRabbitmqStream = '3';
|
||||
} else if (status === 'Installing') {
|
||||
$scope.selectedRabbitmqStream = '4';
|
||||
}
|
||||
if (status === 'Upgrading' && effectiveInstalled) {
|
||||
if (/^4\./.test(effectiveInstalled) || /^3\./.test(effectiveInstalled)) {
|
||||
$scope.rabbitmqBranchChosen = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -715,13 +799,17 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
}
|
||||
|
||||
$scope.selectedVersions = ['latest'];
|
||||
var svcVers = sanitizeVersionsArray(service.versions || []);
|
||||
if (svcVers.length > 0) {
|
||||
$scope.selectedVersions = ['latest'].concat(svcVers);
|
||||
}
|
||||
var curPick = normalizeVersionToken(effectiveInstalled) || effectiveInstalled;
|
||||
if (curPick && $scope.selectedVersions.indexOf(curPick) === -1) {
|
||||
$scope.selectedVersions.push(curPick);
|
||||
var deferVersionList = (service.name === 'RabbitMQ' && !$scope.rabbitmqBranchChosen)
|
||||
|| (service.name === 'Elasticsearch' && !$scope.esMajorChosen);
|
||||
if (!deferVersionList) {
|
||||
var svcVers = sanitizeVersionsArray(service.versions || []);
|
||||
if (svcVers.length > 0) {
|
||||
$scope.selectedVersions = ['latest'].concat(svcVers);
|
||||
}
|
||||
var curPick = normalizeVersionToken(effectiveInstalled) || effectiveInstalled;
|
||||
if (curPick && $scope.selectedVersions.indexOf(curPick) === -1) {
|
||||
$scope.selectedVersions.push(curPick);
|
||||
}
|
||||
}
|
||||
$scope.selectedVersion = 'latest';
|
||||
$scope.requestData = '';
|
||||
@@ -729,7 +817,11 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
var realVers = ($scope.selectedVersions || []).filter(function (v) {
|
||||
return v && v !== 'latest';
|
||||
});
|
||||
$scope.repoShowsOnlyOneStream = ($scope.status === 'Upgrading' && realVers.length <= 1);
|
||||
if (deferVersionList) {
|
||||
$scope.repoShowsOnlyOneStream = false;
|
||||
} else {
|
||||
$scope.repoShowsOnlyOneStream = ($scope.status === 'Upgrading' && realVers.length <= 1);
|
||||
}
|
||||
$scope.recalcSelectedVersionRowIndex();
|
||||
};
|
||||
|
||||
@@ -775,44 +867,28 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
}
|
||||
};
|
||||
if (needMeta) {
|
||||
// applicationMeta uses selectedRabbitmqStream / selectedEsMajor. If the user left
|
||||
// 4.x selected earlier, the first POST would ask for 4.x while the node is on 3.x —
|
||||
// filtered versions come back empty and the Version dropdown shows only "latest".
|
||||
var bootVer = (bootstrapInstalledVersion !== undefined && bootstrapInstalledVersion !== null)
|
||||
? String(bootstrapInstalledVersion).trim()
|
||||
: '';
|
||||
if (!bootVer && appName) {
|
||||
var metaEarly = $scope.findAppMeta(appName);
|
||||
if (metaEarly && metaEarly.installedVersion) {
|
||||
bootVer = String(metaEarly.installedVersion).trim();
|
||||
}
|
||||
}
|
||||
if (appName === 'RabbitMQ' && bootVer) {
|
||||
if (/^4\./.test(bootVer)) {
|
||||
if (appName === 'RabbitMQ') {
|
||||
if (status === 'Installing') {
|
||||
$scope.selectedRabbitmqStream = '4';
|
||||
} else if (/^3\./.test(bootVer)) {
|
||||
$scope.selectedRabbitmqStream = '3';
|
||||
$scope.rabbitmqBranchChosen = true;
|
||||
} else {
|
||||
$scope.rabbitmqBranchChosen = false;
|
||||
}
|
||||
}
|
||||
if (appName === 'Elasticsearch' && bootVer) {
|
||||
var biv = bootVer;
|
||||
if (/^9\./.test(biv)) {
|
||||
$scope.selectedEsMajor = '9';
|
||||
} else if (/^8\./.test(biv)) {
|
||||
$scope.selectedEsMajor = '8';
|
||||
} else if (/^7\./.test(biv)) {
|
||||
$scope.selectedEsMajor = '7';
|
||||
}
|
||||
if (appName === 'Elasticsearch') {
|
||||
$scope.esMajorChosen = false;
|
||||
}
|
||||
// Open immediately with bootstrap / in-memory meta; refresh in background.
|
||||
// Blocking on applicationMeta made "Change version" feel frozen (dnf/repoquery).
|
||||
// RabbitMQ install: default 4.x stream and prefetch metadata. Upgrade: pick stream from installed version.
|
||||
// Elasticsearch: still wait for user major. Redis refreshes on open.
|
||||
$scope.appName = appName;
|
||||
$scope.status = status;
|
||||
$scope.prepareActionByName(appName, status, bootstrapInstalledVersion);
|
||||
showModal();
|
||||
$timeout(function () {
|
||||
$scope.refreshMeta();
|
||||
}, 0);
|
||||
if (appName === 'Redis' || (appName === 'RabbitMQ' && $scope.rabbitmqBranchChosen)) {
|
||||
$timeout(function () {
|
||||
$scope.refreshMeta();
|
||||
}, 0);
|
||||
}
|
||||
} else {
|
||||
$scope.prepareActionByName(appName, status, bootstrapInstalledVersion);
|
||||
showModal();
|
||||
@@ -833,6 +909,22 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (appName === 'RabbitMQ' && (status === 'Installing' || status === 'Upgrading') && !$scope.rabbitmqBranchChosen) {
|
||||
new PNotify({
|
||||
title: 'Stream required',
|
||||
text: 'Choose RabbitMQ 4.x or 3.x above to load versions for that line.',
|
||||
type: 'warning'
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (appName === 'Elasticsearch' && (status === 'Installing' || status === 'Upgrading') && !$scope.esMajorChosen) {
|
||||
new PNotify({
|
||||
title: 'Major version required',
|
||||
text: 'Choose Elasticsearch major (7, 8, or 9) above to load versions for that line.',
|
||||
type: 'warning'
|
||||
});
|
||||
return;
|
||||
}
|
||||
$scope.status = status;
|
||||
$scope.appName = appName;
|
||||
|
||||
@@ -845,7 +937,7 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
status: status,
|
||||
version: $scope.selectedVersion || 'latest',
|
||||
esMajor: $scope.selectedEsMajor || '8',
|
||||
rabbitmqStream: $scope.selectedRabbitmqStream || '3',
|
||||
rabbitmqStream: $scope.selectedRabbitmqStream || '4',
|
||||
confirmAction: $scope.confirmAction === true
|
||||
};
|
||||
|
||||
@@ -932,6 +1024,15 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
// Do not fetch package metadata on page load; it can block workers under DNF load.
|
||||
// Metadata is fetched on-demand when opening install/version-change modals.
|
||||
|
||||
if (typeof window.jQuery !== 'undefined' && jQuery.fn.on) {
|
||||
jQuery('#settings').on('hidden.bs.modal', function () {
|
||||
$scope.$evalAsync(function () {
|
||||
$scope.rabbitmqBranchChosen = false;
|
||||
$scope.esMajorChosen = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/* Java script code */
|
||||
@@ -587,7 +587,44 @@
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div style="margin-bottom: 10px;" ng-if="status == 'Installing' || status == 'Upgrading'">
|
||||
<div style="margin-bottom: 10px;" ng-if="appName == 'Elasticsearch' && (status == 'Installing' || status == 'Upgrading')">
|
||||
<label style="color: #0f172a;">{% trans "Elasticsearch Major" %}</label>
|
||||
<div class="manage-apps-version-picker">
|
||||
<div class="manage-apps-version-current">{% trans "Major" %}:
|
||||
<span ng-if="esMajorChosen" ng-bind="selectedEsMajor"></span>
|
||||
<span ng-if="!esMajorChosen">{% trans "Select a major below — versions load after you choose." %}</span>
|
||||
</div>
|
||||
<div class="manage-apps-version-rows">
|
||||
<button type="button" class="manage-apps-version-row" ng-class="{'is-active': esMajorChosen && selectedEsMajor === '7'}" ng-click="chooseEsMajor('7')">7</button>
|
||||
<button type="button" class="manage-apps-version-row" ng-class="{'is-active': esMajorChosen && selectedEsMajor === '8'}" ng-click="chooseEsMajor('8')">8</button>
|
||||
<button type="button" class="manage-apps-version-row" ng-class="{'is-active': esMajorChosen && selectedEsMajor === '9'}" ng-click="chooseEsMajor('9')">9</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px;" ng-if="appName == 'RabbitMQ' && (status == 'Installing' || status == 'Upgrading')">
|
||||
<label style="color: #0f172a;">{% trans "RabbitMQ major line" %}</label>
|
||||
<div class="manage-apps-version-picker">
|
||||
<div class="manage-apps-version-current">{% trans "Stream" %}:
|
||||
<span ng-if="rabbitmqBranchChosen && selectedRabbitmqStream === '4'">4.x</span>
|
||||
<span ng-if="rabbitmqBranchChosen && selectedRabbitmqStream === '3'">3.x ({% trans "maintenance" %})</span>
|
||||
<span ng-if="!rabbitmqBranchChosen">{% trans "Select a stream below — versions load after you choose." %}</span>
|
||||
</div>
|
||||
<div class="manage-apps-version-rows">
|
||||
<button type="button" class="manage-apps-version-row" ng-class="{'is-active': rabbitmqBranchChosen && selectedRabbitmqStream === '4'}" ng-click="chooseRabbitmqStream('4')">4.x</button>
|
||||
<button type="button" class="manage-apps-version-row" ng-class="{'is-active': rabbitmqBranchChosen && selectedRabbitmqStream === '3'}" ng-click="chooseRabbitmqStream('3')">3.x ({% trans "maintenance" %})</button>
|
||||
</div>
|
||||
</div>
|
||||
<p style="margin-top: 8px; font-size: 12px; color: #64748b;">
|
||||
{% trans "Uses Team RabbitMQ Packagecloud repos; 4.x requires a compatible Erlang (OTP 26+). The installer will try to align Erlang when needed." %}
|
||||
{% trans "Upstream RPMs may be named el8 but are still supported on AlmaLinux/RHEL/Rocky 9." %}
|
||||
</p>
|
||||
<div style="margin-top: 10px; padding: 10px 12px; background: #fff7ed; border-radius: 8px; font-size: 12px; color: #9a3412; border: 1px solid #fed7aa;"
|
||||
ng-if="rabbitmqBranchChosen && findAppMeta('RabbitMQ').rabbitmqVersionsHint">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
<span ng-bind="findAppMeta('RabbitMQ').rabbitmqVersionsHint"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px;" ng-if="(status == 'Installing' || status == 'Upgrading') && (appName != 'RabbitMQ' || rabbitmqBranchChosen) && (appName != 'Elasticsearch' || esMajorChosen)">
|
||||
<label style="color: #0f172a;">{% trans "Version" %}</label>
|
||||
<div class="manage-apps-version-picker">
|
||||
<div class="manage-apps-version-current">
|
||||
@@ -615,30 +652,6 @@
|
||||
ng-if="status == 'Upgrading'">
|
||||
{% trans "A backup of application data is created automatically before upgrading or downgrading. Data is merged into the new version after packages install; the backup is removed only after a successful start." %}
|
||||
</div>
|
||||
<div style="margin-bottom: 10px;" ng-if="appName == 'Elasticsearch' && (status == 'Installing' || status == 'Upgrading')">
|
||||
<label style="color: #0f172a;">{% trans "Elasticsearch Major" %}</label>
|
||||
<div class="manage-apps-version-picker">
|
||||
<div class="manage-apps-version-current">{% trans "Major" %}: <span ng-bind="selectedEsMajor"></span></div>
|
||||
<div class="manage-apps-version-rows">
|
||||
<button type="button" class="manage-apps-version-row" ng-class="{'is-active': selectedEsMajor === '7'}" ng-click="selectedEsMajor = '7'; refreshMeta()">7</button>
|
||||
<button type="button" class="manage-apps-version-row" ng-class="{'is-active': selectedEsMajor === '8'}" ng-click="selectedEsMajor = '8'; refreshMeta()">8</button>
|
||||
<button type="button" class="manage-apps-version-row" ng-class="{'is-active': selectedEsMajor === '9'}" ng-click="selectedEsMajor = '9'; refreshMeta()">9</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px;" ng-if="appName == 'RabbitMQ' && (status == 'Installing' || status == 'Upgrading')">
|
||||
<label style="color: #0f172a;">{% trans "RabbitMQ major line" %}</label>
|
||||
<div class="manage-apps-version-picker">
|
||||
<div class="manage-apps-version-current">{% trans "Stream" %}: <span ng-bind="selectedRabbitmqStream === '4' ? '4.x' : '3.x'"></span></div>
|
||||
<div class="manage-apps-version-rows">
|
||||
<button type="button" class="manage-apps-version-row" ng-class="{'is-active': selectedRabbitmqStream === '3'}" ng-click="selectedRabbitmqStream = '3'; refreshMeta()">3.x ({% trans "maintenance" %})</button>
|
||||
<button type="button" class="manage-apps-version-row" ng-class="{'is-active': selectedRabbitmqStream === '4'}" ng-click="selectedRabbitmqStream = '4'; refreshMeta()">4.x</button>
|
||||
</div>
|
||||
</div>
|
||||
<p style="margin-top: 8px; font-size: 12px; color: #64748b;">
|
||||
{% trans "Uses Team RabbitMQ Packagecloud repos; 4.x requires a compatible Erlang (OTP 26+). The installer will try to align Erlang when needed." %}
|
||||
</p>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px; padding: 10px 12px; background: #f0f9ff; border-radius: 8px; font-size: 13px; color: #1e3a5f; border: 1px solid #bae6fd;"
|
||||
ng-if="(status == 'Installing' || status == 'Upgrading') && findAppMeta(appName).crossBranchUpdateSuggested">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
@@ -647,7 +660,8 @@
|
||||
</div>
|
||||
<div style="margin-bottom: 10px;" ng-if="status == 'Removing' || status == 'Upgrading'">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="confirmAction">
|
||||
{# ng-if creates a child scope; bind to parent so runAction() sees the same flag #}
|
||||
<input type="checkbox" ng-model="$parent.confirmAction">
|
||||
<span ng-if="status == 'Removing'">{% trans "Confirm Remove" %}</span>
|
||||
<span ng-if="status == 'Upgrading'">{% trans "Confirm version change" %}</span>
|
||||
</label>
|
||||
|
||||
@@ -277,7 +277,7 @@ def saveStatus(request):
|
||||
|
||||
def manageApplications(request):
|
||||
services, application_meta_bootstrap_json = build_manage_applications_page_data(
|
||||
'8', '3'
|
||||
'8', '4'
|
||||
)
|
||||
|
||||
proc = httpProc(
|
||||
@@ -308,9 +308,9 @@ def applicationMeta(request):
|
||||
if requested_major not in ('7', '8', '9'):
|
||||
requested_major = '8'
|
||||
|
||||
requested_rmq_stream = str(data.get('rabbitmqStream', '3')).strip()
|
||||
requested_rmq_stream = str(data.get('rabbitmqStream', '4')).strip()
|
||||
if requested_rmq_stream not in ('3', '4'):
|
||||
requested_rmq_stream = '3'
|
||||
requested_rmq_stream = '4'
|
||||
|
||||
response_data = get_application_meta_response_dict(
|
||||
requested_major, requested_rmq_stream
|
||||
@@ -345,9 +345,9 @@ def removeInstall(request):
|
||||
esMajor = str(data.get('esMajor', '8')).strip() or '8'
|
||||
if esMajor not in ('7', '8', '9'):
|
||||
esMajor = '8'
|
||||
rabbitmqStream = str(data.get('rabbitmqStream', '3')).strip() or '3'
|
||||
rabbitmqStream = str(data.get('rabbitmqStream', '4')).strip() or '4'
|
||||
if rabbitmqStream not in ('3', '4'):
|
||||
rabbitmqStream = '3'
|
||||
rabbitmqStream = '4'
|
||||
confirmAction = bool(data.get('confirmAction', False))
|
||||
|
||||
support = managed_apps_os_support()
|
||||
|
||||
@@ -477,6 +477,26 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
return out;
|
||||
}
|
||||
|
||||
function versionMatchesRabbitmqStream(ver, stream) {
|
||||
var s = String(stream || '4').trim();
|
||||
var t = normalizeVersionToken(ver);
|
||||
if (!t || t === 'latest') {
|
||||
return false;
|
||||
}
|
||||
var m = /^(\d+)\./.exec(t);
|
||||
return !!(m && m[1] === s);
|
||||
}
|
||||
|
||||
function versionMatchesEsMajor(ver, major) {
|
||||
var mjr = String(major || '8').trim();
|
||||
var t = normalizeVersionToken(ver);
|
||||
if (!t || t === 'latest') {
|
||||
return false;
|
||||
}
|
||||
var m = /^(\d+)\./.exec(t);
|
||||
return !!(m && m[1] === mjr);
|
||||
}
|
||||
|
||||
$scope.versionLabel = function (v) {
|
||||
if (v === 'latest') {
|
||||
return 'latest';
|
||||
@@ -535,7 +555,8 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
crossBranchUpdateSuggested: !!meta.crossBranchUpdateSuggested,
|
||||
versions: vers,
|
||||
latestAvailable: meta.latestAvailable || '',
|
||||
latestOverall: meta.latestOverall || ''
|
||||
latestOverall: meta.latestOverall || '',
|
||||
rabbitmqVersionsHint: meta.rabbitmqVersionsHint || ''
|
||||
};
|
||||
});
|
||||
} catch (ignore) {
|
||||
@@ -581,10 +602,33 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
}
|
||||
};
|
||||
$scope.selectedEsMajor = '8';
|
||||
$scope.selectedRabbitmqStream = '3';
|
||||
$scope.selectedRabbitmqStream = '4';
|
||||
/** RabbitMQ: 4.x is default for new installs (metadata prefetched). Upgrade may require picking stream if version line is unknown. ES major still user-picked before version list loads. */
|
||||
$scope.rabbitmqBranchChosen = false;
|
||||
$scope.esMajorChosen = false;
|
||||
$scope.confirmAction = false;
|
||||
$scope.selectedCurrentVersion = '';
|
||||
|
||||
$scope.chooseRabbitmqStream = function (stream) {
|
||||
var s = String(stream || '4').trim();
|
||||
if (s !== '3' && s !== '4') {
|
||||
s = '4';
|
||||
}
|
||||
$scope.selectedRabbitmqStream = s;
|
||||
$scope.rabbitmqBranchChosen = true;
|
||||
$scope.refreshMeta();
|
||||
};
|
||||
|
||||
$scope.chooseEsMajor = function (major) {
|
||||
var m = String(major || '8').trim();
|
||||
if (m !== '7' && m !== '8' && m !== '9') {
|
||||
m = '8';
|
||||
}
|
||||
$scope.selectedEsMajor = m;
|
||||
$scope.esMajorChosen = true;
|
||||
$scope.refreshMeta();
|
||||
};
|
||||
|
||||
/**
|
||||
* When the install/upgrade modal is open, re-apply version list from latest applicationMeta.
|
||||
* (Page-load meta can be empty for ES if dnf was slow; opening the modal must refetch.)
|
||||
@@ -596,13 +640,35 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
if ($scope.appName !== 'Elasticsearch' && $scope.appName !== 'Redis' && $scope.appName !== 'RabbitMQ') {
|
||||
return;
|
||||
}
|
||||
if ($scope.appName === 'RabbitMQ' && !$scope.rabbitmqBranchChosen) {
|
||||
$scope.selectedVersions = ['latest'];
|
||||
$scope.selectedVersion = 'latest';
|
||||
$scope.repoShowsOnlyOneStream = false;
|
||||
$scope.recalcSelectedVersionRowIndex();
|
||||
return;
|
||||
}
|
||||
if ($scope.appName === 'Elasticsearch' && !$scope.esMajorChosen) {
|
||||
$scope.selectedVersions = ['latest'];
|
||||
$scope.selectedVersion = 'latest';
|
||||
$scope.repoShowsOnlyOneStream = false;
|
||||
$scope.recalcSelectedVersionRowIndex();
|
||||
return;
|
||||
}
|
||||
var meta = $scope.findAppMeta($scope.appName);
|
||||
var vers = sanitizeVersionsArray((meta && meta.versions) ? meta.versions : []);
|
||||
$scope.selectedVersions = ['latest'].concat(vers);
|
||||
var curRaw = (meta && meta.installedVersion) ? meta.installedVersion : ($scope.selectedCurrentVersion || '');
|
||||
var cur = normalizeVersionToken(curRaw) || String(curRaw || '').trim();
|
||||
if (cur && $scope.selectedVersions.indexOf(cur) === -1) {
|
||||
$scope.selectedVersions.push(cur);
|
||||
var allowCur = true;
|
||||
if ($scope.appName === 'RabbitMQ') {
|
||||
allowCur = versionMatchesRabbitmqStream(cur, $scope.selectedRabbitmqStream);
|
||||
} else if ($scope.appName === 'Elasticsearch') {
|
||||
allowCur = versionMatchesEsMajor(cur, $scope.selectedEsMajor);
|
||||
}
|
||||
if (allowCur) {
|
||||
$scope.selectedVersions.push(cur);
|
||||
}
|
||||
}
|
||||
if (cur) {
|
||||
$scope.selectedCurrentVersion = cur;
|
||||
@@ -646,6 +712,16 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
(payload.apps || []).forEach(function (app) {
|
||||
appMap[app.name] = app;
|
||||
});
|
||||
var esMetaResp = appMap['Elasticsearch'];
|
||||
var rmqMetaResp = appMap['RabbitMQ'];
|
||||
var respEsMaj = String(esMetaResp && esMetaResp.major != null ? esMetaResp.major : '').trim();
|
||||
if (respEsMaj && respEsMaj !== String($scope.selectedEsMajor || '8').trim()) {
|
||||
return;
|
||||
}
|
||||
var respRmqStream = String(rmqMetaResp && rmqMetaResp.rabbitmqStream != null ? rmqMetaResp.rabbitmqStream : '').trim();
|
||||
if (respRmqStream && respRmqStream !== String($scope.selectedRabbitmqStream || '4').trim()) {
|
||||
return;
|
||||
}
|
||||
$scope.apps = $scope.apps.map(function (baseApp) {
|
||||
var meta = appMap[baseApp.name] || {};
|
||||
var vers = meta.versions;
|
||||
@@ -662,7 +738,8 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
crossBranchUpdateSuggested: !!meta.crossBranchUpdateSuggested,
|
||||
versions: vers,
|
||||
latestAvailable: meta.latestAvailable || '',
|
||||
latestOverall: meta.latestOverall || ''
|
||||
latestOverall: meta.latestOverall || '',
|
||||
rabbitmqVersionsHint: meta.rabbitmqVersionsHint || ''
|
||||
};
|
||||
});
|
||||
$scope.syncModalVersionLists();
|
||||
@@ -700,6 +777,13 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
$scope.selectedRabbitmqStream = '4';
|
||||
} else if (effectiveInstalled && /^3\./.test(effectiveInstalled)) {
|
||||
$scope.selectedRabbitmqStream = '3';
|
||||
} else if (status === 'Installing') {
|
||||
$scope.selectedRabbitmqStream = '4';
|
||||
}
|
||||
if (status === 'Upgrading' && effectiveInstalled) {
|
||||
if (/^4\./.test(effectiveInstalled) || /^3\./.test(effectiveInstalled)) {
|
||||
$scope.rabbitmqBranchChosen = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -715,13 +799,17 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
}
|
||||
|
||||
$scope.selectedVersions = ['latest'];
|
||||
var svcVers = sanitizeVersionsArray(service.versions || []);
|
||||
if (svcVers.length > 0) {
|
||||
$scope.selectedVersions = ['latest'].concat(svcVers);
|
||||
}
|
||||
var curPick = normalizeVersionToken(effectiveInstalled) || effectiveInstalled;
|
||||
if (curPick && $scope.selectedVersions.indexOf(curPick) === -1) {
|
||||
$scope.selectedVersions.push(curPick);
|
||||
var deferVersionList = (service.name === 'RabbitMQ' && !$scope.rabbitmqBranchChosen)
|
||||
|| (service.name === 'Elasticsearch' && !$scope.esMajorChosen);
|
||||
if (!deferVersionList) {
|
||||
var svcVers = sanitizeVersionsArray(service.versions || []);
|
||||
if (svcVers.length > 0) {
|
||||
$scope.selectedVersions = ['latest'].concat(svcVers);
|
||||
}
|
||||
var curPick = normalizeVersionToken(effectiveInstalled) || effectiveInstalled;
|
||||
if (curPick && $scope.selectedVersions.indexOf(curPick) === -1) {
|
||||
$scope.selectedVersions.push(curPick);
|
||||
}
|
||||
}
|
||||
$scope.selectedVersion = 'latest';
|
||||
$scope.requestData = '';
|
||||
@@ -729,7 +817,11 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
var realVers = ($scope.selectedVersions || []).filter(function (v) {
|
||||
return v && v !== 'latest';
|
||||
});
|
||||
$scope.repoShowsOnlyOneStream = ($scope.status === 'Upgrading' && realVers.length <= 1);
|
||||
if (deferVersionList) {
|
||||
$scope.repoShowsOnlyOneStream = false;
|
||||
} else {
|
||||
$scope.repoShowsOnlyOneStream = ($scope.status === 'Upgrading' && realVers.length <= 1);
|
||||
}
|
||||
$scope.recalcSelectedVersionRowIndex();
|
||||
};
|
||||
|
||||
@@ -775,44 +867,28 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
}
|
||||
};
|
||||
if (needMeta) {
|
||||
// applicationMeta uses selectedRabbitmqStream / selectedEsMajor. If the user left
|
||||
// 4.x selected earlier, the first POST would ask for 4.x while the node is on 3.x —
|
||||
// filtered versions come back empty and the Version dropdown shows only "latest".
|
||||
var bootVer = (bootstrapInstalledVersion !== undefined && bootstrapInstalledVersion !== null)
|
||||
? String(bootstrapInstalledVersion).trim()
|
||||
: '';
|
||||
if (!bootVer && appName) {
|
||||
var metaEarly = $scope.findAppMeta(appName);
|
||||
if (metaEarly && metaEarly.installedVersion) {
|
||||
bootVer = String(metaEarly.installedVersion).trim();
|
||||
}
|
||||
}
|
||||
if (appName === 'RabbitMQ' && bootVer) {
|
||||
if (/^4\./.test(bootVer)) {
|
||||
if (appName === 'RabbitMQ') {
|
||||
if (status === 'Installing') {
|
||||
$scope.selectedRabbitmqStream = '4';
|
||||
} else if (/^3\./.test(bootVer)) {
|
||||
$scope.selectedRabbitmqStream = '3';
|
||||
$scope.rabbitmqBranchChosen = true;
|
||||
} else {
|
||||
$scope.rabbitmqBranchChosen = false;
|
||||
}
|
||||
}
|
||||
if (appName === 'Elasticsearch' && bootVer) {
|
||||
var biv = bootVer;
|
||||
if (/^9\./.test(biv)) {
|
||||
$scope.selectedEsMajor = '9';
|
||||
} else if (/^8\./.test(biv)) {
|
||||
$scope.selectedEsMajor = '8';
|
||||
} else if (/^7\./.test(biv)) {
|
||||
$scope.selectedEsMajor = '7';
|
||||
}
|
||||
if (appName === 'Elasticsearch') {
|
||||
$scope.esMajorChosen = false;
|
||||
}
|
||||
// Open immediately with bootstrap / in-memory meta; refresh in background.
|
||||
// Blocking on applicationMeta made "Change version" feel frozen (dnf/repoquery).
|
||||
// RabbitMQ install: default 4.x stream and prefetch metadata. Upgrade: pick stream from installed version.
|
||||
// Elasticsearch: still wait for user major. Redis refreshes on open.
|
||||
$scope.appName = appName;
|
||||
$scope.status = status;
|
||||
$scope.prepareActionByName(appName, status, bootstrapInstalledVersion);
|
||||
showModal();
|
||||
$timeout(function () {
|
||||
$scope.refreshMeta();
|
||||
}, 0);
|
||||
if (appName === 'Redis' || (appName === 'RabbitMQ' && $scope.rabbitmqBranchChosen)) {
|
||||
$timeout(function () {
|
||||
$scope.refreshMeta();
|
||||
}, 0);
|
||||
}
|
||||
} else {
|
||||
$scope.prepareActionByName(appName, status, bootstrapInstalledVersion);
|
||||
showModal();
|
||||
@@ -833,6 +909,22 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (appName === 'RabbitMQ' && (status === 'Installing' || status === 'Upgrading') && !$scope.rabbitmqBranchChosen) {
|
||||
new PNotify({
|
||||
title: 'Stream required',
|
||||
text: 'Choose RabbitMQ 4.x or 3.x above to load versions for that line.',
|
||||
type: 'warning'
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (appName === 'Elasticsearch' && (status === 'Installing' || status === 'Upgrading') && !$scope.esMajorChosen) {
|
||||
new PNotify({
|
||||
title: 'Major version required',
|
||||
text: 'Choose Elasticsearch major (7, 8, or 9) above to load versions for that line.',
|
||||
type: 'warning'
|
||||
});
|
||||
return;
|
||||
}
|
||||
$scope.status = status;
|
||||
$scope.appName = appName;
|
||||
|
||||
@@ -845,7 +937,7 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
status: status,
|
||||
version: $scope.selectedVersion || 'latest',
|
||||
esMajor: $scope.selectedEsMajor || '8',
|
||||
rabbitmqStream: $scope.selectedRabbitmqStream || '3',
|
||||
rabbitmqStream: $scope.selectedRabbitmqStream || '4',
|
||||
confirmAction: $scope.confirmAction === true
|
||||
};
|
||||
|
||||
@@ -932,6 +1024,15 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
// Do not fetch package metadata on page load; it can block workers under DNF load.
|
||||
// Metadata is fetched on-demand when opening install/version-change modals.
|
||||
|
||||
if (typeof window.jQuery !== 'undefined' && jQuery.fn.on) {
|
||||
jQuery('#settings').on('hidden.bs.modal', function () {
|
||||
$scope.$evalAsync(function () {
|
||||
$scope.rabbitmqBranchChosen = false;
|
||||
$scope.esMajorChosen = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/* Java script code */
|
||||
@@ -428,10 +428,503 @@ app.controller('pureFTPD', function ($scope, $http, $timeout, $window) {
|
||||
|
||||
app.controller('manageApplications', function ($scope, $http, $timeout, $window) {
|
||||
|
||||
/**
|
||||
* Normalize entries from applicationMeta (strings, numbers, or rare object shapes)
|
||||
* so version pickers never show blank rows. CyberPanel uses {$ ... $} interpolation
|
||||
* in templates; list labels use versionLabel() for consistent display.
|
||||
*/
|
||||
function normalizeVersionToken(v) {
|
||||
if (v === null || v === undefined) {
|
||||
return '';
|
||||
}
|
||||
if (v === 'latest') {
|
||||
return 'latest';
|
||||
}
|
||||
if (typeof v === 'number' && isFinite(v)) {
|
||||
return String(v);
|
||||
}
|
||||
if (angular.isObject(v)) {
|
||||
var o = v;
|
||||
var cand = o.version || o.Version || o.value || o.name || o.ver || o.label;
|
||||
if (cand !== undefined && cand !== null) {
|
||||
return String(cand).trim();
|
||||
}
|
||||
try {
|
||||
return JSON.stringify(o);
|
||||
} catch (ignore) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
return String(v).trim();
|
||||
}
|
||||
|
||||
function sanitizeVersionsArray(vers) {
|
||||
if (!angular.isArray(vers)) {
|
||||
return [];
|
||||
}
|
||||
var out = [];
|
||||
var seen = {};
|
||||
vers.forEach(function (raw) {
|
||||
var t = normalizeVersionToken(raw);
|
||||
if (!t || t === 'latest') {
|
||||
return;
|
||||
}
|
||||
if (!seen[t]) {
|
||||
seen[t] = true;
|
||||
out.push(t);
|
||||
}
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
function versionMatchesRabbitmqStream(ver, stream) {
|
||||
var s = String(stream || '4').trim();
|
||||
var t = normalizeVersionToken(ver);
|
||||
if (!t || t === 'latest') {
|
||||
return false;
|
||||
}
|
||||
var m = /^(\d+)\./.exec(t);
|
||||
return !!(m && m[1] === s);
|
||||
}
|
||||
|
||||
function versionMatchesEsMajor(ver, major) {
|
||||
var mjr = String(major || '8').trim();
|
||||
var t = normalizeVersionToken(ver);
|
||||
if (!t || t === 'latest') {
|
||||
return false;
|
||||
}
|
||||
var m = /^(\d+)\./.exec(t);
|
||||
return !!(m && m[1] === mjr);
|
||||
}
|
||||
|
||||
$scope.versionLabel = function (v) {
|
||||
if (v === 'latest') {
|
||||
return 'latest';
|
||||
}
|
||||
var t = normalizeVersionToken(v);
|
||||
return t || '(unknown)';
|
||||
};
|
||||
|
||||
$scope.versionTrackId = function (idx, v) {
|
||||
return String(idx) + '|' + $scope.versionLabel(v);
|
||||
};
|
||||
|
||||
/* false = long-running install/remove/poll (show spinners); true = idle */
|
||||
$scope.cyberpanelLoading = true;
|
||||
/** Background applicationMeta refresh — separate from cyberpanelLoading so the page does not “freeze” on every modal open. */
|
||||
$scope.appsMetaRefreshing = false;
|
||||
$scope.apps = [
|
||||
{name: 'Elasticsearch', image: '/static/manageServices/images/elastic-search.png'},
|
||||
{name: 'Redis', image: '/static/manageServices/images/redis.png'},
|
||||
{name: 'RabbitMQ', image: '/static/manageServices/images/rabbitmq-logo.svg'}
|
||||
];
|
||||
|
||||
$scope.removeInstall = function (appName, status) {
|
||||
(function mergeMetaBootstrap() {
|
||||
var el = document.getElementById('manageApplicationsMetaBootstrap');
|
||||
if (!el || !el.textContent) {
|
||||
return;
|
||||
}
|
||||
var raw = el.textContent.trim();
|
||||
if (!raw) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
var boot = JSON.parse(raw);
|
||||
if (!boot || Number(boot.status) !== 1) {
|
||||
return;
|
||||
}
|
||||
var appMap = {};
|
||||
(boot.apps || []).forEach(function (a) {
|
||||
if (a && a.name) {
|
||||
appMap[a.name] = a;
|
||||
}
|
||||
});
|
||||
$scope.apps = $scope.apps.map(function (baseApp) {
|
||||
var meta = appMap[baseApp.name] || {};
|
||||
var vers = meta.versions;
|
||||
if (!angular.isArray(vers)) {
|
||||
vers = [];
|
||||
}
|
||||
vers = sanitizeVersionsArray(vers);
|
||||
return {
|
||||
name: baseApp.name,
|
||||
image: baseApp.image,
|
||||
installed: !!meta.installed,
|
||||
installedVersion: meta.installedVersion || '',
|
||||
updateAvailable: !!meta.updateAvailable,
|
||||
crossBranchUpdateSuggested: !!meta.crossBranchUpdateSuggested,
|
||||
versions: vers,
|
||||
latestAvailable: meta.latestAvailable || '',
|
||||
latestOverall: meta.latestOverall || '',
|
||||
rabbitmqVersionsHint: meta.rabbitmqVersionsHint || ''
|
||||
};
|
||||
});
|
||||
} catch (ignore) {
|
||||
/* keep bare apps list */
|
||||
}
|
||||
})();
|
||||
|
||||
$scope.selectedVersion = 'latest';
|
||||
/** Row highlight uses $index so only one row looks selected (avoids sticky :focus / repeater quirks). */
|
||||
$scope.selectedVersionRowIndex = 0;
|
||||
$scope.selectedVersions = ['latest'];
|
||||
|
||||
$scope.recalcSelectedVersionRowIndex = function () {
|
||||
var list = $scope.selectedVersions || [];
|
||||
var sel = $scope.selectedVersion;
|
||||
var i = list.indexOf(sel);
|
||||
if (i < 0) {
|
||||
var normSel = normalizeVersionToken(sel);
|
||||
if (normSel) {
|
||||
for (var j = 0; j < list.length; j += 1) {
|
||||
if (normalizeVersionToken(list[j]) === normSel) {
|
||||
i = j;
|
||||
$scope.selectedVersion = list[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$scope.selectedVersionRowIndex = (i >= 0) ? i : 0;
|
||||
};
|
||||
|
||||
$scope.selectManagedAppVersion = function (idx, v, $event) {
|
||||
var n = (typeof idx === 'number') ? idx : parseInt(idx, 10);
|
||||
if (!isFinite(n) || n < 0) {
|
||||
n = 0;
|
||||
}
|
||||
$scope.selectedVersionRowIndex = n;
|
||||
$scope.selectedVersion = v;
|
||||
if ($event && $event.target && typeof $event.target.blur === 'function') {
|
||||
$event.target.blur();
|
||||
} else if (typeof document !== 'undefined' && document.activeElement && typeof document.activeElement.blur === 'function') {
|
||||
document.activeElement.blur();
|
||||
}
|
||||
};
|
||||
$scope.selectedEsMajor = '8';
|
||||
$scope.selectedRabbitmqStream = '4';
|
||||
/** RabbitMQ: 4.x is default for new installs (metadata prefetched). Upgrade may require picking stream if version line is unknown. ES major still user-picked before version list loads. */
|
||||
$scope.rabbitmqBranchChosen = false;
|
||||
$scope.esMajorChosen = false;
|
||||
$scope.confirmAction = false;
|
||||
$scope.selectedCurrentVersion = '';
|
||||
|
||||
$scope.chooseRabbitmqStream = function (stream) {
|
||||
var s = String(stream || '4').trim();
|
||||
if (s !== '3' && s !== '4') {
|
||||
s = '4';
|
||||
}
|
||||
$scope.selectedRabbitmqStream = s;
|
||||
$scope.rabbitmqBranchChosen = true;
|
||||
$scope.refreshMeta();
|
||||
};
|
||||
|
||||
$scope.chooseEsMajor = function (major) {
|
||||
var m = String(major || '8').trim();
|
||||
if (m !== '7' && m !== '8' && m !== '9') {
|
||||
m = '8';
|
||||
}
|
||||
$scope.selectedEsMajor = m;
|
||||
$scope.esMajorChosen = true;
|
||||
$scope.refreshMeta();
|
||||
};
|
||||
|
||||
/**
|
||||
* When the install/upgrade modal is open, re-apply version list from latest applicationMeta.
|
||||
* (Page-load meta can be empty for ES if dnf was slow; opening the modal must refetch.)
|
||||
*/
|
||||
$scope.syncModalVersionLists = function () {
|
||||
if (!$scope.appName || ($scope.status !== 'Installing' && $scope.status !== 'Upgrading')) {
|
||||
return;
|
||||
}
|
||||
if ($scope.appName !== 'Elasticsearch' && $scope.appName !== 'Redis' && $scope.appName !== 'RabbitMQ') {
|
||||
return;
|
||||
}
|
||||
if ($scope.appName === 'RabbitMQ' && !$scope.rabbitmqBranchChosen) {
|
||||
$scope.selectedVersions = ['latest'];
|
||||
$scope.selectedVersion = 'latest';
|
||||
$scope.repoShowsOnlyOneStream = false;
|
||||
$scope.recalcSelectedVersionRowIndex();
|
||||
return;
|
||||
}
|
||||
if ($scope.appName === 'Elasticsearch' && !$scope.esMajorChosen) {
|
||||
$scope.selectedVersions = ['latest'];
|
||||
$scope.selectedVersion = 'latest';
|
||||
$scope.repoShowsOnlyOneStream = false;
|
||||
$scope.recalcSelectedVersionRowIndex();
|
||||
return;
|
||||
}
|
||||
var meta = $scope.findAppMeta($scope.appName);
|
||||
var vers = sanitizeVersionsArray((meta && meta.versions) ? meta.versions : []);
|
||||
$scope.selectedVersions = ['latest'].concat(vers);
|
||||
var curRaw = (meta && meta.installedVersion) ? meta.installedVersion : ($scope.selectedCurrentVersion || '');
|
||||
var cur = normalizeVersionToken(curRaw) || String(curRaw || '').trim();
|
||||
if (cur && $scope.selectedVersions.indexOf(cur) === -1) {
|
||||
var allowCur = true;
|
||||
if ($scope.appName === 'RabbitMQ') {
|
||||
allowCur = versionMatchesRabbitmqStream(cur, $scope.selectedRabbitmqStream);
|
||||
} else if ($scope.appName === 'Elasticsearch') {
|
||||
allowCur = versionMatchesEsMajor(cur, $scope.selectedEsMajor);
|
||||
}
|
||||
if (allowCur) {
|
||||
$scope.selectedVersions.push(cur);
|
||||
}
|
||||
}
|
||||
if (cur) {
|
||||
$scope.selectedCurrentVersion = cur;
|
||||
}
|
||||
var prevSel = $scope.selectedVersion;
|
||||
if (prevSel && $scope.selectedVersions.indexOf(prevSel) !== -1) {
|
||||
$scope.selectedVersion = prevSel;
|
||||
} else {
|
||||
$scope.selectedVersion = 'latest';
|
||||
}
|
||||
var realVers = ($scope.selectedVersions || []).filter(function (v) {
|
||||
return v && v !== 'latest';
|
||||
});
|
||||
$scope.repoShowsOnlyOneStream = ($scope.status === 'Upgrading' && realVers.length <= 1);
|
||||
$scope.recalcSelectedVersionRowIndex();
|
||||
};
|
||||
|
||||
$scope.refreshMeta = function () {
|
||||
$scope.appsMetaRefreshing = true;
|
||||
var url = "/manageservices/applicationMeta";
|
||||
var data = {
|
||||
esMajor: $scope.selectedEsMajor,
|
||||
rabbitmqStream: $scope.selectedRabbitmqStream
|
||||
};
|
||||
var config = {
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=UTF-8',
|
||||
'X-CSRFToken': getCookie('csrftoken')
|
||||
},
|
||||
transformRequest: function (payload) {
|
||||
return angular.toJson(payload);
|
||||
}
|
||||
};
|
||||
|
||||
return $http.post(url, data, config).then(function (response) {
|
||||
$scope.appsMetaRefreshing = false;
|
||||
var payload = response.data;
|
||||
var ok = payload && (payload.status === 1 || payload.status === '1');
|
||||
if (ok) {
|
||||
var appMap = {};
|
||||
(payload.apps || []).forEach(function (app) {
|
||||
appMap[app.name] = app;
|
||||
});
|
||||
var esMetaResp = appMap['Elasticsearch'];
|
||||
var rmqMetaResp = appMap['RabbitMQ'];
|
||||
var respEsMaj = String(esMetaResp && esMetaResp.major != null ? esMetaResp.major : '').trim();
|
||||
if (respEsMaj && respEsMaj !== String($scope.selectedEsMajor || '8').trim()) {
|
||||
return;
|
||||
}
|
||||
var respRmqStream = String(rmqMetaResp && rmqMetaResp.rabbitmqStream != null ? rmqMetaResp.rabbitmqStream : '').trim();
|
||||
if (respRmqStream && respRmqStream !== String($scope.selectedRabbitmqStream || '4').trim()) {
|
||||
return;
|
||||
}
|
||||
$scope.apps = $scope.apps.map(function (baseApp) {
|
||||
var meta = appMap[baseApp.name] || {};
|
||||
var vers = meta.versions;
|
||||
if (!angular.isArray(vers)) {
|
||||
vers = [];
|
||||
}
|
||||
vers = sanitizeVersionsArray(vers);
|
||||
return {
|
||||
name: baseApp.name,
|
||||
image: baseApp.image,
|
||||
installed: !!meta.installed,
|
||||
installedVersion: meta.installedVersion || '',
|
||||
updateAvailable: !!meta.updateAvailable,
|
||||
crossBranchUpdateSuggested: !!meta.crossBranchUpdateSuggested,
|
||||
versions: vers,
|
||||
latestAvailable: meta.latestAvailable || '',
|
||||
latestOverall: meta.latestOverall || '',
|
||||
rabbitmqVersionsHint: meta.rabbitmqVersionsHint || ''
|
||||
};
|
||||
});
|
||||
$scope.syncModalVersionLists();
|
||||
} else {
|
||||
new PNotify({
|
||||
title: 'Operation Failed!',
|
||||
text: (payload && (payload.error_message || payload.errorMessage)) || 'Could not load application metadata.',
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}, function () {
|
||||
$scope.appsMetaRefreshing = false;
|
||||
new PNotify({
|
||||
title: 'Operation Failed!',
|
||||
text: 'Could not connect to server, please refresh this page',
|
||||
type: 'error'
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
$scope.prepareAction = function (service, status, bootstrapInstalledVersion) {
|
||||
if (bootstrapInstalledVersion === undefined || bootstrapInstalledVersion === null) {
|
||||
bootstrapInstalledVersion = '';
|
||||
} else {
|
||||
bootstrapInstalledVersion = String(bootstrapInstalledVersion).trim();
|
||||
}
|
||||
$scope.status = status;
|
||||
$scope.appName = service.name;
|
||||
$scope.confirmAction = false;
|
||||
var effectiveInstalled = (service.installedVersion || bootstrapInstalledVersion || '').trim();
|
||||
$scope.selectedCurrentVersion = effectiveInstalled;
|
||||
|
||||
if (service.name === 'RabbitMQ') {
|
||||
if (effectiveInstalled && /^4\./.test(effectiveInstalled)) {
|
||||
$scope.selectedRabbitmqStream = '4';
|
||||
} else if (effectiveInstalled && /^3\./.test(effectiveInstalled)) {
|
||||
$scope.selectedRabbitmqStream = '3';
|
||||
} else if (status === 'Installing') {
|
||||
$scope.selectedRabbitmqStream = '4';
|
||||
}
|
||||
if (status === 'Upgrading' && effectiveInstalled) {
|
||||
if (/^4\./.test(effectiveInstalled) || /^3\./.test(effectiveInstalled)) {
|
||||
$scope.rabbitmqBranchChosen = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (service.name === 'Elasticsearch' && effectiveInstalled) {
|
||||
var iv = effectiveInstalled;
|
||||
if (/^9\./.test(iv)) {
|
||||
$scope.selectedEsMajor = '9';
|
||||
} else if (/^8\./.test(iv)) {
|
||||
$scope.selectedEsMajor = '8';
|
||||
} else if (/^7\./.test(iv)) {
|
||||
$scope.selectedEsMajor = '7';
|
||||
}
|
||||
}
|
||||
|
||||
$scope.selectedVersions = ['latest'];
|
||||
var deferVersionList = (service.name === 'RabbitMQ' && !$scope.rabbitmqBranchChosen)
|
||||
|| (service.name === 'Elasticsearch' && !$scope.esMajorChosen);
|
||||
if (!deferVersionList) {
|
||||
var svcVers = sanitizeVersionsArray(service.versions || []);
|
||||
if (svcVers.length > 0) {
|
||||
$scope.selectedVersions = ['latest'].concat(svcVers);
|
||||
}
|
||||
var curPick = normalizeVersionToken(effectiveInstalled) || effectiveInstalled;
|
||||
if (curPick && $scope.selectedVersions.indexOf(curPick) === -1) {
|
||||
$scope.selectedVersions.push(curPick);
|
||||
}
|
||||
}
|
||||
$scope.selectedVersion = 'latest';
|
||||
$scope.requestData = '';
|
||||
|
||||
var realVers = ($scope.selectedVersions || []).filter(function (v) {
|
||||
return v && v !== 'latest';
|
||||
});
|
||||
if (deferVersionList) {
|
||||
$scope.repoShowsOnlyOneStream = false;
|
||||
} else {
|
||||
$scope.repoShowsOnlyOneStream = ($scope.status === 'Upgrading' && realVers.length <= 1);
|
||||
}
|
||||
$scope.recalcSelectedVersionRowIndex();
|
||||
};
|
||||
|
||||
$scope.findAppMeta = function (appName) {
|
||||
var found = null;
|
||||
($scope.apps || []).forEach(function (item) {
|
||||
if (item.name === appName) {
|
||||
found = item;
|
||||
}
|
||||
});
|
||||
return found || {};
|
||||
};
|
||||
|
||||
$scope.prepareActionByName = function (appName, status, bootstrapInstalledVersion) {
|
||||
var meta = $scope.findAppMeta(appName);
|
||||
if (!meta.name) {
|
||||
meta = {name: appName, versions: []};
|
||||
}
|
||||
var mver = meta.versions;
|
||||
if (!angular.isArray(mver)) {
|
||||
mver = [];
|
||||
}
|
||||
var merged = {
|
||||
name: meta.name,
|
||||
image: meta.image,
|
||||
installed: meta.installed,
|
||||
installedVersion: meta.installedVersion || '',
|
||||
versions: mver
|
||||
};
|
||||
$scope.prepareAction(merged, status, bootstrapInstalledVersion);
|
||||
};
|
||||
|
||||
/**
|
||||
* Prepare scope then show modal (do not use data-toggle + ng-click — Bootstrap can
|
||||
* open the dialog before Angular runs ng-click, leaving status/appName unset).
|
||||
* For managed apps, wait for applicationMeta so version lists and installedVersion are correct (upgrade vs downgrade).
|
||||
*/
|
||||
$scope.openApplicationsModal = function (appName, status, bootstrapInstalledVersion) {
|
||||
var needMeta = (appName === 'RabbitMQ' || appName === 'Elasticsearch' || appName === 'Redis');
|
||||
var showModal = function () {
|
||||
if (typeof window.jQuery !== 'undefined' && jQuery('#settings').modal) {
|
||||
jQuery('#settings').modal('show');
|
||||
}
|
||||
};
|
||||
if (needMeta) {
|
||||
if (appName === 'RabbitMQ') {
|
||||
if (status === 'Installing') {
|
||||
$scope.selectedRabbitmqStream = '4';
|
||||
$scope.rabbitmqBranchChosen = true;
|
||||
} else {
|
||||
$scope.rabbitmqBranchChosen = false;
|
||||
}
|
||||
}
|
||||
if (appName === 'Elasticsearch') {
|
||||
$scope.esMajorChosen = false;
|
||||
}
|
||||
// RabbitMQ install: default 4.x stream and prefetch metadata. Upgrade: pick stream from installed version.
|
||||
// Elasticsearch: still wait for user major. Redis refreshes on open.
|
||||
$scope.appName = appName;
|
||||
$scope.status = status;
|
||||
$scope.prepareActionByName(appName, status, bootstrapInstalledVersion);
|
||||
showModal();
|
||||
if (appName === 'Redis' || (appName === 'RabbitMQ' && $scope.rabbitmqBranchChosen)) {
|
||||
$timeout(function () {
|
||||
$scope.refreshMeta();
|
||||
}, 0);
|
||||
}
|
||||
} else {
|
||||
$scope.prepareActionByName(appName, status, bootstrapInstalledVersion);
|
||||
showModal();
|
||||
}
|
||||
};
|
||||
|
||||
$scope.runAction = function () {
|
||||
var appName = $scope.appName;
|
||||
var status = $scope.status;
|
||||
if (!appName || !status) {
|
||||
return;
|
||||
}
|
||||
if ((status === 'Removing' || status === 'Upgrading') && !$scope.confirmAction) {
|
||||
new PNotify({
|
||||
title: 'Confirmation Required',
|
||||
text: 'Please confirm this action before proceeding.',
|
||||
type: 'warning'
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (appName === 'RabbitMQ' && (status === 'Installing' || status === 'Upgrading') && !$scope.rabbitmqBranchChosen) {
|
||||
new PNotify({
|
||||
title: 'Stream required',
|
||||
text: 'Choose RabbitMQ 4.x or 3.x above to load versions for that line.',
|
||||
type: 'warning'
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (appName === 'Elasticsearch' && (status === 'Installing' || status === 'Upgrading') && !$scope.esMajorChosen) {
|
||||
new PNotify({
|
||||
title: 'Major version required',
|
||||
text: 'Choose Elasticsearch major (7, 8, or 9) above to load versions for that line.',
|
||||
type: 'warning'
|
||||
});
|
||||
return;
|
||||
}
|
||||
$scope.status = status;
|
||||
$scope.appName = appName;
|
||||
|
||||
@@ -441,7 +934,11 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
|
||||
var data = {
|
||||
appName: appName,
|
||||
status: status
|
||||
status: status,
|
||||
version: $scope.selectedVersion || 'latest',
|
||||
esMajor: $scope.selectedEsMajor || '8',
|
||||
rabbitmqStream: $scope.selectedRabbitmqStream || '4',
|
||||
confirmAction: $scope.confirmAction === true
|
||||
};
|
||||
|
||||
var config = {
|
||||
@@ -524,6 +1021,18 @@ app.controller('manageApplications', function ($scope, $http, $timeout, $window)
|
||||
|
||||
}
|
||||
|
||||
// Do not fetch package metadata on page load; it can block workers under DNF load.
|
||||
// Metadata is fetched on-demand when opening install/version-change modals.
|
||||
|
||||
if (typeof window.jQuery !== 'undefined' && jQuery.fn.on) {
|
||||
jQuery('#settings').on('hidden.bs.modal', function () {
|
||||
$scope.$evalAsync(function () {
|
||||
$scope.rabbitmqBranchChosen = false;
|
||||
$scope.esMajorChosen = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/* Java script code */
|
||||
Reference in New Issue
Block a user