def _get_cli_compliance(obj): """This function performs the actual compliance for cli configuration.""" feature = { "ordered": obj.rule.config_ordered, "name": obj.rule, } feature.update({"section": obj.rule.match_config.splitlines()}) value = feature_compliance(feature, obj.actual, obj.intended, get_platform(obj.device.platform.slug)) compliance = value["compliant"] if compliance: compliance_int = 1 ordered = value["ordered_compliant"] else: compliance_int = 0 ordered = value["ordered_compliant"] missing = _null_to_empty(value["missing"]) extra = _null_to_empty(value["extra"]) return { "compliance": compliance, "compliance_int": compliance_int, "ordered": ordered, "missing": missing, "extra": extra, }
def save(self, *args, **kwargs): """Performs the actual compliance check.""" feature = { "ordered": self.rule.config_ordered, "name": self.rule, } if self.rule.config_type == ComplianceRuleTypeChoice.TYPE_JSON: feature.update({"section": self.rule.match_config}) diff = DeepDiff(self.actual, self.intended, ignore_order=self.ordered, report_repetition=True) if not diff: self.compliance_int = 1 self.compliance = True self.missing = "" self.extra = "" else: self.compliance_int = 0 self.compliance = False self.missing = null_to_empty( self._normalize_diff(diff, "added")) self.extra = null_to_empty( self._normalize_diff(diff, "removed")) else: feature.update({"section": self.rule.match_config.splitlines()}) value = feature_compliance(feature, self.actual, self.intended, get_platform(self.device.platform.slug)) self.compliance = value["compliant"] if self.compliance: self.compliance_int = 1 else: self.compliance_int = 0 self.ordered = value["ordered_compliant"] self.missing = null_to_empty(value["missing"]) self.extra = null_to_empty(value["extra"]) super().save(*args, **kwargs)
def run_compliance( # pylint: disable=too-many-arguments,too-many-locals task: Task, logger, global_settings, backup_root_path, intended_root_folder, features, ) -> Result: """Prepare data for compliance task. Args: task (Task): Nornir task individual object Returns: result (Result): Result from Nornir task """ obj = task.host.data["obj"] compliance_obj = GoldenConfig.objects.filter(device=obj).first() if not compliance_obj: compliance_obj = GoldenConfig.objects.create(device=obj) compliance_obj.compliance_last_attempt_date = task.host.defaults.data[ "now"] compliance_obj.save() intended_path_template_obj = check_jinja_template( obj, logger, global_settings.intended_path_template) intended_file = os.path.join(intended_root_folder, intended_path_template_obj) if not os.path.exists(intended_file): logger.log_failure( obj, f"Unable to locate intended file for device at {intended_file}") raise NornirNautobotException() backup_template = check_jinja_template( obj, logger, global_settings.backup_path_template) backup_file = os.path.join(backup_root_path, backup_template) if not os.path.exists(backup_file): logger.log_failure( obj, f"Unable to locate backup file for device at {backup_file}") raise NornirNautobotException() platform = obj.platform.slug if not features.get(platform): logger.log_failure( obj, f"There is no `user` defined feature mapping for platform slug {platform}." ) raise NornirNautobotException() if get_platform(platform) not in parser_map.keys(): logger.log_failure( obj, f"There is currently no parser support for platform slug {get_platform(platform)}." ) raise NornirNautobotException() backup_cfg = _open_file_config(backup_file) intended_cfg = _open_file_config(intended_file) # TODO: Make this atomic with compliance_obj step. for feature in features[obj.platform.slug]: # using update_or_create() method to conveniently update actual obj or create new one. ConfigCompliance.objects.update_or_create( device=obj, rule=feature["obj"], defaults={ "actual": section_config(feature, backup_cfg, get_platform(platform)), "intended": section_config(feature, intended_cfg, get_platform(platform)), "missing": "", "extra": "", }, ) compliance_obj.compliance_last_success_date = task.host.defaults.data[ "now"] compliance_obj.compliance_config = "\n".join( diff_files(backup_file, intended_file)) compliance_obj.save() logger.log_success(obj, "Successfully tested compliance.") return Result(host=task.host)
def test_get_platform_no_settings_definition(self): """Test defaults when settings platform_slug_map not used.""" self.assertEqual(get_platform("cisco"), "cisco")
def test_get_platform_defined_but_not_relevant(self): """Test user defined platform mappings not relevant.""" self.assertEqual(get_platform("cisco_ios"), "cisco_ios")
def test_get_platform_user_defined(self): """Test user defined platform mappings.""" self.assertEqual(get_platform("cisco"), "cisco_ios")
def test_get_platform_with_key_none(self): """Test user defined platform mappings and defaults key defined and set to None.""" self.assertEqual(get_platform("cisco"), "cisco")