This is an automated email from the ASF dual-hosted git repository.

krisztiankasa pushed a commit to branch branch-2.7
in repository https://gitbox.apache.org/repos/asf/ambari.git


The following commit(s) were added to refs/heads/branch-2.7 by this push:
     new 1c25b10  AMBARI-24283 - DB consistency warning due to config group 
without service name (#1915) (#1928)
1c25b10 is described below

commit 1c25b1019b8eaa6b03882ae4ee7bdd99b9ae1d5d
Author: kasakrisz <33458261+kasakr...@users.noreply.github.com>
AuthorDate: Wed Aug 1 07:00:25 2018 +0200

    AMBARI-24283 - DB consistency warning due to config group without service 
name (#1915) (#1928)
---
 .../checks/DatabaseConsistencyCheckHelper.java     | 248 ++++++++++++++++++++
 .../ambari/server/upgrade/UpgradeCatalog271.java   |  44 +++-
 .../checks/DatabaseConsistencyCheckHelperTest.java | 257 +++++++++++++++++++++
 .../server/upgrade/UpgradeCatalog271Test.java      |   5 +
 4 files changed, 553 insertions(+), 1 deletion(-)

diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelper.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelper.java
index 669ab81..375bcd9 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelper.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelper.java
@@ -36,6 +36,7 @@ import java.util.Scanner;
 import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
 import javax.annotation.Nullable;
 import javax.inject.Provider;
@@ -59,14 +60,19 @@ import 
org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntity;
 import org.apache.ambari.server.orm.entities.HostComponentStateEntity;
 import org.apache.ambari.server.orm.entities.MetainfoEntity;
 import 
org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity;
+import org.apache.ambari.server.security.authorization.AuthorizationException;
 import org.apache.ambari.server.state.ClientConfigFileDefinition;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.ComponentInfo;
+import org.apache.ambari.server.state.Host;
+import org.apache.ambari.server.state.Service;
 import org.apache.ambari.server.state.ServiceInfo;
 import org.apache.ambari.server.state.State;
 import org.apache.ambari.server.state.UpgradeState;
+import org.apache.ambari.server.state.configgroup.ConfigGroup;
 import org.apache.ambari.server.utils.VersionUtils;
+import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -181,6 +187,9 @@ public class DatabaseConsistencyCheckHelper {
       if (fixIssues) {
         fixHostComponentStatesCountEqualsHostComponentsDesiredStates();
         fixClusterConfigsNotMappedToAnyService();
+        fixConfigGroupServiceNames();
+        fixConfigGroupHostMappings();
+        fixConfigGroupsForDeletedServices();
         fixConfigsSelectedMoreThanOnce();
       }
       checkSchemaName();
@@ -191,6 +200,9 @@ public class DatabaseConsistencyCheckHelper {
       checkHostComponentStates();
       checkServiceConfigs();
       checkForLargeTables();
+      checkConfigGroupsHasServiceName();
+      checkConfigGroupHostMapping(true);
+      checkConfigGroupsForDeletedServices(true);
       LOG.info("******************************* Check database completed 
*******************************");
       return checkResult;
     }
@@ -1147,6 +1159,242 @@ public class DatabaseConsistencyCheckHelper {
 
   }
 
+  /**
+   * This method collects the ConfigGroups with empty or null service name 
field
+   */
+  static Map<Long, ConfigGroup> collectConfigGroupsWithoutServiceName() {
+    Map<Long, ConfigGroup> configGroupMap = new HashMap<>();
+    Clusters clusters = injector.getInstance(Clusters.class);
+    Map<String, Cluster> clusterMap = clusters.getClusters();
+
+    if (MapUtils.isEmpty(clusterMap))
+      return configGroupMap;
+
+    for (Cluster cluster : clusterMap.values()) {
+      Map<Long, ConfigGroup> configGroups = cluster.getConfigGroups();
+
+      if (MapUtils.isEmpty(configGroups)) {
+        continue;
+      }
+
+      for (ConfigGroup configGroup : configGroups.values()) {
+        if (StringUtils.isEmpty(configGroup.getServiceName())) {
+          configGroupMap.put(configGroup.getId(), configGroup);
+        }
+      }
+    }
+
+    return configGroupMap;
+  }
+
+  /**
+   * This method checks if there are any ConfigGroup with empty or null 
service name field
+   */
+  static void checkConfigGroupsHasServiceName() {
+    Map<Long, ConfigGroup> configGroupMap = 
collectConfigGroupsWithoutServiceName();
+    if (MapUtils.isEmpty(configGroupMap))
+      return;
+
+    String message = String.join(" ), ( ",
+            
configGroupMap.values().stream().map(ConfigGroup::getName).collect(Collectors.toList()));
+
+    warning("You have config groups present in the database with no " +
+            "service name, [(ConfigGroup) => ( {} )]. Run --auto-fix-database 
to fix " +
+            "this automatically. Please backup Ambari Server database before 
running --auto-fix-database.", message);
+  }
+
+  /**
+   * Fix inconsistencies found by @collectConfigGroupsWithoutServiceName
+   */
+  @Transactional
+  static void fixConfigGroupServiceNames() {
+    Map<Long, ConfigGroup> configGroupMap = 
collectConfigGroupsWithoutServiceName();
+    if (MapUtils.isEmpty(configGroupMap))
+      return;
+
+    Clusters clusters = injector.getInstance(Clusters.class);
+
+    for (Map.Entry<Long, ConfigGroup> configGroupEntry : 
configGroupMap.entrySet()) {
+      ConfigGroup configGroup = configGroupEntry.getValue();
+      try {
+        Cluster cluster = clusters.getCluster(configGroup.getClusterName());
+        Map<String, Service> serviceMap = cluster.getServices();
+        if (serviceMap.containsKey(configGroup.getTag())) {
+          LOG.info("Setting service name of config group {} with id {} to {}",
+                  configGroup.getName(), configGroupEntry.getKey(), 
configGroup.getTag());
+          configGroup.setServiceName(configGroup.getTag());
+        }
+        else {
+          LOG.info("Config group {} with id {} contains a tag {} which is not 
a service name in the cluster {}",
+                  configGroup.getName(), configGroupEntry.getKey(), 
configGroup.getTag(), cluster.getClusterName());
+        }
+      } catch (AmbariException e) {
+        // Ignore if cluster not found
+      }
+    }
+  }
+
+  /**
+   * This method checks if there are any ConfigGroup host mappings with hosts
+   * that are not longer a part of the cluster.
+   */
+  static Map<Long, Set<Long>> checkConfigGroupHostMapping(boolean warnIfFound) 
{
+    LOG.info("Checking config group host mappings");
+    Map<Long, Set<Long>> nonMappedHostIds = new HashMap<>();
+    Clusters clusters = injector.getInstance(Clusters.class);
+    Map<String, Cluster> clusterMap = clusters.getClusters();
+    StringBuilder output = new StringBuilder("[(ConfigGroup, Service, 
HostCount) => ");
+
+    if (!MapUtils.isEmpty(clusterMap)) {
+      for (Cluster cluster : clusterMap.values()) {
+        Map<Long, ConfigGroup> configGroups = cluster.getConfigGroups();
+        Map<String, Host> clusterHosts = 
clusters.getHostsForCluster(cluster.getClusterName());
+
+        if (!MapUtils.isEmpty(configGroups) && 
!MapUtils.isEmpty(clusterHosts)) {
+          for (ConfigGroup configGroup : configGroups.values()) {
+            // Based on current implementation of ConfigGroupImpl the
+            // host mapping would be loaded only if the host actually exists
+            // in the host table
+            Map<Long, Host> hosts = configGroup.getHosts();
+            boolean addToOutput = false;
+            Set<String> hostnames = new HashSet<>();
+            if (!MapUtils.isEmpty(hosts)) {
+              for (Host host : hosts.values()) {
+                // Lookup by hostname - It does have a unique constraint
+                if (!clusterHosts.containsKey(host.getHostName())) {
+                  Set<Long> hostIds = 
nonMappedHostIds.computeIfAbsent(configGroup.getId(), configGroupId -> new 
HashSet<>());
+                  hostIds.add(host.getHostId());
+                  hostnames.add(host.getHostName());
+                  addToOutput = true;
+                }
+              }
+            }
+            if (addToOutput) {
+              output.append("( ");
+              output.append(configGroup.getName());
+              output.append(", ");
+              output.append(configGroup.getTag());
+              output.append(", ");
+              output.append(hostnames);
+              output.append(" ), ");
+            }
+          }
+        }
+      }
+    }
+    if (!MapUtils.isEmpty(nonMappedHostIds) && warnIfFound) {
+      output.replace(output.lastIndexOf(","), output.length(), "]");
+      warning("You have config group host mappings with hosts that are no " +
+        "longer associated with the cluster, {}. Run --auto-fix-database to " +
+        "fix this automatically. Alternatively, you can remove this mapping " +
+        "from the UI. Please backup Ambari Server database before running 
--auto-fix-database.", output.toString());
+    }
+
+    return nonMappedHostIds;
+  }
+
+  static Map<Long, ConfigGroup> checkConfigGroupsForDeletedServices(boolean 
warnIfFound) {
+    Map<Long, ConfigGroup> configGroupMap = new HashMap<>();
+    Clusters clusters = injector.getInstance(Clusters.class);
+    Map<String, Cluster> clusterMap = clusters.getClusters();
+    StringBuilder output = new StringBuilder("[(ConfigGroup, Service) => ");
+
+    if (!MapUtils.isEmpty(clusterMap)) {
+      for (Cluster cluster : clusterMap.values()) {
+        Map<Long, ConfigGroup> configGroups = cluster.getConfigGroups();
+        Map<String, Service> services = cluster.getServices();
+
+        if (!MapUtils.isEmpty(configGroups)) {
+          for (ConfigGroup configGroup : configGroups.values()) {
+            if (!services.containsKey(configGroup.getServiceName())) {
+              configGroupMap.put(configGroup.getId(), configGroup);
+              output.append("( ");
+              output.append(configGroup.getName());
+              output.append(", ");
+              output.append(configGroup.getServiceName());
+              output.append(" ), ");
+            }
+          }
+        }
+      }
+    }
+
+    if (warnIfFound && !configGroupMap.isEmpty()) {
+      output.replace(output.lastIndexOf(","), output.length(), "]");
+      warning("You have config groups present in the database with no " +
+        "corresponding service found, {}. Run --auto-fix-database to fix " +
+          "this automatically. Please backup Ambari Server database before 
running --auto-fix-database.", output.toString());
+    }
+
+    return configGroupMap;
+  }
+
+  @Transactional
+  static void fixConfigGroupsForDeletedServices() {
+    Map<Long, ConfigGroup> configGroupMap = 
checkConfigGroupsForDeletedServices(false);
+    Clusters clusters = injector.getInstance(Clusters.class);
+
+    if (!MapUtils.isEmpty(configGroupMap)) {
+      for (Map.Entry<Long, ConfigGroup> configGroupEntry : 
configGroupMap.entrySet()) {
+        Long id = configGroupEntry.getKey();
+        ConfigGroup configGroup = configGroupEntry.getValue();
+        if (!StringUtils.isEmpty(configGroup.getServiceName())) {
+          LOG.info("Deleting config group {} with id {} for deleted service 
{}",
+                  configGroup.getName(), id, configGroup.getServiceName());
+          try {
+            Cluster cluster = 
clusters.getCluster(configGroup.getClusterName());
+            cluster.deleteConfigGroup(id);
+          } catch (AuthorizationException e) {
+            // This call does not thrown Authorization Exception
+          } catch (AmbariException e) {
+            // Ignore if cluster not found
+          }
+        }
+        else {
+          warning("The config group {} with id {} can not be fixed 
automatically because service name is missing.",
+                  configGroup.getName(), id);
+        }
+      }
+    }
+  }
+
+  /**
+   * Fix inconsistencies found by @checkConfigGroupHostMapping
+   */
+  @Transactional
+  static void fixConfigGroupHostMappings() {
+    Map<Long, Set<Long>> nonMappedHostIds = checkConfigGroupHostMapping(false);
+    Clusters clusters = injector.getInstance(Clusters.class);
+
+    if (!MapUtils.isEmpty(nonMappedHostIds)) {
+      LOG.info("Fixing {} config groups with inconsistent host mappings", 
nonMappedHostIds.size());
+
+      for (Map.Entry<Long, Set<Long>> nonMappedHostEntry : 
nonMappedHostIds.entrySet()) {
+        if (!MapUtils.isEmpty(clusters.getClusters())) {
+          for (Cluster cluster : clusters.getClusters().values()) {
+            Map<Long, ConfigGroup> configGroups = cluster.getConfigGroups();
+            if (!MapUtils.isEmpty(configGroups)) {
+              ConfigGroup configGroup = 
configGroups.get(nonMappedHostEntry.getKey());
+              if (configGroup != null) {
+                for (Long hostId : nonMappedHostEntry.getValue()) {
+                  try {
+                    configGroup.removeHost(hostId);
+                  } catch (AmbariException e) {
+                    LOG.warn("Unable to fix inconsistency by removing host " +
+                      "mapping for config group: {}, service: {}, hostId = {}",
+                      configGroup.getName(), configGroup.getTag(), hostId);
+                  }
+                }
+              } else {
+                LOG.warn("Unable to find config group with id = {}", 
nonMappedHostEntry.getKey());
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
   private static void ensureConnection() {
     if (connection == null) {
       if (dbAccessor == null) {
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog271.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog271.java
index c8a4d99..010ab62 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog271.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog271.java
@@ -17,6 +17,9 @@
  */
 package org.apache.ambari.server.upgrade;
 
+import static 
org.apache.ambari.server.upgrade.UpgradeCatalog270.AMBARI_INFRA_NEW_NAME;
+import static 
org.apache.ambari.server.upgrade.UpgradeCatalog270.AMBARI_INFRA_OLD_NAME;
+
 import java.sql.SQLException;
 import java.util.HashMap;
 import java.util.Map;
@@ -24,13 +27,17 @@ import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.orm.dao.DaoUtils;
+import org.apache.ambari.server.orm.entities.ServiceConfigEntity;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.Config;
-
+import org.apache.commons.collections.MapUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -97,6 +104,7 @@ public class UpgradeCatalog271 extends 
AbstractUpgradeCatalog {
     addNewConfigurationsFromXml();
     updateRangerLogDirConfigs();
     updateRangerKmsDbUrl();
+    renameAmbariInfraInConfigGroups();
   }
 
   /**
@@ -195,4 +203,38 @@ public class UpgradeCatalog271 extends 
AbstractUpgradeCatalog {
     }
   }
 
+  protected void renameAmbariInfraInConfigGroups() {
+    LOG.info("Renaming service AMBARI_INFRA to AMBARI_INFRA_SOLR in config 
group records");
+    AmbariManagementController ambariManagementController = 
injector.getInstance(AmbariManagementController.class);
+    Clusters clusters = ambariManagementController.getClusters();
+    if (clusters == null)
+      return;
+
+    Map<String, Cluster> clusterMap = clusters.getClusters();
+    if (MapUtils.isEmpty(clusterMap))
+      return;
+
+    EntityManager entityManager = getEntityManagerProvider().get();
+
+    executeInTransaction(() -> {
+      TypedQuery<ServiceConfigEntity> serviceConfigUpdate = 
entityManager.createQuery(
+              "UPDATE ConfigGroupEntity SET serviceName = :newServiceName 
WHERE serviceName = :oldServiceName", ServiceConfigEntity.class);
+      serviceConfigUpdate.setParameter("newServiceName", 
AMBARI_INFRA_NEW_NAME);
+      serviceConfigUpdate.setParameter("oldServiceName", 
AMBARI_INFRA_OLD_NAME);
+      serviceConfigUpdate.executeUpdate();
+    });
+
+    executeInTransaction(() -> {
+      TypedQuery<ServiceConfigEntity> serviceConfigUpdate = 
entityManager.createQuery(
+              "UPDATE ConfigGroupEntity SET tag = :newServiceName WHERE tag = 
:oldServiceName", ServiceConfigEntity.class);
+      serviceConfigUpdate.setParameter("newServiceName", 
AMBARI_INFRA_NEW_NAME);
+      serviceConfigUpdate.setParameter("oldServiceName", 
AMBARI_INFRA_OLD_NAME);
+      serviceConfigUpdate.executeUpdate();
+    });
+
+
+    // Force the clusters object to reload to ensure the renamed service is 
accounted for
+    entityManager.getEntityManagerFactory().getCache().evictAll();
+    clusters.invalidateAllClusters();
+  }
 }
\ No newline at end of file
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelperTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelperTest.java
index 91b18e1..e38b24f 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelperTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelperTest.java
@@ -40,6 +40,7 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import javax.persistence.EntityManager;
 import javax.persistence.TypedQuery;
@@ -52,9 +53,13 @@ import 
org.apache.ambari.server.orm.entities.ClusterConfigEntity;
 import org.apache.ambari.server.stack.StackManagerFactory;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.Host;
+import org.apache.ambari.server.state.Service;
 import org.apache.ambari.server.state.ServiceInfo;
+import org.apache.ambari.server.state.configgroup.ConfigGroup;
 import org.apache.ambari.server.state.stack.OsFamily;
 import org.apache.ambari.server.testutils.PartialNiceMockBinder;
+import org.apache.commons.collections.MapUtils;
 import org.easymock.EasyMockSupport;
 import org.junit.Assert;
 import org.junit.Test;
@@ -523,6 +528,258 @@ public class DatabaseConsistencyCheckHelperTest {
   }
 
   @Test
+  public void testConfigGroupHostMappings() throws Exception {
+    EasyMockSupport easyMockSupport = new EasyMockSupport();
+
+    final DBAccessor mockDBDbAccessor = 
easyMockSupport.createNiceMock(DBAccessor.class);
+
+    final StackManagerFactory mockStackManagerFactory = 
easyMockSupport.createNiceMock(StackManagerFactory.class);
+    final EntityManager mockEntityManager = 
easyMockSupport.createNiceMock(EntityManager.class);
+    final Clusters mockClusters = 
easyMockSupport.createNiceMock(Clusters.class);
+    final OsFamily mockOSFamily = 
easyMockSupport.createNiceMock(OsFamily.class);
+    final Injector mockInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(StackManagerFactory.class).toInstance(mockStackManagerFactory);
+        bind(EntityManager.class).toInstance(mockEntityManager);
+        bind(DBAccessor.class).toInstance(mockDBDbAccessor);
+        bind(Clusters.class).toInstance(mockClusters);
+        bind(OsFamily.class).toInstance(mockOSFamily);
+      }
+    });
+
+    Map<String, Cluster> clusters = new HashMap<>();
+    Cluster cluster = easyMockSupport.createNiceMock(Cluster.class);
+    clusters.put("c1", cluster);
+    expect(mockClusters.getClusters()).andReturn(clusters).anyTimes();
+
+    Map<Long, ConfigGroup> configGroupMap = new HashMap<>();
+    ConfigGroup cg1 = easyMockSupport.createNiceMock(ConfigGroup.class);
+    ConfigGroup cg2 = easyMockSupport.createNiceMock(ConfigGroup.class);
+    configGroupMap.put(1L, cg1);
+    configGroupMap.put(2L, cg2);
+
+    expect(cluster.getConfigGroups()).andReturn(configGroupMap).anyTimes();
+
+    expect(cluster.getClusterName()).andReturn("c1").anyTimes();
+
+    Map<String, Host> hosts = new HashMap<>();
+    Host h1 = easyMockSupport.createNiceMock(Host.class);
+    Host h2 = easyMockSupport.createNiceMock(Host.class);
+    hosts.put("h1", h1);
+    expect(mockClusters.getHostsForCluster("c1")).andReturn(hosts);
+
+    Map<Long, Host> cgHosts = new HashMap<>();
+    cgHosts.put(1L, h1);
+    cgHosts.put(2L, h2);
+
+    expect(cg1.getHosts()).andReturn(cgHosts);
+
+    expect(h1.getHostName()).andReturn("h1").anyTimes();
+    expect(h2.getHostName()).andReturn("h2").anyTimes() ;
+    expect(h1.getHostId()).andReturn(1L).anyTimes();
+    expect(h2.getHostId()).andReturn(2L).anyTimes();
+
+    expect(cg1.getId()).andReturn(1L).anyTimes();
+    expect(cg2.getId()).andReturn(2L).anyTimes();
+    expect(cg1.getName()).andReturn("cg1").anyTimes();
+    expect(cg2.getName()).andReturn("cg2").anyTimes();
+
+    DatabaseConsistencyCheckHelper.setInjector(mockInjector);
+
+    easyMockSupport.replayAll();
+
+    Map<Long, Set<Long>> hostIds = 
DatabaseConsistencyCheckHelper.checkConfigGroupHostMapping(true);
+
+    easyMockSupport.verifyAll();
+
+    Assert.assertNotNull(hostIds);
+    Assert.assertEquals(1, hostIds.size());
+    Assert.assertEquals(1L, hostIds.keySet().iterator().next().longValue());
+    Assert.assertEquals(2L, hostIds.get(1L).iterator().next().longValue());
+  }
+
+  @Test
+  public void testConfigGroupForDeletedServices() throws Exception {
+    EasyMockSupport easyMockSupport = new EasyMockSupport();
+
+    final DBAccessor mockDBDbAccessor = 
easyMockSupport.createNiceMock(DBAccessor.class);
+
+    final StackManagerFactory mockStackManagerFactory = 
easyMockSupport.createNiceMock(StackManagerFactory.class);
+    final EntityManager mockEntityManager = 
easyMockSupport.createNiceMock(EntityManager.class);
+    final Clusters mockClusters = 
easyMockSupport.createNiceMock(Clusters.class);
+    final OsFamily mockOSFamily = 
easyMockSupport.createNiceMock(OsFamily.class);
+    final Injector mockInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(StackManagerFactory.class).toInstance(mockStackManagerFactory);
+        bind(EntityManager.class).toInstance(mockEntityManager);
+        bind(DBAccessor.class).toInstance(mockDBDbAccessor);
+        bind(Clusters.class).toInstance(mockClusters);
+        bind(OsFamily.class).toInstance(mockOSFamily);
+      }
+    });
+
+    Map<String, Cluster> clusters = new HashMap<>();
+    Cluster cluster = easyMockSupport.createStrictMock(Cluster.class);
+    clusters.put("c1", cluster);
+    expect(mockClusters.getClusters()).andReturn(clusters).anyTimes();
+
+    Map<Long, ConfigGroup> configGroupMap = new HashMap<>();
+    ConfigGroup cg1 = easyMockSupport.createNiceMock(ConfigGroup.class);
+    ConfigGroup cg2 = easyMockSupport.createNiceMock(ConfigGroup.class);
+    ConfigGroup cgWithoutServiceName = 
easyMockSupport.createNiceMock(ConfigGroup.class);
+    configGroupMap.put(1L, cg1);
+    configGroupMap.put(2L, cg2);
+    configGroupMap.put(3L, cgWithoutServiceName);
+
+    expect(cluster.getConfigGroups()).andStubReturn(configGroupMap);
+    expect(cg1.getName()).andReturn("cg1").anyTimes();
+    expect(cg1.getId()).andReturn(1L).anyTimes();
+    expect(cg1.getServiceName()).andReturn("YARN").anyTimes();
+    expect(cg2.getServiceName()).andReturn("HDFS").anyTimes();
+    expect(cgWithoutServiceName.getName()).andReturn("cg3").anyTimes();
+    expect(cgWithoutServiceName.getId()).andReturn(3L).anyTimes();
+    expect(cgWithoutServiceName.getServiceName()).andReturn(null).anyTimes();
+
+    Service service = easyMockSupport.createNiceMock(Service.class);
+    Map<String, Service> services = new HashMap<>();
+    services.put("HDFS", service);
+    expect(cluster.getServices()).andReturn(services).anyTimes();
+
+    expect(cg1.getClusterName()).andReturn("c1");
+    expect(mockClusters.getCluster("c1")).andReturn(cluster).anyTimes();
+    cluster.deleteConfigGroup(1L);
+    expectLastCall();
+
+    DatabaseConsistencyCheckHelper.setInjector(mockInjector);
+
+    easyMockSupport.replayAll();
+
+    Map<Long, ConfigGroup> configGroups = 
DatabaseConsistencyCheckHelper.checkConfigGroupsForDeletedServices(true);
+    DatabaseConsistencyCheckHelper.fixConfigGroupsForDeletedServices();
+
+    easyMockSupport.verifyAll();
+
+    Assert.assertFalse(MapUtils.isEmpty(configGroups));
+    Assert.assertEquals(2, configGroups.size());
+    Assert.assertTrue(configGroups.containsKey(1L));
+    Assert.assertFalse(configGroups.containsKey(2L));
+    Assert.assertTrue(configGroups.containsKey(3L));
+  }
+
+  @Test
+  public void testCollectConfigGroupsWithoutServiceName() throws Exception {
+    EasyMockSupport easyMockSupport = new EasyMockSupport();
+
+    final DBAccessor mockDBDbAccessor = 
easyMockSupport.createNiceMock(DBAccessor.class);
+
+    final StackManagerFactory mockStackManagerFactory = 
easyMockSupport.createNiceMock(StackManagerFactory.class);
+    final EntityManager mockEntityManager = 
easyMockSupport.createNiceMock(EntityManager.class);
+    final Clusters mockClusters = 
easyMockSupport.createNiceMock(Clusters.class);
+    final OsFamily mockOSFamily = 
easyMockSupport.createNiceMock(OsFamily.class);
+    final Injector mockInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(StackManagerFactory.class).toInstance(mockStackManagerFactory);
+        bind(EntityManager.class).toInstance(mockEntityManager);
+        bind(DBAccessor.class).toInstance(mockDBDbAccessor);
+        bind(Clusters.class).toInstance(mockClusters);
+        bind(OsFamily.class).toInstance(mockOSFamily);
+      }
+    });
+
+    Map<String, Cluster> clusters = new HashMap<>();
+    Cluster cluster1 = easyMockSupport.createNiceMock(Cluster.class);
+    clusters.put("c1", cluster1);
+    Cluster cluster2 = easyMockSupport.createNiceMock(Cluster.class);
+    clusters.put("c2", cluster2);
+    expect(cluster2.getConfigGroups()).andReturn(new HashMap<Long, 
ConfigGroup>(0)).anyTimes();
+    expect(mockClusters.getClusters()).andReturn(clusters).anyTimes();
+    expect(mockClusters.getCluster("c1")).andReturn(cluster1).anyTimes();
+    expect(mockClusters.getCluster("c2")).andReturn(cluster2).anyTimes();
+
+    Map<Long, ConfigGroup> configGroupMap = new HashMap<>();
+    ConfigGroup cgWithoutServiceName = 
easyMockSupport.createNiceMock(ConfigGroup.class);
+    ConfigGroup cgWithServiceName = 
easyMockSupport.createNiceMock(ConfigGroup.class);
+    ConfigGroup cgForNonExistentService = 
easyMockSupport.createNiceMock(ConfigGroup.class);
+    configGroupMap.put(1L, cgWithoutServiceName);
+    configGroupMap.put(2L, cgWithServiceName);
+    configGroupMap.put(3L, cgForNonExistentService);
+
+    expect(cluster1.getConfigGroups()).andReturn(configGroupMap).anyTimes();
+    expect(cgWithoutServiceName.getId()).andReturn(1L).anyTimes();
+    expect(cgWithoutServiceName.getClusterName()).andReturn("c1").anyTimes();
+    expect(cgWithoutServiceName.getServiceName()).andReturn(null).anyTimes();
+    expect(cgWithoutServiceName.getTag()).andReturn("YARN").anyTimes();
+    cgWithoutServiceName.setServiceName("YARN"); expectLastCall();
+    expect(cgWithServiceName.getId()).andReturn(2L).anyTimes();
+    expect(cgWithServiceName.getClusterName()).andReturn("c1").anyTimes();
+    expect(cgWithServiceName.getServiceName()).andReturn("HDFS").anyTimes();
+    expect(cgForNonExistentService.getId()).andReturn(3L).anyTimes();
+    
expect(cgForNonExistentService.getClusterName()).andReturn("c1").anyTimes();
+    
expect(cgForNonExistentService.getServiceName()).andReturn(null).anyTimes();
+    
expect(cgForNonExistentService.getTag()).andReturn("NOT_EXISTS").anyTimes();
+
+    Service hdfsService = easyMockSupport.createNiceMock(Service.class);
+    Service yarnService = easyMockSupport.createNiceMock(Service.class);
+    Map<String, Service> services = new HashMap<>();
+    services.put("HDFS", hdfsService);
+    services.put("YARN", yarnService);
+    expect(cluster1.getServices()).andReturn(services).anyTimes();
+
+    DatabaseConsistencyCheckHelper.setInjector(mockInjector);
+
+    easyMockSupport.replayAll();
+
+    Map<Long, ConfigGroup> configGroups = 
DatabaseConsistencyCheckHelper.collectConfigGroupsWithoutServiceName();
+    DatabaseConsistencyCheckHelper.fixConfigGroupServiceNames();
+
+    easyMockSupport.verifyAll();
+
+    Assert.assertFalse(MapUtils.isEmpty(configGroups));
+    Assert.assertEquals(2, configGroups.size());
+    Assert.assertTrue(configGroups.containsKey(1L));
+    Assert.assertFalse(configGroups.containsKey(2L));
+    Assert.assertTrue(configGroups.containsKey(3L));
+  }
+
+  @Test
+  public void 
testCollectConfigGroupsWithoutServiceNameReturnsEmptyMapWhenNoClusters() throws 
Exception {
+    EasyMockSupport easyMockSupport = new EasyMockSupport();
+
+    final DBAccessor mockDBDbAccessor = 
easyMockSupport.createNiceMock(DBAccessor.class);
+
+    final StackManagerFactory mockStackManagerFactory = 
easyMockSupport.createNiceMock(StackManagerFactory.class);
+    final EntityManager mockEntityManager = 
easyMockSupport.createNiceMock(EntityManager.class);
+    final Clusters mockClusters = 
easyMockSupport.createNiceMock(Clusters.class);
+    final OsFamily mockOSFamily = 
easyMockSupport.createNiceMock(OsFamily.class);
+    final Injector mockInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(StackManagerFactory.class).toInstance(mockStackManagerFactory);
+        bind(EntityManager.class).toInstance(mockEntityManager);
+        bind(DBAccessor.class).toInstance(mockDBDbAccessor);
+        bind(Clusters.class).toInstance(mockClusters);
+        bind(OsFamily.class).toInstance(mockOSFamily);
+      }
+    });
+
+    Map<String, Cluster> clusters = new HashMap<>();
+    expect(mockClusters.getClusters()).andReturn(clusters).anyTimes();
+
+    DatabaseConsistencyCheckHelper.setInjector(mockInjector);
+
+    easyMockSupport.replayAll();
+
+    Map<Long, ConfigGroup> configGroups = 
DatabaseConsistencyCheckHelper.collectConfigGroupsWithoutServiceName();
+
+    easyMockSupport.verifyAll();
+
+    Assert.assertTrue(MapUtils.isEmpty(configGroups));
+  }
+
+  @Test
   public void testFixConfigsSelectedMoreThanOnce() throws Exception {
     EasyMockSupport easyMockSupport = new EasyMockSupport();
 
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog271Test.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog271Test.java
index d7a1069..8d397f0 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog271Test.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog271Test.java
@@ -55,11 +55,13 @@ public class UpgradeCatalog271Test {
     Method addNewConfigurationsFromXml = 
AbstractUpgradeCatalog.class.getDeclaredMethod("addNewConfigurationsFromXml");
     Method updateRangerLogDirConfigs = 
UpgradeCatalog271.class.getDeclaredMethod("updateRangerLogDirConfigs");
     Method updateRangerKmsDbUrl = 
UpgradeCatalog271.class.getDeclaredMethod("updateRangerKmsDbUrl");
+    Method renameAmbariInfraInConfigGroups = 
UpgradeCatalog271.class.getDeclaredMethod("renameAmbariInfraInConfigGroups");
 
     UpgradeCatalog271 upgradeCatalog271 = 
createMockBuilder(UpgradeCatalog271.class)
       .addMockedMethod(updateRangerKmsDbUrl)
       .addMockedMethod(updateRangerLogDirConfigs)
       .addMockedMethod(addNewConfigurationsFromXml)
+      .addMockedMethod(renameAmbariInfraInConfigGroups)
       .createMock();
 
     upgradeCatalog271.addNewConfigurationsFromXml();
@@ -71,6 +73,9 @@ public class UpgradeCatalog271Test {
     upgradeCatalog271.updateRangerKmsDbUrl();
     expectLastCall().once();
 
+    upgradeCatalog271.renameAmbariInfraInConfigGroups();
+    expectLastCall().once();
+
     replay(upgradeCatalog271);
     upgradeCatalog271.executeDMLUpdates();
     verify(upgradeCatalog271);

Reply via email to