You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by jo...@apache.org on 2017/02/21 17:06:50 UTC

ambari git commit: AMBARI-20055 - Add Upgrade Logic For Removal of clusterconfigmapping (jonathanhurley)

Repository: ambari
Updated Branches:
  refs/heads/branch-feature-AMBARI-20053 e8e2df21f -> 9386eed40


AMBARI-20055 - Add Upgrade Logic For Removal of clusterconfigmapping (jonathanhurley)


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

Branch: refs/heads/branch-feature-AMBARI-20053
Commit: 9386eed4073cb8b75800f516ddfe01c3f6528bb4
Parents: e8e2df2
Author: Jonathan Hurley <jh...@hortonworks.com>
Authored: Mon Feb 20 13:59:55 2017 -0500
Committer: Jonathan Hurley <jh...@hortonworks.com>
Committed: Mon Feb 20 16:49:10 2017 -0500

----------------------------------------------------------------------
 .../orm/helpers/dbms/GenericDbmsHelper.java     |   2 +-
 .../server/upgrade/UpgradeCatalog300.java       |  92 ++++++++++-
 .../server/upgrade/UpgradeCatalog300Test.java   | 155 +++++++++++++++++--
 3 files changed, 233 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/9386eed4/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/GenericDbmsHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/GenericDbmsHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/GenericDbmsHelper.java
index 36fab83..f60c138 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/GenericDbmsHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/GenericDbmsHelper.java
@@ -426,7 +426,7 @@ public class GenericDbmsHelper implements DbmsHelper {
     // org.eclipse.persistence.internal.databaseaccess.appendParameterInternal
     Object dbValue = databasePlatform.convertToDatabaseType(value);
     String valueString = value.toString();
-    if (dbValue instanceof String) {
+    if (dbValue instanceof String || dbValue instanceof Enum) {
       valueString = "'" + value.toString() + "'";
     }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/9386eed4/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog300.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog300.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog300.java
index 0267a5e..d9b9b57 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog300.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog300.java
@@ -18,7 +18,9 @@
 package org.apache.ambari.server.upgrade;
 
 
+import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.sql.Statement;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -44,6 +46,7 @@ import org.apache.ambari.server.state.Config;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.jdbc.support.JdbcUtils;
 
 import com.google.inject.Inject;
 import com.google.inject.Injector;
@@ -55,11 +58,15 @@ public class UpgradeCatalog300 extends AbstractUpgradeCatalog {
    */
   private static final Logger LOG = LoggerFactory.getLogger(UpgradeCatalog300.class);
 
-  private static final String STAGE_TABLE = "stage";
-  private static final String STAGE_STATUS_COLUMN = "status";
-  private static final String STAGE_DISPLAY_STATUS_COLUMN = "display_status";
-  private static final String REQUEST_TABLE = "request";
-  private static final String REQUEST_DISPLAY_STATUS_COLUMN = "display_status";
+  protected static final String STAGE_TABLE = "stage";
+  protected static final String STAGE_STATUS_COLUMN = "status";
+  protected static final String STAGE_DISPLAY_STATUS_COLUMN = "display_status";
+  protected static final String REQUEST_TABLE = "request";
+  protected static final String REQUEST_DISPLAY_STATUS_COLUMN = "display_status";
+  protected static final String CLUSTER_CONFIG_TABLE = "clusterconfig";
+  protected static final String CLUSTER_CONFIG_SELECTED_COLUMN = "selected";
+  protected static final String CLUSTER_CONFIG_SELECTED_TIMESTAMP_COLUMN = "selected_timestamp";
+  protected static final String CLUSTER_CONFIG_MAPPING_TABLE = "clusterconfigmapping";
 
   @Inject
   DaoUtils daoUtils;
@@ -104,6 +111,7 @@ public class UpgradeCatalog300 extends AbstractUpgradeCatalog {
   @Override
   protected void executeDDLUpdates() throws AmbariException, SQLException {
     updateStageTable();
+    updateClusterConfigurationTable();
   }
 
   protected void updateStageTable() throws SQLException {
@@ -120,6 +128,7 @@ public class UpgradeCatalog300 extends AbstractUpgradeCatalog {
    */
   @Override
   protected void executePreDMLUpdates() throws AmbariException, SQLException {
+    setSelectedConfigurationsAndRemoveMappingTable();
   }
 
   /**
@@ -189,7 +198,80 @@ public class UpgradeCatalog300 extends AbstractUpgradeCatalog {
         }
       }
     });
+  }
+
+  /**
+   * Performs the following operations on {@code clusterconfig}:
+   * <ul>
+   * <li>Adds the {@link #CLUSTER_CONFIG_SELECTED_COLUMN} to
+   * {@link #CLUSTER_CONFIG_TABLE}.
+   * <li>Adds the {@link #CLUSTER_CONFIG_SELECTED_TIMESTAMP} to
+   * {@link #CLUSTER_CONFIG_TABLE}.
+   * </ul>
+   */
+  protected void updateClusterConfigurationTable() throws SQLException {
+    dbAccessor.addColumn(CLUSTER_CONFIG_TABLE,
+        new DBAccessor.DBColumnInfo(CLUSTER_CONFIG_SELECTED_COLUMN, Short.class, null, 0, false));
 
+    dbAccessor.addColumn(CLUSTER_CONFIG_TABLE,
+        new DBAccessor.DBColumnInfo(CLUSTER_CONFIG_SELECTED_TIMESTAMP_COLUMN, Long.class, null, 0,
+            false));
   }
 
+  /**
+   * Performs the following operations on {@code clusterconfig} and
+   * {@code clusterconfigmapping}:
+   * <ul>
+   * <li>Sets both selected columns to the current config by querying
+   * {@link #CLUSTER_CONFIG_MAPPING_TABLE}.
+   * <li>Removes {@link #CLUSTER_CONFIG_MAPPING_TABLE}.
+   * </ul>
+   */
+  protected void setSelectedConfigurationsAndRemoveMappingTable() throws SQLException {
+    // update the new selected columns
+    executeInTransaction(new Runnable() {
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public void run() {
+        String selectSQL = String.format(
+            "SELECT cluster_id, type_name, version_tag FROM %s WHERE selected = 1 ORDER BY cluster_id ASC, type_name ASC, version_tag ASC",
+            CLUSTER_CONFIG_MAPPING_TABLE);
+
+        Statement statement = null;
+        ResultSet resultSet = null;
+
+        long now = System.currentTimeMillis();
+
+        try {
+          statement = dbAccessor.getConnection().createStatement();
+          resultSet = statement.executeQuery(selectSQL);
+
+          while (resultSet.next()) {
+            final Long clusterId = resultSet.getLong("cluster_id");
+            final String typeName = resultSet.getString("type_name");
+            final String versionTag = resultSet.getString("version_tag");
+
+            // inefficient since this can be done with a single nested SELECT,
+            // but this way we can log what's happening which is more useful
+            String updateSQL = String.format(
+                "UPDATE %s SET selected = 1, selected_timestamp = %d WHERE cluster_id = %d AND type_name = '%s' AND version_tag = '%s'",
+                CLUSTER_CONFIG_TABLE, now, clusterId, typeName, versionTag);
+
+            dbAccessor.executeQuery(updateSQL);
+          }
+        } catch (SQLException sqlException) {
+          throw new RuntimeException(sqlException);
+        } finally {
+          JdbcUtils.closeResultSet(resultSet);
+          JdbcUtils.closeStatement(statement);
+        }
+      }
+    });
+
+    // if the above execution and committed the transaction, then we can remove
+    // the cluster configuration mapping table
+    dbAccessor.dropTable(CLUSTER_CONFIG_MAPPING_TABLE);
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/9386eed4/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog300Test.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog300Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog300Test.java
index ec001ec..a44c2b3 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog300Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog300Test.java
@@ -17,16 +17,84 @@
  */
 package org.apache.ambari.server.upgrade;
 
+import static org.easymock.EasyMock.capture;
 import static org.easymock.EasyMock.createMockBuilder;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.newCapture;
 import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.reset;
 import static org.easymock.EasyMock.verify;
 
 import java.lang.reflect.Method;
-
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.Statement;
+
+import javax.persistence.Cache;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityTransaction;
+
+import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.controller.MaintenanceStateHelper;
+import org.apache.ambari.server.orm.DBAccessor;
+import org.apache.ambari.server.state.stack.OsFamily;
+import org.easymock.Capture;
+import org.easymock.EasyMock;
+import org.easymock.EasyMockRunner;
+import org.easymock.Mock;
+import org.easymock.MockType;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.google.gson.Gson;
+import com.google.inject.Binder;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+import com.google.inject.Provider;
 
+@RunWith(EasyMockRunner.class)
 public class UpgradeCatalog300Test {
 
+  @Mock(type = MockType.STRICT)
+  private Provider<EntityManager> entityManagerProvider;
+
+  @Mock(type = MockType.NICE)
+  private Injector injector;
+
+  @Mock(type = MockType.NICE)
+  private EntityManager entityManager;
+
+  @Mock(type = MockType.NICE)
+  private DBAccessor dbAccessor;
+
+  @Mock(type = MockType.NICE)
+  private OsFamily osFamily;
+
+  @Mock(type = MockType.NICE)
+  private Configuration configuration;
+
+  @Before
+  public void init() {
+    reset(entityManagerProvider, injector);
+
+    expect(entityManagerProvider.get()).andReturn(entityManager).anyTimes();
+
+    expect(injector.getInstance(Gson.class)).andReturn(null).anyTimes();
+    expect(injector.getInstance(MaintenanceStateHelper.class)).andReturn(null).anyTimes();
+
+    replay(entityManagerProvider, injector);
+  }
+
+  @After
+  public void tearDown() {
+  }
+
   @Test
   public void testExecuteDMLUpdates() throws Exception {
     Method addNewConfigurationsFromXml = AbstractUpgradeCatalog.class.getDeclaredMethod("addNewConfigurationsFromXml");
@@ -54,19 +122,86 @@ public class UpgradeCatalog300Test {
 
   @Test
   public void testExecuteDDLUpdates() throws Exception {
-    Method updateStageTable = UpgradeCatalog300.class.getDeclaredMethod("updateStageTable");
-    UpgradeCatalog300 upgradeCatalog300 = createMockBuilder(UpgradeCatalog300.class)
-        .addMockedMethod(updateStageTable)
-        .createMock();
-
-    upgradeCatalog300.updateStageTable();
+    Module module = new Module() {
+      @Override
+      public void configure(Binder binder) {
+        binder.bind(DBAccessor.class).toInstance(dbAccessor);
+        binder.bind(OsFamily.class).toInstance(osFamily);
+        binder.bind(EntityManager.class).toInstance(entityManager);
+        binder.bind(Configuration.class).toInstance(configuration);
+      }
+    };
+
+    Capture<DBAccessor.DBColumnInfo> clusterConfigSelectedColumn = newCapture();
+    Capture<DBAccessor.DBColumnInfo> clusterConfigSelectedTimestampColumn = newCapture();
+    dbAccessor.addColumn(eq(UpgradeCatalog300.CLUSTER_CONFIG_TABLE), capture(clusterConfigSelectedColumn));
+    dbAccessor.addColumn(eq(UpgradeCatalog300.CLUSTER_CONFIG_TABLE), capture(clusterConfigSelectedTimestampColumn));
+
+    replay(dbAccessor, configuration);
+
+    Injector injector = Guice.createInjector(module);
+    UpgradeCatalog300 upgradeCatalog300 = injector.getInstance(UpgradeCatalog300.class);
+    upgradeCatalog300.executeDDLUpdates();
 
-    replay(upgradeCatalog300);
+    DBAccessor.DBColumnInfo capturedSelectedColumn = clusterConfigSelectedColumn.getValue();
+    Assert.assertNotNull(capturedSelectedColumn);
+    Assert.assertEquals(UpgradeCatalog300.CLUSTER_CONFIG_SELECTED_COLUMN, capturedSelectedColumn.getName());
+    Assert.assertEquals(Short.class, capturedSelectedColumn.getType());
 
-    upgradeCatalog300.executeDDLUpdates();
+    DBAccessor.DBColumnInfo capturedSelectedTimestampColumn = clusterConfigSelectedTimestampColumn.getValue();
+    Assert.assertNotNull(capturedSelectedTimestampColumn);
+    Assert.assertEquals(UpgradeCatalog300.CLUSTER_CONFIG_SELECTED_TIMESTAMP_COLUMN, capturedSelectedTimestampColumn.getName());
+    Assert.assertEquals(Long.class, capturedSelectedTimestampColumn.getType());
 
-    verify(upgradeCatalog300);
+    verify(dbAccessor);
   }
 
+  /**
+   * Tests pre-DML executions.
+   *
+   * @throws Exception
+   */
+  @Test
+  public void testExecutePreDMLUpdates() throws Exception {
+    Module module = new Module() {
+      @Override
+      public void configure(Binder binder) {
+        binder.bind(DBAccessor.class).toInstance(dbAccessor);
+        binder.bind(OsFamily.class).toInstance(osFamily);
+        binder.bind(EntityManager.class).toInstance(entityManager);
+        binder.bind(Configuration.class).toInstance(configuration);
+      }
+    };
+
+    EntityManagerFactory emFactory = EasyMock.createNiceMock(EntityManagerFactory.class);
+    Cache emCache = EasyMock.createNiceMock(Cache.class);
+
+    expect(entityManager.getEntityManagerFactory()).andReturn(emFactory).atLeastOnce();
+    expect(emFactory.getCache()).andReturn(emCache).atLeastOnce();
+
+    EntityTransaction mockTransaction = EasyMock.createNiceMock(EntityTransaction.class);
+    Connection mockConnection = EasyMock.createNiceMock(Connection.class);
+    Statement mockStatement = EasyMock.createNiceMock(Statement.class);
 
+    expect(dbAccessor.getConnection()).andReturn(mockConnection).once();
+    expect(mockConnection.createStatement()).andReturn(mockStatement).once();
+
+    expect(mockStatement.executeQuery(EasyMock.anyString())).andReturn(
+        EasyMock.createNiceMock(ResultSet.class));
+
+    expect(entityManager.getTransaction()).andReturn(
+        mockTransaction).atLeastOnce();
+
+    dbAccessor.dropTable(UpgradeCatalog300.CLUSTER_CONFIG_MAPPING_TABLE);
+    EasyMock.expectLastCall().once();
+
+    replay(dbAccessor, entityManager, emFactory, emCache, mockConnection, mockTransaction,
+        mockStatement, configuration);
+
+    Injector injector = Guice.createInjector(module);
+    UpgradeCatalog300 upgradeCatalog300 = injector.getInstance(UpgradeCatalog300.class);
+    upgradeCatalog300.executePreDMLUpdates();
+
+    verify(dbAccessor, entityManager, emFactory, emCache);
+  }
 }