浏览代码

HUE-1176 [jb] Automatically update the list of apps available depending on selected cluster

Romain Rigaux 8 年之前
父节点
当前提交
5cc2996

+ 6 - 3
apps/jobbrowser/src/jobbrowser/templates/job_browser.mako

@@ -86,8 +86,6 @@ ${ commonheader("Job Browser", "jobbrowser", user, request) | n,unicode }
                 <a class="pointer" data-bind="click: function(){ $parent.selectInterface(interface); }, text: label"></a>
               </li>
             <!-- /ko -->
-            <li data-bind="css: {'active': interface() === 'dataeng-jobs'}"><a class="pointer" data-bind="click: function(){ selectInterface('dataeng-jobs'); }">${ _('Jobs') }</a></li>
-            <li data-bind="css: {'active': interface() === 'dataeng-clusters'}"><a class="pointer" data-bind="click: function(){ selectInterface('dataeng-clusters'); }">${ _('Clusters') }</a></li>
           </ul>
           % if not hiveserver2_impersonation_enabled:
             <div class="pull-right label label-warning" style="margin-top: 16px">${ _("Hive jobs are running as the 'hive' user") }</div>
@@ -1932,20 +1930,25 @@ ${ commonheader("Job Browser", "jobbrowser", user, request) | n,unicode }
         var jobsInterfaceCondition = function () {
           return self.appConfig() && self.appConfig()['browser'] && self.appConfig()['browser']['interpreter_names'].indexOf('yarn') != -1;
         }
+        var dataengInterfaceCondition = function () {
+          return self.appConfig() && self.appConfig()['browser'] && self.appConfig()['browser']['interpreter_names'].indexOf('dataeng') != -1;
+        }
         var schedulerInterfaceCondition = function () {
           return self.appConfig() && self.appConfig()['scheduler'] && self.appConfig()['scheduler']['interpreters'].length > 0;
         }
 
         var interfaces = [
           {'interface': 'jobs', 'label': '${ _ko('Jobs') }', 'condition': jobsInterfaceCondition},
+          {'interface': 'dataeng-jobs', 'label': '${ _ko('Jobs') }', 'condition': dataengInterfaceCondition},
           {'interface': 'workflows', 'label': '${ _ko('Workflows') }', 'condition': schedulerInterfaceCondition},
           {'interface': 'schedules', 'label': '${ _ko('Schedules') }', 'condition': schedulerInterfaceCondition},
           {'interface': 'bundles', 'label': '${ _ko('Bundles') }', 'condition': schedulerInterfaceCondition},
           {'interface': 'slas', 'label': '${ _ko('SLAs') }', 'condition': schedulerInterfaceCondition},
+          {'interface': 'dataeng-clusters', 'label': '${ _ko('Clusters') }', 'condition': dataengInterfaceCondition},
         ];
 
         return interfaces.filter(function (i) {
-          return i.condition()
+          return i.condition();
         });
       });
 

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

@@ -69,12 +69,14 @@ def api_error_handler(func):
 @api_error_handler
 def get_config(request):
   cluster_config = ClusterConfig(request.user)
-  app_config = cluster_config.get_apps()
+
+  cluster_type = request.POST.get('type', 'ini') # TODO pref
+  app_config = cluster_config.get_apps(cluster_type)
 
   return JsonResponse({
     'status': 0,
     'app_config': app_config,
-    'main_button_action': cluster_config.main_quick_action,
+    'main_button_action': cluster_config.get_main_quick_action(app_config),
     'button_actions': [
       app for app in [
         app_config.get('editor'),

+ 35 - 25
desktop/core/src/desktop/models.py

@@ -1541,9 +1541,7 @@ class ClusterConfig():
     pass
 
 
-  @property
-  def main_quick_action(self):
-    apps = self.get_apps()
+  def get_main_quick_action(self, apps):
     if not apps:
       raise PopupException(_('No permission to any app.'))
 
@@ -1553,8 +1551,8 @@ class ClusterConfig():
     try:
       user_default_app = json.loads(UserPreferences.objects.get(user=self.user, key='default_app').value)
       if apps.get(user_default_app['app']):
-        default_app = self.get_apps()[user_default_app['app']]
         default_interpreter = []
+        default_app = apps[user_default_app['app']]
         if default_app.get('interpreters'):
           interpreters = [interpreter for interpreter in default_app['interpreters'] if interpreter['type'] == user_default_app['interpreter']]
           if interpreters:
@@ -1570,7 +1568,7 @@ class ClusterConfig():
       return default_app
 
 
-  def _get_editor(self):
+  def _get_editor(self, cluster_type):
     interpreters = []
 
     if SHOW_NOTEBOOKS.get():
@@ -1582,7 +1580,11 @@ class ClusterConfig():
         'page': '/notebook'
       })
 
-    for interpreter in get_ordered_interpreters(self.user):
+    _interpreters = get_ordered_interpreters(self.user)
+    if cluster_type == 'dataeng':
+      _interpreters = [interpreter for interpreter in _interpreters if interpreter['type'] in ('hive', 'spark2', 'java')]
+
+    for interpreter in _interpreters:
       interpreters.append({
         'name': interpreter['name'],
         'type': interpreter['type'],
@@ -1601,10 +1603,10 @@ class ClusterConfig():
     else:
       return None
 
-  def _get_dashboard(self):
+  def _get_dashboard(self, cluster_type):
     interpreters = [] # TODO Integrate SQL Dashboards and Solr 6 configs
 
-    if IS_DASHBOARD_ENABLED.get():
+    if IS_DASHBOARD_ENABLED.get() and cluster_type != 'dataeng':
       return {
         'name': 'dashboard',
         'displayName': _('Dashboard'),
@@ -1614,10 +1616,10 @@ class ClusterConfig():
     else:
       return None
 
-  def _get_browser(self):
+  def _get_browser(self, cluster_type):
     interpreters = []
 
-    if 'filebrowser' in self.apps:
+    if 'filebrowser' in self.apps and cluster_type != 'dataeng':
       interpreters.append({
         'type': 'hdfs',
         'displayName': _('Files'),
@@ -1641,7 +1643,7 @@ class ClusterConfig():
         'page': '/metastore/tables'
       })
 
-    if 'search' in self.apps:
+    if 'search' in self.apps and cluster_type != 'dataeng':
       interpreters.append({
         'type': 'indexes',
         'displayName': _('Indexes'),
@@ -1650,16 +1652,24 @@ class ClusterConfig():
       })
 
     if 'jobbrowser' in self.apps:
-      from hadoop.cluster import get_default_yarncluster # Circular loop
-      if get_default_yarncluster():
+      if cluster_type == 'dataeng':
         interpreters.append({
-          'type': 'yarn',
+          'type': 'dataeng',
           'displayName': _('Jobs'),
           'tooltip': _('Jobs'),
           'page': '/jobbrowser/'
         })
-
-    if 'hbase' in self.apps:
+      else:
+        from hadoop.cluster import get_default_yarncluster # Circular loop
+        if get_default_yarncluster():
+          interpreters.append({
+            'type': 'yarn',
+            'displayName': _('Jobs'),
+            'tooltip': _('Jobs'),
+            'page': '/jobbrowser/'
+          })
+
+    if 'hbase' in self.apps and cluster_type != 'dataeng':
       interpreters.append({
         'type': 'hbase',
         'displayName': _('HBase'),
@@ -1667,7 +1677,7 @@ class ClusterConfig():
         'page': '/hbase/'
       })
 
-    if 'security' in self.apps:
+    if 'security' in self.apps and cluster_type != 'dataeng':
       interpreters.append({
         'type': 'security',
         'displayName': _('Security'),
@@ -1675,7 +1685,7 @@ class ClusterConfig():
         'page': '/security/hive'
       })
 
-    if 'sqoop' in self.apps:
+    if 'sqoop' in self.apps and cluster_type != 'dataeng':
       interpreters.append({
         'type': 'sqoop',
         'displayName': _('Sqoop'),
@@ -1694,7 +1704,7 @@ class ClusterConfig():
       return None
 
 
-  def _get_scheduler(self):
+  def _get_scheduler(self, cluster_type):
     interpreters = [{
         'type': 'oozie-workflow',
         'displayName': _('Workflow'),
@@ -1713,7 +1723,7 @@ class ClusterConfig():
       }
     ]
 
-    if 'oozie' in self.apps and not self.user.has_hue_permission(action="disable_editor_access", app="oozie") or self.user.is_superuser:
+    if 'oozie' in self.apps and not (self.user.has_hue_permission(action="disable_editor_access", app="oozie") and not self.user.is_superuser):
       return {
           'name': 'oozie',
           'displayName': _('Scheduler'),
@@ -1747,12 +1757,12 @@ class ClusterConfig():
       return None
 
 
-  def get_apps(self):
+  def get_apps(self, cluster_type):
     apps = OrderedDict([app for app in [
-      ('editor', self._get_editor()),
-      ('dashboard', self._get_dashboard()),
-      ('browser', self._get_browser()),
-      ('scheduler', self._get_scheduler()),
+      ('editor', self._get_editor(cluster_type)),
+      ('dashboard', self._get_dashboard(cluster_type)),
+      ('browser', self._get_browser(cluster_type)),
+      ('scheduler', self._get_scheduler(cluster_type)),
       ('sdkapps', self._get_sdk_apps()),
     ] if app[1]])
 

+ 24 - 26
desktop/core/src/desktop/static/desktop/js/clusterConfig.js

@@ -14,35 +14,33 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-(function () {
 
-  function ClusterConfig () {
-    var self = this;
+function ClusterConfig (params) {
+  var self = this;
 
-    self.clusterConfig = undefined;
-    self.loading = true;
+  self.clusterConfig = undefined;
+  self.loading = true;
 
-    ApiHelper.getInstance().getClusterConfig().done(function (data) {
-      if (data.status === 0) {
-        self.loading = false;
-        self.clusterConfig = data;
-        huePubSub.publish('cluster.config.set.config', self.clusterConfig);
-      } else {
-        $(document).trigger("error", data.message);
-        huePubSub.publish('cluster.config.set.config');
-      }
-    }).fail(function () {
-      huePubSub.publish('clustser.config.set.config');
-    }).always(function () {
+  ApiHelper.getInstance().getClusterConfig(params).done(function (data) {
+    if (data.status === 0) {
       self.loading = false;
-    });
+      self.clusterConfig = data;
+      huePubSub.publish('cluster.config.set.config', self.clusterConfig);
+    } else {
+      $(document).trigger("error", data.message);
+      huePubSub.publish('cluster.config.set.config');
+    }
+  }).fail(function () {
+    huePubSub.publish('clustser.config.set.config');
+  }).always(function () {
+    self.loading = false;
+  });
 
-    huePubSub.subscribe('cluster.config.get.config', function () {
-      if (! self.loading) {
-        huePubSub.publish('cluster.config.set.config', self.clusterConfig);
-      }
-    });
-  }
+  huePubSub.subscribe('cluster.config.get.config', function () {
+    if (! self.loading) {
+      huePubSub.publish('cluster.config.set.config', self.clusterConfig);
+    }
+  });
+}
 
-  new ClusterConfig();
-}());
+new ClusterConfig();

+ 50 - 46
desktop/core/src/desktop/templates/hue.mako

@@ -154,6 +154,43 @@ ${ hueIcons.symbols() }
 
 
       <div class="top-nav-middle">
+
+        <div class="btn-group pull-right">
+          <button class="btn" data-bind="text: cluster.cluster().name"></button>
+          <button class="btn dropdown-toggle" data-toggle="dropdown">
+            <span class="caret"></span>
+          </button>
+
+          <ul class="dropdown-menu">
+            <li class="dropdown-submenu">
+              <a data-rel="navigator-tooltip" href="javascript: void(0)" data-bind="click: function(){ page('/editor'); onePageViewModel.changeEditorType('hive', true); }">
+                <i class="fa fa-fw fa-th-large inline-block"></i> ${ _('Data Eng') }
+              </a>
+              <ul class="dropdown-menu">
+               <li><a data-rel="navigator-tooltip" href="#"><span class="dropdown-no-icon"><i class="fa fa-fw fa-plus inline-block"></i></span></a></li>
+                <!-- ko foreach: cluster.clusters()[3]['clusters'] -->
+                  <li>
+                    <a href="javascript: void(0)" data-bind="click: function() { $parent.cluster.cluster($data) }">
+                      <span class="dropdown-no-icon" data-bind="text: name"></span>
+                    </a>
+                  </li>
+                <!-- /ko -->
+              </ul>
+            </li>
+            <li><a href="javascript: void(0)" data-bind="click: function(){ page('/dashboard/new_search') }"><i class="fa fa-fw fa-th-large"></i> ${ _('Team') }</a></li>
+            <li><a href="javascript: void(0)" data-bind="click: function(){ page('/dashboard/new_search') }"><i class="fa fa-fw fa-square"></i> ${ _('Athena') }</a></li>
+            <li class="dropdown-submenu">
+              <a data-rel="navigator-tooltip" href="javascript: void(0)" data-bind="click: function(){ page('/editor'); onePageViewModel.changeEditorType('hive', true); }">
+                <i class="fa fa-fw fa-th-large inline-block"></i> ${ _('Nightly') }
+              </a>
+              <ul class="dropdown-menu">
+              <li><a  href="javascript: void(0)"><span class="dropdown-no-icon">Cluster 1</span></a></li>
+              <li><a  href="javascript: void(0)"><span class="dropdown-no-icon">Cluster 2</span></a></li>
+              </ul>
+            </li>
+          </ul>
+        </div>
+
         <div class="search-container-top">
           <input placeholder="${ _('Search data and saved documents...') }" type="text"
             data-bind="autocomplete: {
@@ -194,7 +231,7 @@ ${ hueIcons.symbols() }
       </div>
 
       <div class="top-nav-right">
-      
+
         % if user.is_authenticated() and section != 'login':
         <div class="dropdown navbar-dropdown pull-right">
           <%
@@ -226,42 +263,6 @@ ${ hueIcons.symbols() }
         <!-- ko if: hasJobBrowser -->
           <!-- ko component: { name: 'hue-job-browser-links', params: { onePageViewModel: onePageViewModel }} --><!-- /ko -->
         <!-- /ko -->
-        
-        <div class="compose-action btn-group">
-          <button class="btn" data-bind="text: cluster.cluster"></button>
-          <button class="btn dropdown-toggle" data-toggle="dropdown">
-            <span class="caret"></span>
-          </button>
-
-          <ul class="dropdown-menu">
-            <li class="dropdown-submenu">
-              <a data-rel="navigator-tooltip" href="javascript: void(0)" data-bind="click: function(){ page('/editor'); onePageViewModel.changeEditorType('hive', true); }">
-                <i class="fa fa-fw fa-send inline-block"></i> ${ _('Data Eng') }
-              </a>
-              <ul class="dropdown-menu">
-               <li><a data-rel="navigator-tooltip" href="#"><span class="dropdown-no-icon"><i class="fa fa-fw fa-plus inline-block"></i></span></a></li>
-                <!-- ko foreach: cluster.clusters()[3]['clusters'] -->
-                  <li>
-                    <a  href="javascript: void(0)">
-                      <span class="dropdown-no-icon" data-bind="text: $data"></span>
-                    </a>
-                  </li>
-                <!-- /ko -->
-              </ul>
-            </li>
-            <li><a href="javascript: void(0)" data-bind="click: function(){ page('/dashboard/new_search') }"><i class="fa fa-fw fa-th-large"></i> ${ _('Team') }</a></li>
-            <li><a href="javascript: void(0)" data-bind="click: function(){ page('/dashboard/new_search') }"><i class="fa fa-fw fa-square"></i> ${ _('Athena') }</a></li>
-            <li class="dropdown-submenu">
-              <a data-rel="navigator-tooltip" href="javascript: void(0)" data-bind="click: function(){ page('/editor'); onePageViewModel.changeEditorType('hive', true); }">
-                <i class="fa fa-fw fa-th-large inline-block"></i> ${ _('Nightly') }
-              </a>
-              <ul class="dropdown-menu">
-              <li><a  href="javascript: void(0)"><span class="dropdown-no-icon">Cluster 1</span></a></li>
-              <li><a  href="javascript: void(0)"><span class="dropdown-no-icon">Cluster 2</span></a></li>
-              </ul>
-            </li>
-          </ul>
-        </div>
       </div>
 
     </div>
@@ -511,7 +512,7 @@ ${ koComponents.all() }
 
 ${ commonHeaderFooterComponents.header_pollers(user, is_s3_enabled, apps) }
 
-## clusterConfig makes an ajax call so it needs to be after commonHeaderFooterComponents
+## clusterConfig makes an Ajax call so it needs to be after commonHeaderFooterComponents
 <script src="${ static('desktop/js/clusterConfig.js') }"></script>
 
 ${ assist.assistJSModels() }
@@ -1173,8 +1174,7 @@ ${ smart_unicode(login_modal(request).content) | n,unicode }
         var ClusterPanelViewModel = function() {
           var self = this;
           self.apiHelper = ApiHelper.getInstance();
-  
-          self.cluster = ko.observable('Ro\'s Cluster');
+
           self.clusters = ko.observableArray([
             {'name': 'Ro\'s Cluster', 'type': 'ini'},
             {'name': 'Team', 'type': 'ini', 'clusters': ko.observableArray()},
@@ -1182,21 +1182,25 @@ ${ smart_unicode(login_modal(request).content) | n,unicode }
             {'name': 'DataEng', 'type': 'dataeng', 'clusters': ko.observableArray()},
             {'name': 'Athena', 'type': 'athena'}
           ]);
-  
+          self.cluster = ko.observable(self.clusters()[0]);
+          self.cluster.subscribe(function() {
+            new ClusterConfig(ko.mapping.toJS(self.cluster));
+          });
+
           self.contextPanelVisible = ko.observable(false);
-          
+
           $.post("/jobbrowser/api/jobs", {
             interface: ko.mapping.toJSON('dataeng-clusters'),
             filters: ko.mapping.toJSON([]),
           }, function (data) {
             if (data.status == 0) {
-              var apps = [];
+              var clusters = [];
               if (data && data.apps) {
-                data.apps.forEach(function (job) {
-                  apps.push(job.id);
+                data.apps.forEach(function (cluster) {
+                  clusters.push({'name': cluster.id, 'type': 'dataeng'});
                 });
               }
-              self.clusters()[3]['clusters'](apps);
+              self.clusters()[3]['clusters'](clusters);
             } else {
               $(document).trigger("error", data.message);
             }