def __init__(self, name, version, container_version=None, app_directory_suffix=None, package_name=None, build_package=True, call_join_scripts=True): self.app_name = name self.app_version = version self.call_join_scripts = call_join_scripts if not app_directory_suffix: self.app_directory_suffix = random_version() else: self.app_directory_suffix = app_directory_suffix self.app_directory = '%s_%s' % (self.app_name, self.app_directory_suffix) if package_name: self.package_name = package_name else: self.package_name = get_app_name() self.package_version = '%s.%s' % (version, get_app_version()) self.ucr = ConfigRegistry() self.ucr.load() if build_package: self.package = DebianPackage(name=self.package_name, version=self.package_version) self.package.build() else: self.package = None self.ini = {} self.ini['ID'] = self.app_name self.ini['Code'] = self.app_name[0:2] self.ini['Name'] = self.app_name self.ini['Version'] = self.app_version self.ini['NotifyVendor'] = False self.ini['Categories'] = 'System services' self.ini['Logo'] = '%s.svg' % self.app_name if self.package: self.ini['DefaultPackages'] = self.package_name self.ini['ServerRole'] = 'domaincontroller_master,domaincontroller_backup,domaincontroller_slave,memberserver' self.scripts = {} if not container_version: self.ucs_version = self.ucr.get('version/version') else: self.ucs_version = container_version self.ini['SupportedUCSVersions'] = '%s-0,%s-0' % (container_version, self.ucr.get('version/version')) self.installed = False self.admin_user = self.ucr.get('tests/domainadmin/account').split(',')[0][len('uid='):] self.admin_pwdfile = self.ucr.get('tests/domainadmin/pwdfile') print repr(self)
class App(object): def __init__(self, name, version, container_version=None, app_directory_suffix=None, package_name=None, build_package=True, call_join_scripts=True): self.app_name = name self.app_version = version self.call_join_scripts = call_join_scripts if not app_directory_suffix: self.app_directory_suffix = random_version() else: self.app_directory_suffix = app_directory_suffix self.app_directory = '%s_%s' % (self.app_name, self.app_directory_suffix) if package_name: self.package_name = package_name else: self.package_name = get_app_name() self.package_version = '%s.%s' % (version, get_app_version()) self.ucr = ConfigRegistry() self.ucr.load() if build_package: self.package = DebianPackage(name=self.package_name, version=self.package_version) self.package.build() else: self.package = None self.ini = {} self.ini['ID'] = self.app_name self.ini['Code'] = self.app_name[0:2] self.ini['Name'] = self.app_name self.ini['Version'] = self.app_version self.ini['NotifyVendor'] = False self.ini['Categories'] = 'System services' self.ini['Logo'] = '%s.svg' % self.app_name if self.package: self.ini['DefaultPackages'] = self.package_name self.ini[ 'ServerRole'] = 'domaincontroller_master,domaincontroller_backup,domaincontroller_slave,memberserver' self.scripts = {} if not container_version: self.ucs_version = self.ucr.get('version/version') else: self.ucs_version = container_version # make sure version of default appbox image is part of SupportedUCSVersions self.ini['SupportedUCSVersions'] = '%s-0,4.3-0,%s-0' % ( container_version, self.ucr.get('version/version')) self.installed = False self.admin_user = self.ucr.get('tests/domainadmin/account').split( ',')[0][len('uid='):] self.admin_pwdfile = self.ucr.get('tests/domainadmin/pwdfile') print repr(self) def __repr__(self): return '%s(app_name=%r, app_version=%r)' % (super( App, self).__repr__(), self.app_name, self.app_version) def set_ini_parameter(self, **kwargs): for key, value in kwargs.iteritems(): print 'set_ini_parameter(%s=%s)' % (key, value) self.ini[key] = value def add_to_local_appcenter(self): self._dump_ini() if self.package: self._copy_package() self._dump_scripts() def add_script(self, **kwargs): for key, value in kwargs.iteritems(): self.scripts[key] = value def install(self): print 'App.install()' self._update() cmd = ['univention-app', 'install'] if self.call_join_scripts is False: cmd.append('--do-not-call-join-scripts') cmd.append('--noninteractive') cmd.append('--username=%s' % self.admin_user) cmd.append('--pwdfile=%s' % self.admin_pwdfile) cmd.append('%s=%s' % (self.app_name, self.app_version)) print cmd ret = subprocess.call(' '.join(cmd), shell=True) if ret != 0: raise UCSTest_DockerApp_InstallationFailed() self.ucr.load() self.container_id = self.ucr.get('appcenter/apps/%s/container' % self.app_name) self.installed = True def file(self, fname): if fname.startswith('/'): fname = fname[1:] dirname = subprocess.check_output([ 'docker', 'inspect', '--format={{.GraphDriver.Data.MergedDir}}', self.container_id ]).strip() return os.path.join(dirname, fname) def configure(self, args): set_vars = [] unset_vars = [] for key, value in args.iteritems(): if value is None: unset_vars.append(key) else: set_vars.append('%s=%s' % (key, value)) cmd = [ 'univention-app', 'configure', '%s=%s' % (self.app_name, self.app_version) ] if set_vars: cmd.extend(['--set'] + set_vars) if unset_vars: cmd.extend(['--unset'] + unset_vars) ret = subprocess.call(cmd) if ret != 0: raise UCSTest_DockerApp_ConfigureFailed() def install_via_umc(self): def _thread(event, options): try: client.umc_command("appcenter/keep_alive") finally: event.set() print 'App.umc_install()' client = umc.Client.get_test_connection() client.umc_get('session-info') options = dict(function='install', application=self.app_name, app=self.app_name, force=True) resp = client.umc_command('appcenter/docker/invoke', options).result progress_id = resp.get('id') if not resp: raise UCTTest_DockerApp_UMCInstallFailed(resp, None) errors = list() finished = False progress = None event = threading.Event() threading.Thread(target=_thread, args=(event, options)).start() while not (event.wait(3) and finished): options = dict(progress_id=progress_id) progress = client.umc_command('appcenter/docker/progress', options, print_request_data=False, print_response=False).result progress.get('info', None) for i in progress.get('intermediate', []): if i['level'] in ['ERROR', 'CRITICAL']: errors.append(i) finished = progress.get('finished', False) if not progress['result'].get('success', False) or not progress['result'].get( 'can_continue', False): raise UCTTest_DockerApp_UMCInstallFailed(progress, errors) self.ucr.load() self.container_id = self.ucr.get('appcenter/apps/%s/container' % self.app_name) self.installed = True if errors: raise UCTTest_DockerApp_UMCInstallFailed(None, errors) def install_via_add_app(self): raise RuntimeError('"univention-add-app" is NOT supported!') self._update() # ret = subprocess.call('univention-app install --noninteractive --do-not-revert --username=%s --pwdfile=%s %s' % cmd = 'univention-add-app -a -l %s' % self.app_name print cmd ret = subprocess.call(cmd, shell=True) if ret != 0: raise UCSTest_DockerApp_InstallationFailed() self.ucr.load() self.installed = True def _update(self): ret = subprocess.call(['univention-app', 'update']) if ret != 0: raise UCSTest_DockerApp_UpdateFailed() def register(self): print 'App.register()' cmd = ['univention-app', 'register', '--app'] print cmd ret = subprocess.call(' '.join(cmd), shell=True) if ret != 0: raise UCSTest_DockerApp_RegisterFailed() def upgrade(self): print 'App.upgrade()' self._update() cmd = ['univention-app', 'upgrade'] if self.call_join_scripts is False: cmd.append('--do-not-call-join-scripts') cmd.append('--noninteractive') cmd.append('--username=%s' % self.admin_user) cmd.append('--pwdfile=%s' % self.admin_pwdfile) cmd.append('%s=%s' % (self.app_name, self.app_version)) print cmd ret = subprocess.call(' '.join(cmd), shell=True) if ret != 0: raise UCSTest_DockerApp_UpgradeFailed() self.ucr.load() self.container_id = self.ucr.get('appcenter/apps/%s/container' % self.app_name) self.installed = True def verify(self, joined=True): print 'App.verify(%r)' % (joined, ) ret = subprocess.call('univention-app status %s=%s' % (self.app_name, self.app_version), shell=True) if ret != 0: raise UCSTest_DockerApp_VerifyFailed() if joined: ret = subprocess.call( 'docker exec %s univention-check-join-status' % self.container_id, stderr=subprocess.STDOUT, shell=True) if ret != 0: raise UCSTest_DockerApp_VerifyFailed() if self.package: try: output = subprocess.check_output( 'univention-app shell %s=%s dpkg-query -W %s' % (self.app_name, self.app_version, self.package_name), shell=True) expected_output1 = '%s\t%s\r\n' % (self.package_name, self.package_version) expected_output2 = '%s\t%s\n' % (self.package_name, self.package_version) if output not in [expected_output1, expected_output2]: raise UCSTest_DockerApp_VerifyFailed( '%r != %r' % (output, expected_output2)) except subprocess.CalledProcessError: raise UCSTest_DockerApp_VerifyFailed( 'univention-app shell failed') def uninstall(self): print 'App.uninstall()' if self.installed: cmd = ['univention-app', 'remove'] if self.call_join_scripts is False: cmd.append('--do-not-call-join-scripts') cmd.append('--noninteractive') cmd.append('--username=%s' % self.admin_user) cmd.append('--pwdfile=%s' % self.admin_pwdfile) cmd.append('%s=%s' % (self.app_name, self.app_version)) print cmd ret = subprocess.call(' '.join(cmd), shell=True) if ret != 0: raise UCSTest_DockerApp_RemoveFailed() def execute_command_in_container(self, cmd): print 'Execute: %s' % cmd return subprocess.check_output('docker exec %s %s' % (self.container_id, cmd), stderr=subprocess.STDOUT, shell=True) def remove(self): print 'App.remove()' if self.package: self.package.remove() def _dump_ini(self): if not os.path.exists('/var/www/meta-inf/%s' % self.ucs_version): os.makedirs('/var/www/meta-inf/%s' % self.ucs_version) if self.ucs_version == '4.2': if not os.path.exists('/var/www/meta-inf/4.1'): os.makedirs('/var/www/meta-inf/4.1') target = os.path.join('/var/www/meta-inf/%s' % self.ucs_version, '%s.ini' % self.app_directory) f = open(target, 'w') print 'Write ini file: %s' % target f.write('[Application]\n') print '[Application]' for key in self.ini.keys(): f.write('%s: %s\n' % (key, self.ini[key])) print '%s: %s' % (key, self.ini[key]) print f.close() svg = os.path.join('/var/www/meta-inf/%s' % self.ucs_version, self.ini.get('Logo')) f = open(svg, 'w') f.write(get_dummy_svg()) f.close() def _dump_scripts(self): for script in self.scripts.keys(): comp_path = os.path.join( '/var/www/univention-repository/%s/maintained/component' % self.ucs_version, '%s' % self.app_directory) if not os.path.exists(comp_path): os.makedirs(comp_path) target = os.path.join(comp_path, script) print 'Create %s' % target print self.scripts[script] f = open(target, 'w') f.write(self.scripts[script]) f.close() def _copy_package(self): target = os.path.join( '/var/www/univention-repository/%s/maintained/component' % self.ucs_version, '%s/all' % self.app_directory) os.makedirs(target) shutil.copy(self.package.get_binary_name(), target) subprocess.call(''' cd /var/www/univention-repository/%(version)s/maintained/component; apt-ftparchive packages %(app)s/all >%(app)s/all/Packages; gzip -c %(app)s/all/Packages >%(app)s/all/Packages.gz ''' % { 'version': self.ucs_version, 'app': self.app_directory }, shell=True) def create_basic_modproxy_settings(self): self.add_script(setup='''#!/bin/bash set -x -e eval "$(ucr shell)" if [ "$version_version" = 4.0 ]; then ucr set repository/online/server="$(echo $repository_online_server | sed -e 's|.*//\(.*\)|\\1|')" fi univention-install --yes univention-apache mkdir /var/www/%(app_name)s echo "TEST-%(app_name)s" >>/var/www/%(app_name)s/index.txt /usr/share/univention-docker-container-mode/setup "$@" ''' % {'app_name': self.app_name}) def configure_tinyapp_modproxy(self): fqdn = '%s.%s' % (self.ucr['hostname'], self.ucr['domainname']) self.execute_command_in_container('apk add apache2-ssl') self.execute_command_in_container( "sed -i 's#/var/www/localhost/htdocs#/web/html#g' /etc/apache2/conf.d/ssl.conf" ) self.execute_command_in_container( "sed -i 's#/var/www/localhost/cgi-bin#/web/cgi-bin#g' /etc/apache2/conf.d/ssl.conf" ) self.execute_command_in_container( "sed -i 's#www.example.com#%s#g' /etc/apache2/conf.d/ssl.conf" % fqdn) self.execute_command_in_container( 'cp /etc/apache2/conf.d/ssl.conf /web/config/conf.d') self.execute_command_in_container('sv restart apache2') self.execute_command_in_container( 'cat /etc/ssl/apache2/server.pem > /root/server.pem') self.execute_command_in_container('mkdir /web/html/%s' % self.app_name) self.execute_command_in_container( '/bin/sh -c "echo TEST-%s > /web/html/%s/index.txt"' % (self.app_name, self.app_name)) def verify_basic_modproxy_settings_tinyapp(self, http=True, https=True): fqdn = '%s.%s' % (self.ucr['hostname'], self.ucr['domainname']) test_string = 'TEST-%s\n' % self.app_name if http is not None: try: response = urllib2.urlopen('http://%s/%s/index.txt' % (fqdn, self.app_name)) except urllib2.HTTPError: if http: raise else: html = response.read() if http: correct = html == test_string else: correct = html != test_string if not correct: raise UCSTest_DockerApp_ModProxyFailed( 'Got: %r\nTested against: %r\nTested equality: %r' % (html, test_string, http)) if https is not None: try: ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE response = urllib2.urlopen('https://%s/%s/index.txt' % (fqdn, self.app_name), context=ctx) except urllib2.HTTPError: if https: raise else: html = response.read() if https: correct = html == test_string else: correct = html != test_string if not correct: raise UCSTest_DockerApp_ModProxyFailed( 'Got: %r\nTested against: %r\nTested equality: %r' % (html, test_string, https)) def verify_basic_modproxy_settings(self, http=True, https=True): fqdn = '%s.%s' % (self.ucr['hostname'], self.ucr['domainname']) test_string = 'TEST-%s\n' % self.app_name if http is not None: try: response = urllib2.urlopen('http://%s/%s/index.txt' % (fqdn, self.app_name)) except urllib2.HTTPError: if http: raise else: html = response.read() if http: correct = html == test_string else: correct = html != test_string if not correct: raise UCSTest_DockerApp_ModProxyFailed( 'Got: %r\nTested against: %r\nTested equality: %r' % (html, test_string, http)) if https is not None: try: response = urllib2.urlopen( 'https://%s/%s/index.txt' % (fqdn, self.app_name), cafile='/etc/univention/ssl/ucsCA/CAcert.pem') except urllib2.HTTPError: if https: raise else: html = response.read() if https: correct = html == test_string else: correct = html != test_string if not correct: raise UCSTest_DockerApp_ModProxyFailed( 'Got: %r\nTested against: %r\nTested equality: %r' % (html, test_string, https))
def test_ucr_register_api(): package_name = random_string() package_version = random_version() package = DebianPackage(name=package_name, version=package_version) package.create_debian_file_from_buffer( '/etc/univention/templates/modules/%s.py' % (package_name, ), UCR_MODULE) package.create_debian_file_from_buffer( '/etc/univention/templates/info/%s.info' % (package_name, ), UCR_INFO % (package_name, package_name)) try: package.build() package.install() with UCSTestConfigRegistry(): subprocess.call(['ucr', 'set', '%s/foo=bar' % (package_name, )]) changes = json.loads( subprocess.check_output(['ucr', 'register', package_name]).split(b'####')[1]) expected = { '%s/.*$' % (package_name, ): [None, None], '%s/foo' % (package_name, ): [None, 'bar'], } assert changes == expected, changes changes = json.loads( subprocess.check_output( ['ucr', 'set', '%s/foo=blub' % (package_name, )]).split(b'####')[1]) expected = {'%s/foo' % (package_name, ): ['bar', 'blub']} assert changes == expected, changes finally: package.uninstall() package.remove()