Repository: ambari
Updated Branches:
  refs/heads/branch-2.5 e8cef81e4 -> b5f29c9d3


AMBARI-19848. Hive View 2.0: Allow user to create database. (dipayanb)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/b5f29c9d
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/b5f29c9d
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/b5f29c9d

Branch: refs/heads/branch-2.5
Commit: b5f29c9d322ca5b3c6d3d177ff2a916e5418243b
Parents: e8cef81
Author: Dipayan Bhowmick <dipayan.bhowm...@gmail.com>
Authored: Mon Feb 6 11:24:12 2017 +0530
Committer: Dipayan Bhowmick <dipayan.bhowm...@gmail.com>
Committed: Mon Feb 6 11:24:12 2017 +0530

----------------------------------------------------------------------
 .../CreateDatabaseQueryGenerator.java           | 44 +++++++++++++
 .../DeleteDatabaseQueryGenerator.java           |  2 +-
 .../view/hive20/resources/browser/DDLProxy.java | 12 ++++
 .../hive20/resources/browser/DDLService.java    | 31 +++++++++
 .../main/resources/ui/app/adapters/database.js  |  8 +++
 .../ui/app/components/create-database-form.js   | 59 +++++++++++++++++
 .../hive20/src/main/resources/ui/app/router.js  |  1 +
 .../main/resources/ui/app/routes/databases.js   |  4 --
 .../databases/database/tables/new-database.js   | 68 ++++++++++++++++++++
 .../ui/app/services/table-operations.js         | 11 ++++
 .../components/create-database-form.hbs         | 31 +++++++++
 .../resources/ui/app/templates/databases.hbs    |  2 +-
 .../databases/database/tables/new-database.hbs  | 47 ++++++++++++++
 13 files changed, 314 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/b5f29c9d/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/CreateDatabaseQueryGenerator.java
----------------------------------------------------------------------
diff --git 
a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/CreateDatabaseQueryGenerator.java
 
b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/CreateDatabaseQueryGenerator.java
new file mode 100644
index 0000000..c72df03
--- /dev/null
+++ 
b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/CreateDatabaseQueryGenerator.java
@@ -0,0 +1,44 @@
+/**
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you 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.
+*/
+
+package org.apache.ambari.view.hive20.internal.query.generators;
+
+import org.apache.ambari.view.hive20.exceptions.ServiceException;
+import org.apache.commons.lang3.StringUtils;
+import com.google.common.base.Optional;
+
+public class CreateDatabaseQueryGenerator implements QueryGenerator {
+  public final String databaseName;
+
+  public CreateDatabaseQueryGenerator(String databaseName) {
+    this.databaseName = databaseName;
+  }
+
+  public String getDatabaseName() {
+    return databaseName;
+  }
+
+  @Override
+  public Optional<String> getQuery() throws ServiceException {
+    if(StringUtils.isEmpty(this.getDatabaseName())){
+      throw new ServiceException("Database name cannot be null or empty.");
+    }
+
+    return Optional.of("CREATE DATABASE `" + this.getDatabaseName() + "`");
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5f29c9d/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/DeleteDatabaseQueryGenerator.java
----------------------------------------------------------------------
diff --git 
a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/DeleteDatabaseQueryGenerator.java
 
b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/DeleteDatabaseQueryGenerator.java
index 6e1e1a5..189cd5e 100644
--- 
a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/DeleteDatabaseQueryGenerator.java
+++ 
b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/DeleteDatabaseQueryGenerator.java
@@ -1,4 +1,4 @@
-/*
+/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5f29c9d/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/browser/DDLProxy.java
----------------------------------------------------------------------
diff --git 
a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/browser/DDLProxy.java
 
b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/browser/DDLProxy.java
index 7210c75..f75b008 100644
--- 
a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/browser/DDLProxy.java
+++ 
b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/browser/DDLProxy.java
@@ -44,6 +44,7 @@ import 
org.apache.ambari.view.hive20.internal.dto.TableResponse;
 import org.apache.ambari.view.hive20.internal.parsers.TableMetaParserImpl;
 import 
org.apache.ambari.view.hive20.internal.query.generators.AlterTableQueryGenerator;
 import 
org.apache.ambari.view.hive20.internal.query.generators.AnalyzeTableQueryGenerator;
+import 
org.apache.ambari.view.hive20.internal.query.generators.CreateDatabaseQueryGenerator;
 import 
org.apache.ambari.view.hive20.internal.query.generators.CreateTableQueryGenerator;
 import 
org.apache.ambari.view.hive20.internal.query.generators.DeleteDatabaseQueryGenerator;
 import 
org.apache.ambari.view.hive20.internal.query.generators.DeleteTableQueryGenerator;
@@ -310,6 +311,17 @@ public class DDLProxy {
     }
   }
 
+  public Job createDatabase(String databaseName, JobResourceManager 
resourceManager) throws ServiceException {
+    CreateDatabaseQueryGenerator queryGenerator = new 
CreateDatabaseQueryGenerator(databaseName);
+    Optional<String> deleteDatabase = queryGenerator.getQuery();
+    if(deleteDatabase.isPresent()) {
+      String deleteQuery = deleteDatabase.get();
+      return createJob("default", deleteQuery, "CREATE DATABASE " + 
databaseName , resourceManager);
+    }else{
+      throw new ServiceException("Failed to generate create database query for 
database " + databaseName);
+    }
+  }
+
   public Job createJob(String databaseName, String deleteQuery, String 
jobTitle, JobResourceManager resourceManager)
     throws ServiceException {
     LOG.info("Creating job for : {}", deleteQuery );

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5f29c9d/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/browser/DDLService.java
----------------------------------------------------------------------
diff --git 
a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/browser/DDLService.java
 
b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/browser/DDLService.java
index 5c955a2..af8e1cd 100644
--- 
a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/browser/DDLService.java
+++ 
b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/browser/DDLService.java
@@ -112,6 +112,23 @@ public class DDLService extends BaseService {
     }
   }
 
+  @POST
+  @Path("databases")
+  @Produces(MediaType.APPLICATION_JSON)
+  public Response createDatabase(CreateDatabaseRequestWrapper wrapper) {
+    String databaseId = wrapper.database.name;
+    Job job = null;
+    try {
+      job = proxy.createDatabase(databaseId, getResourceManager());
+      JSONObject response = new JSONObject();
+      response.put("job", job);
+      return 
Response.status(Response.Status.ACCEPTED).entity(response).build();
+    } catch (ServiceException e) {
+      LOG.error("Exception occurred while delete database {}", databaseId, e);
+      throw new ServiceFormattedException(e);
+    }
+  }
+
   @GET
   @Path("databases/{database_id}/tables")
   @Produces(MediaType.APPLICATION_JSON)
@@ -315,4 +332,18 @@ public class DDLService extends BaseService {
   public static class TableMetaRequest {
     public TableMeta tableInfo;
   }
+
+  /**
+   * Wrapper class for create database request
+   */
+  public static class CreateDatabaseRequestWrapper {
+    public CreateDatabaseRequest database;
+  }
+
+  /**
+   * Request class for create database
+   */
+  public static class CreateDatabaseRequest {
+    public String name;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5f29c9d/contrib/views/hive20/src/main/resources/ui/app/adapters/database.js
----------------------------------------------------------------------
diff --git 
a/contrib/views/hive20/src/main/resources/ui/app/adapters/database.js 
b/contrib/views/hive20/src/main/resources/ui/app/adapters/database.js
index 6333ae6..8c1fb96 100644
--- a/contrib/views/hive20/src/main/resources/ui/app/adapters/database.js
+++ b/contrib/views/hive20/src/main/resources/ui/app/adapters/database.js
@@ -22,5 +22,13 @@ export default DDLAdapter.extend({
   deleteDatabase(databaseName) {
     let deletURL = this.urlForFindRecord(databaseName, 'database');
     return this.ajax(deletURL, 'DELETE');
+  },
+
+  createDatabase(databaseName) {
+    let createUrl = this.urlForFindAll('database');
+    let data = {
+      database: { name: databaseName}
+    };
+    return this.ajax(createUrl, 'POST', {data: data});
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5f29c9d/contrib/views/hive20/src/main/resources/ui/app/components/create-database-form.js
----------------------------------------------------------------------
diff --git 
a/contrib/views/hive20/src/main/resources/ui/app/components/create-database-form.js
 
b/contrib/views/hive20/src/main/resources/ui/app/components/create-database-form.js
new file mode 100644
index 0000000..5a7dd53
--- /dev/null
+++ 
b/contrib/views/hive20/src/main/resources/ui/app/components/create-database-form.js
@@ -0,0 +1,59 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 Ember from 'ember';
+
+export default Ember.Component.extend({
+  classNames: ['form-horizontal'],
+
+  errorCleaner: Ember.observer('newDatabaseName', function() {
+    if(this.get('error')) {
+      this.clearError();
+    }
+  }),
+
+  validate() {
+    if(Ember.isEmpty(this.get('newDatabaseName'))) {
+      this.setError("Database name cannot be empty");
+      return false;
+    }
+    return true;
+  },
+
+  setError(message) {
+    this.set('error', true);
+    this.set('errorMessage', message);
+  },
+
+  clearError() {
+    this.set('error');
+    this.set('errorMessage');
+  },
+
+  actions: {
+    rename() {
+      if(this.validate()) {
+        this.sendAction('create', this.get('newDatabaseName'));
+      }
+    },
+
+    cancel() {
+      this.sendAction('cancel');
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5f29c9d/contrib/views/hive20/src/main/resources/ui/app/router.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/resources/ui/app/router.js 
b/contrib/views/hive20/src/main/resources/ui/app/router.js
index bc9bfa5..150a3fd 100644
--- a/contrib/views/hive20/src/main/resources/ui/app/router.js
+++ b/contrib/views/hive20/src/main/resources/ui/app/router.js
@@ -36,6 +36,7 @@ Router.map(function() {
     this.route('newtable');
     this.route('database', {path: '/:databaseId'}, function() {
       this.route('tables', {path: '/tables'}, function() {
+        this.route('new-database');
         this.route('new');
         this.route('table', {path: '/:name'}, function() {
           this.route('columns');

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5f29c9d/contrib/views/hive20/src/main/resources/ui/app/routes/databases.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/src/main/resources/ui/app/routes/databases.js 
b/contrib/views/hive20/src/main/resources/ui/app/routes/databases.js
index fd19905..123a93f 100644
--- a/contrib/views/hive20/src/main/resources/ui/app/routes/databases.js
+++ b/contrib/views/hive20/src/main/resources/ui/app/routes/databases.js
@@ -76,10 +76,6 @@ export default Ember.Route.extend({
       this.get('controller').set('confirmDropDatabase', true);
     },
 
-    createTable() {
-      console.log("Table created");
-    },
-
     notEmptyDialogClosed() {
       this.get('controller').set('databaseNotEmpty', false);
       this.get('controller').set('databaseToDelete', undefined);

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5f29c9d/contrib/views/hive20/src/main/resources/ui/app/routes/databases/database/tables/new-database.js
----------------------------------------------------------------------
diff --git 
a/contrib/views/hive20/src/main/resources/ui/app/routes/databases/database/tables/new-database.js
 
b/contrib/views/hive20/src/main/resources/ui/app/routes/databases/database/tables/new-database.js
new file mode 100644
index 0000000..b421bdc
--- /dev/null
+++ 
b/contrib/views/hive20/src/main/resources/ui/app/routes/databases/database/tables/new-database.js
@@ -0,0 +1,68 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 Ember from 'ember';
+
+export default Ember.Route.extend({
+
+  tableOperations: Ember.inject.service(),
+
+  actions: {
+    cancel() {
+      this.transitionTo('databases');
+    },
+
+    create(newDatabaseName) {
+      this._createDatabase(newDatabaseName);
+    }
+  },
+
+  _createDatabase(newDatabaseName) {
+    this._modalStatus(true, 'Submitting request to create database');
+    this.get('tableOperations').createDatabase(newDatabaseName).then((job) => {
+      this._modalStatus(true, 'Waiting for the database to be created');
+      return this.get('tableOperations').waitForJobToComplete(job.get('id'), 5 
* 1000);
+    }).then((status) => {
+      this._modalStatus(true, 'Successfully created database');
+      this._transitionToDatabases(newDatabaseName);
+    }).catch((err) => {
+      this._modalStatus(true, 'Failed to create database');
+      this._alertMessage('Failed to create database', err);
+      this._transitionToDatabases();
+    });
+  },
+
+  _modalStatus(status, message) {
+    this.controller.set('showModal', status);
+    if(status) {
+      this.controller.set('modalMessage', message);
+    }
+  },
+
+  _transitionToDatabases(databaseName) {
+    Ember.run.later(() => {
+      this._modalStatus(false);
+      this.transitionTo('databases');
+    }, 2000);
+  },
+
+  _alertMessage(message, err) {
+    console.log(message, err);
+    // TODO: user alert message here
+  }
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5f29c9d/contrib/views/hive20/src/main/resources/ui/app/services/table-operations.js
----------------------------------------------------------------------
diff --git 
a/contrib/views/hive20/src/main/resources/ui/app/services/table-operations.js 
b/contrib/views/hive20/src/main/resources/ui/app/services/table-operations.js
index 264e617..2a0aeed 100644
--- 
a/contrib/views/hive20/src/main/resources/ui/app/services/table-operations.js
+++ 
b/contrib/views/hive20/src/main/resources/ui/app/services/table-operations.js
@@ -67,6 +67,17 @@ export default Ember.Service.extend({
     })
   },
 
+  createDatabase(database) {
+    return new Promise((resolve, reject) => {
+      
this.get('store').adapterFor('database').createDatabase(database).then((data) 
=> {
+        this.get('store').pushPayload(data);
+        resolve(this.get('store').peekRecord('job', data.job.id));
+      }, (err) => {
+        reject(err);
+      });
+    })
+  },
+
   waitForJobToComplete(jobId, after) {
     return new Ember.RSVP.Promise((resolve, reject) => {
       Ember.run.later(() => {

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5f29c9d/contrib/views/hive20/src/main/resources/ui/app/templates/components/create-database-form.hbs
----------------------------------------------------------------------
diff --git 
a/contrib/views/hive20/src/main/resources/ui/app/templates/components/create-database-form.hbs
 
b/contrib/views/hive20/src/main/resources/ui/app/templates/components/create-database-form.hbs
new file mode 100644
index 0000000..00e0606
--- /dev/null
+++ 
b/contrib/views/hive20/src/main/resources/ui/app/templates/components/create-database-form.hbs
@@ -0,0 +1,31 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you 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.
+}}
+
+<div class="form-group">
+  <label class="col-sm-4 control-label">New Database Name</label>
+  <div class="col-sm-8 {{if error 'has-error'}}">
+    {{input value=newDatabaseName class="form-control" placeholder="Database 
Name"}}
+    <span class="help-block">{{errorMessage}}</span>
+  </div>
+</div>
+<div class="form-group">
+  <div class="col-sm-offset-4 col-sm-8">
+    <button type="submit" class="btn btn-warning" {{action 
"rename"}}>{{fa-icon "pencil-square-o"}} Create</button>
+    <button type="submit" class="btn btn-primary" {{action 
"cancel"}}>{{fa-icon "times"}} Cancel</button>
+  </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5f29c9d/contrib/views/hive20/src/main/resources/ui/app/templates/databases.hbs
----------------------------------------------------------------------
diff --git 
a/contrib/views/hive20/src/main/resources/ui/app/templates/databases.hbs 
b/contrib/views/hive20/src/main/resources/ui/app/templates/databases.hbs
index 9a4a892..bb4d680 100644
--- a/contrib/views/hive20/src/main/resources/ui/app/templates/databases.hbs
+++ b/contrib/views/hive20/src/main/resources/ui/app/templates/databases.hbs
@@ -23,8 +23,8 @@
       {{fa-icon "navicon"}}
     </button>
     <ul class="dropdown-menu dropdown-menu-right">
+      <li>{{#link-to "databases.database.tables.new-database" 
class="text-uppercase"}}{{fa-icon "plus"}} create database{{/link-to}}</li>
       <li><a href="#" {{action "dropDatabase"}} 
class="text-uppercase">{{fa-icon "trash"}} drop database</a></li>
-      <li><a href="#" {{action "createTable"}} 
class="text-uppercase">{{fa-icon "plus"}} create table</a></li>
     </ul>
   </div>
 </div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/b5f29c9d/contrib/views/hive20/src/main/resources/ui/app/templates/databases/database/tables/new-database.hbs
----------------------------------------------------------------------
diff --git 
a/contrib/views/hive20/src/main/resources/ui/app/templates/databases/database/tables/new-database.hbs
 
b/contrib/views/hive20/src/main/resources/ui/app/templates/databases/database/tables/new-database.hbs
new file mode 100644
index 0000000..3b2b99f
--- /dev/null
+++ 
b/contrib/views/hive20/src/main/resources/ui/app/templates/databases/database/tables/new-database.hbs
@@ -0,0 +1,47 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you 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.
+}}
+
+<div class="row">
+  <div class="col-md-12">
+    <div class="alert alert-info">
+      <p class="lead">{{fa-icon "plus" size=1}} Create Database</p>
+    </div>
+  </div>
+
+</div>
+
+<div class="row stats-section">
+  <div class="col-md-6">
+    {{create-database-form create="create" cancel="cancel"}}
+  </div>
+</div>
+
+{{#if showModal}}
+  {{#modal-dialog
+    translucentOverlay=true
+    container-class="modal-dialog modal-sm"}}
+    <div class="modal-content">
+      <div class="modal-header text-danger">
+        <p class="modal-title">{{fa-icon "plus"}}&nbsp;&nbsp;&nbsp; Create 
Database</p>
+      </div>
+      <div class="modal-body text-center text-primary">
+        <p>{{modalMessage}}</p>
+      </div>
+    </div><!-- /.modal-content -->
+  {{/modal-dialog}}
+{{/if}}
\ No newline at end of file

Reply via email to