class RestCallForm(ServiceForm, ValidationForm): form_type = HiddenField(default="RestCallService") has_targets = BooleanField("Has Target Devices") call_type = SelectField(choices=( ("GET", "GET"), ("POST", "POST"), ("PUT", "PUT"), ("DELETE", "DELETE"), ("PATCH", "PATCH"), )) rest_url = SubstitutionField() payload = JsonSubstitutionField() params = DictSubstitutionField() headers = DictSubstitutionField() verify_ssl_certificate = BooleanField("Verify SSL Certificate") timeout = IntegerField(default=15) username = StringField() password = PasswordField() groups = { "Main Parameters": [ "has_targets", "call_type", "rest_url", "payload", "params", "headers", "verify_ssl_certificate", "timeout", "username", "password", ], "Validation Parameters": ValidationForm.group, }
class AnsiblePlaybookForm(ServiceForm, ValidationForm): form_type = HiddenField(default="AnsiblePlaybookService") has_targets = BooleanField("Has Target Devices") playbook_path = NoValidationSelectField("Playbook Path", choices=()) arguments = SubstitutionField("Arguments (Ansible command line options)") pass_device_properties = BooleanField( "Pass Device Inventory Properties (to be used " "in the playbook as {{name}} or {{ip_address}})") options = DictSubstitutionField( "Options (passed to ansible as -e extra args)") groups = { "Main Parameters": [ "has_targets", "playbook_path", "arguments", "pass_device_properties", "options", ], "Validation Parameters": ValidationForm.group, } def validate(self) -> bool: valid_form = super().validate() pass_properties_error = (self.pass_device_properties.data and not self.has_targets.data) if pass_properties_error: self.pass_device_properties.errors.append( "'pass device properties' requires 'has device targets' to be selected." ) return valid_form and not pass_properties_error
class RestCallForm(ServiceForm): form_type = HiddenField(default="rest_call_service") call_type = SelectField(choices=( ("GET", "GET"), ("POST", "POST"), ("PUT", "PUT"), ("DELETE", "DELETE"), ("PATCH", "PATCH"), )) rest_url = SubstitutionField() payload = JsonSubstitutionField() params = DictSubstitutionField() headers = DictSubstitutionField() verify_ssl_certificate = BooleanField("Verify SSL Certificate") timeout = IntegerField(default=15) username = StringField() password = PasswordField()
class AnsiblePlaybookForm(ServiceForm): form_type = HiddenField(default="ansible_playbook_service") playbook_path = NoValidationSelectField("Playbook Path", choices=()) arguments = SubstitutionField("Arguments (Ansible command line options)") pass_device_properties = BooleanField( "Pass Device Inventory Properties (to be used " "in the playbook as {{name}} or {{ip_address}})") options = DictSubstitutionField( "Options (passed to ansible as -e extra args)")
class ValidationForm(BaseForm): form_type = HiddenField(default="service_validation") abstract_service = True conversion_method = SelectField( choices=( ("none", "No conversion"), ("text", "Text"), ("json", "Json dictionary"), ("xml", "XML dictionary"), ) ) validation_method = SelectField( "Validation Method", choices=( ("text", "Validation by text match"), ("dict_included", "Validation by dictionary inclusion"), ("dict_equal", "Validation by dictionary equality"), ), ) content_match = SubstitutionField( "Content Match", widget=TextArea(), render_kw={"rows": 8} ) content_match_regex = BooleanField("Match content with Regular Expression") dict_match = DictSubstitutionField("Dictionary to Match Against") negative_logic = BooleanField("Negative logic") delete_spaces_before_matching = BooleanField("Delete Spaces before Matching") group = { "commands": [ "conversion_method", "validation_method", "content_match", "content_match_regex", "dict_match", "negative_logic", "delete_spaces_before_matching", ], "default": "expanded", } def validate(self) -> bool: valid_form = super().validate() conversion_validation_mismatch = ( self.conversion_method.data == "text" and "dict" in self.validation_method.data or self.conversion_method.data in ("xml", "json") and "dict" not in self.validation_method.data ) if conversion_validation_mismatch: self.conversion_method.errors.append( f"The conversion method is set to '{self.conversion_method.data}'" f" and the validation method to '{self.validation_method.data}' :" " these do not match." ) return valid_form and not conversion_validation_mismatch
class DictValidationForm(BaseForm): form_type = HiddenField(default="dict_service_validation") abstract_service = True validation_method = SelectField( "Validation Method", choices=( ("dict_equal", "Validation by dictionary equality"), ("dict_included", "Validation by dictionary inclusion"), ), ) dict_match = DictSubstitutionField("Dictionary to Match Against") negative_logic = BooleanField("Negative logic") group = ["validation_method", "dict_match", "negative_logic"]
class ServiceForm(BaseForm): template = "service" form_type = HiddenField(default="service") id = HiddenField() name = StringField("Name") type = StringField("Service Type") shared = BooleanField("Shared Service") scoped_name = StringField("Scoped Name", [InputRequired()]) description = StringField("Description") device_query = StringField("Device Query") device_query_property = SelectField("Query Property Type", choices=(("name", "Name"), ("ip_address", "IP address"))) devices = MultipleInstanceField("Devices") pools = MultipleInstanceField("Pools") workflows = MultipleInstanceField("Workflows") waiting_time = IntegerField("Waiting time (in seconds)", default=0) send_notification = BooleanField("Send a notification") send_notification_method = SelectField( "Notification Method", choices=(("mail", "Mail"), ("slack", "Slack"), ("mattermost", "Mattermost")), ) notification_header = StringField(widget=TextArea(), render_kw={"rows": 5}) include_device_results = BooleanField("Include Device Results") include_link_in_summary = BooleanField("Include Result Link in Summary") display_only_failed_nodes = BooleanField("Display only Failed Devices") mail_recipient = StringField("Mail Recipients (separated by comma)") number_of_retries = IntegerField("Number of retries", default=0) time_between_retries = IntegerField("Time between retries (in seconds)", default=10) maximum_runs = IntegerField("Maximum number of runs", default=1) skip = BooleanField("Skip") skip_query = StringField("Skip Query (Python)") vendor = StringField("Vendor") operating_system = StringField("Operating System") initial_payload = DictField() iteration_values = StringField("Iteration Values (Python Query)") iteration_variable_name = StringField("Iteration Variable Name", default="iteration_value") iteration_devices = StringField("Iteration Devices (Python Query)") iteration_devices_property = SelectField( "Iteration Devices Property", choices=(("name", "Name"), ("ip_address", "IP address")), ) result_postprocessing = StringField(widget=TextArea(), render_kw={"rows": 7}) multiprocessing = BooleanField("Multiprocessing") max_processes = IntegerField("Maximum number of processes", default=50) conversion_method = SelectField(choices=( ("none", "No conversion"), ("text", "Text"), ("json", "Json dictionary"), ("xml", "XML dictionary"), )) validation_method = SelectField( "Validation Method", choices=( ("none", "No validation"), ("text", "Validation by text match"), ("dict_included", "Validation by dictionary inclusion"), ("dict_equal", "Validation by dictionary equality"), ), ) content_match = SubstitutionField("Content Match", widget=TextArea(), render_kw={"rows": 8}) content_match_regex = BooleanField("Match content with Regular Expression") dict_match = DictSubstitutionField("Dictionary to Match Against") negative_logic = BooleanField("Negative logic") delete_spaces_before_matching = BooleanField( "Delete Spaces before Matching") query_fields = [ "device_query", "skip_query", "iteration_values", "result_postprocessing", ] def validate(self): valid_form = super().validate() no_recipient_error = (self.send_notification.data and self.send_notification_method.data == "mail" and not self.mail_recipient.data and not app.config["mail"]["recipients"]) if no_recipient_error: self.mail_recipient.errors.append( "Please add at least one recipient for the mail notification.") bracket_error = False for query_field in self.query_fields: field = getattr(self, query_field) try: parse(field.data) except Exception as exc: bracket_error = True field.errors.append(f"Wrong python expression ({exc}).") if "{{" in field.data and "}}" in field.data: bracket_error = True field.errors.append( "You cannot use variable substitution " "in a field expecting a python expression.") conversion_validation_mismatch = ( self.conversion_method.data == "text" and "dict" in self.validation_method.data or self.conversion_method.data in ("xml", "json") and "dict" not in self.validation_method.data) if conversion_validation_mismatch: self.conversion_method.errors.append( f"The conversion method is set to '{self.conversion_method.data}'" f" and the validation method to '{self.validation_method.data}' :" " these do not match.") return (valid_form and not no_recipient_error and not bracket_error and not conversion_validation_mismatch)