diff --git a/src/service/clmcservice/alertsapi/views.py b/src/service/clmcservice/alertsapi/views.py index b8ee7db6dbccce7cadfe5b7824fe2ed7d41248dc..60333012bb3a483102c0efb5a66f57b157e13287 100644 --- a/src/service/clmcservice/alertsapi/views.py +++ b/src/service/clmcservice/alertsapi/views.py @@ -101,37 +101,11 @@ class AlertsConfigurationAPI(object): kapacitor_host, kapacitor_port = self.request.registry.settings['kapacitor_host'], self.request.registry.settings['kapacitor_port'] sfemc_fqdn, sfemc_port = self.request.registry.settings['sfemc_fqdn'], self.request.registry.settings['sfemc_port'] + # since this is not a POST request, need to fetch the alert specification file from request.params, rather than request.POST alert_spec_reference = self.request.params.get('alert-spec') - # check that the alerts specification file was sent - if not hasattr(alert_spec_reference, "file") or not hasattr(alert_spec_reference, "filename"): - raise HTTPBadRequest("Request to this API endpoint must include a (YAML) file input referenced as 'alert-spec' representing the TOSCA Alert Specification.") - - # extract alert specification file and filename - alerts_input_filename = alert_spec_reference.filename - alerts_input_file = alert_spec_reference.file - - if not (alerts_input_filename.lower().endswith('.yaml') or alerts_input_filename.lower.endswith('.yml')): - raise HTTPBadRequest("Request to this API endpoint must include a (YAML) file input referenced as 'alert-spec' representing the TOSCA Alerts Specification.") - - # parse the alerts specification file - try: - alerts_yaml_content = load(alerts_input_file) - adjust_tosca_definitions_import(alerts_yaml_content) - except YAMLError as err: - log.error("Couldn't parse user request file {0} to yaml format due to error: {1}".format(alerts_input_filename, err)) - log.error("Invalid content is: {0}".format(alerts_input_file.read())) - raise HTTPBadRequest("Request alert specification file could not be parsed as valid YAML document.") - - try: - tosca_tpl = ToscaTemplate(yaml_dict_tpl=alerts_yaml_content) - except Exception as e: - log.error(e) - raise HTTPBadRequest("Request alert specification file could not be parsed as a valid TOSCA document.") - - valid_alert_spec = validate_clmc_alerts_specification(tosca_tpl.tpl) - if not valid_alert_spec: - raise HTTPBadRequest("Request alert specification file could not be validated as a CLMC TOSCA alerts specification document.") + # parse the alert specification file into a tosca template (including validation) + tosca_tpl = self._parse_alert_spec(alert_spec_reference) # TODO next release - uncomment # sfc, sfc_instance = tosca_tpl.tpl["metadata"]["sfc"], tosca_tpl.tpl["metadata"]["sfci"] @@ -202,42 +176,17 @@ class AlertsConfigurationAPI(object): if not hasattr(resource_spec_reference, "file") or not hasattr(resource_spec_reference, "filename"): raise HTTPBadRequest("Request to this API endpoint must include a (YAML) file input referenced as 'resource-spec' representing the TOSCA Resource Specification.") + # extract the required information from the resource specification and return an error if an exception was encountered try: resource_spec_sfc, resource_spec_sfc_instance, resource_spec_policy_triggers = get_resource_spec_policy_triggers(resource_spec_reference) except Exception as e: log.error("Couldn't extract resource specification event IDs due to error: {0}".format(e)) raise HTTPBadRequest("Couldn't extract resource specification event IDs - invalid TOSCA resource specification.") - # check that the alerts specification file was sent - if not hasattr(alert_spec_reference, "file") or not hasattr(alert_spec_reference, "filename"): - raise HTTPBadRequest("Request to this API endpoint must include a (YAML) file input referenced as 'alert-spec' representing the TOSCA Alert Specification.") - - # extract alert specification file and filename - alerts_input_filename = alert_spec_reference.filename - alerts_input_file = alert_spec_reference.file - - if not (alerts_input_filename.lower().endswith('.yaml') or alerts_input_filename.lower.endswith('.yml')): - raise HTTPBadRequest("Request to this API endpoint must include a (YAML) file input referenced as 'alert-spec' representing the TOSCA Alerts Specification.") - - # parse the alerts specification file - try: - alerts_yaml_content = load(alerts_input_file) - adjust_tosca_definitions_import(alerts_yaml_content) - except YAMLError as err: - log.error("Couldn't parse user request file {0} to yaml format due to error: {1}".format(alerts_input_filename, err)) - log.error("Invalid content is: {0}".format(alerts_input_file.read())) - raise HTTPBadRequest("Request alert specification file could not be parsed as valid YAML document.") - - try: - tosca_tpl = ToscaTemplate(yaml_dict_tpl=alerts_yaml_content) - except Exception as e: - log.error(e) - raise HTTPBadRequest("Request alert specification file could not be parsed as a valid TOSCA document.") - - valid_alert_spec = validate_clmc_alerts_specification(tosca_tpl.tpl) - if not valid_alert_spec: - raise HTTPBadRequest("Request alert specification file could not be validated as a CLMC TOSCA alerts specification document.") + # parse the alert specification file into a tosca template (including validation) + tosca_tpl = self._parse_alert_spec(alert_spec_reference) + # extract the information needed from the alert spec. for validation between the two TOSCA documents alert_spec_policy_triggers = get_alert_spec_policy_triggers(tosca_tpl) # TODO next release - uncomment # sfc, sfc_instance = tosca_tpl.tpl["metadata"]["sfc"], tosca_tpl.tpl["metadata"]["sfci"] @@ -444,6 +393,50 @@ class AlertsConfigurationAPI(object): "error": response_content.get("error") }) + def _parse_alert_spec(self, alert_spec_reference): + """ + Parses an alert specification file to TOSCA template and validates it against the CLMC alerts specification schema. + + :param alert_spec_reference: the alert specification file received in the request + + :return: the parsed tosca template + """ + + # check that the alerts specification file was sent correctly + if not hasattr(alert_spec_reference, "file") or not hasattr(alert_spec_reference, "filename"): + raise HTTPBadRequest("Request to this API endpoint must include a (YAML) file input referenced as 'alert-spec' representing the TOSCA Alert Specification.") + + # extract alert specification file and filename + alerts_input_filename = alert_spec_reference.filename + alerts_input_file = alert_spec_reference.file + + # allow only .yaml and .yml extensions for filename + if not (alerts_input_filename.lower().endswith('.yaml') or alerts_input_filename.lower.endswith('.yml')): + raise HTTPBadRequest("Request to this API endpoint must include a (YAML) file input referenced as 'alert-spec' representing the TOSCA Alerts Specification.") + + # parse the alerts specification file + try: + alerts_yaml_content = load(alerts_input_file) + adjust_tosca_definitions_import(alerts_yaml_content) + except YAMLError as err: + log.error("Couldn't parse user request file {0} to yaml format due to error: {1}".format(alerts_input_filename, err)) + log.error("Invalid content is: {0}".format(alerts_input_file.read())) + raise HTTPBadRequest("Request alert specification file could not be parsed as valid YAML document.") + + # convert to tosca template + try: + tosca_tpl = ToscaTemplate(yaml_dict_tpl=alerts_yaml_content) + except Exception as e: + log.error(e) + raise HTTPBadRequest("Request alert specification file could not be parsed as a valid TOSCA document.") + + # validate against CLMC spec. + valid_alert_spec = validate_clmc_alerts_specification(tosca_tpl.tpl) + if not valid_alert_spec: + raise HTTPBadRequest("Request alert specification file could not be validated as a CLMC TOSCA alerts specification document.") + + return tosca_tpl + @staticmethod def get_hash(message): """