fix(test): align order dependency fault preflight with Nacos v3
This commit is contained in:
@@ -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)}))
|
||||
|
||||
Reference in New Issue
Block a user