test(order): verify warehouse faults and await recovery projection
This commit is contained in:
@@ -24,8 +24,10 @@ from pathlib import Path
|
||||
|
||||
ORDER = 'firstleg-test-order'
|
||||
ENTRYPOINT = ['sh', '-c', 'exec java $JAVA_OPTS org.springframework.boot.loader.launch.JarLauncher']
|
||||
PROPERTIES = {'IAM': 'baiyue.clients.iam.url', 'FINANCE': 'baiyue.clients.finance.url'}
|
||||
UPSTREAM_CONTAINERS = {'IAM': 'firstleg-test-iam', 'FINANCE': 'firstleg-test-finance'}
|
||||
PROPERTIES = {'IAM': 'baiyue.clients.iam.url', 'FINANCE': 'baiyue.clients.finance.url',
|
||||
'WAREHOUSE': 'baiyue.clients.warehouse.url'}
|
||||
UPSTREAM_CONTAINERS = {'IAM': 'firstleg-test-iam', 'FINANCE': 'firstleg-test-finance',
|
||||
'WAREHOUSE': 'firstleg-test-warehouse'}
|
||||
|
||||
|
||||
class NoRedirect(urllib.request.HTTPRedirectHandler):
|
||||
@@ -63,10 +65,12 @@ def private_write(path, value):
|
||||
|
||||
|
||||
def validate_scope(scope):
|
||||
if set(scope) != {'marker', 'customerId', 'orderIds', 'planSha256'} or not re.fullmatch(r'[A-Za-z0-9_-]{1,80}', scope['marker']):
|
||||
if set(scope) != {'marker', 'customerId', 'receivingWarehouseId', 'orderIds', 'planSha256'} or not re.fullmatch(r'[A-Za-z0-9_-]{1,80}', scope['marker']):
|
||||
raise RuntimeError('INVALID_SCOPE')
|
||||
if not re.fullmatch(r'[1-9][0-9]{0,19}', scope['customerId']) or set(scope['orderIds']) != {'merchant', 'platform'}:
|
||||
raise RuntimeError('INVALID_SCOPE')
|
||||
if not re.fullmatch(r'[1-9][0-9]{0,19}', scope['receivingWarehouseId']):
|
||||
raise RuntimeError('INVALID_RECEIVING_WAREHOUSE')
|
||||
if any(not re.fullmatch(r'[1-9][0-9]{0,19}', value) for value in scope['orderIds'].values()) or len(set(scope['orderIds'].values())) != 2:
|
||||
raise RuntimeError('TWO_DISTINCT_ORDERS_REQUIRED')
|
||||
if not re.fullmatch(r'[0-9a-f]{64}', scope['planSha256']): raise RuntimeError('INVALID_PLAN_HASH')
|
||||
@@ -125,7 +129,8 @@ class Runtime:
|
||||
"""Real authenticated reads, not manufactured business responses. No body/secret is returned."""
|
||||
customer = self.scope['customerId']; results = {}
|
||||
targets = {'IAM': '/internal/iam/tenants/' + customer + '/order-eligibility',
|
||||
'FINANCE': '/internal/finance/v1/wallet/accounts/' + customer}
|
||||
'FINANCE': '/internal/finance/v1/wallet/accounts/' + customer,
|
||||
'WAREHOUSE': '/internal/warehouses/0/' + self.scope['receivingWarehouseId'] + '/active'}
|
||||
for dependency, path in targets.items():
|
||||
req = urllib.request.Request(state['upstreams'][dependency] + path,
|
||||
headers={'X-Internal-Service-Token': state['internalToken']})
|
||||
@@ -136,6 +141,12 @@ class Runtime:
|
||||
if dependency == 'IAM' and data.get('eligible') is not True: raise RuntimeError('CUSTOMER_NOT_ELIGIBLE')
|
||||
if dependency == 'FINANCE' and (data.get('actualBalance') is None or float(data['actualBalance']) < 0):
|
||||
raise RuntimeError('CUSTOMER_BALANCE_NOT_READY')
|
||||
if dependency == 'WAREHOUSE':
|
||||
warehouse = data.get('warehouse') or {}
|
||||
if (str(warehouse.get('id')) != self.scope['receivingWarehouseId']
|
||||
or str(warehouse.get('tenantId')) != '0' or warehouse.get('status') != 'ACTIVE'
|
||||
or warehouse.get('warehouseType') != 'DOMESTIC' or not warehouse.get('warehouseName')):
|
||||
raise RuntimeError('RECEIVING_WAREHOUSE_NOT_READY')
|
||||
results[dependency] = True
|
||||
return results
|
||||
|
||||
@@ -229,8 +240,9 @@ class Runtime:
|
||||
proxy = self.directory / 'proxy.py'; proxy.write_bytes(base64.b64decode(config['proxySource'])); os.chmod(proxy, 0o600)
|
||||
private_write(self.directory / 'proxy-config.json', {k: state[k] for k in
|
||||
['internalToken', 'controlToken', 'proxyPort', 'controlPort', 'upstreams', 'orderIps']} | {'customerId': self.scope['customerId'],
|
||||
'receivingWarehouseId': self.scope['receivingWarehouseId'],
|
||||
'requestIds': ['dep-' + self.scope['marker'] + '-' + dependency + '-' + role
|
||||
for dependency in ('IAM', 'FINANCE') for role in ('merchant', 'platform')]})
|
||||
for dependency in PROPERTIES for role in ('merchant', 'platform')]})
|
||||
state['phase'] = 'PROXY_START_INTENT'; state['proxyLaunchIntent'] = True; self.save(state)
|
||||
with open(self.directory / 'proxy-output.log', 'ab') as output:
|
||||
os.chmod(self.directory / 'proxy-output.log', 0o600)
|
||||
@@ -361,7 +373,7 @@ class Runtime:
|
||||
if self.config_fingerprint(current, state['routing']) != state['routingSourceSha256']:
|
||||
raise RuntimeError('NACOS_ROUTE_CONFIGURATION_CHANGED')
|
||||
checks = self.probes(state)
|
||||
if checks != {'IAM': True, 'FINANCE': True}: raise RuntimeError('RESTORED_ROUTE_PROBE_INVALID')
|
||||
if checks != {dependency: True for dependency in PROPERTIES}: raise RuntimeError('RESTORED_ROUTE_PROBE_INVALID')
|
||||
state['routeReadsVerified'] = checks; self.save(state)
|
||||
return {'healthy': True, 'originalFingerprint': state['originalFingerprint'], 'currentFingerprint': self.tools['fingerprint'](current),
|
||||
'originalImageId': state['originalImageId'], 'currentImageId': current['Image'], 'upstreamReads': checks,
|
||||
|
||||
Reference in New Issue
Block a user