def test_select_distinct_payload(self): expr = PayloadBuilder().\ SELECT().DISTINCT(["description"])\ .WHERE(["id", "<", 1000]).payload() assert _payload("data/payload_distinct.json") == json.loads(expr)
async def check_schedules(storage, schedule_name): payload = PayloadBuilder().SELECT("schedule_name").WHERE( ['schedule_name', '=', schedule_name]).payload() result = await storage.query_tbl_with_payload('schedules', payload) return result['count']
async def check_notification_schedule(storage): payload = PayloadBuilder().SELECT("process_name").payload() result = await storage.query_tbl_with_payload('schedules', payload) return result
async def delete_statistics_key(storage, key): payload = PayloadBuilder().WHERE(['key', '=', key]).payload() await storage.delete_from_tbl('statistics', payload)
async def add_configuration_item(request): """ Args: request: A JSON object that defines the config item and has key-pair (default, type, description, value[optional]) Returns: Json response with message key :Example: curl -d '{"default": "true", "description": "Test description", "type": "boolean"}' -X POST https://localhost:1995/foglamp/category/{category_name}/{new_config_item} --insecure curl -d '{"default": "true", "description": "Test description", "type": "boolean", "value": "false"}' -X POST https://localhost:1995/foglamp/category/{category_name}/{new_config_item} --insecure """ category_name = request.match_info.get('category_name', None) new_config_item = request.match_info.get('config_item', None) try: storage_client = connect.get_storage() cf_mgr = ConfigurationManager(storage_client) data = await request.json() if not isinstance(data, dict): raise ValueError('Data payload must be a dictionary') # if value key is in data then go ahead with data payload and validate # else update the data payload with value key and set its value to default value and validate val = data.get('value', None) if val is None: data.update({'value': data.get('default')}) config_item_dict = {new_config_item: data} else: config_item_dict = {new_config_item: data} # validate configuration category value await cf_mgr._validate_category_val( category_val=config_item_dict, set_value_val_from_default_val=False) # validate category category = await cf_mgr.get_category_all_items(category_name) if category is None: raise NameError( "No such Category found for {}".format(category_name)) # check if config item is already in use if new_config_item in category.keys(): raise KeyError( "Config item is already in use for {}".format(category_name)) # merge category values with keep_original_items True merge_cat_val = await cf_mgr._merge_category_vals( config_item_dict, category, keep_original_items=True) # update category value in storage payload = PayloadBuilder().SET(value=merge_cat_val).WHERE( ["key", "=", category_name]).payload() result = storage_client.update_tbl("configuration", payload) response = result['response'] # logged audit new config item for category audit = AuditLogger(storage_client) audit_details = { 'category': category_name, 'item': new_config_item, 'value': config_item_dict } await audit.information('CONAD', audit_details) except (KeyError, ValueError, TypeError) as ex: raise web.HTTPBadRequest(reason=str(ex)) except NameError as ex: raise web.HTTPNotFound(reason=str(ex)) except Exception as ex: raise web.HTTPException(reason=str(ex)) return web.json_response({ "message": "{} config item has been saved for {} category".format( new_config_item, category_name) })
def test_select_payload_with_alias_and_format(self, test_input, expected): res = PayloadBuilder().SELECT(test_input).ALIAS('return', ('user_ts', 'timestamp')).\ FORMAT('return', ('user_ts', "YYYY-MM-DD HH24:MI:SS.MS")).payload() assert expected == json.loads(res)
def test_from_payload(self, test_input, expected): res = PayloadBuilder().FROM(test_input).payload() assert expected == json.loads(res)
def test_having_payload(self, expected): res = PayloadBuilder().HAVING().payload() assert expected == json.loads(res)
def test_select_payload(self, test_input, expected): res = PayloadBuilder().SELECT(test_input).payload() assert expected == json.loads(res)
def test_and_query_params_payload(self, test_input1, test_input2, expected): res = PayloadBuilder().WHERE(test_input1).AND_WHERE( test_input2).query_params() assert expected == res
def test_or_query_params_payload(self, test_input1, test_input2, expected): """Since URL does not support OR hence only 1 value should be parsed as query parameter""" res = PayloadBuilder().WHERE(test_input1).OR_WHERE( test_input2).query_params() assert expected == res
def test_query_params_payload(self): res = PayloadBuilder().WHERE(["key", "=", "value1"]).query_params() assert "key=value1" == res
def test_limit_skip_payload(self, test_input, expected): res = PayloadBuilder().LIMIT(test_input).SKIP(test_input).payload() assert expected == json.loads(res)
def test_limit_offset_payload(self, test_input, expected): res = PayloadBuilder().LIMIT(test_input).OFFSET(test_input).payload() assert expected == json.loads(res)
def test_delete_payload(self, test_input, expected): res = PayloadBuilder().DELETE(test_input).payload() assert expected == json.loads(res)
def test_json_properties3(self, test_input1, test_input2, expected): res = PayloadBuilder().JSON_PROPERTY(test_input1).JSON_PROPERTY( test_input2).payload() assert expected == json.loads(res)
def test_delete_where_payload(self, input_where, input_table, expected): res = PayloadBuilder().DELETE(input_table).WHERE(input_where).payload() assert expected == json.loads(res)
def test_aggregate_with_where(self): res = PayloadBuilder().WHERE(["ts", "newer", 60]).AGGREGATE(["count", "*"]).payload() assert _payload("data/payload_aggregate_where.json") == json.loads(res)
def test_select_payload_with_alias3(self, test_input, expected): res = PayloadBuilder().SELECT(test_input).ALIAS( 'return', ('name', 'my_name'), ('id', 'my_id')).payload() assert expected == json.loads(res)
def test_insert_payload(self): res = PayloadBuilder().INSERT(key="x").payload() assert _payload("data/payload_insert1.json") == json.loads(res)
async def add_task(request): """ Create a new task to run a specific plugin :Example: curl -X POST http://localhost:8081/foglamp/scheduled/task -d '{ "name": "North Readings to PI", "plugin": "pi_server", "type": "north", "schedule_type": 3, "schedule_day": 0, "schedule_time": 0, "schedule_repeat": 30, "schedule_enabled": true }' curl -sX POST http://localhost:8081/foglamp/scheduled/task -d '{"name": "PI-2", "plugin": "pi_server", "type": "north", "schedule_type": 3, "schedule_day": 0, "schedule_time": 0, "schedule_repeat": 30, "schedule_enabled": true, "config": { "producerToken": {"value": "uid=180905062754237&sig=kx5l+"}, "URL": {"value": "https://10.2.5.22:5460/ingress/messages"}}}' """ try: data = await request.json() if not isinstance(data, dict): raise ValueError('Data payload must be a valid JSON') name = data.get('name', None) plugin = data.get('plugin', None) task_type = data.get('type', None) schedule_type = data.get('schedule_type', None) schedule_day = data.get('schedule_day', None) schedule_time = data.get('schedule_time', None) schedule_repeat = data.get('schedule_repeat', None) enabled = data.get('schedule_enabled', None) config = data.get('config', None) if name is None: raise web.HTTPBadRequest( reason='Missing name property in payload.') if plugin is None: raise web.HTTPBadRequest( reason='Missing plugin property in payload.') if task_type is None: raise web.HTTPBadRequest( reason='Missing type property in payload.') if utils.check_reserved(name) is False: raise web.HTTPBadRequest( reason='Invalid name property in payload.') if utils.check_foglamp_reserved(name) is False: raise web.HTTPBadRequest( reason= "'{}' is reserved for FogLAMP and can not be used as task name!" .format(name)) if utils.check_reserved(plugin) is False: raise web.HTTPBadRequest( reason='Invalid plugin property in payload.') if task_type not in ['north']: raise web.HTTPBadRequest(reason='Only north type is supported.') if schedule_type is None: raise web.HTTPBadRequest(reason='schedule_type is mandatory') if not isinstance(schedule_type, int) and not schedule_type.isdigit(): raise web.HTTPBadRequest( reason='Error in schedule_type: {}'.format(schedule_type)) if int(schedule_type) not in list(Schedule.Type): raise web.HTTPBadRequest( reason='schedule_type error: {}'.format(schedule_type)) if int(schedule_type) == Schedule.Type.STARTUP: raise web.HTTPBadRequest( reason='schedule_type cannot be STARTUP: {}'.format( schedule_type)) schedule_type = int(schedule_type) if schedule_day is not None: if isinstance(schedule_day, float) or ( isinstance(schedule_day, str) and (schedule_day.strip() != "" and not schedule_day.isdigit())): raise web.HTTPBadRequest( reason='Error in schedule_day: {}'.format(schedule_day)) else: schedule_day = int( schedule_day) if schedule_day is not None else None if schedule_time is not None and (not isinstance(schedule_time, int) and not schedule_time.isdigit()): raise web.HTTPBadRequest( reason='Error in schedule_time: {}'.format(schedule_time)) else: schedule_time = int( schedule_time) if schedule_time is not None else None if schedule_repeat is not None and (not isinstance( schedule_repeat, int) and not schedule_repeat.isdigit()): raise web.HTTPBadRequest( reason='Error in schedule_repeat: {}'.format(schedule_repeat)) else: schedule_repeat = int( schedule_repeat) if schedule_repeat is not None else None if schedule_type == Schedule.Type.TIMED: if not schedule_time: raise web.HTTPBadRequest( reason= 'schedule_time cannot be empty/None for TIMED schedule.') if schedule_day is not None and (schedule_day < 1 or schedule_day > 7): raise web.HTTPBadRequest( reason= 'schedule_day {} must either be None or must be an integer, 1(Monday) ' 'to 7(Sunday).'.format(schedule_day)) if schedule_time < 0 or schedule_time > 86399: raise web.HTTPBadRequest( reason= 'schedule_time {} must be an integer and in range 0-86399.' .format(schedule_time)) if schedule_type == Schedule.Type.INTERVAL: if schedule_repeat is None: raise web.HTTPBadRequest( reason= 'schedule_repeat {} is required for INTERVAL schedule_type.' .format(schedule_repeat)) elif not isinstance(schedule_repeat, int): raise web.HTTPBadRequest( reason='schedule_repeat {} must be an integer.'.format( schedule_repeat)) if enabled is not None: if enabled not in ['true', 'false', True, False]: raise web.HTTPBadRequest( reason= 'Only "true", "false", true, false are allowed for value of enabled.' ) is_enabled = True if ( (type(enabled) is str and enabled.lower() in ['true']) or ((type(enabled) is bool and enabled is True))) else False # Check if a valid plugin has been provided try: # "plugin_module_path" is fixed by design. It is MANDATORY to keep the plugin in the exactly similar named # folder, within the plugin_module_path. # if multiple plugin with same name are found, then python plugin import will be tried first plugin_module_path = "{}/python/foglamp/plugins/{}/{}".format( _FOGLAMP_ROOT, task_type, plugin) plugin_info = common.load_and_fetch_python_plugin_info( plugin_module_path, plugin, task_type) plugin_config = plugin_info['config'] script = '["tasks/north"]' process_name = 'north' except FileNotFoundError as ex: # Checking for C-type plugins script = '["tasks/north_c"]' plugin_info = apiutils.get_plugin_info(plugin, dir=task_type) if plugin_info['type'] != task_type: msg = "Plugin of {} type is not supported".format( plugin_info['type']) _logger.exception(msg) return web.HTTPBadRequest(reason=msg) plugin_config = plugin_info['config'] process_name = 'north_c' if not plugin_config: _logger.exception("Plugin %s import problem from path %s. %s", plugin, plugin_module_path, str(ex)) raise web.HTTPNotFound( reason='Plugin "{}" import problem from path "{}"'.format( plugin, plugin_module_path)) except TypeError as ex: raise web.HTTPBadRequest(reason=str(ex)) except Exception as ex: _logger.exception("Failed to fetch plugin configuration. %s", str(ex)) raise web.HTTPInternalServerError( reason='Failed to fetch plugin configuration.') storage = connect.get_storage_async() config_mgr = ConfigurationManager(storage) # Abort the operation if there are already executed tasks payload = PayloadBuilder() \ .SELECT(["id", "schedule_name"]) \ .WHERE(['schedule_name', '=', name]) \ .LIMIT(1) \ .payload() result = await storage.query_tbl_with_payload('tasks', payload) if result['count'] >= 1: msg = 'Unable to reuse name {0}, already used by a previous task.'.format( name) _logger.exception(msg) raise web.HTTPBadRequest(reason=msg) # Check whether category name already exists category_info = await config_mgr.get_category_all_items( category_name=name) if category_info is not None: raise web.HTTPBadRequest( reason="The '{}' category already exists".format(name)) # Check that the schedule name is not already registered count = await check_schedules(storage, name) if count != 0: raise web.HTTPBadRequest( reason='A north instance with this name already exists') # Check that the process name is not already registered count = await check_scheduled_processes(storage, process_name) if count == 0: # Create the scheduled process entry for the new task payload = PayloadBuilder().INSERT(name=process_name, script=script).payload() try: res = await storage.insert_into_tbl("scheduled_processes", payload) except StorageServerError as ex: _logger.exception("Failed to create scheduled process. %s", ex.error) raise web.HTTPInternalServerError( reason='Failed to create north instance.') except Exception as ex: _logger.exception("Failed to create scheduled process. %s", ex) raise web.HTTPInternalServerError( reason='Failed to create north instance.') # If successful then create a configuration entry from plugin configuration try: # Create a configuration category from the configuration defined in the plugin category_desc = plugin_config['plugin']['description'] await config_mgr.create_category( category_name=name, category_description=category_desc, category_value=plugin_config, keep_original_items=True) # Create the parent category for all North tasks await config_mgr.create_category("North", {}, 'North tasks', True) await config_mgr.create_child_category("North", [name]) # If config is in POST data, then update the value for each config item if config is not None: if not isinstance(config, dict): raise ValueError('Config must be a JSON object') for k, v in config.items(): await config_mgr.set_category_item_value_entry( name, k, v['value']) except Exception as ex: await config_mgr.delete_category_and_children_recursively(name) _logger.exception("Failed to create plugin configuration. %s", str(ex)) raise web.HTTPInternalServerError( reason='Failed to create plugin configuration.') # If all successful then lastly add a schedule to run the new task at startup try: schedule = TimedSchedule() if schedule_type == Schedule.Type.TIMED else \ IntervalSchedule() if schedule_type == Schedule.Type.INTERVAL else \ ManualSchedule() schedule.name = name schedule.process_name = process_name schedule.day = schedule_day m, s = divmod(schedule_time if schedule_time is not None else 0, 60) h, m = divmod(m, 60) schedule.time = datetime.time().replace(hour=h, minute=m, second=s) schedule.repeat = datetime.timedelta( seconds=schedule_repeat if schedule_repeat is not None else 0) schedule.exclusive = True schedule.enabled = False # if "enabled" is supplied, it gets activated in save_schedule() via is_enabled flag # Save schedule await server.Server.scheduler.save_schedule(schedule, is_enabled) schedule = await server.Server.scheduler.get_schedule_by_name(name) except StorageServerError as ex: await config_mgr.delete_category_and_children_recursively(name) _logger.exception("Failed to create schedule. %s", ex.error) raise web.HTTPInternalServerError( reason='Failed to create north instance.') except Exception as ex: await config_mgr.delete_category_and_children_recursively(name) _logger.exception("Failed to create schedule. %s", str(ex)) raise web.HTTPInternalServerError( reason='Failed to create north instance.') except ValueError as e: raise web.HTTPBadRequest(reason=str(e)) else: return web.json_response({ 'name': name, 'id': str(schedule.schedule_id) })
def test_insert_into_payload(self): res = PayloadBuilder().INSERT_INTO("test").payload() assert _payload("data/payload_from1.json") == json.loads(res)
async def get_audit_entries(request): """ Returns a list of audit trail entries sorted with most recent first and total count (including the criteria search if applied) :Example: curl -X GET http://localhost:8081/foglamp/audit curl -X GET http://localhost:8081/foglamp/audit?limit=5 curl -X GET http://localhost:8081/foglamp/audit?limit=5&skip=3 curl -X GET http://localhost:8081/foglamp/audit?skip=2 curl -X GET http://localhost:8081/foglamp/audit?source=PURGE curl -X GET http://localhost:8081/foglamp/audit?severity=ERROR curl -X GET http://localhost:8081/foglamp/audit?source=LOGGN&severity=INFORMATION&limit=10 """ try: limit = request.query.get( 'limit') if 'limit' in request.query else __DEFAULT_LIMIT offset = request.query.get( 'skip') if 'skip' in request.query else __DEFAULT_OFFSET source = request.query.get( 'source') if 'source' in request.query else None severity = request.query.get( 'severity') if 'severity' in request.query else None # HACK: This way when we can more future we do not get an exponential # explosion of if statements payload = PayloadBuilder().WHERE(['1', '=', '1']) if source is not None and source != "": payload.AND_WHERE(['code', '=', source]) if severity is not None and severity != "": payload.AND_WHERE(['level', '=', Severity[severity].value]) _and_where_payload = payload.chain_payload() # SELECT *, count(*) OVER() FROM log - No support yet from storage layer # TODO: FOGL-740, FOGL-663 once ^^ resolved we should replace below storage call for getting total rows # TODO: FOGL-643 - Aggregate with alias support needed to use payload builder aggregate = {"operation": "count", "column": "*", "alias": "count"} d = OrderedDict() d['aggregate'] = aggregate d.update(_and_where_payload) total_count_payload = json.dumps(d) # SELECT count (*) FROM log <_and_where_payload> storage_client = connect.get_storage() result = storage_client.query_tbl_with_payload('log', total_count_payload) total_count = result['rows'][0]['count'] payload.ORDER_BY(['ts', 'desc']) payload.LIMIT(int(limit)) if offset != '' and int(offset) > 0: payload.OFFSET(int(offset)) # SELECT * FROM log <payload.payload()> results = storage_client.query_tbl_with_payload( 'log', payload.payload()) res = [] for row in results['rows']: r = dict() r["details"] = row["log"] severity_level = int(row["level"]) r["severity"] = Severity( severity_level).name if severity_level in range( 1, 5) else "UNKNOWN" r["source"] = row["code"] r["timestamp"] = row["ts"] res.append(r) return web.json_response({'audit': res, 'totalCount': total_count}) except ValueError as ex: raise web.HTTPNotFound(reason=str(ex))
def test_update_table_payload(self, test_input, expected): res = PayloadBuilder().UPDATE_TABLE(test_input).payload() assert expected == json.loads(res)
async def add_service(request): """ Create a new service to run a specific plugin :Example: curl -X POST http://localhost:8081/foglamp/service -d '{"name": "DHT 11", "plugin": "dht11", "type": "south", "enabled": true}' curl -sX POST http://localhost:8081/foglamp/service -d '{"name": "Sine", "plugin": "sinusoid", "type": "south", "enabled": true, "config": {"dataPointsPerSec": {"value": "10"}}}' | jq curl -X POST http://localhost:8081/foglamp/service -d '{"name": "NotificationServer", "type": "notification", "enabled": true}' | jq curl -sX POST http://localhost:8081/foglamp/service?action=install -d '{"format":"repository", "name": "foglamp-service-notification"}' curl -sX POST http://localhost:8081/foglamp/service?action=install -d '{"format":"repository", "name": "foglamp-service-notification", "version":"1.6.0"}' """ try: data = await request.json() if not isinstance(data, dict): raise ValueError('Data payload must be a valid JSON') name = data.get('name', None) plugin = data.get('plugin', None) service_type = data.get('type', None) enabled = data.get('enabled', None) config = data.get('config', None) if name is None: raise web.HTTPBadRequest( reason='Missing name property in payload.') if 'action' in request.query and request.query['action'] != '': if request.query['action'] == 'install': file_format = data.get('format', None) if file_format is None: raise ValueError("format param is required") if file_format not in ["repository"]: raise ValueError("Invalid format. Must be 'repository'") version = data.get('version', None) if version: delimiter = '.' if str(version).count(delimiter) != 2: raise ValueError( 'Service semantic version is incorrect; it should be like X.Y.Z' ) services, log_path = common.fetch_available_packages("service") if name not in services: raise KeyError( '{} service is not available for the given repository or already installed' .format(name)) _platform = platform.platform() pkg_mgt = 'yum' if 'centos' in _platform or 'redhat' in _platform else 'apt' code, msg = await install.install_package_from_repo( name, pkg_mgt, version) if code != 0: raise ValueError(msg) message = "{} is successfully installed".format(name) return web.json_response({'message': message}) else: raise web.HTTPBadRequest(reason='{} is not a valid action'. format(request.query['action'])) if utils.check_reserved(name) is False: raise web.HTTPBadRequest( reason='Invalid name property in payload.') if utils.check_foglamp_reserved(name) is False: raise web.HTTPBadRequest( reason= "'{}' is reserved for FogLAMP and can not be used as service name!" .format(name)) if service_type is None: raise web.HTTPBadRequest( reason='Missing type property in payload.') service_type = str(service_type).lower() if service_type == 'north': raise web.HTTPNotAcceptable( reason='north type is not supported for the time being.') if service_type not in ['south', 'notification']: raise web.HTTPBadRequest( reason='Only south and notification type are supported.') if plugin is None and service_type == 'south': raise web.HTTPBadRequest( reason='Missing plugin property for type south in payload.') if plugin and utils.check_reserved(plugin) is False: raise web.HTTPBadRequest( reason='Invalid plugin property in payload.') if enabled is not None: if enabled not in ['true', 'false', True, False]: raise web.HTTPBadRequest( reason='Only "true", "false", true, false' ' are allowed for value of enabled.') is_enabled = True if ( (type(enabled) is str and enabled.lower() in ['true']) or ((type(enabled) is bool and enabled is True))) else False # Check if a valid plugin has been provided plugin_module_path, plugin_config, process_name, script = "", {}, "", "" if service_type == 'south': # "plugin_module_path" is fixed by design. It is MANDATORY to keep the plugin in the exactly similar named # folder, within the plugin_module_path. # if multiple plugin with same name are found, then python plugin import will be tried first plugin_module_path = "{}/python/foglamp/plugins/{}/{}".format( _FOGLAMP_ROOT, service_type, plugin) try: plugin_info = common.load_and_fetch_python_plugin_info( plugin_module_path, plugin, service_type) plugin_config = plugin_info['config'] if not plugin_config: _logger.exception("Plugin %s import problem from path %s", plugin, plugin_module_path) raise web.HTTPNotFound( reason='Plugin "{}" import problem from path "{}".'. format(plugin, plugin_module_path)) process_name = 'south_c' script = '["services/south_c"]' except FileNotFoundError as ex: # Checking for C-type plugins plugin_config = load_c_plugin(plugin, service_type) if not plugin_config: _logger.exception( "Plugin %s import problem from path %s. %s", plugin, plugin_module_path, str(ex)) raise web.HTTPNotFound( reason='Plugin "{}" import problem from path "{}".'. format(plugin, plugin_module_path)) process_name = 'south_c' script = '["services/south_c"]' except TypeError as ex: _logger.exception(str(ex)) raise web.HTTPBadRequest(reason=str(ex)) except Exception as ex: _logger.exception("Failed to fetch plugin configuration. %s", str(ex)) raise web.HTTPInternalServerError( reason='Failed to fetch plugin configuration') elif service_type == 'notification': process_name = 'notification_c' script = '["services/notification_c"]' storage = connect.get_storage_async() config_mgr = ConfigurationManager(storage) # Check whether category name already exists category_info = await config_mgr.get_category_all_items( category_name=name) if category_info is not None: raise web.HTTPBadRequest( reason="The '{}' category already exists".format(name)) # Check that the schedule name is not already registered count = await check_schedules(storage, name) if count != 0: raise web.HTTPBadRequest( reason='A service with this name already exists.') # Check that the process name is not already registered count = await check_scheduled_processes(storage, process_name) if count == 0: # Now first create the scheduled process entry for the new service payload = PayloadBuilder().INSERT(name=process_name, script=script).payload() try: res = await storage.insert_into_tbl("scheduled_processes", payload) except StorageServerError as ex: _logger.exception("Failed to create scheduled process. %s", ex.error) raise web.HTTPInternalServerError( reason='Failed to create service.') except Exception as ex: _logger.exception("Failed to create scheduled process. %s", str(ex)) raise web.HTTPInternalServerError( reason='Failed to create service.') # check that notification service is not already registered, right now notification service LIMIT to 1 if service_type == 'notification': res = await check_notification_schedule(storage) for ps in res['rows']: if 'notification_c' in ps['process_name']: raise web.HTTPBadRequest( reason='A Notification service schedule already exists.' ) elif service_type == 'south': try: # Create a configuration category from the configuration defined in the plugin category_desc = plugin_config['plugin']['description'] await config_mgr.create_category( category_name=name, category_description=category_desc, category_value=plugin_config, keep_original_items=True) # Create the parent category for all South services await config_mgr.create_category("South", {}, "South microservices", True) await config_mgr.create_child_category("South", [name]) # If config is in POST data, then update the value for each config item if config is not None: if not isinstance(config, dict): raise ValueError('Config must be a JSON object') for k, v in config.items(): await config_mgr.set_category_item_value_entry( name, k, v['value']) except Exception as ex: await config_mgr.delete_category_and_children_recursively(name) _logger.exception("Failed to create plugin configuration. %s", str(ex)) raise web.HTTPInternalServerError( reason='Failed to create plugin configuration.') # If all successful then lastly add a schedule to run the new service at startup try: schedule = StartUpSchedule() schedule.name = name schedule.process_name = process_name schedule.repeat = datetime.timedelta(0) schedule.exclusive = True # if "enabled" is supplied, it gets activated in save_schedule() via is_enabled flag schedule.enabled = False # Save schedule await server.Server.scheduler.save_schedule(schedule, is_enabled) schedule = await server.Server.scheduler.get_schedule_by_name(name) except StorageServerError as ex: await config_mgr.delete_category_and_children_recursively(name) _logger.exception("Failed to create schedule. %s", ex.error) raise web.HTTPInternalServerError( reason='Failed to create service.') except Exception as ex: await config_mgr.delete_category_and_children_recursively(name) _logger.exception("Failed to create service. %s", str(ex)) raise web.HTTPInternalServerError( reason='Failed to create service.') except ValueError as e: raise web.HTTPBadRequest(reason=str(e)) except KeyError as ex: raise web.HTTPNotFound(reason=str(ex)) else: return web.json_response({ 'name': name, 'id': str(schedule.schedule_id) })
def test_set_payload(self, test_input, expected): res = PayloadBuilder().SET(value=test_input).payload() assert expected == json.loads(res)
async def get_schedule(storage, schedule_name): payload = PayloadBuilder().SELECT(["id", "enabled"]).WHERE( ['schedule_name', '=', schedule_name]).payload() result = await storage.query_tbl_with_payload('schedules', payload) return result
def test_update_set_where_payload(self, input_set, input_where, input_table, expected): res = PayloadBuilder().SET(value=input_set).WHERE( input_where).UPDATE_TABLE(input_table).payload() assert expected == json.loads(res)
def test_conditions_payload(self, test_input, expected): res = PayloadBuilder().WHERE(test_input).payload() assert expected == json.loads(res)
def test_select_all_payload(self): res = PayloadBuilder().SELECT().payload() expected = {} assert expected == json.loads(res)