فهرست منبع

HUE-9125 [api] Add API endpoint for fetching the hue config in json

Johan Ahlen 5 سال پیش
والد
کامیت
f411ea14c0
4فایلهای تغییر یافته به همراه100 افزوده شده و 90 حذف شده
  1. 56 2
      desktop/core/src/desktop/api2.py
  2. 43 0
      desktop/core/src/desktop/api2_tests.py
  3. 0 88
      desktop/core/src/desktop/tests.py
  4. 1 0
      desktop/core/src/desktop/urls.py

+ 56 - 2
desktop/core/src/desktop/api2.py

@@ -18,8 +18,8 @@
 from future import standard_library
 standard_library.install_aliases()
 from builtins import map
-from builtins import str
 import logging
+import os
 import json
 import sys
 import tempfile
@@ -42,11 +42,15 @@ from metadata.catalog_api import search_entities as metadata_search_entities, _h
 from notebook.connectors.altus import SdxApi, AnalyticDbApi, DataEngApi, DataWarehouse2Api
 from notebook.connectors.base import Notebook, get_interpreter
 
+from desktop import appmanager
+from desktop.auth.backend import is_admin
+from desktop.conf import ENABLE_CONNECTORS, ENABLE_GIST_PREVIEW, get_clusters, IS_K8S_ONLY
+from desktop.lib.conf import BoundContainer, GLOBAL_CONFIG, is_anonymous
 from desktop.lib.django_util import JsonResponse, login_notrequired, render
-from desktop.conf import get_clusters, IS_K8S_ONLY, ENABLE_GIST_PREVIEW
 from desktop.lib.exceptions_renderable import PopupException
 from desktop.lib.export_csvxls import make_response
 from desktop.lib.i18n import smart_str, force_unicode
+from desktop.lib.paths import get_desktop_root
 from desktop.models import Document2, Document, Directory, FilesystemException, uuid_default, \
   UserPreferences, get_user_preferences, set_user_preferences, get_cluster_config, __paginate, _get_gist_document
 
@@ -83,6 +87,56 @@ def get_config(request):
 
   return JsonResponse(config)
 
+@api_error_handler
+def get_hue_config(request):
+  if not is_admin(request.user):
+    raise PopupException(_('You must be a superuser.'))
+
+  show_private = request.GET.get('private', False)
+
+  app_modules = appmanager.DESKTOP_MODULES
+  config_modules = GLOBAL_CONFIG.get().values()
+
+  if ENABLE_CONNECTORS.get():
+    app_modules = [app_module for app_module in app_modules if app_module.name == 'desktop']
+    config_modules = [config_module for config_module in config_modules if config_module.config.key == 'desktop']
+
+  apps = [{
+    'name': app.name,
+    'has_ui': app.menu_index != 999,
+    'display_name': app.display_name
+  } for app in sorted(app_modules, key=lambda app: app.name)]
+
+  def recurse_conf(modules):
+    attrs = []
+    for module in modules:
+      if not show_private and module.config.private:
+        continue
+
+      conf = {
+        'help': module.config.help or _('No help available.'),
+        'key': module.config.key,
+        'is_anonymous': is_anonymous(module.config.key)
+      }
+      if isinstance(module, BoundContainer):
+        conf['values'] = recurse_conf(module.get().values())
+      else:
+        conf['default'] = str(module.config.default)
+        if 'password' in module.config.key:
+          conf['value'] = '*' * 10
+        elif sys.version_info[0] > 2:
+          conf['value'] = str(module.get_raw())
+        else:
+          conf['value'] = str(module.get_raw()).decode('utf-8', 'replace')
+      attrs.append(conf)
+
+    return attrs
+
+  return JsonResponse({
+    'config': sorted(recurse_conf(config_modules), key=lambda conf: conf.get('key')),
+    'conf_dir': os.path.realpath(os.getenv('HUE_CONF_DIR', get_desktop_root('conf'))),
+    'apps': apps
+  })
 
 @api_error_handler
 def get_context_namespaces(request, interface):

+ 43 - 0
desktop/core/src/desktop/api2_tests.py

@@ -24,6 +24,8 @@ from nose.tools import assert_true, assert_false, assert_equal, assert_not_equal
 
 from useradmin.models import get_default_user_group, User
 
+from beeswax.conf import HIVE_SERVER_HOST
+
 from desktop.conf import ENABLE_GIST_PREVIEW
 from desktop.lib.django_test_util import make_logged_in_client
 from desktop.lib.test_utils import grant_access
@@ -64,6 +66,47 @@ class TestApi2(object):
     finally:
       query.delete()
 
+  def test_get_hue_config(self):
+    client = make_logged_in_client(username="api2_superuser", groupname="default", recreate=True, is_superuser=True)
+    user = User.objects.get(username="api2_superuser")
+    grant_access(user.username, user.username, "desktop")
+    response = client.get('/desktop/api2/get_hue_config', data={})
+
+    # It should have multiple config sections in json
+    config = json.loads(response.content)['config']
+    assert_true(len(config) > 1)
+
+    # It should only allow superusers
+    client_not_me = make_logged_in_client(username='not_me', is_superuser=False, groupname='test')
+    grant_access("not_me", "test", "desktop")
+    response = client_not_me.get('/desktop/api2/get_hue_config', data={})
+    assert_true(b"You must be a superuser" in response.content, response.content)
+
+    # It should contain a config parameter
+    CANARY = b"abracadabra"
+    clear = HIVE_SERVER_HOST.set_for_testing(CANARY)
+    try:
+      response = client.get('/desktop/api2/get_hue_config', data={})
+      assert_true(CANARY in response.content, response.content)
+    finally:
+      clear()
+
+  def test_get_hue_config_private(self):
+    client = make_logged_in_client(username="api2_superuser", groupname="default", recreate=True, is_superuser=True)
+    user = User.objects.get(username="api2_superuser")
+    grant_access(user.username, user.username, "desktop")
+
+    # Not showing private if not asked for
+    response = client.get('/desktop/api2/get_hue_config', data={})
+    assert_false(b'bind_password' in response.content)
+
+    # Masking passwords if private
+    private_response = client.get('/desktop/api2/get_hue_config', data={'private': True})
+    assert_true(b'bind_password' in private_response.content)
+    assert_true(re.search(r'"value":\s*"[*]+"[^}]+"key":\s*"bind_password"', private_response.content))
+
+    # There should be more private than non-private
+    assert_true(len(response.content) < len(private_response.content))
 
 class TestDocumentApiSharingPermissions(object):
 

+ 0 - 88
desktop/core/src/desktop/tests.py

@@ -48,7 +48,6 @@ from nose.tools import assert_true, assert_false, assert_equal, assert_not_equal
 
 from dashboard.conf import HAS_SQL_ENABLED
 from desktop.settings import DATABASES
-from beeswax.conf import HIVE_SERVER_HOST
 from useradmin.models import GroupPermission, User
 
 import desktop
@@ -204,93 +203,6 @@ def test_download_log_view():
   response = c.get(URL)
   assert_equal("application/zip", response.get('Content-Type', ''))
 
-def test_dump_config():
-  c = make_logged_in_client()
-
-  CANARY = b"abracadabra"
-
-  # Depending on the order of the conf.initialize() in settings, the set_for_testing() are not seen in the global settings variable
-  clear = HIVE_SERVER_HOST.set_for_testing(CANARY)
-
-  try:
-    response1 = c.get(reverse('desktop.views.dump_config'))
-    assert_true(CANARY in response1.content, response1.content)
-
-    response2 = c.get(reverse('desktop.views.dump_config'), {'private': 'true'})
-    assert_true(CANARY in response2.content)
-
-    # There are more private variables...
-    assert_true(len(response1.content) < len(response2.content))
-  finally:
-    clear()
-
-  CANARY = "(localhost|127\.0\.0\.1):(50030|50070|50060|50075)"
-  clear = proxy.conf.WHITELIST.set_for_testing(CANARY)
-
-  try:
-    response1 = c.get(reverse('desktop.views.dump_config'))
-    if not isinstance(CANARY, bytes):
-      CANARY = CANARY.encode('utf-8')
-    assert_true(CANARY in response1.content)
-  finally:
-    clear()
-
-  # Malformed port per HUE-674
-  CANARY = "asdfoijaoidfjaosdjffjfjaoojosjfiojdosjoidjfoa"
-  clear = HIVE_SERVER_HOST.set_for_testing(CANARY)
-
-  try:
-    response1 = c.get(reverse('desktop.views.dump_config'))
-    if not isinstance(CANARY, bytes):
-      CANARY = CANARY.encode('utf-8')
-    assert_true(CANARY in response1.content, response1.content)
-  finally:
-    clear()
-
-  CANARY = '/tmp/spacé.dat'
-  finish = proxy.conf.WHITELIST.set_for_testing(CANARY)
-  try:
-    response = c.get(reverse('desktop.views.dump_config'))
-    response_content = response.content
-    if not isinstance(response_content, str):
-      response_content = response_content.decode('utf-8')
-    assert_true(CANARY in response_content, response_content)
-  finally:
-    finish()
-
-  # Not showing some passwords
-  response = c.get(reverse('desktop.views.dump_config'))
-  assert_false(b'bind_password' in response.content)
-
-  # Login as someone else
-  client_not_me = make_logged_in_client(username='not_me', is_superuser=False, groupname='test')
-  grant_access("not_me", "test", "desktop")
-
-  response = client_not_me.get(reverse('desktop.views.dump_config'))
-  assert_true(b"You must be a superuser" in response.content, response.content)
-
-  prev_env_conf = os.environ.get("HUE_CONF_DIR")
-  try:
-    os.environ["HUE_CONF_DIR"] = "/tmp/test_hue_conf_dir"
-    resp = c.get(reverse('desktop.views.dump_config'))
-    assert_true(b'/tmp/test_hue_conf_dir' in resp.content, resp)
-  finally:
-    if prev_env_conf is None:
-      os.environ.pop("HUE_CONF_DIR", None)
-    else:
-      os.environ["HUE_CONF_DIR"] = prev_env_conf
-
-
-  finish = desktop.conf.ENABLE_CONNECTORS.set_for_testing(True)
-  try:
-    with patch('desktop.lib.fsmanager.has_hdfs_enabled') as has_hdfs_enabled:
-      has_hdfs_enabled.return_value = True
-      response = c.get(reverse('desktop.views.dump_config'))
-      assert_equal(1, len(response.context[0]['apps']), response.context[0])
-  finally:
-    finish()
-
-
 def hue_version():
   global HUE_VERSION
   HUE_VERSION_BAK = HUE_VERSION

+ 1 - 0
desktop/core/src/desktop/urls.py

@@ -164,6 +164,7 @@ dynamic_patterns += [
   url(r'^desktop/api2/doc/share/?$', desktop_api2.share_document),
 
   url(r'^desktop/api2/get_config/?$', desktop_api2.get_config),
+  url(r'^desktop/api2/get_hue_config/?$', desktop_api2.get_hue_config),
   url(r'^desktop/api2/context/namespaces/(?P<interface>[\w\-]+)/?$', desktop_api2.get_context_namespaces),
   url(r'^desktop/api2/context/computes/(?P<interface>[\w\-]+)/?$', desktop_api2.get_context_computes),
   url(r'^desktop/api2/context/clusters/(?P<interface>[\w\-]+)/?$', desktop_api2.get_context_clusters),