def setUp(self): self.request_mock = Mock() self.ts_epoch = 1451606400000 self.ts_dt = datetime.datetime(2016, 1, 1) self.request_dict = { "children": [], "parent": None, "system": "system_name", "system_version": "0.0.1", "instance_name": "default", "command": "say", "id": "58542eb571afd47ead90d25f", "parameters": {}, "comment": "bye!", "output": "nested output", "output_type": "STRING", "status": "IN_PROGRESS", "command_type": "ACTION", "created_at": self.ts_epoch, "updated_at": self.ts_epoch, "error_class": None, "metadata": {}, "has_parent": True, "requester": None, } self.job_dict = { "name": "job_name", "trigger_type": "date", "trigger": {"run_date": self.ts_epoch, "timezone": "utc"}, "request_template": { "system": "system", "system_version": "1.0.0", "instance_name": "default", "command": "speak", "parameters": {"message": "hey!"}, "comment": "hi!", "metadata": {"request": "stuff"}, }, "misfire_grace_time": 3, "coalesce": True, "next_run_time": self.ts_epoch, "success_count": 0, "error_count": 0, } db_dict = copy.deepcopy(self.job_dict) db_dict["request_template"] = RequestTemplate(**db_dict["request_template"]) db_dict["trigger"]["run_date"] = self.ts_dt db_dict["trigger"] = DateTrigger(**db_dict["trigger"]) db_dict["next_run_time"] = self.ts_dt self.job = Job(**db_dict) db_dict = copy.deepcopy(self.request_dict) db_dict["created_at"] = self.ts_dt db_dict["updated_at"] = self.ts_dt self.request = Request(**db_dict) super(RequestAPITest, self).setUp()
def test_save_update_updated_at(self): request = Request( system="foo", command="bar", status="CREATED", updated_at="this_will_be_updated", ) request.save() self.assertNotEqual(request.updated_at, "this_will_be_updated")
def test_command_lookup(self, monkeypatch, validator): request = Request(parameters={}) lookup_mock = Mock(return_value=Mock(parameters=[])) monkeypatch.setattr(validator, "get_and_validate_command_for_system", lookup_mock) validator.get_and_validate_parameters(request) lookup_mock.assert_called_once_with(request)
def get(self, request_id): """ --- summary: Retrieve a specific Request parameters: - name: request_id in: path required: true description: The ID of the Request type: string responses: 200: description: Request with the given ID schema: $ref: '#/definitions/Request' 404: $ref: '#/definitions/404Error' 50x: $ref: '#/definitions/50xError' tags: - Requests """ self.logger.debug("Getting Request: %s", request_id) req = Request.objects.get(id=str(request_id)) req.children = Request.objects(parent=req) self.write(self.parser.serialize_request(req, to_string=False))
def test_validate_command_choices_dictionary_list_response( self, validator): mock_client = Mock() mock_client.send_bg_request.return_value.output = '[{"value": "value"}]' validator._client = mock_client request = Request( system="foo", command="command1", parameters={"key1": "value"}, system_version="0.0.1", instance_name="instance_name", ) command = Mock(parameters=[ Parameter( key="key1", choices=Choices(type="command", value="command_name"), optional=False, ) ]) validator.get_and_validate_parameters(request, command) mock_client.send_bg_request.assert_called_with( _command="command_name", _system_name="foo", _system_version="0.0.1", _instance_name="instance_name", )
def _update_request_has_parent_model(): from bg_utils.mongo.models import Request raw_collection = Request._get_collection() raw_collection.update_many({"parent": None}, {"$set": {"has_parent": False}}) raw_collection.update_many( {"parent": {"$not": {"$eq": None}}}, {"$set": {"has_parent": True}} )
def _update_request_parent_field_type(): """Change GenericReferenceField to ReferenceField""" from bg_utils.mongo.models import Request raw_collection = Request._get_collection() for request in raw_collection.find({"parent._ref": {"$type": "object"}}): raw_collection.update_one( {"_id": request["_id"]}, {"$set": {"parent": request["parent"]["_ref"]}} )
def test_validate_value_in_choices_no_choices(self, validator): req = Request(system="foo", command="command1", parameters={"key1": "value"}) command_parameter = Mock(key="key1", multi=False, type="String", choices=None) command = Mock(parameters=[command_parameter]) validator.get_and_validate_parameters(req, command)
def test_update_and_validate_parameter_extract_parameter_multi_not_list( self, validator): req = Request(system="foo", command="command1", parameters={"key1": "NOT A LIST"}) command_parameter = Mock(key="key1", multi=True) command = Mock(parameters=[command_parameter]) with pytest.raises(ModelValidationError): validator.get_and_validate_parameters(req, command)
def __init__(self, clients, heartbeat_interval=10, timeout_seconds=30): self.logger = logging.getLogger(__name__) self.display_name = "Plugin Status Monitor" self.clients = clients self.heartbeat_interval = heartbeat_interval self.timeout = timedelta(seconds=timeout_seconds) self.status_request = Request(command="_status", command_type="EPHEMERAL") super(PluginStatusMonitor, self).__init__(logger=self.logger, name="PluginStatusMonitor")
def test_update_and_validate_parameter_extract_parameter_nullable_no_default( self, validator): req = Request(system="foo", command="command1", parameters={}) command_parameter = Parameter(key="key1", multi=False, nullable=True, default=None) command = Mock(parameters=[command_parameter]) validated_parameters = validator.get_and_validate_parameters( req, command) assert validated_parameters["key1"] is None
def test_update_and_validate_parameter_extract_parameter_optional_no_default( self, validator): req = Request(system="foo", command="command1", parameters={}) command_parameter = Parameter(key="key1", multi=False, optional=True, default=None) command = Mock(parameters=[command_parameter]) with pytest.raises(ModelValidationError): validator.get_and_validate_parameters(req, command)
def test_validate_regex_nullable(self, validator): req = Request(system="foo", command="command1", parameters={"key1": None}) command_parameter = Parameter(key="key1", multi=False, type="String", regex=r"^Hi.*", nullable=True) command = Command("test", parameters=[command_parameter]) validator.get_and_validate_parameters(req, command)
def test_validate_value_in_choices_multi_valid_choice(self, validator): req = Request(system="foo", command="command1", parameters={"key1": ["v1", "v2"]}) command_parameter = Mock( key="key1", multi=True, type="String", choices=Mock(type="static", value=["v1", "v2"]), ) command = Mock(parameters=[command_parameter]) validator.get_and_validate_parameters(req, command)
def test_validate_value_in_choices_optional_none_allowed(self, validator): req = Request(system="foo", command="command1", parameters={}) command_parameter = Mock( key="key1", multi=False, type="String", optional=True, default=None, choices=Mock(type="static", value=["value1", "value3"]), ) command = Mock(parameters=[command_parameter]) validator.get_and_validate_parameters(req, command)
def initialize_counts(): for request in Request.objects(status__in=["CREATED", "IN_PROGRESS"]): label_args = { "system": request.system, "system_version": request.system_version, "instance_name": request.instance_name, } if request.status == "CREATED": queued_request_gauge.labels(**label_args).inc() elif request.status == "IN_PROGRESS": in_progress_request_gauge.labels(**label_args).inc()
def setUp(self): brew_view.backend = Mock() brew_view.transport = Mock() self.default_request = Request( system="foo", command="bar", parameters={"baz": "bat"}, output="output", status="CREATED", ) self.default_request.validate_backend = Mock() self.app = brew_view.app.test_client()
def test_extract_parameter_non_multi_calls_with_default( self, validate_mock, validator): req = Request(system="foo", command="command1", parameters={}) command_parameter = Mock(key="key1", multi=False, default="default_value") command = Mock(parameters=[command_parameter]) validate_mock.side_effect = lambda w, x, y, z: w validator.get_and_validate_parameters(req, command) validate_mock.assert_called_once_with("default_value", command_parameter, command, req)
def test_validate_parameter_based_on_type_null_not_nullable( self, validator): req = Request(system="foo", command="command1", parameters={"key1": None}) command_parameter = Mock(key="key1", multi=False, type="String", nullable=False) command = Mock(parameters=[command_parameter]) with pytest.raises(ModelValidationError): validator.get_and_validate_parameters(req, command)
def test_validate_maximum_nullable(self, validator): req = Request(system="foo", command="command1", parameters={"key1": None}) command_parameter = Parameter( key="key1", multi=False, type="Integer", optional=False, minimum=3, nullable=True, ) command = Command("test", parameters=[command_parameter]) validator.get_and_validate_parameters(req, command)
def test_validate_value_in_choices_multi_invalid_choice(self, validator): req = Request(system="foo", command="command1", parameters={"key1": ["v1", "v2"]}) command_parameter = Mock( key="key1", multi=True, type="String", optional=False, choices=Mock(type="static", value=["v1", "v3"]), ) command = Mock(parameters=[command_parameter]) with pytest.raises(ModelValidationError): validator.get_and_validate_parameters(req, command)
def test_missing_nested_parameters(self, validator): req = Request(system="foo", command="command1", parameters={"key1": {}}) nested_parameter = Mock(key="foo", multi=False, type="String", optional=False) command_parameter = Mock(key="key1", multi=False, type="Dictionary", parameters=[nested_parameter]) command = Mock(parameters=[command_parameter]) with pytest.raises(ModelValidationError): validator.get_and_validate_parameters(req, command)
def setUp(self): self.app = brew_view.app.test_client() self.default_request = Request( system="foo", command="bar", parameters={"baz": "bat"}, output="output", status="CREATED", ) self.default_request.validate_backend = Mock() objects_patch = patch("bg_utils.mongo.models.Request.objects") self.addCleanup(objects_patch.stop) self.objects_mock = objects_patch.start() self.objects_mock.return_value = None self.objects_mock.get = Mock(return_value=self.default_request)
def test_update_and_validate_parameter_extract_parameter_multi( self, validate_mock, validator): req = Request(system="foo", command="command1", parameters={"key1": [1, 2]}) command_parameter = Mock(key="key1", multi=True) command = Mock(parameters=[command_parameter]) validate_mock.side_effect = lambda w, x, y, z: w validator.get_and_validate_parameters(req, command) validate_mock.assert_has_calls( [ call(1, command_parameter, command, req), call(2, command_parameter, command, req), ], any_order=True, )
def processRequest(self, request_id): """Validates and publishes a Request. :param str request_id: The ID of the Request to process :raises InvalidRequest: If the Request is invalid in some way :return: None """ request_id = str(request_id) self.logger.info("Processing Request: %s", request_id) try: request = Request.find_or_none(request_id) if request is None: raise ModelValidationError( "Could not find request with ID '%s'" % request_id) # Validates the request based on what is in the database. # This includes the validation of the request parameters, # systems are there, commands are there etc. request = self.request_validator.validate_request(request) request.save() try: self.clients["pika"].publish_request( request, confirm=True, mandatory=True, delivery_mode=pika.spec.PERSISTENT_DELIVERY_MODE, ) except Exception: msg = "Error while publishing request to queue (%s[%s]-%s %s)" % ( request.system, request.system_version, request.instance_name, request.command, ) raise bg_utils.bg_thrift.PublishException(msg) except (mongoengine.ValidationError, ModelValidationError, RestError) as ex: self.logger.exception(ex) raise bg_utils.bg_thrift.InvalidRequest(request_id, str(ex))
def test_validate_command_choices_bad_value_type(self, validator): mock_client = Mock() mock_client.send_bg_request.return_value.output = '["value"]' validator._client = mock_client request = Request( system="foo", command="command1", parameters={"key1": "value"}, system_version="0.0.1", instance_name="instance_name", ) command = Mock(parameters=[ Parameter(key="key1", optional=False, choices=Choices(type="command", value=1)) ]) with pytest.raises(ModelValidationError): validator.get_and_validate_parameters(request, command)
def test_validate_minimum_non_sequence(self, validator): req = Request(system="foo", command="command1", parameters={"key1": 5}) command_parameter = Parameter(key="key1", multi=False, type="Integer", optional=False, minimum=3) command = Command("test", parameters=[command_parameter]) validator.get_and_validate_parameters(req, command) command_parameter = Parameter(key="key1", multi=False, type="Integer", optional=False, minimum=10) command = Command("test", parameters=[command_parameter]) with pytest.raises(ModelValidationError): validator.get_and_validate_parameters(req, command)
def test_validate_choices_static_bad_type(self, validator): command_parameter = Mock( key="key1", multi=False, type="String", optional=False, default=None, choices=Mock(type="static", value="bad str"), minimum=None, maximum=None, regex=None, ) command = Mock(parameters=[command_parameter]) req = Request(system="foo", command="command1", parameters={"key1": "1"}) with pytest.raises(ModelValidationError): validator.get_and_validate_parameters(req, command)
def test_validate_url_choices(self, validator, response): session_mock = Mock() session_mock.get.return_value.text = response validator._session = session_mock req = Request(system="foo", command="command1", parameters={"key1": "value"}) command_parameter = Mock( key="key1", type="String", optional=False, multi=False, choices=Mock(type="url", value="http://localhost"), minimum=None, maximum=None, regex=None, ) command = Mock(parameters=[command_parameter]) validator.get_and_validate_parameters(req, command) session_mock.get.assert_called_with("http://localhost", params={})
def test_validate_regex(self, validator): req = Request(system="foo", command="command1", parameters={"key1": "Hi World!"}) command_parameter = Parameter(key="key1", multi=False, type="String", optional=False, regex=r"^Hi.*") command = Command("test", parameters=[command_parameter]) validator.get_and_validate_parameters(req, command) command_parameter = Parameter(key="key1", multi=False, type="String", optional=False, regex=r"^Hello.*") command = Command("test", parameters=[command_parameter]) with pytest.raises(ModelValidationError): validator.get_and_validate_parameters(req, command)