This is an automated email from the ASF dual-hosted git repository.
sijie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar.git
The following commit(s) were added to refs/heads/master by this push:
new 4fa87a4 [dashboard] fix admin path (#5030)
4fa87a4 is described below
commit 4fa87a4822c550cd81a5d8d646452157d1f481d5
Author: Yi Tang <[email protected]>
AuthorDate: Mon Aug 26 12:16:34 2019 +0800
[dashboard] fix admin path (#5030)
access v1/v2 admin api by namespace name pattern
---
dashboard/django/stats/urls.py | 6 +--
dashboard/django/stats/views.py | 102 +++++++++++++++++++++++++++++++---------
2 files changed, 83 insertions(+), 25 deletions(-)
diff --git a/dashboard/django/stats/urls.py b/dashboard/django/stats/urls.py
index 3fa9003..fa831b3 100644
--- a/dashboard/django/stats/urls.py
+++ b/dashboard/django/stats/urls.py
@@ -24,7 +24,7 @@ from . import views
urlpatterns = [
url(r'^property/(?P<property_name>.+)/$', views.property, name='property'),
url(r'^namespace/(?P<namespace_name>.+)/$', views.namespace,
name='namespace'),
- url(r'^deleteNamespace/(?P<namespace_name>.+)$', views.deleteNamespace,
name='deleteNamespace'),
+ url(r'^deleteNamespace/(?P<namespace_name>.+)$', views.delete_namespace,
name='deleteNamespace'),
url(r'^brokers/$', views.brokers, name='brokers'),
@@ -35,7 +35,7 @@ urlpatterns = [
url(r'^topic/(?P<topic_name>.+)/$', views.topic, name='topic'),
url(r'^clusters/$', views.clusters, name='clusters'),
- url(r'^clearSubscription/(?P<topic_name>.+)/(?P<subscription_name>.+)$',
views.clearSubscription, name='clearSubscription'),
- url(r'^deleteSubscription/(?P<topic_name>.+)/(?P<subscription_name>.+)$',
views.deleteSubscription, name='deleteSubscription'),
+ url(r'^clearSubscription/(?P<topic_name>.+)/(?P<subscription_name>.+)$',
views.clear_subscription, name='clearSubscription'),
+ url(r'^deleteSubscription/(?P<topic_name>.+)/(?P<subscription_name>.+)$',
views.delete_subscription, name='deleteSubscription'),
url(r'^messages/(?P<topic_name>.+)/(?P<subscription_name>.+)$',
views.messages, name='messages'),
]
diff --git a/dashboard/django/stats/views.py b/dashboard/django/stats/views.py
index 8941bec..9654fc6 100644
--- a/dashboard/django/stats/views.py
+++ b/dashboard/django/stats/views.py
@@ -37,6 +37,68 @@ pulsar = import_utils.try_import("pulsar")
logger = logging.getLogger(__name__)
+class AdminPath:
+ v1 = "/admin"
+ v2 = "/admin/v2"
+
+ @staticmethod
+ def get(is_v2):
+ return AdminPath.v2 if is_v2 else AdminPath.v1
+
+
+class TopicName:
+ def __init__(self, topic_name):
+ try:
+ self.scheme, self.path = topic_name.split("://", 1)
+ except ValueError:
+ self.scheme, self.path = topic_name.split("/", 1)
+ self.namespace_path, self.name = self.path.rsplit("/", 1)
+ self.namespace = NamespaceName(self.namespace_path)
+
+ def is_v2(self):
+ return self.namespace.is_v2()
+
+ def url_name(self):
+ return "/".join([self.scheme, self.path])
+
+ def full_name(self):
+ return "://".join([self.scheme, self.path])
+
+ def short_name(self):
+ return self.name
+
+ def is_global(self):
+ return self.namespace.is_global()
+
+ def admin_path(self):
+ b = AdminPath.get(self.is_v2())
+ return settings.SERVICE_URL + b + "/" + self.url_name()
+
+
+class NamespaceName:
+
+ def __init__(self, namespace_name):
+ self.path = namespace_name.strip("/")
+ path_parts = self.path.split("/")
+ if len(path_parts) == 2:
+ self.tenant, self.namespace = path_parts
+ self.cluster = None
+ elif len(path_parts) == 3:
+ self.tenant, self.cluster, self.namespace = path_parts
+ else:
+ raise ValueError("invalid namespace:" + namespace_name)
+
+ def is_v2(self):
+ return self.cluster is None
+
+ def is_global(self):
+ return self.cluster == "global"
+
+ def admin_path(self):
+ b = AdminPath.get(self.is_v2())
+ return settings.SERVICE_URL + b + "/namespaces/" + self.path
+
+
def get_timestamp():
try:
return LatestTimestamp.objects.get(name='latest').timestamp
@@ -139,8 +201,8 @@ def namespace(request, namespace_name):
})
-def deleteNamespace(request, namespace_name):
- url = settings.SERVICE_URL + '/admin/v2/namespaces/' + namespace_name
+def delete_namespace(request, namespace_name):
+ url = NamespaceName(namespace_name).admin_path()
response = requests.delete(url)
status = response.status_code
logger.debug("Delete namespace " + namespace_name + " status - " +
str(status))
@@ -148,9 +210,10 @@ def deleteNamespace(request, namespace_name):
Namespace.objects.filter(name=namespace_name,
timestamp=get_timestamp()).update(deleted=True)
return redirect('property', property_name=namespace_name.split('/', 1)[0])
+
def topic(request, topic_name):
timestamp = get_timestamp()
- topic_name = extract_topic_db_name(topic_name)
+ topic_name = TopicName(topic_name).full_name()
cluster_name = request.GET.get('cluster')
clusters = []
@@ -314,12 +377,12 @@ def clusters(request):
})
-def clearSubscription(request, topic_name, subscription_name):
- url = settings.SERVICE_URL + '/admin/v2/' + topic_name + '/subscription/'
+ subscription_name + '/skip_all'
+def clear_subscription(request, topic_name, subscription_name):
+ url = "%s/subscription/%s/skip_all" % (TopicName(topic_name).admin_path(),
subscription_name)
response = requests.post(url)
if response.status_code == 204:
ts = get_timestamp()
- topic_db_name = extract_topic_db_name(topic_name)
+ topic_db_name = TopicName(topic_name).full_name()
topic = Topic.objects.get(name=topic_db_name, timestamp=ts)
subscription = Subscription.objects.get(name=subscription_name,
topic=topic, timestamp=ts)
topic.backlog = topic.backlog - subscription.msgBacklog
@@ -328,13 +391,14 @@ def clearSubscription(request, topic_name,
subscription_name):
subscription.save(update_fields=['msgBacklog'])
return redirect('topic', topic_name=topic_name)
-def deleteSubscription(request, topic_name, subscription_name):
- url = settings.SERVICE_URL + '/admin/v2/' + topic_name + '/subscription/'
+ subscription_name
+
+def delete_subscription(request, topic_name, subscription_name):
+ url = "%s/subscription/%s" % (TopicName(topic_name).admin_path(),
subscription_name)
response = requests.delete(url)
status = response.status_code
if status == 204:
ts = get_timestamp()
- topic_db_name = extract_topic_db_name(topic_name)
+ topic_db_name = TopicName(topic_name).full_name()
topic = Topic.objects.get(name=topic_db_name, timestamp=ts)
deleted_subscription =
Subscription.objects.get(name=subscription_name, topic=topic, timestamp=ts)
deleted_subscription.deleted = True
@@ -353,7 +417,8 @@ def deleteSubscription(request, topic_name,
subscription_name):
def messages(request, topic_name, subscription_name):
- topic_db_name = extract_topic_db_name(topic_name)
+ topic_name_obj = TopicName(topic_name)
+ topic_db_name = topic_name_obj.full_name()
timestamp = get_timestamp()
cluster_name = request.GET.get('cluster')
@@ -371,7 +436,7 @@ def messages(request, topic_name, subscription_name):
message = None
message_position = request.GET.get('message-position')
if message_position and message_position.isnumeric():
- message = peek_message(topic_obj, subscription_name, message_position)
+ message = peek_message(topic_name_obj, subscription_name,
message_position)
if not isinstance(message, list):
message = [message]
@@ -485,19 +550,12 @@ def get_message_from_http_response(response):
response.content)
-def peek_message(topic_obj, subscription_name, message_position):
+def peek_message(topic_name, subscription_name, message_position):
+ if not isinstance(topic_name, TopicName):
+ topic_name = TopicName(topic_name)
peek_url = "%s/subscription/%s/position/%s" % (
- topic_path(topic_obj), subscription_name, message_position)
+ topic_name.admin_path(), subscription_name, message_position)
peek_response = requests.get(peek_url)
if peek_response.status_code != 200:
return {"ERROR": "%s(%d)" % (peek_response.reason,
peek_response.status_code)}
return get_message_from_http_response(peek_response)
-
-
-def topic_path(topic_obj):
- admin_base = "/admin/v2/" if topic_obj.is_v2() else "/admin/"
- return settings.SERVICE_URL + admin_base + topic_obj.url_name()
-
-
-def extract_topic_db_name(topic_name):
- return 'persistent://' + topic_name.split('persistent/', 1)[1]