IOTData: Fix bug where publish() could only be called once (#5812)
This commit is contained in:
		
							parent
							
								
									031f89dee0
								
							
						
					
					
						commit
						d68fb04ee1
					
				
							
								
								
									
										4
									
								
								.github/workflows/test_outdated_versions.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/test_outdated_versions.yml
									
									
									
									
										vendored
									
									
								
							| @ -41,7 +41,7 @@ jobs: | |||||||
| 
 | 
 | ||||||
|     - name: Run tests |     - name: Run tests | ||||||
|       run: | |       run: | | ||||||
|         pytest -sv tests/test_core ./tests/test_apigateway/test_apigateway_integration.py ./tests/test_s3/test_server.py |         pytest -sv tests/test_core ./tests/test_apigateway/test_apigateway_integration.py tests/test_iotdata ./tests/test_s3/test_server.py | ||||||
| 
 | 
 | ||||||
|     - name: Start MotoServer |     - name: Start MotoServer | ||||||
|       run: | |       run: | | ||||||
| @ -52,7 +52,7 @@ jobs: | |||||||
|       env: |       env: | ||||||
|         TEST_SERVER_MODE: ${{ true }} |         TEST_SERVER_MODE: ${{ true }} | ||||||
|       run: | |       run: | | ||||||
|         pytest -sv tests/test_core tests/test_awslambda tests/test_cloudformation |         pytest -sv tests/test_core tests/test_awslambda tests/test_cloudformation tests/test_iotdata | ||||||
|     - name: "Stop MotoServer" |     - name: "Stop MotoServer" | ||||||
|       if: always() |       if: always() | ||||||
|       run: | |       run: | | ||||||
|  | |||||||
| @ -8,6 +8,12 @@ class IoTDataPlaneResponse(BaseResponse): | |||||||
|     def __init__(self): |     def __init__(self): | ||||||
|         super().__init__(service_name="iot-data") |         super().__init__(service_name="iot-data") | ||||||
| 
 | 
 | ||||||
|  |     def _get_action(self) -> str: | ||||||
|  |         if self.path and self.path.startswith("/topics/"): | ||||||
|  |             # Special usecase - there is no way identify this action, besides the URL | ||||||
|  |             return "publish" | ||||||
|  |         return super()._get_action() | ||||||
|  | 
 | ||||||
|     @property |     @property | ||||||
|     def iotdata_backend(self): |     def iotdata_backend(self): | ||||||
|         return iotdata_backends[self.current_account][self.region] |         return iotdata_backends[self.current_account][self.region] | ||||||
| @ -30,18 +36,8 @@ class IoTDataPlaneResponse(BaseResponse): | |||||||
|         payload = self.iotdata_backend.delete_thing_shadow(thing_name=thing_name) |         payload = self.iotdata_backend.delete_thing_shadow(thing_name=thing_name) | ||||||
|         return json.dumps(payload.to_dict()) |         return json.dumps(payload.to_dict()) | ||||||
| 
 | 
 | ||||||
|     def dispatch_publish(self, request, full_url, headers): |  | ||||||
|         # This endpoint requires specialized handling because it has |  | ||||||
|         # a uri parameter containing forward slashes that is not |  | ||||||
|         # correctly url encoded when we're running in server mode. |  | ||||||
|         # https://github.com/pallets/flask/issues/900 |  | ||||||
|         self.setup_class(request, full_url, headers) |  | ||||||
|         self.querystring["Action"] = ["Publish"] |  | ||||||
|         topic = self.path.partition("/topics/")[-1] |  | ||||||
|         self.querystring["target"] = [unquote(topic)] if "%" in topic else [topic] |  | ||||||
|         return self.call_action() |  | ||||||
| 
 |  | ||||||
|     def publish(self): |     def publish(self): | ||||||
|         topic = self._get_param("target") |         topic = self.path.split("/topics/")[-1] | ||||||
|  |         topic = unquote(topic) if "%" in topic else topic | ||||||
|         self.iotdata_backend.publish(topic=topic, payload=self.body) |         self.iotdata_backend.publish(topic=topic, payload=self.body) | ||||||
|         return json.dumps(dict()) |         return json.dumps(dict()) | ||||||
|  | |||||||
| @ -10,18 +10,9 @@ response = IoTDataPlaneResponse() | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| url_paths = { | url_paths = { | ||||||
|     # |  | ||||||
|     # Paths for :class:`moto.core.models.MockAWS` |  | ||||||
|     # |  | ||||||
|     # This route requires special handling. |  | ||||||
|     "{0}/topics/(?P<topic>.*)$": response.dispatch_publish, |  | ||||||
|     # The remaining routes can be handled by the default dispatcher. |  | ||||||
|     "{0}/.*$": response.dispatch, |     "{0}/.*$": response.dispatch, | ||||||
|     # |     # | ||||||
|     # (Flask) Paths for :class:`moto.core.models.ServerModeMockAWS` |     # (Flask) Paths for :class:`moto.core.models.ServerModeMockAWS` | ||||||
|     # |     # | ||||||
|     # This route requires special handling. |  | ||||||
|     "{0}/topics/<path:topic>$": response.dispatch_publish, |  | ||||||
|     # The remaining routes can be handled by the default dispatcher. |  | ||||||
|     "{0}/<path:route>$": response.dispatch, |     "{0}/<path:route>$": response.dispatch, | ||||||
| } | } | ||||||
|  | |||||||
| @ -110,12 +110,16 @@ def test_update(): | |||||||
| def test_publish(): | def test_publish(): | ||||||
|     region_name = "ap-northeast-1" |     region_name = "ap-northeast-1" | ||||||
|     client = boto3.client("iot-data", region_name=region_name) |     client = boto3.client("iot-data", region_name=region_name) | ||||||
|     client.publish(topic="test/topic", qos=1, payload=b"pl") |     client.publish(topic="test/topic1", qos=1, payload=b"pl1") | ||||||
|  |     client.publish(topic="test/topic2", qos=1, payload=b"pl2") | ||||||
|  |     client.publish(topic="test/topic3", qos=1, payload=b"pl3") | ||||||
| 
 | 
 | ||||||
|     if not settings.TEST_SERVER_MODE: |     if not settings.TEST_SERVER_MODE: | ||||||
|         mock_backend = moto.iotdata.models.iotdata_backends[ACCOUNT_ID][region_name] |         mock_backend = moto.iotdata.models.iotdata_backends[ACCOUNT_ID][region_name] | ||||||
|         mock_backend.published_payloads.should.have.length_of(1) |         mock_backend.published_payloads.should.have.length_of(3) | ||||||
|         mock_backend.published_payloads.should.contain(("test/topic", "pl")) |         mock_backend.published_payloads.should.contain(("test/topic1", "pl1")) | ||||||
|  |         mock_backend.published_payloads.should.contain(("test/topic2", "pl2")) | ||||||
|  |         mock_backend.published_payloads.should.contain(("test/topic3", "pl3")) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @mock_iot | @mock_iot | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user