Source code for univention.appcenter.actions.upgrade

#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# Univention App Center
#  univention-app module for upgrading an app
#
# Copyright 2015-2022 Univention GmbH
#
# https://www.univention.de/
#
# All rights reserved.
#
# The source code of this program is made available
# under the terms of the GNU Affero General Public License version 3
# (GNU AGPL V3) as published by the Free Software Foundation.
#
# Binary versions of this program provided by Univention to you as
# well as other copyrighted, protected or trademarked materials like
# Logos, graphics, fonts, specific documentations and configurations,
# cryptographic keys etc. are subject to a license agreement between
# you and Univention and not subject to the GNU AGPL V3.
#
# In the case you use this program under the terms of the GNU AGPL V3,
# the program is provided 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public
# License with the Debian GNU/Linux or Univention distribution in file
# /usr/share/common-licenses/AGPL-3; if not, see
# <https://www.gnu.org/licenses/>.
#

from univention.admindiary.client import write_event
from univention.admindiary.events import APP_UPGRADE_START, APP_UPGRADE_SUCCESS, APP_UPGRADE_FAILURE

from univention.appcenter.app_cache import Apps
from univention.appcenter.actions.install import Install
from univention.appcenter.ucr import ucr_is_true
from univention.appcenter.packages import install_packages, dist_upgrade


[docs]class Upgrade(Install): '''Upgrades an installed application from the Univention App Center.''' help = 'Upgrade an app' pre_readme = 'readme_update' post_readme = 'readme_post_update' def __init__(self): super(Upgrade, self).__init__() # original_app: The App installed when the whole action started # old_app: The current App installed when trying to upgrade # - should be the same most of the time. But Docker Apps may upgrade # themselves multiple times during one run and old_app will be set # after each iteration self.original_app = self.old_app = None
[docs] def setup_parser(self, parser): super(Install, self).setup_parser(parser) parser.add_argument('--only-master-packages', action='store_true', help='Install only Primary Node packages') parser.add_argument('--do-not-install-master-packages-remotely', action='store_false', dest='install_master_packages_remotely', help='Do not install Primary Node packages on Primary or Backup Directory Node systems')
def _app_too_old(self, current_app, specified_app): if current_app >= specified_app: self.fatal('A newer version of %s than the one installed must be present and chosen' % current_app.id) return True return False
[docs] def main(self, args): apps = args.app real_apps = [] for app in apps: old_app = Apps().find(app.id) if app == old_app: app = Apps().find_candidate(app) or app if not args.only_master_packages: # always allow only_master_packages if self._app_too_old(old_app, app): continue real_apps.append(app) if not real_apps: return args.app = real_apps return self.do_it(args)
[docs] def do_it_once(self, app, args): self.old_app = self.original_app = Apps().find(app.id) return super(Upgrade, self).do_it_once(app, args)
def _write_start_event(self, app, args): return write_event(APP_UPGRADE_START, {'name': app.name, 'version': self.old_app.version}, username=self._get_username(args)) def _write_success_event(self, app, context_id, args): return write_event(APP_UPGRADE_SUCCESS, {'name': app.name, 'version': app.version}, username=self._get_username(args), context_id=context_id) def _write_fail_event(self, app, context_id, status, args): return write_event(APP_UPGRADE_FAILURE, {'name': app.name, 'version': self.old_app.version, 'error_code': str(status)}, username=self._get_username(args), context_id=context_id) def _call_action_hooks(self, directory): super(Upgrade, self)._run_parts(directory)
[docs] def needs_credentials(self, app): needs_credentials = super(Upgrade, self).needs_credentials(app) if needs_credentials: return True if app.docker and app.docker_script_update_packages: return True if app.docker and app.docker_script_update_app_version: return True return False
def _revert(self, app, args): try: self.log('Trying to revert to old version. This may lead to problems, but it is better than leaving it the way it is now') args.revert = False self._do_it(self.old_app, args) except Exception: pass def _show_license(self, app, args): old_app = Apps().find(app.id) if app.license_agreement != old_app.license_agreement: return super(Upgrade, self)._show_license(app, args) def _call_prescript(self, app, args): return super(Upgrade, self)._call_prescript(app, args, old_version=self.old_app.version) def _send_information(self, app, status, value=None): if app > self.original_app: super(Upgrade, self)._send_information(app, status, value) def _install_packages(self, packages): return install_packages(packages) and dist_upgrade()
[docs] @classmethod def iter_upgradable_apps(self): for app in Apps().get_all_locally_installed_apps(): if ucr_is_true(app.ucr_upgrade_key): yield app
def _dry_run(self, app, args): return self._install_packages_dry_run(app, args, with_dist_upgrade=True)