/* * 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.nifi.web.api; import org.apache.nifi.cluster.coordination.ClusterCoordinator; import org.apache.nifi.cluster.coordination.node.NodeWorkload; import org.apache.nifi.cluster.protocol.NodeIdentifier; import org.apache.nifi.remote.protocol.ResponseCode; import org.apache.nifi.remote.protocol.http.HttpHeaders; import org.apache.nifi.util.NiFiProperties; import org.apache.nifi.web.NiFiServiceFacade; import org.apache.nifi.web.api.dto.ControllerDTO; import org.apache.nifi.web.api.dto.remote.PeerDTO; import org.apache.nifi.web.api.entity.ControllerEntity; import org.apache.nifi.web.api.entity.PeersEntity; import org.apache.nifi.web.api.entity.TransactionResultEntity; import org.junit.BeforeClass; import org.junit.Test; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.Response; import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.stream.IntStream; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class TestSiteToSiteResource { @BeforeClass public static void setup() throws Exception { final URL resource = TestSiteToSiteResource.class.getResource("/site-to-site/nifi.properties"); final String propertiesFile = resource.toURI().getPath(); System.setProperty(NiFiProperties.PROPERTIES_FILE_PATH, propertiesFile); } @Test public void testGetControllerForOlderVersion() throws Exception { final HttpServletRequest req = mock(HttpServletRequest.class); final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class); final ControllerEntity controllerEntity = new ControllerEntity(); final ControllerDTO controller = new ControllerDTO(); controllerEntity.setController(controller); controller.setRemoteSiteHttpListeningPort(8080); controller.setRemoteSiteListeningPort(9990); doReturn(controller).when(serviceFacade).getSiteToSiteDetails(); final SiteToSiteResource resource = getSiteToSiteResource(serviceFacade); final Response response = resource.getSiteToSiteDetails(req); ControllerEntity resultEntity = (ControllerEntity)response.getEntity(); assertEquals(200, response.getStatus()); assertNull("remoteSiteHttpListeningPort should be null since older version doesn't recognize this field" + " and throws JSON mapping exception.", resultEntity.getController().getRemoteSiteHttpListeningPort()); assertEquals("Other fields should be retained.", new Integer(9990), controllerEntity.getController().getRemoteSiteListeningPort()); } @Test public void testGetController() throws Exception { final HttpServletRequest req = createCommonHttpServletRequest(); final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class); final ControllerEntity controllerEntity = new ControllerEntity(); final ControllerDTO controller = new ControllerDTO(); controllerEntity.setController(controller); controller.setRemoteSiteHttpListeningPort(8080); controller.setRemoteSiteListeningPort(9990); doReturn(controller).when(serviceFacade).getSiteToSiteDetails(); final SiteToSiteResource resource = getSiteToSiteResource(serviceFacade); final Response response = resource.getSiteToSiteDetails(req); ControllerEntity resultEntity = (ControllerEntity)response.getEntity(); assertEquals(200, response.getStatus()); assertEquals("remoteSiteHttpListeningPort should be retained", new Integer(8080), resultEntity.getController().getRemoteSiteHttpListeningPort()); assertEquals("Other fields should be retained.", new Integer(9990), controllerEntity.getController().getRemoteSiteListeningPort()); } private HttpServletRequest createCommonHttpServletRequest() { final HttpServletRequest req = mock(HttpServletRequest.class); doReturn("1").when(req).getHeader(eq(HttpHeaders.PROTOCOL_VERSION)); return req; } @Test public void testPeers() throws Exception { final HttpServletRequest req = createCommonHttpServletRequest(); final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class); final SiteToSiteResource resource = getSiteToSiteResource(serviceFacade); final Response response = resource.getPeers(req); PeersEntity resultEntity = (PeersEntity) response.getEntity(); assertEquals(200, response.getStatus()); assertEquals(1, resultEntity.getPeers().size()); final PeerDTO peer = resultEntity.getPeers().iterator().next(); assertEquals(8080, peer.getPort()); } @Test public void testPeersPortForwarding() throws Exception { final HttpServletRequest req = createCommonHttpServletRequest(); final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class); final Map<String, String> additionalProperties = new HashMap<>(); additionalProperties.put(NiFiProperties.WEB_HTTP_PORT_FORWARDING, "80"); final SiteToSiteResource resource = getSiteToSiteResource(serviceFacade, additionalProperties); final Response response = resource.getPeers(req); PeersEntity resultEntity = (PeersEntity) response.getEntity(); assertEquals(200, response.getStatus()); assertEquals(1, resultEntity.getPeers().size()); final PeerDTO peer = resultEntity.getPeers().iterator().next(); assertEquals(80, peer.getPort()); } @Test public void testPeersClustered() throws Exception { final HttpServletRequest req = createCommonHttpServletRequest(); final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class); final Map<String, String> clusterSettings = new HashMap<>(); clusterSettings.put(NiFiProperties.CLUSTER_IS_NODE, "true"); final SiteToSiteResource resource = getSiteToSiteResource(serviceFacade, clusterSettings); final ClusterCoordinator clusterCoordinator = mock(ClusterCoordinator.class); final Map<String, NodeWorkload> hostportWorkloads = new HashMap<>(); final Map<NodeIdentifier, NodeWorkload> workloads = new HashMap<>(); IntStream.range(1, 4).forEach(i -> { final String hostname = "node" + i; final int siteToSiteHttpApiPort = 8110 + i; final NodeIdentifier nodeId = new NodeIdentifier(hostname, hostname, 8080 + i, hostname, 8090 + i, hostname, 8100 + i, siteToSiteHttpApiPort, false); final NodeWorkload workload = new NodeWorkload(); workload.setReportedTimestamp(System.currentTimeMillis() - i); workload.setFlowFileBytes(1024 * i); workload.setFlowFileCount(10 * i); workload.setActiveThreadCount(i); workload.setSystemStartTime(System.currentTimeMillis() - (1000 * i)); workloads.put(nodeId, workload); hostportWorkloads.put(hostname + ":" + siteToSiteHttpApiPort, workload); }); when(clusterCoordinator.getClusterWorkload()).thenReturn(workloads); resource.setClusterCoordinator(clusterCoordinator); final Response response = resource.getPeers(req); PeersEntity resultEntity = (PeersEntity) response.getEntity(); assertEquals(200, response.getStatus()); assertEquals(3, resultEntity.getPeers().size()); resultEntity.getPeers().stream().forEach(peerDTO -> { final NodeWorkload workload = hostportWorkloads.get(peerDTO.getHostname() + ":" + peerDTO.getPort()); assertNotNull(workload); assertEquals(workload.getFlowFileCount(), peerDTO.getFlowFileCount()); }); } @Test public void testPeersVersionWasNotSpecified() throws Exception { final HttpServletRequest req = mock(HttpServletRequest.class); final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class); final SiteToSiteResource resource = getSiteToSiteResource(serviceFacade); final Response response = resource.getPeers(req); TransactionResultEntity resultEntity = (TransactionResultEntity) response.getEntity(); assertEquals(400, response.getStatus()); assertEquals(ResponseCode.ABORT.getCode(), resultEntity.getResponseCode()); } @Test public void testPeersVersionNegotiationDowngrade() throws Exception { final HttpServletRequest req = mock(HttpServletRequest.class); doReturn("999").when(req).getHeader(eq(HttpHeaders.PROTOCOL_VERSION)); final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class); final SiteToSiteResource resource = getSiteToSiteResource(serviceFacade); final Response response = resource.getPeers(req); PeersEntity resultEntity = (PeersEntity) response.getEntity(); assertEquals(200, response.getStatus()); assertEquals(1, resultEntity.getPeers().size()); assertEquals(new Integer(1), response.getMetadata().getFirst(HttpHeaders.PROTOCOL_VERSION)); } private SiteToSiteResource getSiteToSiteResource(final NiFiServiceFacade serviceFacade) { return getSiteToSiteResource(serviceFacade, null); } private SiteToSiteResource getSiteToSiteResource(final NiFiServiceFacade serviceFacade, final Map<String, String> additionalProperties) { final NiFiProperties properties = NiFiProperties.createBasicNiFiProperties(null, additionalProperties); final SiteToSiteResource resource = new SiteToSiteResource(properties) { @Override protected void authorizeSiteToSite() { } }; resource.setProperties(properties); resource.setServiceFacade(serviceFacade); return resource; } }