def load_app_safe(container, container_dir, app_json=STATE_JSON): """Load app manifest as object. If app manifest is corrupted or invalid, return object with key attributes. """ try: return load_app(container_dir, app_json=app_json) except ValueError as err: _LOGGER.error('Manifest file is corrupted or invalid: %s', err) appname = appcfg.app_name(container) return utils.to_obj({ 'name': appname, 'app': appcfg.appname_basename(appname), 'task': appcfg.appname_task_id(appname), 'uniqueid': appcfg.app_unique_id(container), })
def load(event): """Loads the app event file, ensuring it is in valid format, and supplement it into a full Treadmill manifest. :param event: Full path to the application node event in the zookeeper cache. :type event: ``str`` :return: Application manifest object :rtype: ``dict`` """ # pylint: disable=too-many-statements # # TODO: need better input validation / setting defaults process. name = os.path.basename(event) manifest = read(event, 'yaml') utils.validate(manifest, [('image', False, str)]) app_type = appcfg.AppType.get_app_type(manifest.get('image')) schema = [ ('proid', True, str), ('environment', True, str), ('services', app_type == appcfg.AppType.NATIVE, list), ('command', False, str), ('args', False, list), ('endpoints', False, list), ('environ', False, list), ('cpu', True, str), ('memory', True, str), ('disk', True, str), ('keytabs', False, list), ] utils.validate(manifest, schema) manifest['system_services'] = [] manifest['name'] = name manifest['app'] = appcfg.appname_basename(name) manifest['type'] = app_type.value manifest['uniqueid'] = appcfg.gen_uniqueid(event) if manifest['environment'] not in ['dev', 'qa', 'uat', 'prod']: _LOGGER.warning('Unrecognized environment: %s', manifest['environment']) raise Exception('Invalid environment: ' + manifest['environment']) if manifest['cpu'].endswith('%'): manifest['cpu'] = int(manifest['cpu'][:-1]) # By default network is private. if 'shared_network' not in manifest: manifest['shared_network'] = False else: manifest['shared_network'] = bool(manifest['shared_network']) # By default host IP is not shared, not used in the container. if 'shared_ip' not in manifest: manifest['shared_ip'] = False else: manifest['shared_ip'] = bool(manifest['shared_ip']) # Check archive manifest['archive'] = list(manifest.get('archive', [])) if manifest['archive'] is None: manifest['archive'] = [] # Adds cell specific information to the loaded manifest. manifest['cell'] = context.GLOBAL.cell manifest['zookeeper'] = context.GLOBAL.zk.url def _set_default(attr, value, obj=None): """Set default manifest attribute if it is not present.""" if obj is None: obj = manifest if attr not in obj: obj[attr] = value _set_default('command', None) _set_default('args', []) _set_default('environ', []) _set_default('endpoints', []) _set_default('passthrough', []) _set_default('services', []) _set_default('vring', {}) _set_default('cells', [], manifest['vring']) _set_default('identity_group', None) _set_default('identity', None) _set_default('data_retention_timeout', None) _set_default('lease', None) _set_default('keytabs', []) # Normalize optional and port information manifest['endpoints'] = [{ 'name': endpoint['name'], 'port': int(endpoint['port']), 'type': endpoint.get('type', None), 'proto': endpoint.get('proto', 'tcp'), } for endpoint in manifest.get('endpoints', [])] # TODO: need better way to normalize. if 'ephemeral_ports' not in manifest: manifest['ephemeral_ports'] = {'tcp': 0, 'udp': 0} if 'tcp' not in manifest['ephemeral_ports']: manifest['ephemeral_ports']['tcp'] = 0 else: manifest['ephemeral_ports']['tcp'] = int( manifest['ephemeral_ports']['tcp']) if 'udp' not in manifest['ephemeral_ports']: manifest['ephemeral_ports']['udp'] = 0 else: manifest['ephemeral_ports']['udp'] = int( manifest['ephemeral_ports']['udp']) return manifest