async def test_message_from_bob_to_alice_multi_backends( postgresql_url, alice, bob, backend_factory, backend_sock_factory ): d1 = datetime(2000, 1, 1) async with backend_factory( config={"blockstore_config": PostgreSQLBlockStoreConfig(), "db_url": postgresql_url} ) as backend_1, backend_factory( populated=False, config={"blockstore_config": PostgreSQLBlockStoreConfig(), "db_url": postgresql_url}, ) as backend_2: async with backend_sock_factory(backend_1, alice) as alice_backend_sock: await events_subscribe(alice_backend_sock) async with events_listen(alice_backend_sock) as listen: await backend_2.message.send( bob.organization_id, bob.device_id, alice.user_id, d1, b"Hello from Bob !" ) assert listen.rep == {"status": "ok", "event": APIEvent.MESSAGE_RECEIVED, "index": 1} rep = await message_get(alice_backend_sock) assert rep == { "status": "ok", "messages": [ { "body": b"Hello from Bob !", "sender": bob.device_id, "timestamp": d1, "count": 1, } ], }
def test_parse_simple_raid(): config = _parse_blockstore_params([ "raid0:0:MOCKED", "raid0:1:POSTGRESQL", "raid0:2:s3:s3.example.com:region1:bucketA:key123:S3cr3t", "raid0:3:swift:swift.example.com:tenant2:containerB:user123:S3cr3t", ]) assert config == RAID0BlockStoreConfig(blockstores=[ MockedBlockStoreConfig(), PostgreSQLBlockStoreConfig(), S3BlockStoreConfig( s3_endpoint_url="s3.example.com", s3_region="region1", s3_bucket="bucketA", s3_key="key123", s3_secret="S3cr3t", ), SWIFTBlockStoreConfig( swift_authurl="swift.example.com", swift_tenant="tenant2", swift_container="containerB", swift_user="******", swift_password="******", ), ])
async def test_retry_policy_allow_retry(postgresql_url, unused_tcp_port, asyncio_loop): host = "localhost" port = unused_tcp_port app_config = BackendConfig( administration_token="s3cr3t", db_min_connections=1, db_max_connections=5, debug=False, blockstore_config=PostgreSQLBlockStoreConfig(), email_config=None, backend_addr=None, forward_proto_enforce_https=None, ssl_context=False, spontaneous_organization_bootstrap=False, organization_bootstrap_webhook_url=None, db_url=postgresql_url, ) # Allow to retry once retry_policy = RetryPolicy(maximum_attempts=1, pause_before_retry=0) async with trio.open_nursery() as nursery: # Run backend in the background nursery.start_soon(lambda: _run_backend(host, port, ssl_context=False, retry_policy=retry_policy, app_config=app_config)) # Connect to PostgreSQL database async with triopg.connect(postgresql_url) as conn: # Test for 10 cycles pid = None for _ in range(10): # Wait for the backend to be connected new_pid, = await wait_for_listeners(conn) # Make sure a new connection has been created assert new_pid != pid pid = new_pid # Terminate the backend listener connection value, = await conn.fetchrow("SELECT pg_terminate_backend($1)", pid) assert value # Wait for the listener to terminate await wait_for_listeners(conn, to_terminate=True) # Cancel the backend nursery nursery.cancel_scope.cancel()
def _parse_blockstore_param(value): if value.upper() == "MOCKED": return MockedBlockStoreConfig() elif value.upper() == "POSTGRESQL": return PostgreSQLBlockStoreConfig() else: parts = _split_with_escaping(value) if parts[0].upper() == "S3": try: endpoint_url, region, bucket, key, secret = parts[1:] except ValueError: raise click.BadParameter( "Invalid S3 config, must be `s3:[<endpoint_url>]:<region>:<bucket>:<key>:<secret>`" ) # Provide https by default to avoid anoying escaping for most cases if (endpoint_url and not endpoint_url.startswith("http://") and not endpoint_url.startswith("https://")): endpoint_url = f"https://{endpoint_url}" return S3BlockStoreConfig( s3_endpoint_url=endpoint_url or None, s3_region=region, s3_bucket=bucket, s3_key=key, s3_secret=secret, ) elif parts[0].upper() == "SWIFT": try: auth_url, tenant, container, user, password = parts[1:] except ValueError: raise click.BadParameter( "Invalid SWIFT config, must be `swift:<auth_url>:<tenant>:<container>:<user>:<password>`" ) # Provide https by default to avoid anoying escaping for most cases if (auth_url and not auth_url.startswith("http://") and not auth_url.startswith("https://")): auth_url = f"https://{auth_url}" return SWIFTBlockStoreConfig( swift_authurl=auth_url, swift_tenant=tenant, swift_container=container, swift_user=user, swift_password=password, ) else: raise click.BadParameter(f"Invalid blockstore type `{parts[0]}`")
async def test_retry_policy_no_retry(postgresql_url, unused_tcp_port, asyncio_loop): host = "localhost" port = unused_tcp_port app_config = BackendConfig( administration_token="s3cr3t", db_min_connections=1, db_max_connections=5, debug=False, blockstore_config=PostgreSQLBlockStoreConfig(), email_config=None, backend_addr=None, forward_proto_enforce_https=None, ssl_context=False, spontaneous_organization_bootstrap=False, organization_bootstrap_webhook_url=None, db_url=postgresql_url, ) # No retry retry_policy = RetryPolicy(maximum_attempts=0, pause_before_retry=0) # Expect a connection error with pytest.raises(ConnectionError): async with trio.open_nursery() as nursery: # Run backend in the background nursery.start_soon(lambda: _run_backend(host, port, ssl_context=False, retry_policy=retry_policy, app_config=app_config)) # Connect to PostgreSQL database async with triopg.connect(postgresql_url) as conn: # Wait for the backend to be connected pid, = await wait_for_listeners(conn) # Terminate the backend listener connection value, = await conn.fetchrow("SELECT pg_terminate_backend($1)", pid) assert value # Wait to get cancelled by the connection error `_run_backend` with trio.fail_after(3): await trio.sleep_forever()
def blockstore(request, backend_store): # TODO: allow to test against swift ? if backend_store.startswith("postgresql://"): config = PostgreSQLBlockStoreConfig() else: config = MockedBlockStoreConfig() # More or less a hack to be able to to configure this fixture from # the test function by adding tags to it if request.node.get_closest_marker("raid0_blockstore"): config = RAID0BlockStoreConfig( blockstores=[config, MockedBlockStoreConfig()]) if request.node.get_closest_marker("raid1_blockstore"): config = RAID1BlockStoreConfig( blockstores=[config, MockedBlockStoreConfig()]) if request.node.get_closest_marker("raid5_blockstore"): config = RAID5BlockStoreConfig(blockstores=[ config, MockedBlockStoreConfig(), MockedBlockStoreConfig() ]) return config
def _parse_blockstore_param(value): if value.upper() == "MOCKED": return MockedBlockStoreConfig() elif value.upper() == "POSTGRESQL": return PostgreSQLBlockStoreConfig() else: parts = value.split(":") if parts[0].upper() == "S3": try: endpoint_url, region, bucket, key, secret = parts[1:] except ValueError: raise click.BadParameter( "Invalid S3 config, must be `s3:<endpoint_url>:<region>:<bucket>:<key>:<secret>`" ) return S3BlockStoreConfig( s3_endpoint_url=endpoint_url or None, s3_region=region, s3_bucket=bucket, s3_key=key, s3_secret=secret, ) elif parts[0].upper() == "SWIFT": try: authurl, tenant, container, user, password = parts[1:] except ValueError: raise click.BadParameter( "Invalid SWIFT config, must be `swift:<authurl>:<tenant>:<container>:<user>:<password>`" ) return SWIFTBlockStoreConfig( swift_authurl=authurl, swift_tenant=tenant, swift_container=container, swift_user=user, swift_password=password, ) else: raise click.BadParameter(f"Invalid blockstore type `{parts[0]}`")
def blockstore(backend_store, fixtures_customization): # TODO: allow to test against swift ? if backend_store.startswith("postgresql://"): config = PostgreSQLBlockStoreConfig() else: config = MockedBlockStoreConfig() raid = fixtures_customization.get("blockstore_mode", "NO_RAID").upper() if raid == "RAID0": config = RAID0BlockStoreConfig( blockstores=[config, MockedBlockStoreConfig()]) elif raid == "RAID1": config = RAID1BlockStoreConfig( blockstores=[config, MockedBlockStoreConfig()]) elif raid == "RAID1_PARTIAL_CREATE_OK": config = RAID1BlockStoreConfig( blockstores=[config, MockedBlockStoreConfig()], partial_create_ok=True) elif raid == "RAID5": config = RAID5BlockStoreConfig(blockstores=[ config, MockedBlockStoreConfig(), MockedBlockStoreConfig() ]) elif raid == "RAID5_PARTIAL_CREATE_OK": config = RAID5BlockStoreConfig( blockstores=[ config, MockedBlockStoreConfig(), MockedBlockStoreConfig() ], partial_create_ok=True, ) else: assert raid == "NO_RAID" return config
def test_parse_postgresql(): config = _parse_blockstore_params(["POSTGRESQL"]) assert config == PostgreSQLBlockStoreConfig()