123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- #
- # Copyright 2019 The FATE Authors. All Rights Reserved.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- #
- import logging
- import json
- import requests
- from requests.adapters import HTTPAdapter
- from urllib3.util.retry import Retry
- from fate_arch.common.log import getLogger
- logger = getLogger()
- MAX_RETRIES = 10
- MAX_REDIRECT = 5
- BACKOFF_FACTOR = 1
- # sleep time equips to {BACKOFF_FACTOR} * (2 ** ({NUMBER_OF_TOTALRETRIES} - 1))
- CLUSTER = 'clusters/{}'
- TENANT = 'tenants/{}'
- # APIs are refer to https://pulsar.apache.org/admin-rest-api/?version=2.7.0&apiversion=v2
- class PulsarManager():
- def __init__(self, host: str, port: str, runtime_config: dict = {}):
- self.service_url = "http://{}:{}/admin/v2/".format(host, port)
- self.runtime_config = runtime_config
- # create session is used to construct url and request parameters
- def _create_session(self):
- # retry mechanism refers to
- # https://urllib3.readthedocs.io/en/latest/reference/urllib3.util.html#urllib3.util.Retry
- retry = Retry(total=MAX_RETRIES, redirect=MAX_REDIRECT,
- backoff_factor=BACKOFF_FACTOR)
- s = requests.Session()
- # initialize headers
- s.headers.update({'Content-Type': 'application/json'})
- http_adapter = HTTPAdapter(max_retries=retry)
- s.mount('http://', http_adapter)
- s.mount('https://', http_adapter)
- return s
- # allocator
- def get_allocator(self, allocator: str = 'default'):
- session = self._create_session()
- response = session.get(
- self.service_url + 'broker-stats/allocator-stats/{}'.format(allocator))
- return response
- # cluster
- def get_cluster(self, cluster_name: str = ''):
- session = self._create_session()
- response = session.get(
- self.service_url + CLUSTER.format(cluster_name))
- return response
- def delete_cluster(self, cluster_name: str = ''):
- session = self._create_session()
- response = session.delete(
- self.service_url + CLUSTER.format(cluster_name))
- return response
- # service_url need to provide "http://" prefix
- def create_cluster(self, cluster_name: str, broker_url: str, service_url: str = '',
- service_url_tls: str = '', broker_url_tls: str = '',
- proxy_url: str = '', proxy_protocol: str = "SNI", peer_cluster_names: list = [],
- ):
- # initialize data
- data = {
- 'serviceUrl': service_url,
- 'serviceUrlTls': service_url_tls,
- 'brokerServiceUrl': broker_url,
- 'brokerServiceUrlTls': broker_url_tls,
- 'peerClusterNames': peer_cluster_names,
- 'proxyServiceUrl': proxy_url,
- 'proxyProtocol': proxy_protocol
- }
- session = self._create_session()
- response = session.put(
- self.service_url + CLUSTER.format(cluster_name), data=json.dumps(data))
- return response
- def update_cluster(self, cluster_name: str, broker_url: str, service_url: str = '',
- service_url_tls: str = '', broker_url_tls: str = '',
- proxy_url: str = '', proxy_protocol: str = "SNI", peer_cluster_names: list = [],
- ):
- # initialize data
- data = {
- 'serviceUrl': service_url,
- 'serviceUrlTls': service_url_tls,
- 'brokerServiceUrl': broker_url,
- 'brokerServiceUrlTls': broker_url_tls,
- 'peerClusterNames': peer_cluster_names,
- 'proxyServiceUrl': proxy_url,
- 'proxyProtocol': proxy_protocol
- }
- session = self._create_session()
- response = session.post(
- self.service_url + CLUSTER.format(cluster_name), data=json.dumps(data))
- return response
- # tenants
- def get_tenant(self, tenant: str = ''):
- session = self._create_session()
- response = session.get(self.service_url + TENANT.format(tenant))
- return response
- def create_tenant(self, tenant: str, admins: list, clusters: list):
- session = self._create_session()
- data = {'adminRoles': admins,
- 'allowedClusters': clusters}
- response = session.put(
- self.service_url + TENANT.format(tenant), data=json.dumps(data))
- return response
- def delete_tenant(self, tenant: str):
- session = self._create_session()
- response = session.delete(
- self.service_url + TENANT.format(tenant))
- return response
- def update_tenant(self, tenant: str, admins: list, clusters: list):
- session = self._create_session()
- data = {'adminRoles': admins,
- 'allowedClusters': clusters}
- response = session.post(
- self.service_url + TENANT.format(tenant), data=json.dumps(data))
- return response
- # namespace
- def get_namespace(self, tenant: str):
- session = self._create_session()
- response = session.get(
- self.service_url + 'namespaces/{}'.format(tenant))
- return response
- # 'replication_clusters' is always required
- def create_namespace(self, tenant: str, namespace: str, policies: dict = {}):
- session = self._create_session()
- response = session.put(
- self.service_url + 'namespaces/{}/{}'.format(tenant, namespace),
- data=json.dumps(policies)
- )
- return response
- def delete_namespace(self, tenant: str, namespace: str):
- session = self._create_session()
- response = session.delete(
- self.service_url +
- 'namespaces/{}/{}'.format(tenant, namespace)
- )
- return response
- def set_clusters_to_namespace(self, tenant: str, namespace: str, clusters: list):
- session = self._create_session()
- response = session.post(
- self.service_url + 'namespaces/{}/{}/replication'.format(tenant, namespace), json=clusters
- )
- return response
- def get_cluster_from_namespace(self, tenant: str, namespace: str):
- session = self._create_session()
- response = session.get(
- self.service_url +
- 'namespaces/{}/{}/replication'.format(tenant, namespace)
- )
- return response
- def set_subscription_expiration_time(self, tenant: str, namespace: str, mintues: int = 0):
- session = self._create_session()
- response = session.post(
- self.service_url + 'namespaces/{}/{}/subscriptionExpirationTime'.format(tenant, namespace), json=mintues
- )
- return response
- def set_message_ttl(self, tenant: str, namespace: str, mintues: int = 0):
- session = self._create_session()
- response = session.post(
- # the API accepts data as seconds
- self.service_url + 'namespaces/{}/{}/messageTTL'.format(tenant, namespace), json=mintues * 60
- )
- return response
- def unsubscribe_namespace_all_topics(self, tenant: str, namespace: str, subscription_name: str):
- session = self._create_session()
- response = session.post(
- self.service_url +
- 'namespaces/{}/{}/unsubscribe/{}'.format(
- tenant, namespace, subscription_name)
- )
- return response
- def set_retention(self, tenant: str, namespace: str,
- retention_time_in_minutes: int = 0, retention_size_in_MB: int = 0):
- session = self._create_session()
- data = {'retentionTimeInMinutes': retention_time_in_minutes,
- 'retentionSizeInMB': retention_size_in_MB}
- response = session.post(
- self.service_url +
- 'namespaces/{}/{}/retention'.format(tenant, namespace), data=json.dumps(data)
- )
- return response
- def remove_retention(self, tenant: str, namespace: str):
- session = self._create_session()
- response = session.delete(
- self.service_url +
- 'namespaces/{}/{}/retention'.format(tenant, namespace),
- )
- return response
- # topic
- def unsubscribe_topic(self, tenant: str, namespace: str, topic: str, subscription_name: str):
- session = self._create_session()
- response = session.delete(
- self.service_url +
- 'persistent/{}/{}/{}/subscription/{}'.format(
- tenant, namespace, topic, subscription_name)
- )
- return response
|