content: /*
   * 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.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;
  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.Collections;
  import java.util.HashMap;
  import java.util.Map;
  
  import org.apache.ambari.server.AmbariException;
  import org.apache.ambari.server.H2DatabaseCleaner;
  import org.apache.ambari.server.HostNotFoundException;
  import org.apache.ambari.server.controller.AmbariSessionManager;
  import org.apache.ambari.server.controller.internal.DeleteHostComponentStatusMetaData;
  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.entities.RepositoryVersionEntity;
  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.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.collections4.MapUtils;
  import org.junit.AfterClass;
  import org.junit.BeforeClass;
  import org.junit.Test;
  
  import com.google.common.collect.ImmutableMap;
  import com.google.common.collect.Sets;
  import com.google.inject.Guice;
  import com.google.inject.Injector;
  
  public class ClusterImplTest {
  
    private static Injector injector;
    private static Clusters clusters;
    private static OrmTestHelper ormTestHelper;
  
    @BeforeClass
    public static void setUpClass() throws Exception {
      injector = Guice.createInjector(new InMemoryDefaultTestModule());
      injector.getInstance(GuiceJpaInitializer.class);
      clusters = injector.getInstance(Clusters.class);
      ormTestHelper = injector.getInstance(OrmTestHelper.class);
    }
  
    @AfterClass
    public static void teardown() throws AmbariException, SQLException {
      H2DatabaseCleaner.clearDatabaseAndStopPersistenceService(injector);
    }
  
    @Test
    public void testAddSessionAttributes() throws Exception {
      Map<String, Object> attributes = new HashMap<>();
      attributes.put("foo", "bar");
  
      AmbariSessionManager sessionManager = createMock(AmbariSessionManager.class);
  
      ClusterImpl cluster =
          createMockBuilder(ClusterImpl.class).
              addMockedMethod("getSessionManager").
              addMockedMethod("getClusterName").
              addMockedMethod("getSessionAttributes").
              createMock();
  
      expect(cluster.getSessionManager()).andReturn(sessionManager);
      expect(cluster.getClusterName()).andReturn("c1");
      expect(cluster.getSessionAttributes()).andReturn(attributes);
      sessionManager.setAttribute("cluster_session_attributes:c1", attributes);
  
      replay(sessionManager, cluster);
  
      cluster.addSessionAttributes(attributes);
  
      verify(sessionManager, cluster);
    }
  
    @Test
    public void testSetSessionAttribute() throws Exception {
      Map<String, Object> attributes = new HashMap<>();
      attributes.put("foo", "bar");
      attributes.put("foo2", "bar2");
  
      Map<String, Object> updatedAttributes = new HashMap<>(attributes);
      updatedAttributes.put("foo2", "updated value");
  
      Map<String, Object> addedAttributes = new HashMap<>(updatedAttributes);
      updatedAttributes.put("foo3", "added value");
  
      AmbariSessionManager sessionManager = createMock(AmbariSessionManager.class);
  
      ClusterImpl cluster =
        createMockBuilder(ClusterImpl.class).
          addMockedMethod("getSessionManager").
          addMockedMethod("getClusterName").
          addMockedMethod("getSessionAttributes").
          createMock();
  
      expect(cluster.getSessionManager()).andReturn(sessionManager);
      expect(cluster.getClusterName()).andReturn("c1");
      expect(cluster.getSessionAttributes()).andReturn(attributes);
  
      sessionManager.setAttribute("cluster_session_attributes:c1", updatedAttributes);
      expectLastCall().once();
  
      expect(cluster.getSessionManager()).andReturn(sessionManager);
      expect(cluster.getClusterName()).andReturn("c1");
      expect(cluster.getSessionAttributes()).andReturn(updatedAttributes);
  
      sessionManager.setAttribute("cluster_session_attributes:c1", addedAttributes);
      expectLastCall().once();
  
      replay(sessionManager, cluster);
  
      cluster.setSessionAttribute("foo2", "updated value");
      cluster.setSessionAttribute("foo3", "added value");
  
      verify(sessionManager, cluster);
    }
  
    @Test
    public void testRemoveSessionAttribute() throws Exception {
      Map<String, Object> attributes = new HashMap<>();
      attributes.put("foo", "bar");
      attributes.put("foo2", "bar2");
  
      Map<String, Object> trimmedAttributes = new HashMap<>(attributes);
      trimmedAttributes.remove("foo2");
  
      AmbariSessionManager sessionManager = createMock(AmbariSessionManager.class);
  
      ClusterImpl cluster =
        createMockBuilder(ClusterImpl.class).
          addMockedMethod("getSessionManager").
          addMockedMethod("getClusterName").
          addMockedMethod("getSessionAttributes").
          createMock();
  
      expect(cluster.getSessionManager()).andReturn(sessionManager);
      expect(cluster.getClusterName()).andReturn("c1");
      expect(cluster.getSessionAttributes()).andReturn(attributes);
      sessionManager.setAttribute("cluster_session_attributes:c1", trimmedAttributes);
      expectLastCall().once();
  
      replay(sessionManager, cluster);
  
      cluster.removeSessionAttribute("foo2");
  
      verify(sessionManager, cluster);
    }
  
    @Test
    public void testGetSessionAttributes() throws Exception {
      Map<String, Object> attributes = new HashMap<>();
      attributes.put("foo", "bar");
  
      AmbariSessionManager sessionManager = createMock(AmbariSessionManager.class);
  
      ClusterImpl cluster =
          createMockBuilder(ClusterImpl.class).
              addMockedMethod("getSessionManager").
              addMockedMethod("getClusterName").
              createMock();
  
      expect(cluster.getSessionManager()).andReturn(sessionManager).anyTimes();
      expect(cluster.getClusterName()).andReturn("c1").anyTimes();
      expect(sessionManager.getAttribute("cluster_session_attributes:c1")).andReturn(attributes);
      expect(sessionManager.getAttribute("cluster_session_attributes:c1")).andReturn(null);
  
      replay(sessionManager, cluster);
  
      assertEquals(attributes, cluster.getSessionAttributes());
      assertEquals(Collections.<String, Object>emptyMap(), cluster.getSessionAttributes());
  
      verify(sessionManager, cluster);
    }
  
    @Test
    public void testDeleteService() throws Exception {
      // Given
      String serviceToDelete = "TEZ";
  
      String clusterName = "TEST_CLUSTER";
      String hostName1 = "HOST1", hostName2 = "HOST2";
  
      String stackVersion = "HDP-2.1.1";
      String repoVersion = "2.1.1-1234";
      StackId stackId = new StackId(stackVersion);
      ormTestHelper.createStack(stackId);
  
      clusters.addCluster(clusterName, stackId);
      Cluster cluster = clusters.getCluster(clusterName);
  
      RepositoryVersionEntity repositoryVersion = ormTestHelper.getOrCreateRepositoryVersion(
          new StackId(stackVersion), repoVersion);
  
      clusters.addHost(hostName1);
      clusters.addHost(hostName2);
  
      Host host1 = clusters.getHost(hostName1);
      host1.setHostAttributes(ImmutableMap.of("os_family", "centos", "os_release_version", "6.0"));
  
      Host host2 = clusters.getHost(hostName2);
      host2.setHostAttributes(ImmutableMap.of("os_family", "centos", "os_release_version", "6.0"));
  
      clusters.mapAndPublishHostsToCluster(Sets.newHashSet(hostName1, hostName2), clusterName);
  
      Service hdfs = cluster.addService("HDFS", repositoryVersion);
  
      ServiceComponent nameNode = hdfs.addServiceComponent("NAMENODE");
      nameNode.addServiceComponentHost(hostName1);
  
      ServiceComponent dataNode = hdfs.addServiceComponent("DATANODE");
      dataNode.addServiceComponentHost(hostName1);
      dataNode.addServiceComponentHost(hostName2);
  
      ServiceComponent hdfsClient = hdfs.addServiceComponent("HDFS_CLIENT");
      hdfsClient.addServiceComponentHost(hostName1);
      hdfsClient.addServiceComponentHost(hostName2);
  
      Service tez = cluster.addService(serviceToDelete, repositoryVersion);
  
      ServiceComponent tezClient = tez.addServiceComponent("TEZ_CLIENT");
      ServiceComponentHost tezClientHost1 =  tezClient.addServiceComponentHost(hostName1);
      ServiceComponentHost tezClientHost2 = tezClient.addServiceComponentHost(hostName2);
  
      // When
      cluster.deleteService(serviceToDelete, new DeleteHostComponentStatusMetaData());
  
      // Then
      assertFalse("Deleted service should be removed from the service collection !", cluster.getServices().containsKey(serviceToDelete));
  
      assertEquals("All components of the deleted service should be removed from all hosts", 0, cluster.getServiceComponentHosts(serviceToDelete, null).size());
  
      boolean checkHost1 = !cluster.getServiceComponentHosts(hostName1).contains(tezClientHost1);
      boolean checkHost2 = !cluster.getServiceComponentHosts(hostName2).contains(tezClientHost2);
  
      assertTrue("All components of the deleted service should be removed from all hosts", checkHost1 && checkHost2);
  
    }
  
    @Test
    public void testDeleteHost() throws Exception {
      // Given
      String clusterName = "TEST_DELETE_HOST";
      String hostName1 = "HOSTNAME1", hostName2 = "HOSTNAME2";
      String hostToDelete = hostName2;
      StackId stackId = new StackId("HDP-2.1.1");
  
      ormTestHelper.createStack(stackId);
      clusters.addCluster(clusterName, stackId);
  
      Cluster cluster = clusters.getCluster(clusterName);
  
      clusters.addHost(hostName1);
      clusters.addHost(hostName2);
  
      Host host1 = clusters.getHost(hostName1);
      host1.setHostAttributes(ImmutableMap.of("os_family", "centos", "os_release_version", "6.0"));
  
      Host host2 = clusters.getHost(hostName2);
      host2.setHostAttributes(ImmutableMap.of("os_family", "centos", "os_release_version", "6.0"));
  
      clusters.mapAndPublishHostsToCluster(Sets.newHashSet(hostName1, hostName2), clusterName);
  
      // When
      clusters.deleteHost(hostToDelete);
  
      // Then
      assertTrue(clusters.getClustersForHost(hostToDelete).isEmpty());
      assertFalse(clusters.getHostsForCluster(clusterName).containsKey(hostToDelete));
  
      assertFalse(cluster.getHosts().contains(hostToDelete));
  
      try {
        clusters.getHost(hostToDelete);
        fail("getHost(hostName) should throw Exception when invoked for deleted host !");
      }
      catch(HostNotFoundException e){
  
      }
    }
  
    @Test
    public void testGetClusterSize() throws Exception {
      // Given
      String clusterName = "TEST_CLUSTER_SIZE";
      String hostName1 = "host1", hostName2 = "host2";
      StackId stackId = new StackId("HDP", "2.1.1");
      ormTestHelper.createStack(stackId);
      clusters.addCluster(clusterName, stackId);
  
      Cluster cluster = clusters.getCluster(clusterName);
      clusters.addHost(hostName1);
      clusters.addHost(hostName2);
  
      Host host1 = clusters.getHost(hostName1);
      host1.setHostAttributes(ImmutableMap.of("os_family", "centos", "os_release_version", "6.0"));
  
      Host host2 = clusters.getHost(hostName2);
      host2.setHostAttributes(ImmutableMap.of("os_family", "centos", "os_release_version", "6.0"));
  
      clusters.mapAndPublishHostsToCluster(Sets.newHashSet(hostName1, hostName2), clusterName);
  
      // When
      int clusterSize = cluster.getClusterSize();
  
      // Then
      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);
    }
  }
  