Ejemplo n.º 1
0
    async def patch(self):
        """
        ---
        summary: Initiate administrative actions
        description: |
          The body of the request needs to contain a set of instructions
          detailing the operations to perform.

          Currently the supported operations are `rescan`:
          ```JSON
          [
            { "operation": "rescan" }
          ]
          ```
          * Will remove from the registry and database any currently stopped
            plugins who's directory has been removed.
          * Will add and start any new plugin directories.

          And reloading the plugin logging configuration:
          ```JSON
          [
            {
              "operation": "reload",
              "path": "/config/logging/plugin"
            }
          ]
          ```
        parameters:
          - name: patch
            in: body
            required: true
            description: Instructions for operations
            schema:
              $ref: '#/definitions/Patch'
        responses:
          204:
            description: Operation successfully initiated
          50x:
            $ref: '#/definitions/50xError'
        tags:
          - Admin
        """
        self.verify_user_permission_for_object(GARDEN_UPDATE, local_garden())

        operations = SchemaParser.parse_patch(
            self.request.decoded_body, many=True, from_string=True
        )

        for op in operations:
            if op.operation == "rescan":
                await self.client(Operation(operation_type="RUNNER_RESCAN"))
            elif op.operation == "reload":
                if op.path == "/config/logging/plugin":
                    await self.client(Operation(operation_type="PLUGIN_LOG_RELOAD"))
                else:
                    raise ModelValidationError(f"Unsupported path '{op.path}'")
            else:
                raise ModelValidationError(f"Unsupported operation '{op.operation}'")

        self.set_status(204)
Ejemplo n.º 2
0
    def get_and_validate_system(self, request):
        """Ensure there is a system in the DB that corresponds to this Request.

        :param request: The request to validate
        :return: The system corresponding to this Request
        :raises ModelValidationError: There is no system that corresponds to this Request
        """
        system = db.query_unique(
            System,
            namespace=request.namespace,
            name=request.system,
            version=request.system_version,
        )
        if system is None:
            raise ModelValidationError(
                "Could not find System named '%s' matching version '%s'" %
                (request.system, request.system_version))

        if request.instance_name not in system.instance_names:
            raise ModelValidationError(
                "Could not find instance with name '%s' in system '%s'" %
                (request.instance_name, system.name))

        self.logger.debug("Found System %s-%s" %
                          (request.system, request.instance_name))
        return system
Ejemplo n.º 3
0
    def clean(self):
        """Validate before saving to the database"""

        if self.status not in BrewtilsRequest.STATUS_LIST:
            raise ModelValidationError(
                f"Can not save Request {self}: Invalid status '{self.status}'")

        if (self.command_type is not None
                and self.command_type not in BrewtilsRequest.COMMAND_TYPES):
            raise ModelValidationError(
                f"Can not save Request {self}: Invalid command type"
                f" '{self.command_type}'")

        if (self.output_type is not None
                and self.output_type not in BrewtilsRequest.OUTPUT_TYPES):
            raise ModelValidationError(
                f"Can not save Request {self}: Invalid output type '{self.output_type}'"
            )

        # Deal with has_parent
        if self.has_parent is None:
            self.has_parent = bool(self.parent)
        elif self.has_parent != bool(self.parent):
            raise ModelValidationError(
                f"Cannot save Request {self}: parent value of {self.parent!r} is not "
                f"consistent with has_parent value of {self.has_parent}")

        if (self.namespace == config.get("garden.name")) and (
                "status" in self.changed_fields or self.created):
            self.status_updated_at = datetime.datetime.utcnow()
Ejemplo n.º 4
0
    def clean(self):
        if self.type == "static" and not isinstance(self.value, (list, dict)):
            raise ModelValidationError(
                f"Can not save choices '{self}': type is 'static' but the value is "
                "not a list or dictionary")
        elif self.type == "url" and not isinstance(self.value,
                                                   six.string_types):
            raise ModelValidationError(
                f"Can not save choices '{self}': type is 'url' but the value is "
                "not a string")
        elif self.type == "command" and not isinstance(
                self.value, (six.string_types, dict)):
            raise ModelValidationError(
                f"Can not save choices '{self}': type is 'command' but the value is "
                "not a string or dict")

        if self.type == "command" and isinstance(self.value, dict):
            value_keys = self.value.keys()
            for required_key in ("command", "system", "version"):
                if required_key not in value_keys:
                    raise ModelValidationError(
                        f"Can not save choices '{self}': specifying value as a "
                        f"dictionary requires a '{required_key}' item")

        try:
            if self.details == {}:
                if isinstance(self.value, six.string_types):
                    self.details = parse(self.value)
                elif isinstance(self.value, dict):
                    self.details = parse(self.value["command"])
        except (LarkError, ParseError):
            raise ModelValidationError(
                f"Can not save choices '{self}': Unable to parse")
Ejemplo n.º 5
0
    def clean(self):
        if self.type == "static" and not isinstance(self.value, (list, dict)):
            raise ModelValidationError(
                "Error saving choices '%s' - type was 'static' "
                "but the value was not a list or dictionary" % self.value)
        elif self.type == "url" and not isinstance(self.value,
                                                   six.string_types):
            raise ModelValidationError(
                "Error saving choices '%s' - type was 'url' but "
                "the value was not a string" % self.value)
        elif self.type == "command" and not isinstance(
                self.value, (six.string_types, dict)):
            raise ModelValidationError(
                "Error saving choices '%s' - type was 'command' "
                "but the value was not a string or dict" % self.value)

        if self.type == "command" and isinstance(self.value, dict):
            value_keys = self.value.keys()
            for required_key in ("command", "system", "version"):
                if required_key not in value_keys:
                    raise ModelValidationError(
                        "Error saving choices '%s' - specifying "
                        "value as a dictionary requires a '%s' "
                        "item" % (self.value, required_key))

        try:
            if self.details == {}:
                if isinstance(self.value, six.string_types):
                    self.details = parse(self.value)
                elif isinstance(self.value, dict):
                    self.details = parse(self.value["command"])
        except (LarkError, ParseError):
            raise ModelValidationError(
                "Error saving choices '%s' - unable to parse" % self.value)
Ejemplo n.º 6
0
    def patch(self):
        """
        ---
        summary: Refresh an auth token.
        description: |
          The body of the request needs to contain a set of instructions. Currently the
          only operation supported is `refresh`, with path `/payload`:
          ```JSON
          {
            "operations": [
              { "operation": "refresh", "path": "/payload", "value": "REFRESH_ID" }
            ]
          }
          ```
          If you do not know your REFRESH_ID, it should be set in a cookie by the
          server. If you leave `value` as `null` and include this cookie, then we
          will automatically refresh. Also, if you are using a cookie, you should
          really consider just using a GET on /api/v1/tokens as it has the same effect.
        parameters:
          - name: patch
            in: body
            required: true
            description: Instructions for what to do
            schema:
              $ref: '#/definitions/Patch'
        responses:
          200:
            description: New Auth token
            schema:
              $ref: '#/definitions/RefreshToken'
          400:
            $ref: '#/definitions/400Error'
          404:
            $ref: '#/definitions/404Error'
          50x:
            $ref: '#/definitions/50xError'
        tags:
          - Tokens
        """
        operations = self.parser.parse_patch(self.request.decoded_body,
                                             many=True,
                                             from_string=True)
        token = None

        for op in operations:
            if op.operation == "refresh":
                if op.path == "/payload":
                    token = self._refresh_token(op.value)
                else:
                    raise ModelValidationError("Unsupported path '%s'" %
                                               op.path)
            else:
                raise ModelValidationError("Unsupported operation '%s'" %
                                           op.operation)

        self.write(json.dumps(token))
Ejemplo n.º 7
0
    def _validate_parameter_based_on_type(self, value, parameter, command,
                                          request):
        """Validates the value passed in, ensures the type matches.
        Recursive calls for dictionaries which also have nested parameters"""

        try:
            if value is None and not parameter.nullable:
                raise ModelValidationError(
                    "There is no value for parameter '%s' "
                    "and this field is not nullable." % parameter.key)
            elif parameter.type.upper() == "STRING":
                if isinstance(value, six.string_types):
                    return str(value)
                else:
                    raise TypeError("Invalid value for string (%s)" % value)
            elif parameter.type.upper() == "INTEGER":
                if int(value) != float(value):
                    raise TypeError("Invalid value for integer (%s)" % value)
                return int(value)
            elif parameter.type.upper() == "FLOAT":
                return float(value)
            elif parameter.type.upper() == "ANY":
                return value
            elif parameter.type.upper() == "BOOLEAN":
                if value in [True, False]:
                    return value
                else:
                    raise TypeError("Invalid value for boolean (%s)" % value)
            elif parameter.type.upper() == "DICTIONARY":
                dict_value = dict(value)
                if parameter.parameters:
                    self.logger.debug("Found Nested Parameters.")
                    return self.get_and_validate_parameters(
                        request, command, parameter.parameters, dict_value)
                return dict_value
            elif parameter.type.upper() == "DATE":
                return int(value)
            elif parameter.type.upper() == "DATETIME":
                return int(value)
            elif parameter.type.upper() == "BASE64":
                return value
            else:
                raise ModelValidationError(
                    "Unknown type for parameter. Please contact a system administrator."
                )
        except TypeError as ex:
            self.logger.exception(ex)
            raise ModelValidationError(
                "Value for key: %s is not the correct type. Should be: %s" %
                (parameter.key, parameter.type))
        except ValueError as ex:
            self.logger.exception(ex)
            raise ModelValidationError(
                "Value for key: %s is not the correct type. Should be: %s" %
                (parameter.key, parameter.type))
Ejemplo n.º 8
0
    def clean(self):
        """Validate before saving to the database"""
        if not list(filter(lambda i: i != "", self.pattern)):
            raise ModelValidationError(
                "Cannot save FileTrigger. Must have at least one non-empty pattern."
            )

        if True not in self.callbacks.values():
            raise ModelValidationError(
                "Cannot save FileTrigger. Must have at least one callback selected."
            )
Ejemplo n.º 9
0
    def post(self):
        """
        ---
        summary: Create a new Role
        parameters:
          - name: role
            in: body
            description: The Role definition
            schema:
              $ref: '#/definitions/Role'
        consumes:
          - application/json
        responses:
          201:
            description: A new Role has been created
            schema:
              $ref: '#/definitions/Role'
          400:
            $ref: '#/definitions/400Error'
          50x:
            $ref: '#/definitions/50xError'
        tags:
          - Roles
        """
        role = BeerGardenSchemaParser.parse_role(self.request.decoded_body,
                                                 from_string=True)

        # Make sure all new permissions are real
        if not set(role.permissions).issubset(Permissions.values):
            invalid = set(role.permissions).difference(Permissions.values)
            raise ModelValidationError("Permissions %s do not exist" % invalid)

        # And the same for nested roles
        nested_roles = []
        for nested_role in role.roles:
            try:
                db_role = Role.objects.get(name=nested_role.name)

                # There shouldn't be any way to construct a cycle with a new
                # role, but check just to be sure
                ensure_no_cycles(role, db_role)

                nested_roles.append(db_role)
            except DoesNotExist:
                raise ModelValidationError("Role '%s' does not exist" %
                                           nested_role.name)
        role.roles = nested_roles

        role.save()

        self.set_status(201)
        self.write(BeerGardenSchemaParser.serialize_role(role,
                                                         to_string=False))
Ejemplo n.º 10
0
    def clean(self):
        """Validate before saving to the database"""

        if self.trigger_type not in self.TRIGGER_MODEL_MAPPING:
            raise ModelValidationError(
                "Cannot save job. No matching model for trigger type: %s" %
                self.trigger_type)

        if not isinstance(self.trigger,
                          self.TRIGGER_MODEL_MAPPING[self.trigger_type]):
            raise ModelValidationError(
                "Cannot save job. Trigger type: %s but got trigger: %s" %
                (self.trigger_type, type(self.trigger)))
Ejemplo n.º 11
0
    def clean(self):
        """Validate before saving to the database"""

        if len(self.instances) > self.max_instances > -1:
            raise ModelValidationError(
                "Can not save System %s: Number of instances (%s) "
                "exceeds system limit (%s)" %
                (str(self), len(self.instances), self.max_instances))

        if len(self.instances) != len(
                set(instance.name for instance in self.instances)):
            raise ModelValidationError(
                "Can not save System %s: Duplicate instance names" % str(self))
Ejemplo n.º 12
0
    def clean(self):
        """Validate before saving to the database"""

        if self.trigger_type not in self.TRIGGER_MODEL_MAPPING:
            raise ModelValidationError(
                f"Cannot save job. No mongo model for trigger type {self.trigger_type}"
            )

        trigger_class = self.TRIGGER_MODEL_MAPPING.get(self.trigger_type)
        if not isinstance(self.trigger, trigger_class):
            raise ModelValidationError(
                f"Cannot save job. Expected trigger type {self.trigger_type} but "
                f"actual type was {type(self.trigger)}")
Ejemplo n.º 13
0
    def clean(self):
        """Validate before saving to the database"""

        if not self.nullable and self.optional and self.default is None:
            raise ModelValidationError(
                "Can not save Parameter %s: For this Parameter "
                "nulls are not allowed, but the parameter is "
                "optional with no default defined." % self.key)

        if len(self.parameters) != len(
                set(parameter.key for parameter in self.parameters)):
            raise ModelValidationError(
                "Can not save Parameter %s: Contains Parameters "
                "with duplicate keys" % self.key)
Ejemplo n.º 14
0
    def clean(self):
        """Validate before saving to the database"""

        if not self.nullable and self.optional and self.default is None:
            raise ModelValidationError(
                f"Can not save Parameter {self}: For this Parameter nulls are not "
                "allowed, but the parameter is optional with no default defined."
            )

        if len(self.parameters) != len(
                set(parameter.key for parameter in self.parameters)):
            raise ModelValidationError(
                f"Can not save Parameter {self}: Contains Parameters with duplicate"
                " keys")
Ejemplo n.º 15
0
    def get_and_validate_command_for_system(self, request, system=None):
        """Ensure the System has a command with a name that matches this request.

        :param request: The request to validate
        :param system: Specifies a System to use. If None a system lookup will be attempted.
        :return: The database command
        :raises ValidationError: if the request or command is invalid
        """
        self.logger.debug("Getting and Validating Command for System")
        if system is None:
            self.logger.debug("No System was passed in")
            system = self.get_and_validate_system(request)

        if request.command is None:
            raise ModelValidationError(
                "Could not validate command because it was None.")

        self.logger.debug(
            "Looking through Command Names to find the Command Specified.")
        command_names = []
        for command in system.commands:
            if command.name == request.command:
                self.logger.debug("Found Command with name: %s" %
                                  request.command)

                if request.command_type is None:
                    request.command_type = command.command_type
                elif command.command_type != request.command_type:
                    raise ModelValidationError(
                        "Command Type for Request was %s but the command specified "
                        "the type as %s" %
                        (request.command_type, command.command_type))

                if request.output_type is None:
                    request.output_type = command.output_type
                elif command.output_type != request.output_type:
                    raise ModelValidationError(
                        "Output Type for Request was %s but the command specified "
                        "the type as %s" %
                        (request.output_type, command.output_type))
                request.hidden = command.hidden

                return command

            command_names.append(command.name)

        raise ModelValidationError(
            "No Command with name: %s could be found. Valid Commands for %s are: %s"
            % (request.command, system.name, command_names))
Ejemplo n.º 16
0
def check_file(file_id: str, upsert: bool = False) -> File:
    """Checks that the file with file_id exists in the DB

    Args:
        file_id: The id for the requested file.
        upsert: If the file doesn't exist create a placeholder file

    Returns:
        The file object

    Raises:
        NotFoundError: File with the requested ID doesn't exist and is expected to
        ModelValidationError: Incorrectly formatted ID is given
    """
    try:
        ObjectId(file_id)
    except (InvalidId, TypeError):
        raise ModelValidationError(
            f"Cannot create a file id with the string {file_id}. "
            "Requires 24-character hex string.")

    res = db.query_unique(File, id=file_id)

    if res is None:
        if upsert:
            create_file("BG_placeholder", 0, 0, file_id)
            res = db.query_unique(File, id=file_id)
        else:
            raise NotFoundError(f"Tried to fetch an unsaved file {file_id}")

        db.modify(res, updated_at=datetime.utcnow())

    return res
Ejemplo n.º 17
0
    def clean(self):
        """Validate before saving to the database"""

        if self.status not in BrewtilsInstance.INSTANCE_STATUSES:
            raise ModelValidationError(
                "Can not save Instance %s: Invalid status '%s' "
                "provided." % (self.name, self.status))
Ejemplo n.º 18
0
    def clean(self):
        """Validate before saving to the database"""

        if self.status not in BrewtilsInstance.INSTANCE_STATUSES:
            raise ModelValidationError(
                f"Can not save Instance {self}: Invalid status '{self.status}'"
            )
Ejemplo n.º 19
0
    def prepare(self):
        """Called before each verb handler"""

        # Used for recording prometheus metrics.
        # We keep this time in seconds, also time-zone does not matter
        # because we are just calculating a duration.
        self.request.created_time = time.time()

        # This is used for sending event notifications
        self.request.event = Event()
        self.request.event_extras = {}

        content_type = self.request.headers.get('content-type', '')
        if self.request.method.upper() in ['POST', 'PATCH'] and content_type:
            content_type = content_type.split(';')

            self.request.mime_type = content_type[0]
            if self.request.mime_type not in [
                    'application/json', 'application/x-www-form-urlencoded'
            ]:
                raise ModelValidationError(
                    'Unsupported or missing content-type header')

            # Attempt to parse out the charset and decode the body, default to utf-8
            charset = 'utf-8'
            if len(content_type) > 1:
                search_result = self.charset_re.search(content_type[1])
                if search_result:
                    charset = search_result.group(1)
            self.request.charset = charset
            self.request.decoded_body = self.request.body.decode(charset)
Ejemplo n.º 20
0
    def delete(self, role_id):
        """
        ---
        summary: Delete a specific Role
        parameters:
          - name: role_id
            in: path
            required: true
            description: The ID of the Role
            type: string
        responses:
          204:
            description: Role has been successfully deleted
          404:
            $ref: '#/definitions/404Error'
          50x:
            $ref: '#/definitions/50xError'
        tags:
          - Roles
        """
        role = Role.objects.get(id=str(role_id))
        if role.name in ("bg-admin", "bg-anonymous", "bg-plugin"):
            raise ModelValidationError("Unable to remove '%s' role" %
                                       role.name)

        role.delete()

        self.set_status(204)
Ejemplo n.º 21
0
    def _extract_parameter_value_from_request(self, request, command_parameter,
                                              request_parameters, command):
        """Extracts the expected value based on the parameter in the database,
        uses the default and validates the type of the request parameter"""
        request_value = request_parameters.get(command_parameter.key,
                                               command_parameter.default)

        if request_value is None and command_parameter.nullable:
            return None

        if command_parameter.multi:
            request_values = request_value
            if not isinstance(request_values, list):
                raise ModelValidationError(
                    "%s was specified as a list, but was not provided as such"
                    % command_parameter.key)

            value_to_return = []
            for value in request_values:
                value_to_return.append(
                    self._validate_parameter_based_on_type(
                        value, command_parameter, command, request))
        else:
            value_to_return = self._validate_parameter_based_on_type(
                request_value, command_parameter, command, request)

        return value_to_return
Ejemplo n.º 22
0
    def prepare(self):
        """Called before each verb handler"""

        # Used for calculating request handling duration
        self.request.created_time = datetime.datetime.utcnow()

        content_type = self.request.headers.get("content-type", "")
        if self.request.method.upper() in ["POST", "PATCH"] and content_type:
            content_type = content_type.split(";")

            self.request.mime_type = content_type[0]
            if self.request.mime_type not in [
                    "application/json",
                    "application/x-www-form-urlencoded",
            ]:
                raise ModelValidationError(
                    "Unsupported or missing content-type header")

            # Attempt to parse out the charset and decode the body, default to utf-8
            charset = "utf-8"
            if len(content_type) > 1:
                search_result = self.charset_re.search(content_type[1])
                if search_result:
                    charset = search_result.group(1)
            self.request.charset = charset
            self.request.decoded_body = self.request.body.decode(charset)
Ejemplo n.º 23
0
    async def patch(self):
        """
        ---
        summary: Partially update a Garden
        description: |
          The body of the request needs to contain a set of instructions detailing the
          updates to apply. Currently the only operations are:

          * sync

          ```JSON
          [
            { "operation": "" }
          ]
          ```
        parameters:
          - name: garden_name
            in: path
            required: true
            description: Garden to use
            type: string
          - name: patch
            in: body
            required: true
            description: Instructions for how to update the Garden
            schema:
              $ref: '#/definitions/Patch'
        responses:
          200:
            description: Execute Patch action against Gardens
            schema:
              $ref: '#/definitions/Garden'
          400:
            $ref: '#/definitions/400Error'
          404:
            $ref: '#/definitions/404Error'
          50x:
            $ref: '#/definitions/50xError'
        tags:
          - Garden
        """

        patch = SchemaParser.parse_patch(self.request.decoded_body, from_string=True)

        for op in patch:
            operation = op.operation.lower()

            if operation == "sync":
                response = await self.client(
                    Operation(
                        operation_type="GARDEN_SYNC",
                    )
                )

            else:
                raise ModelValidationError(f"Unsupported operation '{op.operation}'")

        self.set_header("Content-Type", "application/json; charset=UTF-8")
        self.write(response)
Ejemplo n.º 24
0
    def test_type_match(self):
        e = ModelValidationError('error message')
        self.objects_mock.get.side_effect = e

        response = self.fetch('/api/v1/commands/id')
        self.assertEqual(400, response.code)
        self.assertEqual(json.dumps({'message': str(e)}),
                         response.body.decode('utf-8'))
Ejemplo n.º 25
0
    def test_type_match(self):
        e = ModelValidationError("error message")
        self.objects_mock.get.side_effect = e

        response = self.fetch("/api/v1/commands/id")
        self.assertEqual(400, response.code)
        self.assertEqual(json.dumps({"message": str(e)}),
                         response.body.decode("utf-8"))
Ejemplo n.º 26
0
 def _validate_regex(self, value, command_parameter):
     """Validate that the value matches the regex"""
     if value is not None and not command_parameter.optional:
         if command_parameter.regex:
             if not re.match(command_parameter.regex, value):
                 raise ModelValidationError(
                     "Value %s does not match regular expression %s" %
                     (value, command_parameter.regex))
Ejemplo n.º 27
0
    def clean(self):
        """Validate before saving to the database"""

        if self.status not in BrewtilsRequest.STATUS_LIST:
            raise ModelValidationError(
                'Can not save Request %s: Invalid status "%s"' %
                (str(self), self.status))

        if (self.command_type is not None
                and self.command_type not in BrewtilsRequest.COMMAND_TYPES):
            raise ModelValidationError("Can not save Request %s: Invalid "
                                       'command type "%s"' %
                                       (str(self), self.command_type))

        if (self.output_type is not None
                and self.output_type not in BrewtilsRequest.OUTPUT_TYPES):
            raise ModelValidationError(
                "Can not save Request %s: Invalid output "
                'type "%s"' % (str(self), self.output_type))
Ejemplo n.º 28
0
 def _validate_minimum(self, value, command_parameter):
     """Validate that the value(s) are above the specified minimum"""
     if value is not None and not command_parameter.optional:
         if command_parameter.minimum:
             if isinstance(value, Sequence):
                 if len(value) < command_parameter.minimum:
                     raise ModelValidationError(
                         "Length %s is less than the minimum allowed length (%s) "
                         "for parameter %s" % (
                             len(value),
                             command_parameter.minimum,
                             command_parameter.key,
                         ))
             else:
                 if value < command_parameter.minimum:
                     raise ModelValidationError(
                         "Value %s is less than the minimum allowed value (%s) "
                         "for parameter %s" %
                         (value, command_parameter.minimum,
                          command_parameter.key))
Ejemplo n.º 29
0
 def _validate_no_extra_request_parameter_keys(self, request_parameters,
                                               command_parameters):
     """Validate that all the parameters passed in were valid keys. If there is a key
     specified that is not noted in the database, then a validation error is thrown"""
     self.logger.debug("Validating Keys")
     valid_keys = [cp.key for cp in command_parameters]
     self.logger.debug("Valid Keys are : %s" % valid_keys)
     for key in request_parameters:
         if key not in valid_keys:
             raise ModelValidationError(
                 "Unknown key '%s' provided in the parameters. Valid Keys are: %s"
                 % (key, valid_keys))
Ejemplo n.º 30
0
 def _validate_required_parameter_is_included_in_request(
         self, request, command_parameter, request_parameters):
     """If the parameter is required but was not provided in the request_parameters
     and does not have a default, then raise a ValidationError"""
     self.logger.debug(
         "Validating that Required Parameters are included in the request.")
     if not command_parameter.optional:
         if (command_parameter.key not in request_parameters
                 and command_parameter.default is None):
             raise ModelValidationError(
                 "Required key '%s' not provided in request. Parameters are: %s"
                 % (command_parameter.key, request.parameters))