#!/usr/share/ucs-test/runner python
## desc: Checks if apps are installable (except for apps/packages conflicting with installed apps)
## tags: [basic]
## roles-not: [basesystem]
## exposure: safe
## packages:
##   - univention-management-console-module-appcenter

import sys
import subprocess

from univention.lib.package_manager import PackageManager
from univention.management.console.modules.appcenter.app_center import Application
from univention.management.console.modules.appcenter.util import ComponentManager
from univention.config_registry import ConfigRegistry
from univention.updater import UniventionUpdater

# monkey patch Application to avoid the error 'must_not_have_concurrent_operation'
Application.must_not_have_concurrent_operation = lambda x: True

# the next lines are a workaround for the following traceback:
#   Error in function stop
#   Traceback (most recent call last):
#     File "/usr/lib/python2.7/dist-packages/apt/progress/text.py", line 229, in stop
#       signal.signal(signal.SIGWINCH, self._signal)
#   ValueError: signal only works in main thread
def _dummy(*args):
	pass
import signal
signal._signal_old = signal.signal
signal.signal = _dummy

# helper functions
def _msg_handler(msg_type):
	def _handler(msg):
		print '%s: %s' % (msg_type, msg)

# initiate UCR and manager instances
ucr = ConfigRegistry()
ucr.load()
# instantiate needed tools
pm = PackageManager(
	info_handler=_msg_handler('INFO'),
	step_handler=_msg_handler('STEP'),
	error_handler=_msg_handler('WARN'),
	lock=False,
	always_noninteractive=True,
)
pm.update()
uu = UniventionUpdater(False)
cm = ComponentManager(ucr, uu)

# more helper functions/variables
is_master = ucr.get('server/role') == 'domaincontroller_master' or ucr.get('server/role') == 'domaincontroller_backup'

def _packages_to_install(app):
	packages = []
	packages.extend(app.get('defaultpackages'))
	if is_master:
		packages.extend(app.get('defaultpackagesmaster'))
	return packages

def _apt_get_simulate(app):
	app.register(cm, pm)
	packages = _packages_to_install(app)
	cmd = ['/usr/bin/apt-get', 'install', '-s'] + packages
	print 'Executing the command: %s' % cmd
	subprocess.call(cmd, stderr=subprocess.STDOUT)
	app.unregister(cm)

# print overview of installed apps
all_apps = Application.all()
_installed_apps = [app for app in all_apps if app.is_installed(pm)]
installed_apps = set([app.id for app in _installed_apps])

print 'Installed apps: %s' % [app for app in installed_apps]

failed = []
for app in all_apps:
	forbidden, warning = app.check_invokation('install', pm)
	if forbidden:
		print 'Ignoring app %r: requirements not met -> %s' % (app, forbidden)
		continue

	print 'Checking app: %r' % app
	result, previously_registered_by_dry_run = app.install_dry_run(pm, cm)
	if result['broken']:
		failed.append((app, result['broken']))

if failed:
	print '\nTEST FAILED: the following apps cannot be installed due to broken packages...'
	for app, brokenPackages in failed:
		print '\n[ APP: %s ]' % app.id
		print 'broken packages: %s' % brokenPackages
		print 'output of apt-get install -s'
		_apt_get_simulate(app)
	sys.exit(1)

sys.exit(0)

