import time from contextlib import contextmanager from copy import deepcopy import requests from . import schemas class HttpEndpoint(object): def __init__(self, base_url: str, session: requests.Session = None): self.base_url = base_url self.session = session or requests.Session() def request(self, method, path, schema=None, **kwargs): return schemas.validate_response(self.session.request(method, self._url(path), **kwargs), schema) def get(self, path, schema=None, **kwargs): return schemas.validate_response(self.session.get(self._url(path), **kwargs), schema) def options(self, path, schema=None, **kwargs): return schemas.validate_response(self.session.options(self._url(path), **kwargs), schema) def head(self, path, schema=None, **kwargs): return schemas.validate_response(self.session.head(self._url(path), **kwargs), schema) def post(self, path, data=None, json=None, schema=None, **kwargs): return schemas.validate_response(self.session.post(self._url(path), data, json, **kwargs), schema) def put(self, path, data=None, schema=None, **kwargs): return schemas.validate_response(self.session.put(self._url(path), data, **kwargs), schema) def patch(self, path, data=None, schema=None, **kwargs): return schemas.validate_response(self.session.patch(self._url(path), data, **kwargs), schema) def delete(self, path, schema=None, **kwargs): return schemas.validate_response(self.session.delete(self._url(path), **kwargs), schema) def _url(self, path): return self.base_url + path def wait_until(poll, message=None, timeout=900, poll_interval=5): start = time.time() while time.time() < start + timeout: if poll(): return time.sleep(poll_interval) raise RuntimeError(message or "wait timeout") class InstanceUtil(object): default_passwd = "qa123@pingcap" default_info = { "password": default_passwd, "version": "v3.0.5", "tags": [], "azs": ["cn-east-1", "cn-west-1", "cn-north-1"], "replicationFactor": 3, "pd": {"replicas": 3, "resourceTemplate": {"cpu": 1, "memory": 1}}, "tikv": {"replicas": 3, "resourceTemplate": {"cpu": 2, "memory": 2}}, "tidb": {"replicas": 1, "resourceTemplate": {"cpu": 2, "memory": 2}}, } def __init__(self, cli: HttpEndpoint): self.cli = cli @contextmanager def new_instance(self, name, info=None, predicate=None, timeout=900): body = deepcopy(self.default_info) body['clusterName'] = name if info: body.update(info) resp = self.cli.post('/v1/tidbclusters', json=body) assert resp.status_code < 300 path = '/v1/tidbclusters/'+resp.json()['metadata']['name'] if predicate is None: predicate = InstanceUtil.check_instance_ready def poll(): resp = self.cli.get(path) assert resp.status_code == 200 return predicate(resp.json()) wait_until(poll, timeout=timeout, poll_interval=10, message="wait for instance " + resp.json()['metadata']['name']) yield self.cli.get(path).json() self.cli.delete(path) @staticmethod def check_instance_ready(o): return o['status'] == 'running'