def set_manager_attributes(self, command): result = {} required_arg_spec = {'manager_attributes': {'required': True}} try: check_required_arguments(required_arg_spec, self.module.params) except TypeError as e: msg = to_native(e) self.module.fail_json(msg=msg) key = "Attributes" command_manager_attributes_uri_map = { "SetManagerAttributes": self.manager_uri, "SetLifecycleControllerAttributes": "/redfish/v1/Managers/LifecycleController.Embedded.1", "SetSystemAttributes": "/redfish/v1/Managers/System.Embedded.1" } manager_uri = command_manager_attributes_uri_map.get(command, self.manager_uri) attributes = self.module.params['manager_attributes'] attrs_to_patch = {} attrs_skipped = {} # Search for key entry and extract URI from it response = self.get_request(self.root_uri + manager_uri + "/" + key) if response['ret'] is False: return response result['ret'] = True data = response['data'] if key not in data: return {'ret': False, 'msg': "%s: Key %s not found" % (command, key)} for attr_name, attr_value in attributes.items(): # Check if attribute exists if attr_name not in data[u'Attributes']: return {'ret': False, 'msg': "%s: Manager attribute %s not found" % (command, attr_name)} # Find out if value is already set to what we want. If yes, exclude # those attributes if data[u'Attributes'][attr_name] == attr_value: attrs_skipped.update({attr_name: attr_value}) else: attrs_to_patch.update({attr_name: attr_value}) if not attrs_to_patch: return {'ret': True, 'changed': False, 'msg': "Manager attributes already set"} payload = {"Attributes": attrs_to_patch} response = self.patch_request(self.root_uri + manager_uri + "/" + key, payload) if response['ret'] is False: return response return {'ret': True, 'changed': True, 'msg': "%s: Modified Manager attributes %s" % (command, attrs_to_patch)}
def test_check_required_arguments_missing_multiple(arguments_terms_multiple): params = { 'apples': 'woohoo', } expected = "missing required arguments: bar, foo" with pytest.raises(TypeError) as e: check_required_arguments(arguments_terms_multiple, params) assert to_native(e.value) == expected
def _check_required_arguments(self, spec=None, param=None): if spec is None: spec = self.argument_spec if param is None: param = self.params try: check_required_arguments(spec, param) except TypeError as e: msg = to_native(e) if self._options_context: msg += " found in %s" % " -> ".join(self._options_context) self.fail_json(msg=msg)
def test_check_required_arguments_missing_none(): terms = None params = { 'foo': 'bar', 'baz': 'buzz', } assert check_required_arguments(terms, params) == []
def validate(self, parameters, *args, **kwargs): """Validate ``parameters`` against argument spec. Error messages in the :class:`ValidationResult` may contain no_log values and should be sanitized with :func:`~ansible.module_utils.common.parameters.sanitize_keys` before logging or displaying. :arg parameters: Parameters to validate against the argument spec :type parameters: dict[str, dict] :return: :class:`ValidationResult` containing validated parameters. :Simple Example: .. code-block:: text argument_spec = { 'name': {'type': 'str'}, 'age': {'type': 'int'}, } parameters = { 'name': 'bo', 'age': '42', } validator = ArgumentSpecValidator(argument_spec) result = validator.validate(parameters) if result.error_messages: sys.exit("Validation failed: {0}".format(", ".join(result.error_messages)) valid_params = result.validated_parameters """ result = ValidationResult(parameters) result._no_log_values.update( set_fallbacks(self.argument_spec, result._validated_parameters)) alias_warnings = [] alias_deprecations = [] try: result._aliases.update( _handle_aliases(self.argument_spec, result._validated_parameters, alias_warnings, alias_deprecations)) except (TypeError, ValueError) as e: result.errors.append(AliasError(to_native(e))) legal_inputs = _get_legal_inputs(self.argument_spec, result._validated_parameters, result._aliases) for option, alias in alias_warnings: result._warnings.append({'option': option, 'alias': alias}) for deprecation in alias_deprecations: result._deprecations.append({ 'name': deprecation['name'], 'version': deprecation.get('version'), 'date': deprecation.get('date'), 'collection_name': deprecation.get('collection_name'), }) try: result._no_log_values.update( _list_no_log_values(self.argument_spec, result._validated_parameters)) except TypeError as te: result.errors.append(NoLogError(to_native(te))) try: result._unsupported_parameters.update( _get_unsupported_parameters(self.argument_spec, result._validated_parameters, legal_inputs)) except TypeError as te: result.errors.append(RequiredDefaultError(to_native(te))) except ValueError as ve: result.errors.append(AliasError(to_native(ve))) try: check_mutually_exclusive(self._mutually_exclusive, result._validated_parameters) except TypeError as te: result.errors.append(MutuallyExclusiveError(to_native(te))) result._no_log_values.update( _set_defaults(self.argument_spec, result._validated_parameters, False)) try: check_required_arguments(self.argument_spec, result._validated_parameters) except TypeError as e: result.errors.append(RequiredError(to_native(e))) _validate_argument_types(self.argument_spec, result._validated_parameters, errors=result.errors) _validate_argument_values(self.argument_spec, result._validated_parameters, errors=result.errors) for check in _ADDITIONAL_CHECKS: try: check['func'](getattr(self, "_{attr}".format(attr=check['attr'])), result._validated_parameters) except TypeError as te: result.errors.append(check['err'](to_native(te))) result._no_log_values.update( _set_defaults(self.argument_spec, result._validated_parameters)) _validate_sub_spec( self.argument_spec, result._validated_parameters, errors=result.errors, no_log_values=result._no_log_values, unsupported_parameters=result._unsupported_parameters) if result._unsupported_parameters: flattened_names = [] for item in result._unsupported_parameters: if isinstance(item, tuple): flattened_names.append(".".join(item)) else: flattened_names.append(item) unsupported_string = ", ".join(sorted(list(flattened_names))) supported_string = ", ".join(self._valid_parameter_names) result.errors.append( UnsupportedError( "{0}. Supported parameters include: {1}.".format( unsupported_string, supported_string))) return result
def _validate_sub_spec(argument_spec, parameters, prefix='', options_context=None, errors=None, no_log_values=None, unsupported_parameters=None): """Validate sub argument spec. This function is recursive. """ if options_context is None: options_context = [] if errors is None: errors = AnsibleValidationErrorMultiple() if no_log_values is None: no_log_values = set() if unsupported_parameters is None: unsupported_parameters = set() for param, value in argument_spec.items(): wanted = value.get('type') if wanted == 'dict' or (wanted == 'list' and value.get('elements', '') == 'dict'): sub_spec = value.get('options') if value.get('apply_defaults', False): if sub_spec is not None: if parameters.get(param) is None: parameters[param] = {} else: continue elif sub_spec is None or param not in parameters or parameters[ param] is None: continue # Keep track of context for warning messages options_context.append(param) # Make sure we can iterate over the elements if not isinstance(parameters[param], Sequence) or isinstance( parameters[param], string_types): elements = [parameters[param]] else: elements = parameters[param] for idx, sub_parameters in enumerate(elements): no_log_values.update(set_fallbacks(sub_spec, sub_parameters)) if not isinstance(sub_parameters, dict): errors.append( SubParameterTypeError( "value of '%s' must be of type dict or list of dicts" % param)) continue # Set prefix for warning messages new_prefix = prefix + param if wanted == 'list': new_prefix += '[%d]' % idx new_prefix += '.' alias_warnings = [] alias_deprecations = [] try: options_aliases = _handle_aliases(sub_spec, sub_parameters, alias_warnings, alias_deprecations) except (TypeError, ValueError) as e: options_aliases = {} errors.append(AliasError(to_native(e))) for option, alias in alias_warnings: warn('Both option %s and its alias %s are set.' % (option, alias)) try: no_log_values.update( _list_no_log_values(sub_spec, sub_parameters)) except TypeError as te: errors.append(NoLogError(to_native(te))) legal_inputs = _get_legal_inputs(sub_spec, sub_parameters, options_aliases) unsupported_parameters.update( _get_unsupported_parameters(sub_spec, sub_parameters, legal_inputs, options_context)) try: check_mutually_exclusive(value.get('mutually_exclusive'), sub_parameters, options_context) except TypeError as e: errors.append(MutuallyExclusiveError(to_native(e))) no_log_values.update( _set_defaults(sub_spec, sub_parameters, False)) try: check_required_arguments(sub_spec, sub_parameters, options_context) except TypeError as e: errors.append(RequiredError(to_native(e))) _validate_argument_types(sub_spec, sub_parameters, new_prefix, options_context, errors=errors) _validate_argument_values(sub_spec, sub_parameters, options_context, errors=errors) for check in _ADDITIONAL_CHECKS: try: check['func'](value.get(check['attr']), sub_parameters, options_context) except TypeError as e: errors.append(check['err'](to_native(e))) no_log_values.update(_set_defaults(sub_spec, sub_parameters)) # Handle nested specs _validate_sub_spec(sub_spec, sub_parameters, new_prefix, options_context, errors, no_log_values, unsupported_parameters) options_context.pop()
def validate_sub_spec(argument_spec, parameters, prefix='', options_context=None, errors=None, no_log_values=None, unsupported_parameters=None): """Validate sub argument spec. This function is recursive.""" if options_context is None: options_context = [] if errors is None: errors = [] if no_log_values is None: no_log_values = set() if unsupported_parameters is None: unsupported_parameters = set() for param, value in argument_spec.items(): wanted = value.get('type') if wanted == 'dict' or (wanted == 'list' and value.get('elements', '') == dict): sub_spec = value.get('options') if value.get('apply_defaults', False): if sub_spec is not None: if parameters.get(value) is None: parameters[param] = {} else: continue elif sub_spec is None or param not in parameters or parameters[param] is None: continue # Keep track of context for warning messages options_context.append(param) # Make sure we can iterate over the elements if isinstance(parameters[param], dict): elements = [parameters[param]] else: elements = parameters[param] for idx, sub_parameters in enumerate(elements): if not isinstance(sub_parameters, dict): errors.append("value of '%s' must be of type dict or list of dicts" % param) # Set prefix for warning messages new_prefix = prefix + param if wanted == 'list': new_prefix += '[%d]' % idx new_prefix += '.' no_log_values.update(set_fallbacks(sub_spec, sub_parameters)) alias_warnings = [] try: options_aliases, legal_inputs = handle_aliases(sub_spec, sub_parameters, alias_warnings) except (TypeError, ValueError) as e: options_aliases = {} legal_inputs = None errors.append(to_native(e)) for option, alias in alias_warnings: warn('Both option %s and its alias %s are set.' % (option, alias)) no_log_values.update(list_no_log_values(sub_spec, sub_parameters)) if legal_inputs is None: legal_inputs = list(options_aliases.keys()) + list(sub_spec.keys()) unsupported_parameters.update(get_unsupported_parameters(sub_spec, sub_parameters, legal_inputs)) try: check_mutually_exclusive(value.get('mutually_exclusive'), sub_parameters) except TypeError as e: errors.append(to_native(e)) no_log_values.update(set_defaults(sub_spec, sub_parameters, False)) try: check_required_arguments(sub_spec, sub_parameters) except TypeError as e: errors.append(to_native(e)) validate_argument_types(sub_spec, sub_parameters, new_prefix, options_context, errors=errors) validate_argument_values(sub_spec, sub_parameters, options_context, errors=errors) checks = [ (check_required_together, 'required_together'), (check_required_one_of, 'required_one_of'), (check_required_if, 'required_if'), (check_required_by, 'required_by'), ] for check in checks: try: check[0](value.get(check[1]), parameters) except TypeError as e: errors.append(to_native(e)) no_log_values.update(set_defaults(sub_spec, sub_parameters)) # Handle nested specs validate_sub_spec(sub_spec, sub_parameters, new_prefix, options_context, errors, no_log_values, unsupported_parameters) options_context.pop()
def validate(self, parameters, *args, **kwargs): """Validate module parameters against argument spec. Returns a ValidationResult object. Error messages in the ValidationResult may contain no_log values and should be sanitized before logging or displaying. :Example: validator = ArgumentSpecValidator(argument_spec) result = validator.validate(parameters) if result.error_messages: sys.exit("Validation failed: {0}".format(", ".join(result.error_messages)) valid_params = result.validated_parameters :param argument_spec: Specification of parameters, type, and valid values :type argument_spec: dict :param parameters: Parameters provided to the role :type parameters: dict :return: Object containing validated parameters. :rtype: ValidationResult """ result = ValidationResult(parameters) result._no_log_values.update( set_fallbacks(self.argument_spec, result._validated_parameters)) alias_warnings = [] alias_deprecations = [] try: aliases = _handle_aliases(self.argument_spec, result._validated_parameters, alias_warnings, alias_deprecations) except (TypeError, ValueError) as e: aliases = {} result.errors.append(AliasError(to_native(e))) legal_inputs = _get_legal_inputs(self.argument_spec, result._validated_parameters, aliases) for option, alias in alias_warnings: result._warnings.append({'option': option, 'alias': alias}) for deprecation in alias_deprecations: result._deprecations.append({ 'name': deprecation['name'], 'version': deprecation.get('version'), 'date': deprecation.get('date'), 'collection_name': deprecation.get('collection_name'), }) try: result._no_log_values.update( _list_no_log_values(self.argument_spec, result._validated_parameters)) except TypeError as te: result.errors.append(NoLogError(to_native(te))) try: result._unsupported_parameters.update( _get_unsupported_parameters(self.argument_spec, result._validated_parameters, legal_inputs)) except TypeError as te: result.errors.append(RequiredDefaultError(to_native(te))) except ValueError as ve: result.errors.append(AliasError(to_native(ve))) try: check_mutually_exclusive(self._mutually_exclusive, result._validated_parameters) except TypeError as te: result.errors.append(MutuallyExclusiveError(to_native(te))) result._no_log_values.update( _set_defaults(self.argument_spec, result._validated_parameters, False)) try: check_required_arguments(self.argument_spec, result._validated_parameters) except TypeError as e: result.errors.append(RequiredError(to_native(e))) _validate_argument_types(self.argument_spec, result._validated_parameters, errors=result.errors) _validate_argument_values(self.argument_spec, result._validated_parameters, errors=result.errors) for check in _ADDITIONAL_CHECKS: try: check['func'](getattr(self, "_{attr}".format(attr=check['attr'])), result._validated_parameters) except TypeError as te: result.errors.append(check['err'](to_native(te))) result._no_log_values.update( _set_defaults(self.argument_spec, result._validated_parameters)) _validate_sub_spec( self.argument_spec, result._validated_parameters, errors=result.errors, no_log_values=result._no_log_values, unsupported_parameters=result._unsupported_parameters) if result._unsupported_parameters: flattened_names = [] for item in result._unsupported_parameters: if isinstance(item, tuple): flattened_names.append(".".join(item)) else: flattened_names.append(item) unsupported_string = ", ".join(sorted(list(flattened_names))) supported_string = ", ".join(self._valid_parameter_names) result.errors.append( UnsupportedError( "{0}. Supported parameters include: {1}.".format( unsupported_string, supported_string))) return result
def test_check_required_arguments_no_params(arguments_terms): with pytest.raises(TypeError) as te: check_required_arguments(arguments_terms, None) assert "'NoneType' is not iterable" in to_native(te.value)
def test_check_required_arguments(arguments_terms): params = { 'foo': 'hello', 'bar': 'haha', } assert check_required_arguments(arguments_terms, params) == []
def validate(self, *args, **kwargs): """Validate module parameters against argument spec. :Example: validator = ArgumentSpecValidator(argument_spec, parameters) passeded = validator.validate() :param argument_spec: Specification of parameters, type, and valid values :type argument_spec: dict :param parameters: Parameters provided to the role :type parameters: dict :returns: True if no errors were encountered, False if any errors were encountered. :rtype: bool """ self._no_log_values.update(set_fallbacks(self.argument_spec, self._validated_parameters)) alias_warnings = [] alias_deprecations = [] try: alias_results, legal_inputs = handle_aliases(self.argument_spec, self._validated_parameters, alias_warnings, alias_deprecations) except (TypeError, ValueError) as e: alias_results = {} legal_inputs = None self._add_error(to_native(e)) for option, alias in alias_warnings: warn('Both option %s and its alias %s are set.' % (option, alias)) for deprecation in alias_deprecations: deprecate("Alias '%s' is deprecated. See the module docs for more information" % deprecation['name'], version=deprecation.get('version'), date=deprecation.get('date'), collection_name=deprecation.get('collection_name')) self._no_log_values.update(list_no_log_values(self.argument_spec, self._validated_parameters)) if legal_inputs is None: legal_inputs = list(alias_results.keys()) + list(self.argument_spec.keys()) self._unsupported_parameters.update(get_unsupported_parameters(self.argument_spec, self._validated_parameters, legal_inputs)) self._no_log_values.update(set_defaults(self.argument_spec, self._validated_parameters, False)) try: check_required_arguments(self.argument_spec, self._validated_parameters) except TypeError as e: self._add_error(to_native(e)) validate_argument_types(self.argument_spec, self._validated_parameters, errors=self._error_messages) validate_argument_values(self.argument_spec, self._validated_parameters, errors=self._error_messages) self._no_log_values.update(set_defaults(self.argument_spec, self._validated_parameters)) validate_sub_spec(self.argument_spec, self._validated_parameters, errors=self._error_messages, no_log_values=self._no_log_values, unsupported_parameters=self._unsupported_parameters) if self._unsupported_parameters: self._add_error('Unsupported parameters: %s' % ', '.join(sorted(list(self._unsupported_parameters)))) self._sanitize_error_messages() if self.error_messages: return False else: return True