/** * 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.alerts; import static junit.framework.Assert.assertEquals; import static org.easymock.EasyMock.expect; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.persistence.EntityManager; import org.apache.ambari.server.api.services.AmbariMetaInfo; import org.apache.ambari.server.events.AlertEvent; import org.apache.ambari.server.events.AlertReceivedEvent; import org.apache.ambari.server.events.MockEventListener; import org.apache.ambari.server.events.publishers.AlertEventPublisher; import org.apache.ambari.server.orm.DBAccessor; import org.apache.ambari.server.orm.dao.AlertDefinitionDAO; import org.apache.ambari.server.orm.entities.AlertDefinitionEntity; import org.apache.ambari.server.orm.entities.ClusterVersionEntity; import org.apache.ambari.server.orm.entities.RepositoryVersionEntity; import org.apache.ambari.server.orm.entities.UpgradeEntity; import org.apache.ambari.server.stack.StackManagerFactory; import org.apache.ambari.server.state.Alert; import org.apache.ambari.server.state.AlertState; 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.ServiceComponentHost; import org.apache.ambari.server.state.StackId; import org.apache.ambari.server.state.stack.OsFamily; import org.easymock.EasyMock; import org.easymock.EasyMockSupport; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.google.common.eventbus.EventBus; import com.google.inject.Binder; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Module; /** * Tests {@link ComponentVersionAlertRunnable}. */ public class ComponentVersionAlertRunnableTest extends EasyMockSupport { private final static long CLUSTER_ID = 1; private final static String CLUSTER_NAME = "c1"; private final static String HOSTNAME_1 = "c6401.ambari.apache.org"; private final static String HOSTNAME_2 = "c6402.ambari.apache.org"; private final static String EXPECTED_VERSION = "2.6.0.0-1234"; private final static String WRONG_VERSION = "9.9.9.9-9999"; private final static String DEFINITION_NAME = "ambari_server_component_version"; private final static String DEFINITION_SERVICE = "AMBARI"; private final static String DEFINITION_COMPONENT = "AMBARI_SERVER"; private final static String DEFINITION_LABEL = "Mock Definition"; private Clusters m_clusters; private Cluster m_cluster; private Injector m_injector; private AlertDefinitionDAO m_definitionDao; private AlertDefinitionEntity m_definition; private MockEventListener m_listener; private AmbariMetaInfo m_metaInfo; private AlertEventPublisher m_eventPublisher; private EventBus m_synchronizedBus; private Collection<Host> m_hosts; private Map<String, List<ServiceComponentHost>> m_hostComponentMap = new HashMap<>(); private StackId m_desidredStackId; /** * */ @Before public void setup() throws Exception { m_injector = Guice.createInjector(new MockModule()); m_definitionDao = m_injector.getInstance(AlertDefinitionDAO.class); m_clusters = m_injector.getInstance(Clusters.class); m_cluster = m_injector.getInstance(Cluster.class); m_eventPublisher = m_injector.getInstance(AlertEventPublisher.class); m_listener = m_injector.getInstance(MockEventListener.class); m_definition = createNiceMock(AlertDefinitionEntity.class); m_metaInfo = m_injector.getInstance(AmbariMetaInfo.class); // !!! need a synchronous op for testing m_synchronizedBus = new EventBus(); Field field = AlertEventPublisher.class.getDeclaredField("m_eventBus"); field.setAccessible(true); field.set(m_eventPublisher, m_synchronizedBus); // register mock listener m_synchronizedBus.register(m_listener); // create the cluster map Map<String,Cluster> clusterMap = new HashMap<>(); clusterMap.put(CLUSTER_NAME, m_cluster); // hosts m_hosts = new ArrayList<>(); Host host1 = createNiceMock(Host.class); Host host2 = createNiceMock(Host.class); expect(host1.getHostName()).andReturn(HOSTNAME_1).atLeastOnce(); expect(host2.getHostName()).andReturn(HOSTNAME_2).atLeastOnce(); m_hosts.add(host1); m_hosts.add(host2); m_hostComponentMap.put(HOSTNAME_1, new ArrayList<ServiceComponentHost>()); m_hostComponentMap.put(HOSTNAME_2, new ArrayList<ServiceComponentHost>()); // desired stack m_desidredStackId = createNiceMock(StackId.class); expect(m_desidredStackId.getStackName()).andReturn("SOME-STACK").atLeastOnce(); expect(m_desidredStackId.getStackVersion()).andReturn("STACK-VERSION").atLeastOnce(); // components ServiceComponentHost sch1_1 = createNiceMock(ServiceComponentHost.class); ServiceComponentHost sch1_2 = createNiceMock(ServiceComponentHost.class); ServiceComponentHost sch2_1 = createNiceMock(ServiceComponentHost.class); ServiceComponentHost sch2_2 = createNiceMock(ServiceComponentHost.class); expect(sch1_1.getServiceName()).andReturn("FOO").atLeastOnce(); expect(sch1_1.getServiceComponentName()).andReturn("FOO_COMPONENT").atLeastOnce(); expect(sch1_1.getVersion()).andReturn(EXPECTED_VERSION).atLeastOnce(); expect(sch1_1.getDesiredStackVersion()).andReturn(m_desidredStackId).atLeastOnce(); expect(sch1_2.getServiceName()).andReturn("BAR").atLeastOnce(); expect(sch1_2.getServiceComponentName()).andReturn("BAR_COMPONENT").atLeastOnce(); expect(sch1_2.getVersion()).andReturn(EXPECTED_VERSION).atLeastOnce(); expect(sch1_2.getDesiredStackVersion()).andReturn(m_desidredStackId).atLeastOnce(); expect(sch2_1.getServiceName()).andReturn("FOO").atLeastOnce(); expect(sch2_1.getServiceComponentName()).andReturn("FOO_COMPONENT").atLeastOnce(); expect(sch2_1.getVersion()).andReturn(EXPECTED_VERSION).atLeastOnce(); expect(sch2_1.getDesiredStackVersion()).andReturn(m_desidredStackId).atLeastOnce(); expect(sch2_2.getServiceName()).andReturn("BAZ").atLeastOnce(); expect(sch2_2.getServiceComponentName()).andReturn("BAZ_COMPONENT").atLeastOnce(); expect(sch2_2.getVersion()).andReturn(EXPECTED_VERSION).atLeastOnce(); expect(sch2_2.getDesiredStackVersion()).andReturn(m_desidredStackId).atLeastOnce(); m_hostComponentMap.get(HOSTNAME_1).add(sch1_1); m_hostComponentMap.get(HOSTNAME_1).add(sch1_2); m_hostComponentMap.get(HOSTNAME_2).add(sch2_1); m_hostComponentMap.get(HOSTNAME_2).add(sch2_2); // mock the definition for the alert expect(m_definition.getDefinitionName()).andReturn(DEFINITION_NAME).atLeastOnce(); expect(m_definition.getServiceName()).andReturn(DEFINITION_SERVICE).atLeastOnce(); expect(m_definition.getComponentName()).andReturn(DEFINITION_COMPONENT).atLeastOnce(); expect(m_definition.getLabel()).andReturn(DEFINITION_LABEL).atLeastOnce(); expect(m_definition.getEnabled()).andReturn(true).atLeastOnce(); // mock the cluster expect(m_cluster.getClusterId()).andReturn(CLUSTER_ID).atLeastOnce(); expect(m_cluster.getClusterName()).andReturn(CLUSTER_NAME).atLeastOnce(); expect(m_cluster.getHosts()).andReturn(m_hosts).atLeastOnce(); ClusterVersionEntity clusterVersionEntity = createNiceMock(ClusterVersionEntity.class); RepositoryVersionEntity repositoryVersionEntity = createNiceMock(RepositoryVersionEntity.class); expect(clusterVersionEntity.getRepositoryVersion()).andReturn( repositoryVersionEntity).anyTimes(); expect(repositoryVersionEntity.getVersion()).andReturn(EXPECTED_VERSION).anyTimes(); expect(m_cluster.getCurrentClusterVersion()).andReturn(clusterVersionEntity).anyTimes(); // mock clusters expect(m_clusters.getClusters()).andReturn(clusterMap).atLeastOnce(); // mock the definition DAO expect(m_definitionDao.findByName(CLUSTER_ID, DEFINITION_NAME)).andReturn( m_definition).atLeastOnce(); m_metaInfo.init(); EasyMock.expectLastCall().anyTimes(); // expect the cluster host mapping expect(m_cluster.getServiceComponentHosts(HOSTNAME_1)).andReturn( m_hostComponentMap.get(HOSTNAME_1)).once(); expect(m_cluster.getServiceComponentHosts(HOSTNAME_2)).andReturn( m_hostComponentMap.get(HOSTNAME_2)).once(); // expect the component from metainfo ComponentInfo componentInfo = createNiceMock(ComponentInfo.class); expect(componentInfo.isVersionAdvertised()).andReturn(true).atLeastOnce(); expect(m_metaInfo.getComponent(EasyMock.anyString(), EasyMock.anyString(), EasyMock.anyString(), EasyMock.anyString())).andReturn(componentInfo).atLeastOnce(); } /** * @throws Exception */ @After public void teardown() throws Exception { } /** * Tests that the alert is SKIPPED when there is an upgrade in progress. */ @Test public void testUpgradeInProgress() throws Exception { UpgradeEntity upgrade = createNiceMock(UpgradeEntity.class); expect(upgrade.getToVersion()).andReturn("VERSION").once(); expect(m_cluster.getUpgradeInProgress()).andReturn(upgrade).once(); replayAll(); m_metaInfo.init(); // precondition that no events were fired assertEquals(0, m_listener.getAlertEventReceivedCount(AlertReceivedEvent.class)); // instantiate and inject mocks ComponentVersionAlertRunnable runnable = new ComponentVersionAlertRunnable( m_definition.getDefinitionName()); m_injector.injectMembers(runnable); // run the alert runnable.run(); assertEquals(1, m_listener.getAlertEventReceivedCount(AlertReceivedEvent.class)); List<AlertEvent> events = m_listener.getAlertEventInstances(AlertReceivedEvent.class); assertEquals(1, events.size()); AlertReceivedEvent event = (AlertReceivedEvent) events.get(0); Alert alert = event.getAlert(); assertEquals("AMBARI", alert.getService()); assertEquals("AMBARI_SERVER", alert.getComponent()); assertEquals(AlertState.SKIPPED, alert.getState()); assertEquals(DEFINITION_NAME, alert.getName()); } /** * Tests the alert that fires when all components are reporting correct * versions. */ @Test public void testAllComponentVersionsCorrect() throws Exception { replayAll(); m_metaInfo.init(); // precondition that no events were fired assertEquals(0, m_listener.getAlertEventReceivedCount(AlertReceivedEvent.class)); // instantiate and inject mocks ComponentVersionAlertRunnable runnable = new ComponentVersionAlertRunnable( m_definition.getDefinitionName()); m_injector.injectMembers(runnable); // run the alert runnable.run(); assertEquals(1, m_listener.getAlertEventReceivedCount(AlertReceivedEvent.class)); List<AlertEvent> events = m_listener.getAlertEventInstances(AlertReceivedEvent.class); assertEquals(1, events.size()); AlertReceivedEvent event = (AlertReceivedEvent) events.get(0); Alert alert = event.getAlert(); assertEquals("AMBARI", alert.getService()); assertEquals("AMBARI_SERVER", alert.getComponent()); assertEquals(AlertState.OK, alert.getState()); assertEquals(DEFINITION_NAME, alert.getName()); verifyAll(); } /** * Tests that the alert which fires when there is a mismatch is a WARNING. */ @Test public void testomponentVersionMismatch() throws Exception { // reset expectation so that it returns a wrong version ServiceComponentHost sch = m_hostComponentMap.get(HOSTNAME_1).get(0); EasyMock.reset(sch); expect(sch.getServiceName()).andReturn("FOO").atLeastOnce(); expect(sch.getServiceComponentName()).andReturn("FOO_COMPONENT").atLeastOnce(); expect(sch.getVersion()).andReturn(WRONG_VERSION).atLeastOnce(); expect(sch.getDesiredStackVersion()).andReturn(m_desidredStackId).atLeastOnce(); replayAll(); m_metaInfo.init(); // precondition that no events were fired assertEquals(0, m_listener.getAlertEventReceivedCount(AlertReceivedEvent.class)); // instantiate and inject mocks ComponentVersionAlertRunnable runnable = new ComponentVersionAlertRunnable( m_definition.getDefinitionName()); m_injector.injectMembers(runnable); // run the alert runnable.run(); assertEquals(1, m_listener.getAlertEventReceivedCount(AlertReceivedEvent.class)); List<AlertEvent> events = m_listener.getAlertEventInstances(AlertReceivedEvent.class); assertEquals(1, events.size()); AlertReceivedEvent event = (AlertReceivedEvent) events.get(0); Alert alert = event.getAlert(); assertEquals("AMBARI", alert.getService()); assertEquals("AMBARI_SERVER", alert.getComponent()); assertEquals(AlertState.WARNING, alert.getState()); assertEquals(DEFINITION_NAME, alert.getName()); verifyAll(); } /** * */ private class MockModule implements Module { /** * */ @Override public void configure(Binder binder) { Cluster cluster = createNiceMock(Cluster.class); binder.bind(Clusters.class).toInstance(createNiceMock(Clusters.class)); binder.bind(OsFamily.class).toInstance(createNiceMock(OsFamily.class)); binder.bind(DBAccessor.class).toInstance(createNiceMock(DBAccessor.class)); binder.bind(Cluster.class).toInstance(cluster); binder.bind(AlertDefinitionDAO.class).toInstance(createNiceMock(AlertDefinitionDAO.class)); binder.bind(EntityManager.class).toInstance(createNiceMock(EntityManager.class)); binder.bind(AmbariMetaInfo.class).toInstance(createNiceMock(AmbariMetaInfo.class)); binder.bind(StackManagerFactory.class).toInstance(createNiceMock(StackManagerFactory.class)); } } }