You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by mp...@apache.org on 2019/01/25 18:57:13 UTC

[ambari] branch trunk updated: AMBARI-24606. Deleting a service should do a better job of cleaning up the Ambari DB. (#2784)

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

mpapirkovskyy pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 845f777  AMBARI-24606. Deleting a service should do a better job of cleaning up the Ambari DB. (#2784)
845f777 is described below

commit 845f7773f85b93b16cf6fd547b171c1474e8e5f9
Author: Myroslav Papirkovskyi <mp...@apache.org>
AuthorDate: Fri Jan 25 20:57:08 2019 +0200

    AMBARI-24606. Deleting a service should do a better job of cleaning up the Ambari DB. (#2784)
    
    * AMBARI-24606. Deleting a service should do a better job of cleaning up the Ambari DB. (mpapirkovskyy)
    
    * AMBARI-24606. Deleting a service should do a better job of cleaning up the Ambari DB. (mpapirkovskyy)
---
 .../checks/DatabaseConsistencyCheckHelper.java     |  5 +-
 .../internal/ConfigGroupResourceProvider.java      |  2 -
 .../org/apache/ambari/server/state/Cluster.java    | 10 ++-
 .../apache/ambari/server/state/ConfigHelper.java   |  3 +-
 .../apache/ambari/server/state/ServiceImpl.java    | 17 ++++-
 .../ambari/server/state/cluster/ClusterImpl.java   | 19 +++++-
 .../checks/DatabaseConsistencyCheckHelperTest.java | 59 +++++++++++++++++
 .../apache/ambari/server/state/ServiceTest.java    | 77 ++++++++++++++++++++++
 .../server/state/cluster/ClusterImplTest.java      | 43 ++++++++++++
 9 files changed, 223 insertions(+), 12 deletions(-)

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 c1e8aa8..7f52b66 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
@@ -59,7 +59,6 @@ import org.apache.ambari.server.orm.entities.ClusterConfigEntity;
 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.security.authorization.AuthorizationException;
 import org.apache.ambari.server.state.ClientConfigFileDefinition;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
@@ -589,7 +588,7 @@ public class DatabaseConsistencyCheckHelper {
     List<ClusterConfigEntity> notMappedClusterConfigs = getNotMappedClusterConfigsToService();
 
     for (ClusterConfigEntity clusterConfigEntity : notMappedClusterConfigs){
-      if (!clusterConfigEntity.isUnmapped()){
+      if (clusterConfigEntity.isUnmapped()){
         continue; // skip clusterConfigs that did not leave after service deletion
       }
       List<String> types = new ArrayList<>();
@@ -1339,8 +1338,6 @@ public class DatabaseConsistencyCheckHelper {
           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
           }
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ConfigGroupResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ConfigGroupResourceProvider.java
index 30e2fc3..df3ba4c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ConfigGroupResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ConfigGroupResourceProvider.java
@@ -519,8 +519,6 @@ public class ConfigGroupResourceProvider extends
         cluster.getClusterName(), getManagementController().getAuthName(), configGroup.getName(), request.getId());
 
     cluster.deleteConfigGroup(request.getId());
-
-    m_configHelper.get().updateAgentConfigs(Collections.singleton(request.getClusterName()));
   }
 
   private void validateRequest(ConfigGroupRequest request) {
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java b/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
index afc5f1d..c4b418c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
@@ -35,7 +35,6 @@ import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.PrivilegeEntity;
 import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.orm.entities.UpgradeEntity;
-import org.apache.ambari.server.security.authorization.AuthorizationException;
 import org.apache.ambari.server.state.configgroup.ConfigGroup;
 import org.apache.ambari.server.state.repository.VersionDefinitionXml;
 import org.apache.ambari.server.state.scheduler.RequestExecution;
@@ -504,7 +503,7 @@ public interface Cluster {
    * @param id
    * @throws AmbariException
    */
-  void deleteConfigGroup(Long id) throws AmbariException, AuthorizationException;
+  void deleteConfigGroup(Long id) throws AmbariException;
 
   /**
    * Find all config groups associated with the give hostname
@@ -522,6 +521,13 @@ public interface Cluster {
   ConfigGroup getConfigGroupsById(Long configId);
 
   /**
+   * Find all config groups associated with the give service name
+   * @param serviceName
+   * @return Map of config group id to config group
+   */
+  Map<Long, ConfigGroup> getConfigGroupsByServiceName(String serviceName);
+
+  /**
    * Add a @RequestExecution to the cluster
    * @param requestExecution
    * @throws AmbariException
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
index 6d622ef..91fe76e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
@@ -1531,7 +1531,8 @@ public class ConfigHelper {
           currentConfigEvents.put(host.getHostId(), m_agentConfigsHolder.get().getCurrentData(hostId));
         }
         if (!previousConfigEvents.containsKey(host.getHostId())) {
-          previousConfigEvents.put(host.getHostId(), m_agentConfigsHolder.get().getData(hostId));
+          previousConfigEvents.put(host.getHostId(),
+              m_agentConfigsHolder.get().initializeDataIfNeeded(hostId, true));
         }
       }
     }
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
index 15424c3..8e56904 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
@@ -593,7 +593,7 @@ public class ServiceImpl implements Service {
     // de-select every configuration from the service
     if (lastServiceConfigEntity != null) {
       for (ClusterConfigEntity serviceConfigEntity : lastServiceConfigEntity.getClusterConfigEntities()) {
-        LOG.info("Disabling configuration {}", serviceConfigEntity);
+        LOG.info("Disabling and unmapping configuration {}", serviceConfigEntity);
         serviceConfigEntity.setSelected(false);
         serviceConfigEntity.setUnmapped(true);
         clusterDAO.merge(serviceConfigEntity);
@@ -606,12 +606,26 @@ public class ServiceImpl implements Service {
         serviceConfigDAO.findByService(cluster.getClusterId(), getName());
 
     for (ServiceConfigEntity serviceConfigEntity : serviceConfigEntities) {
+      // unmapping all service configs
+      for (ClusterConfigEntity clusterConfigEntity : serviceConfigEntity.getClusterConfigEntities()) {
+        if (!clusterConfigEntity.isUnmapped()) {
+          LOG.info("Unmapping configuration {}", clusterConfigEntity);
+          clusterConfigEntity.setUnmapped(true);
+          clusterDAO.merge(clusterConfigEntity);
+        }
+      }
       // Only delete the historical version information and not original
       // config data
       serviceConfigDAO.remove(serviceConfigEntity);
     }
   }
 
+  void deleteAllServiceConfigGroups() throws AmbariException {
+    for (Long configGroupId : cluster.getConfigGroupsByServiceName(serviceName).keySet()) {
+      cluster.deleteConfigGroup(configGroupId);
+    }
+  }
+
   @Override
   @Transactional
   public void deleteAllComponents(DeleteHostComponentStatusMetaData deleteMetaData) {
@@ -682,6 +696,7 @@ public class ServiceImpl implements Service {
     StackId stackId = getDesiredStackId();
     try {
       deleteAllServiceConfigs();
+      deleteAllServiceConfigGroups();
 
       removeEntities();
     } catch (AmbariException e) {
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
index e23c571..09654cf 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
@@ -113,7 +113,6 @@ import org.apache.ambari.server.orm.entities.ServiceConfigEntity;
 import org.apache.ambari.server.orm.entities.StackEntity;
 import org.apache.ambari.server.orm.entities.TopologyRequestEntity;
 import org.apache.ambari.server.orm.entities.UpgradeEntity;
-import org.apache.ambari.server.security.authorization.AuthorizationException;
 import org.apache.ambari.server.stack.upgrade.orchestrate.UpgradeContext;
 import org.apache.ambari.server.stack.upgrade.orchestrate.UpgradeContextFactory;
 import org.apache.ambari.server.state.BlueprintProvisioningState;
@@ -541,6 +540,20 @@ public class ClusterImpl implements Cluster {
   }
 
   @Override
+  public Map<Long, ConfigGroup> getConfigGroupsByServiceName(String serviceName) {
+    Map<Long, ConfigGroup> configGroups = new HashMap<>();
+
+    for (Entry<Long, ConfigGroup> groupEntry : clusterConfigGroups.entrySet()) {
+      Long id = groupEntry.getKey();
+      ConfigGroup group = groupEntry.getValue();
+      if (StringUtils.equals(serviceName, group.getServiceName())) {
+        configGroups.put(id, group);
+      }
+    }
+    return configGroups;
+  }
+
+  @Override
   public void addRequestExecution(RequestExecution requestExecution) throws AmbariException {
     LOG.info("Adding a new request schedule" + ", clusterName = " + getClusterName() + ", id = "
         + requestExecution.getId() + ", description = " + requestExecution.getDescription());
@@ -572,7 +585,7 @@ public class ClusterImpl implements Cluster {
   }
 
   @Override
-  public void deleteConfigGroup(Long id) throws AmbariException, AuthorizationException {
+  public void deleteConfigGroup(Long id) throws AmbariException {
     ConfigGroup configGroup = clusterConfigGroups.get(id);
     if (configGroup == null) {
       throw new ConfigGroupNotFoundException(getClusterName(), id.toString());
@@ -583,6 +596,8 @@ public class ClusterImpl implements Cluster {
 
     configGroup.delete();
     clusterConfigGroups.remove(id);
+
+    configHelper.updateAgentConfigs(Collections.singleton(configGroup.getClusterName()));
   }
 
   public ServiceComponentHost getServiceComponentHost(String serviceName,
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 2817661..bddff1a 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
@@ -28,6 +28,7 @@ import static org.easymock.EasyMock.createStrictMock;
 import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.expectLastCall;
 import static org.easymock.EasyMock.replay;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
@@ -45,22 +46,32 @@ import java.util.Set;
 import javax.persistence.EntityManager;
 import javax.persistence.TypedQuery;
 
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.H2DatabaseCleaner;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.orm.DBAccessor;
+import org.apache.ambari.server.orm.GuiceJpaInitializer;
+import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
+import org.apache.ambari.server.orm.OrmTestHelper;
 import org.apache.ambari.server.orm.dao.ClusterDAO;
 import org.apache.ambari.server.orm.entities.ClusterConfigEntity;
+import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 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.ConfigFactory;
 import org.apache.ambari.server.state.Host;
 import org.apache.ambari.server.state.Service;
+import org.apache.ambari.server.state.ServiceFactory;
 import org.apache.ambari.server.state.ServiceInfo;
+import org.apache.ambari.server.state.StackId;
 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.After;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -72,6 +83,15 @@ import com.google.inject.Injector;
 
 public class DatabaseConsistencyCheckHelperTest {
 
+  private Injector injector;
+
+  @After
+  public void teardown() throws AmbariException, SQLException {
+    if (injector != null) {
+      H2DatabaseCleaner.clearDatabaseAndStopPersistenceService(injector);
+    }
+  }
+
   @Test
   public void testCheckForConfigsSelectedMoreThanOnce() throws Exception {
     EasyMockSupport easyMockSupport = new EasyMockSupport();
@@ -854,6 +874,45 @@ public class DatabaseConsistencyCheckHelperTest {
     easyMockSupport.verifyAll();
   }
 
+  @Test
+  public void testCheckForConfigsNotMappedToService() throws SQLException, AmbariException {
+    injector = Guice.createInjector(new InMemoryDefaultTestModule());
+    injector.getInstance(GuiceJpaInitializer.class);
+    Clusters clusters = injector.getInstance(Clusters.class);
+    ServiceFactory serviceFactory = injector.getInstance(ServiceFactory.class);
+    ConfigFactory configFactory = injector.getInstance(ConfigFactory.class);
+    DatabaseConsistencyCheckHelper.setInjector(injector);
+
+    String STACK_VERSION = "0.1";
+    String REPO_VERSION = "0.1-1234";
+    StackId STACK_ID = new StackId("HDP", STACK_VERSION);
+    OrmTestHelper ormTestHelper = injector.getInstance(OrmTestHelper.class);
+    RepositoryVersionEntity repositoryVersion = ormTestHelper.getOrCreateRepositoryVersion(STACK_ID, REPO_VERSION);
+
+    String clusterName = "foo";
+    clusters.addCluster(clusterName, STACK_ID);
+    Cluster cluster = clusters.getCluster(clusterName);
+
+    String serviceName = "HDFS";
+    Service s = serviceFactory.createNew(cluster, serviceName, repositoryVersion);
+    cluster.addService(s);
+
+    // add some cluster configs
+    configFactory.createNew(cluster, "hdfs-site", "version1",
+        new HashMap<String, String>() {{ put("a", "b"); }}, new HashMap<>());
+
+    configFactory.createNew(cluster, "hdfs-site", "version2",
+        new HashMap<String, String>() {{ put("a", "b"); }}, new HashMap<>());
+
+    DatabaseConsistencyCheckHelper.checkForConfigsNotMappedToService();
+    assertEquals(DatabaseConsistencyCheckResult.DB_CHECK_WARNING, DatabaseConsistencyCheckHelper.getLastCheckResult());
+
+    DatabaseConsistencyCheckHelper.fixClusterConfigsNotMappedToAnyService();
+    DatabaseConsistencyCheckHelper.resetCheckResult();
+    DatabaseConsistencyCheckHelper.checkForConfigsNotMappedToService();
+    assertEquals(DatabaseConsistencyCheckResult.DB_CHECK_SUCCESS, DatabaseConsistencyCheckHelper.getLastCheckResult());
+  }
+
   private Injector createInjectorWithAmbariMetaInfo(AmbariMetaInfo mockAmbariMetainfo,
                                                     DBAccessor mockDBDbAccessor) {
     return Guice.createInjector(new AbstractModule() {
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceTest.java
index 3d4fbbf..8768d47 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceTest.java
@@ -18,10 +18,17 @@
 
 package org.apache.ambari.server.state;
 
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import java.sql.SQLException;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
@@ -34,8 +41,11 @@ import org.apache.ambari.server.orm.GuiceJpaInitializer;
 import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
 import org.apache.ambari.server.orm.OrmTestHelper;
 import org.apache.ambari.server.orm.dao.ClusterServiceDAO;
+import org.apache.ambari.server.orm.entities.ClusterConfigEntity;
 import org.apache.ambari.server.orm.entities.ClusterServiceEntity;
 import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
+import org.apache.ambari.server.state.configgroup.ConfigGroup;
+import org.apache.commons.collections.MapUtils;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -55,6 +65,7 @@ public class ServiceTest {
   private ServiceComponentFactory serviceComponentFactory;
   private ServiceComponentHostFactory serviceComponentHostFactory;
   private OrmTestHelper ormTestHelper;
+  private ConfigFactory configFactory;
 
   private final String STACK_VERSION = "0.1";
   private final String REPO_VERSION = "0.1-1234";
@@ -69,6 +80,7 @@ public class ServiceTest {
     serviceFactory = injector.getInstance(ServiceFactory.class);
     serviceComponentFactory = injector.getInstance(ServiceComponentFactory.class);
     serviceComponentHostFactory = injector.getInstance(ServiceComponentHostFactory.class);
+    configFactory = injector.getInstance(ConfigFactory.class);
 
     ormTestHelper = injector.getInstance(OrmTestHelper.class);
     repositoryVersion = ormTestHelper.getOrCreateRepositoryVersion(STACK_ID, REPO_VERSION);
@@ -347,6 +359,71 @@ public class ServiceTest {
 
   }
 
+  @Test
+  public void testClusterConfigsUnmappingOnDeleteAllServiceConfigs() throws AmbariException {
+    String serviceName = "HDFS";
+    Service s = serviceFactory.createNew(cluster, serviceName, repositoryVersion);
+    cluster.addService(s);
+
+    Service service = cluster.getService(serviceName);
+
+    // add some cluster and service configs
+    Config config1 = configFactory.createNew(cluster, "hdfs-site", "version1",
+        new HashMap<String, String>() {{ put("a", "b"); }}, new HashMap<>());
+    cluster.addDesiredConfig("admin", Collections.singleton(config1));
+
+    Config config2 = configFactory.createNew(cluster, "hdfs-site", "version2",
+        new HashMap<String, String>() {{ put("a", "b"); }}, new HashMap<>());
+    cluster.addDesiredConfig("admin", Collections.singleton(config2));
+
+
+    // check all cluster configs are mapped
+    Collection<ClusterConfigEntity> clusterConfigEntities = cluster.getClusterEntity().getClusterConfigEntities();
+    for (ClusterConfigEntity clusterConfigEntity : clusterConfigEntities) {
+      assertFalse(clusterConfigEntity.isUnmapped());
+    }
+
+    ((ServiceImpl)service).deleteAllServiceConfigs();
+
+    // check all cluster configs are unmapped
+    clusterConfigEntities = cluster.getClusterEntity().getClusterConfigEntities();
+    for (ClusterConfigEntity clusterConfigEntity : clusterConfigEntities) {
+      assertTrue(clusterConfigEntity.isUnmapped());
+    }
+  }
+
+  @Test
+  public void testDeleteAllServiceConfigGroups() throws AmbariException {
+    String serviceName = "HDFS";
+    Service s = serviceFactory.createNew(cluster, serviceName, repositoryVersion);
+    cluster.addService(s);
+
+    Service service = cluster.getService(serviceName);
+
+    ConfigGroup configGroup1 = createNiceMock(ConfigGroup.class);
+    ConfigGroup configGroup2 = createNiceMock(ConfigGroup.class);
+
+    expect(configGroup1.getId()).andReturn(1L).anyTimes();
+    expect(configGroup2.getId()).andReturn(2L).anyTimes();
+
+    expect(configGroup1.getServiceName()).andReturn(serviceName).anyTimes();
+    expect(configGroup2.getServiceName()).andReturn(serviceName).anyTimes();
+
+    expect(configGroup1.getClusterName()).andReturn(cluster.getClusterName()).anyTimes();
+    expect(configGroup2.getClusterName()).andReturn(cluster.getClusterName()).anyTimes();
+
+    replay(configGroup1, configGroup2);
+
+    cluster.addConfigGroup(configGroup1);
+    cluster.addConfigGroup(configGroup2);
+
+    ((ServiceImpl)service).deleteAllServiceConfigGroups();
+
+    assertTrue(MapUtils.isEmpty(cluster.getConfigGroupsByServiceName(serviceName)));
+
+    verify(configGroup1, configGroup2);
+  }
+
   private void addHostToCluster(String hostname,
                                 String clusterName) throws AmbariException {
     clusters.addHost(hostname);
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterImplTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterImplTest.java
index 5a977b8..5311367 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterImplTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterImplTest.java
@@ -20,6 +20,7 @@ package org.apache.ambari.server.state.cluster;
 
 import static org.easymock.EasyMock.createMock;
 import static org.easymock.EasyMock.createMockBuilder;
+import static org.easymock.EasyMock.createNiceMock;
 import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.expectLastCall;
 import static org.easymock.EasyMock.replay;
@@ -50,6 +51,8 @@ import org.apache.ambari.server.state.Service;
 import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.ServiceComponentHost;
 import org.apache.ambari.server.state.StackId;
+import org.apache.ambari.server.state.configgroup.ConfigGroup;
+import org.apache.commons.collections.MapUtils;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -338,4 +341,44 @@ public class ClusterImplTest {
     assertEquals(2, clusterSize);
 
   }
+
+  @Test
+  public void testGetConfigGroupsByServiceName() throws AmbariException {
+    // Given
+    String clusterName = "TEST_CONFIG_GROUPS";
+    String hostName1 = "HOSTNAME1", hostName2 = "HOSTNAME2";
+    String hostToDelete = hostName2;
+    StackId stackId = new StackId("HDP-2.1.1");
+
+    String serviceToCheckName = "serviceName1";
+    String serviceNotToCheckName = "serviceName2";
+
+    ormTestHelper.createStack(stackId);
+    clusters.addCluster(clusterName, stackId);
+
+    Cluster cluster = clusters.getCluster(clusterName);
+
+    ConfigGroup serviceConfigGroup1 = createNiceMock(ConfigGroup.class);
+    ConfigGroup serviceConfigGroup2 = createNiceMock(ConfigGroup.class);
+
+    expect(serviceConfigGroup1.getId()).andReturn(1L).anyTimes();
+    expect(serviceConfigGroup2.getId()).andReturn(2L).anyTimes();
+
+    expect(serviceConfigGroup1.getServiceName()).andReturn(serviceToCheckName).anyTimes();
+    expect(serviceConfigGroup2.getServiceName()).andReturn(serviceNotToCheckName).anyTimes();
+
+    replay(serviceConfigGroup1, serviceConfigGroup2);
+
+    cluster.addConfigGroup(serviceConfigGroup1);
+    cluster.addConfigGroup(serviceConfigGroup2);
+
+    Map<Long, ConfigGroup> configGroupsToCheck = cluster.getConfigGroupsByServiceName(serviceToCheckName);
+
+    assertFalse(MapUtils.isEmpty(configGroupsToCheck));
+    assertEquals(1L, configGroupsToCheck.size());
+    assertTrue(configGroupsToCheck.keySet().contains(1L));
+    assertEquals(serviceToCheckName, configGroupsToCheck.get(1L).getServiceName());
+
+    verify(serviceConfigGroup1, serviceConfigGroup2);
+  }
 }