fix(test): align order dependency fault preflight with Nacos v3

This commit is contained in:
2026-10-03 06:21:57 +08:00
parent bde1cd532e
commit c55bd7f4b6
4 changed files with 57 additions and 14 deletions
@@ -19,6 +19,7 @@ import sys
import time
import urllib.parse
import urllib.request
import urllib.error
from pathlib import Path
ORDER = 'firstleg-test-order'
@@ -139,7 +140,7 @@ class Runtime:
return results
def config_fingerprint(self, container, routing):
"""Read the two actual Nacos imports using explicitly reviewed v1 endpoints.
"""Read the two actual Nacos imports using the current v3 Admin endpoints.
No endpoint guessing/fallback and no Nacos write operation is supported.
"""
env = self.tools['env_of'](container); config = routing.get('nacos', {})
@@ -150,8 +151,8 @@ class Runtime:
network.get('Gateway') for network in container['NetworkSettings']['Networks'].values()}
if (base.scheme not in ('http', 'https') or base.hostname not in allowed_hosts or base.port != configured.port
or base.path not in ('', '/') or base.username or base.password or base.query or base.fragment
or config.get('loginPath') not in ('/nacos/v1/auth/users/login', '/nacos/v1/auth/login')
or config.get('configPath') != '/nacos/v1/cs/configs'):
or config.get('loginPath') != '/nacos/v3/auth/user/login'
or config.get('configPath') != '/nacos/v3/admin/cs/config'):
raise RuntimeError('EXPLICIT_NACOS_READ_ENDPOINTS_REQUIRED')
if any(not env.get(key) for key in ['NACOS_USERNAME', 'NACOS_PASSWORD', 'NACOS_GROUP', 'NACOS_NAMESPACE']):
raise RuntimeError('NACOS_READ_IDENTITY_UNAVAILABLE')
@@ -163,11 +164,20 @@ class Runtime:
if not isinstance(token, str) or not token: raise RuntimeError('NACOS_READ_LOGIN_FAILED')
fingerprints = {}
for data_id in ('baiyue-common.yml', 'order-service.yml'):
query = urllib.parse.urlencode({'dataId': data_id, 'group': env['NACOS_GROUP'], 'tenant': env['NACOS_NAMESPACE'], 'accessToken': token})
with http_open(origin + config['configPath'] + '?' + query, timeout=8) as response:
query = urllib.parse.urlencode({'dataId': data_id, 'groupName': env['NACOS_GROUP'], 'namespaceId': env['NACOS_NAMESPACE']})
request = urllib.request.Request(origin + config['configPath'] + '?' + query,
headers={'Authorization': 'Bearer ' + token})
with http_open(request, timeout=8) as response:
if response.status != 200: raise RuntimeError('NACOS_SOURCE_READ_FAILED')
content = response.read()
if not content or content.lstrip().startswith((b'{', b'<')): raise RuntimeError('NACOS_SOURCE_NOT_YAML')
value = json.load(response)
data = value.get('data')
if value.get('code') != 0 or not isinstance(data, dict): raise RuntimeError('NACOS_SOURCE_RESPONSE_INVALID')
if (data.get('dataId') != data_id or data.get('groupName') != env['NACOS_GROUP']
or data.get('namespaceId') != env['NACOS_NAMESPACE']): raise RuntimeError('NACOS_SOURCE_IDENTITY_MISMATCH')
content = data.get('content')
if not isinstance(content, str) or not content.strip() or content.lstrip().startswith(('{', '<')):
raise RuntimeError('NACOS_SOURCE_NOT_YAML')
content = content.encode('utf-8')
fingerprints[data_id] = hashlib.sha256(content).hexdigest()
return digest({'imports': fingerprints, 'namespace': env['NACOS_NAMESPACE'], 'group': env['NACOS_GROUP']})
@@ -436,10 +446,21 @@ def main(config):
finally: os.close(fd)
def safe_error_code(error):
message = str(error)
if isinstance(error, urllib.error.HTTPError):
path = urllib.parse.urlsplit(error.geturl()).path
stage = 'NACOS_CONFIG' if path == '/nacos/v3/admin/cs/config' else (
'NACOS_LOGIN' if path == '/nacos/v3/auth/user/login' else 'DEPENDENCY_HTTP')
return stage + '_' + str(error.code)
if isinstance(error, urllib.error.URLError):
return 'DEPENDENCY_TRANSPORT_FAILED'
return message if re.fullmatch(r'[A-Z_0-9]{1,90}', message) else 'ORDER_DEPENDENCY_ACTION_FAILED'
if __name__ == '__main__':
try:
result = main(json.loads(base64.b64decode(sys.argv[1])))
print('ORDER_DEPENDENCY_JSON=' + json.dumps({'ok': True, 'data': result}))
except Exception as error:
message = str(error)
print('ORDER_DEPENDENCY_JSON=' + json.dumps({'ok': False, 'error': message if re.fullmatch(r'[A-Z_0-9]{1,90}', message) else 'ORDER_DEPENDENCY_ACTION_FAILED'}))
print('ORDER_DEPENDENCY_JSON=' + json.dumps({'ok': False, 'error': safe_error_code(error)}))