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
   * <p>
   * http://www.apache.org/licenses/LICENSE-2.0
   * <p>
   * 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.view.utils.ambari;
  
  
  import org.apache.ambari.view.URLStreamProvider;
  import org.apache.ambari.view.ViewContext;
  import org.apache.ambari.view.cluster.Cluster;
  import org.apache.commons.io.IOUtils;
  import org.easymock.EasyMock;
  import org.easymock.EasyMockSupport;
  import org.junit.Test;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.util.HashMap;
  import java.util.Map;
  
  import static org.easymock.EasyMock.*;
  import static org.junit.Assert.assertEquals;
  
  public class ServicesTest extends EasyMockSupport {
  
    private static final String HTTP_RM_URL1 = "http://c1.ambari.apache.org:8088";
    private static final String HTTP_RM_URL2 = "http://c2.ambari.apache.org:8088";
    private static final String HTTPS_RM_URL1 = "https://c1.ambari.apache.org:8088";
    private static final String HTTPS_RM_URL2 = "https://c2.ambari.apache.org:8088";
    private static final String RM_URL1_HOST = "c1.ambari.apache.org";
    private static final String RM_URL2_HOST = "c2.ambari.apache.org";
    private static final String RM_URL1_HOST_PORT = "c1.ambari.apache.org:8088";
    private static final String RM_URL2_HOST_PORT = "c2.ambari.apache.org:8088";
    private static final String RM_INFO_API_ENDPOINT = Services.RM_INFO_API_ENDPOINT;
  
    @Test(expected = AmbariApiException.class)
    public void shouldCheckForEmptyATSUrlInCustomConfig() {
      ViewContext viewContext = getViewContext(new HashMap<String, String>());
      AmbariApi ambariApi = createNiceMock(AmbariApi.class);
      expect(ambariApi.isClusterAssociated()).andReturn(false);
  
      replay(viewContext);
  
      Services services = new Services(ambariApi, viewContext);
      services.getTimelineServerUrl();
  
    }
  
    @Test
    public void shouldReturnATSUrlConfiguredInCustomMode() throws Exception {
      Map<String, String> map = new HashMap<>();
      map.put("yarn.ats.url", HTTP_RM_URL1);
      ViewContext viewContext = getViewContext(map);
  
      AmbariApi ambariApi = createNiceMock(AmbariApi.class);
      expect(ambariApi.isClusterAssociated()).andReturn(false);
  
      replay(viewContext);
  
      Services services = new Services(ambariApi, viewContext);
      assertEquals(HTTP_RM_URL1, services.getTimelineServerUrl());
    }
  
    @Test(expected = AmbariApiException.class)
    public void shouldThrowExceptionIfNoProtocolInCustomMode() {
      Map<String, String> map = new HashMap<>();
      map.put("yarn.ats.url", RM_URL1_HOST_PORT);
      ViewContext viewContext = getViewContext(map);
  
      AmbariApi ambariApi = createNiceMock(AmbariApi.class);
      expect(ambariApi.isClusterAssociated()).andReturn(false);
  
      replay(viewContext);
  
      Services services = new Services(ambariApi, viewContext);
      services.getTimelineServerUrl();
    }
  
  
    @Test
    public void shouldReturnATSUrlFromYarnSiteInClusteredMode() throws Exception {
      ViewContext viewContext = getViewContext(new HashMap<String, String>());
      AmbariApi ambariApi = createNiceMock(AmbariApi.class);
      Cluster cluster = createNiceMock(Cluster.class);
      Services services = new Services(ambariApi, viewContext);
  
      expect(ambariApi.isClusterAssociated()).andReturn(true).anyTimes();
      setClusterExpectation(cluster, "HTTP_ONLY");
      expect(viewContext.getCluster()).andReturn(cluster).anyTimes();
      replayAll();
  
      assertEquals(HTTP_RM_URL1, services.getTimelineServerUrl());
  
      reset(cluster);
      setClusterExpectation(cluster, "HTTPS_ONLY");
      replay(cluster);
  
      assertEquals(HTTPS_RM_URL2, services.getTimelineServerUrl());
  
    }
  
    @Test(expected = AmbariApiException.class)
    public void shouldCheckForEmptyYarnRMUrlInCustomConfig() {
      ViewContext viewContext = getViewContext(new HashMap<String, String>());
      AmbariApi ambariApi = createNiceMock(AmbariApi.class);
      expect(ambariApi.isClusterAssociated()).andReturn(false);
  
      replay(viewContext);
  
      Services services = new Services(ambariApi, viewContext);
      services.getRMUrl();
  
  
    }
  
    @Test(expected = AmbariApiException.class)
    public void shouldCheckIfAllRMUrlsHaveProtocolInCustomConfig() {
      Map<String, String> map = new HashMap<>();
      map.put("yarn.resourcemanager.url", HTTP_RM_URL1 + "," + RM_URL2_HOST_PORT);
      ViewContext viewContext = getViewContext(map);
      AmbariApi ambariApi = createNiceMock(AmbariApi.class);
      expect(ambariApi.isClusterAssociated()).andReturn(false);
  
      replay(viewContext);
  
      Services services = new Services(ambariApi, viewContext);
      services.getRMUrl();
    }
  
    @Test
    public void shouldReturnUrlIfSingleIsConfiguredInCustomConfig() {
      Map<String, String> map = new HashMap<>();
      map.put("yarn.resourcemanager.url", HTTP_RM_URL1);
      ViewContext viewContext = getViewContext(map);
      AmbariApi ambariApi = createNiceMock(AmbariApi.class);
      expect(ambariApi.isClusterAssociated()).andReturn(false);
  
      replay(viewContext);
  
      Services services = new Services(ambariApi, viewContext);
      assertEquals(HTTP_RM_URL1, services.getRMUrl());
    }
  
    @Test
    public void shouldConnectToFirstUrlWhenMultipleRMUrlIsConfiguredInCustomConfig() throws IOException {
      Map<String, String> map = new HashMap<>();
      map.put("yarn.resourcemanager.url", HTTP_RM_URL1 + ", " + HTTP_RM_URL2);
      ViewContext viewContext = getViewContext(map);
  
      AmbariApi ambariApi = createNiceMock(AmbariApi.class);
      URLStreamProvider urlStreamProvider = createNiceMock(URLStreamProvider.class);
  
      InputStream inputStream = IOUtils.toInputStream("{\"clusterInfo\": {\"haState\": \"ACTIVE\"}}");
  
      expect(ambariApi.isClusterAssociated()).andReturn(false);
      expect(viewContext.getURLStreamProvider()).andReturn(urlStreamProvider);
      expect(urlStreamProvider.readFrom(eq(HTTP_RM_URL1 + RM_INFO_API_ENDPOINT), eq("GET"), anyString(), EasyMock.<Map<String, String>>anyObject())).andReturn(inputStream);
  
      replayAll();
  
      Services services = new Services(ambariApi, viewContext);
      assertEquals(HTTP_RM_URL1, services.getRMUrl());
  
    }
  
    @Test
    public void shouldConnectToSecondUrlWhenTheFirstURLTimesOut() throws Exception {
      Map<String, String> map = new HashMap<>();
      map.put("yarn.resourcemanager.url", HTTP_RM_URL1 + ", " + HTTP_RM_URL2);
      ViewContext viewContext = getViewContext(map);
  
      AmbariApi ambariApi = createNiceMock(AmbariApi.class);
      URLStreamProvider urlStreamProvider = createNiceMock(URLStreamProvider.class);
  
      InputStream inputStream = IOUtils.toInputStream("{\"clusterInfo\": {\"haState\": \"ACTIVE\"}}");
  
      expect(ambariApi.isClusterAssociated()).andReturn(false);
      expect(viewContext.getURLStreamProvider()).andReturn(urlStreamProvider).anyTimes();
      expect(urlStreamProvider.readFrom(eq(HTTP_RM_URL1 + RM_INFO_API_ENDPOINT), eq("GET"), anyString(), EasyMock.<Map<String, String>>anyObject())).andThrow(new IOException());
      expect(urlStreamProvider.readFrom(eq(HTTP_RM_URL2 + RM_INFO_API_ENDPOINT), eq("GET"), anyString(), EasyMock.<Map<String, String>>anyObject())).andReturn(inputStream);
  
      replayAll();
  
      Services services = new Services(ambariApi, viewContext);
      assertEquals(HTTP_RM_URL2, services.getRMUrl());
  
    }
  
    @Test(expected = AmbariApiException.class)
    public void shouldThrowExceptionWhenAllUrlCannotBeReached() throws Exception {
      Map<String, String> map = new HashMap<>();
      map.put("yarn.resourcemanager.url", HTTP_RM_URL1 + ", " + HTTP_RM_URL2);
      ViewContext viewContext = getViewContext(map);
  
      AmbariApi ambariApi = createNiceMock(AmbariApi.class);
      URLStreamProvider urlStreamProvider = createNiceMock(URLStreamProvider.class);
  
      expect(ambariApi.isClusterAssociated()).andReturn(false);
      expect(viewContext.getURLStreamProvider()).andReturn(urlStreamProvider).anyTimes();
      expect(urlStreamProvider.readFrom(eq(HTTP_RM_URL1 + RM_INFO_API_ENDPOINT), eq("GET"), anyString(), EasyMock.<Map<String, String>>anyObject())).andThrow(new IOException());
      expect(urlStreamProvider.readFrom(eq(HTTP_RM_URL2 + RM_INFO_API_ENDPOINT), eq("GET"), anyString(), EasyMock.<Map<String, String>>anyObject())).andThrow(new IOException());
  
      replayAll();
  
      Services services = new Services(ambariApi, viewContext);
      services.getRMUrl();
    }
  
    @Test
    public void shouldReturnActiveRMUrlWhenConnectingToStandby() throws Exception {
      Map<String, String> map = new HashMap<>();
      map.put("yarn.resourcemanager.url", HTTP_RM_URL1 + ", " + HTTP_RM_URL2);
      ViewContext viewContext = getViewContext(map);
  
      AmbariApi ambariApi = createNiceMock(AmbariApi.class);
      URLStreamProvider urlStreamProvider = createNiceMock(URLStreamProvider.class);
  
      InputStream inputStream = IOUtils.toInputStream("{\"clusterInfo\": {\"haState\": \"STANDBY\"}}");
  
      expect(ambariApi.isClusterAssociated()).andReturn(false);
      expect(viewContext.getURLStreamProvider()).andReturn(urlStreamProvider).anyTimes();
      expect(urlStreamProvider.readFrom(eq(HTTP_RM_URL1 + RM_INFO_API_ENDPOINT), eq("GET"), anyString(), EasyMock.<Map<String, String>>anyObject())).andReturn(inputStream);
  
      InputStream inputStreamActive = IOUtils.toInputStream("{\"clusterInfo\": {\"haState\": \"ACTIVE\"}}");
      expect(urlStreamProvider.readFrom(eq(HTTP_RM_URL2 + RM_INFO_API_ENDPOINT), eq("GET"), anyString(), EasyMock.<Map<String, String>>anyObject())).andReturn(inputStreamActive);
  
      replayAll();
  
      Services services = new Services(ambariApi, viewContext);
      assertEquals(HTTP_RM_URL2, services.getRMUrl());
  
      verify(urlStreamProvider);
  
    }
  
    @Test
    public void shouldConnectToRMConfiguredInClusterMode() throws Exception {
      ViewContext viewContext = getViewContext(new HashMap<String, String>());
      AmbariApi ambariApi = createNiceMock(AmbariApi.class);
      Cluster cluster = createNiceMock(Cluster.class);
  
      expect(ambariApi.isClusterAssociated()).andReturn(true).anyTimes();
      setClusterExpectation(cluster, "HTTP_ONLY");
      expect(viewContext.getCluster()).andReturn(cluster).anyTimes();
  
      replayAll();
  
      Services services = new Services(ambariApi, viewContext);
      assertEquals(HTTP_RM_URL1, services.getRMUrl());
  
      reset(cluster);
      setClusterExpectation(cluster, "HTTPS_ONLY");
      replay(cluster);
  
      assertEquals(HTTPS_RM_URL2, services.getRMUrl());
  
      reset(cluster);
      setClusterExpectation(cluster, "HTTPS_ONLY_XYZ");
      replay(cluster);
  
      assertEquals(HTTP_RM_URL1, services.getRMUrl());
    }
  
    @Test
    public void shouldConnectToDefaultHostPortInClusterModeWhenWebaddressConfigIsEmpty() throws Exception {
      ViewContext viewContext = getViewContext(new HashMap<String, String>());
      AmbariApi ambariApi = createNiceMock(AmbariApi.class);
      Cluster cluster = createNiceMock(Cluster.class);
  
      expect(ambariApi.isClusterAssociated()).andReturn(true).anyTimes();
      setClusterExpectationWithEmptyWebappConfig(cluster, "HTTP_ONLY");
      expect(viewContext.getCluster()).andReturn(cluster).anyTimes();
  
      Services services = new Services(ambariApi, viewContext);
  
      replayAll();
      assertEquals("http://" + RM_URL1_HOST + ":8088", services.getRMUrl());
  
      reset(cluster);
      setClusterExpectationWithEmptyWebappConfig(cluster, "HTTPS_ONLY");
      replay(cluster);
  
      assertEquals("https://" + RM_URL1_HOST + ":8090", services.getRMUrl());
  
    }
  
    @Test
    public void shouldConnectToDefaultHostPortInClusterModeWithHAWhenWebaddressConfigIsEmpty() throws Exception {
      ViewContext viewContext = getViewContext(new HashMap<String, String>());
      AmbariApi ambariApi = createNiceMock(AmbariApi.class);
      Cluster cluster = createNiceMock(Cluster.class);
      URLStreamProvider urlStreamProvider = createNiceMock(URLStreamProvider.class);
  
      expect(ambariApi.isClusterAssociated()).andReturn(true).anyTimes();
      setClusterExpectationInHAWithEmptyWebappConfig(cluster, "HTTP_ONLY");
      expect(viewContext.getCluster()).andReturn(cluster).anyTimes();
  
      Services services = new Services(ambariApi, viewContext);
  
      InputStream inputStream = IOUtils.toInputStream("{\"clusterInfo\": {\"haState\": \"ACTIVE\"}}");
      expect(viewContext.getURLStreamProvider()).andReturn(urlStreamProvider).anyTimes();
      expect(urlStreamProvider.readFrom(eq("http://" + RM_URL1_HOST + ":8088" + RM_INFO_API_ENDPOINT), eq("GET"), anyString(), EasyMock.<Map<String, String>>anyObject())).andReturn(inputStream);
  
      replayAll();
      assertEquals("http://" + RM_URL1_HOST + ":8088", services.getRMUrl());
  
      reset(cluster, urlStreamProvider);
      setClusterExpectationInHAWithEmptyWebappConfig(cluster, "HTTPS_ONLY");
      inputStream = IOUtils.toInputStream("{\"clusterInfo\": {\"haState\": \"ACTIVE\"}}");
      expect(urlStreamProvider.readFrom(eq("https://" + RM_URL1_HOST + ":8090" + RM_INFO_API_ENDPOINT), eq("GET"), anyString(), EasyMock.<Map<String, String>>anyObject())).andReturn(inputStream);
      replay(cluster, urlStreamProvider);
  
      assertEquals("https://" + RM_URL1_HOST + ":8090", services.getRMUrl());
  
    }
  
    @Test
    public void shouldFetchRMUrlsWhileHAEnabledInClusterMode() throws Exception {
      ViewContext viewContext = getViewContext(new HashMap<String, String>());
      AmbariApi ambariApi = createNiceMock(AmbariApi.class);
      Cluster cluster = createNiceMock(Cluster.class);
      URLStreamProvider urlStreamProvider = createNiceMock(URLStreamProvider.class);
      Services services = new Services(ambariApi, viewContext);
  
      InputStream inputStream = IOUtils.toInputStream("{\"clusterInfo\": {\"haState\": \"ACTIVE\"}}");
  
  
  
      expect(ambariApi.isClusterAssociated()).andReturn(true).anyTimes();
      setClusterExpectationInHA(cluster, "HTTP_ONLY");
      expect(viewContext.getCluster()).andReturn(cluster).anyTimes();
      expect(viewContext.getURLStreamProvider()).andReturn(urlStreamProvider).anyTimes();
      expect(urlStreamProvider.readFrom(eq(HTTP_RM_URL1 + RM_INFO_API_ENDPOINT), eq("GET"), anyString(), EasyMock.<Map<String, String>>anyObject())).andReturn(inputStream);
  
      replayAll();
  
      assertEquals(HTTP_RM_URL1, services.getRMUrl());
  
      reset(cluster, urlStreamProvider);
      setClusterExpectationInHA(cluster, "HTTP_ONLY");
      inputStream = IOUtils.toInputStream("{\"clusterInfo\": {\"haState\": \"ACTIVE\"}}");
      expect(urlStreamProvider.readFrom(eq(HTTP_RM_URL1 + RM_INFO_API_ENDPOINT), eq("GET"), anyString(), EasyMock.<Map<String, String>>anyObject())).andThrow(new IOException());
      expect(urlStreamProvider.readFrom(eq(HTTP_RM_URL2 + RM_INFO_API_ENDPOINT), eq("GET"), anyString(), EasyMock.<Map<String, String>>anyObject())).andReturn(inputStream);
      replay(cluster, urlStreamProvider);
  
      assertEquals(HTTP_RM_URL2, services.getRMUrl());
  
      reset(cluster, urlStreamProvider);
      setClusterExpectationInHA(cluster, "HTTPS_ONLY");
      inputStream = IOUtils.toInputStream("{\"clusterInfo\": {\"haState\": \"ACTIVE\"}}");
      expect(urlStreamProvider.readFrom(eq(HTTPS_RM_URL1 + RM_INFO_API_ENDPOINT), eq("GET"), anyString(), EasyMock.<Map<String, String>>anyObject())).andReturn(inputStream);
      replay(cluster, urlStreamProvider);
  
      assertEquals(HTTPS_RM_URL1, services.getRMUrl());
  
      reset(cluster, urlStreamProvider);
      setClusterExpectationInHA(cluster, "HTTPS_ONLY");
      inputStream = IOUtils.toInputStream("{\"clusterInfo\": {\"haState\": \"ACTIVE\"}}");
      expect(urlStreamProvider.readFrom(eq(HTTPS_RM_URL1 + RM_INFO_API_ENDPOINT), eq("GET"), anyString(), EasyMock.<Map<String, String>>anyObject())).andThrow(new IOException());
      expect(urlStreamProvider.readFrom(eq(HTTPS_RM_URL2 + RM_INFO_API_ENDPOINT), eq("GET"), anyString(), EasyMock.<Map<String, String>>anyObject())).andReturn(inputStream);
      replay(cluster, urlStreamProvider);
  
      assertEquals(HTTPS_RM_URL2, services.getRMUrl());
    }
  
    @Test
    public void basicGetYARNProtocol() throws Exception {
      ViewContext viewContext = getViewContext(new HashMap<String, String>());
      AmbariApi ambariApi = createNiceMock(AmbariApi.class);
      Cluster cluster = createNiceMock(Cluster.class);
  
      expect(ambariApi.isClusterAssociated()).andReturn(true).anyTimes();
      setClusterExpectationWithEmptyWebappConfig(cluster, "HTTP_ONLY");
      expect(viewContext.getCluster()).andReturn(cluster).anyTimes();
  
      Services services = new Services(ambariApi, viewContext);
  
      replayAll();
      assertEquals("http", services.getYARNProtocol());
    }
  
    private void setClusterExpectation(Cluster cluster, String httpPolicy) {
      expect(cluster.getConfigurationValue("yarn-site", "yarn.resourcemanager.ha.enabled")).andReturn("false");
      expect(cluster.getConfigurationValue("yarn-site", "yarn.http.policy")).andReturn(httpPolicy);
      expect(cluster.getConfigurationValue("yarn-site", "yarn.resourcemanager.webapp.address")).andReturn(RM_URL1_HOST_PORT);
      expect(cluster.getConfigurationValue("yarn-site", "yarn.resourcemanager.webapp.https.address")).andReturn(RM_URL2_HOST_PORT);
      expect(cluster.getConfigurationValue("yarn-site", "yarn.timeline-service.webapp.address")).andReturn(RM_URL1_HOST_PORT);
      expect(cluster.getConfigurationValue("yarn-site", "yarn.timeline-service.webapp.https.address")).andReturn(RM_URL2_HOST_PORT);
    }
  
    private void setClusterExpectationInHA(Cluster cluster, String httpPolicy) {
      expect(cluster.getConfigurationValue("yarn-site", "yarn.resourcemanager.ha.enabled")).andReturn("true");
      expect(cluster.getConfigurationValue("yarn-site", "yarn.http.policy")).andReturn(httpPolicy);
      expect(cluster.getConfigurationValue("yarn-site", "yarn.resourcemanager.ha.rm-ids")).andReturn("rm1,rm2");
      expect(cluster.getConfigurationValue("yarn-site", "yarn.resourcemanager.webapp.address.rm1")).andReturn(RM_URL1_HOST_PORT);
      expect(cluster.getConfigurationValue("yarn-site", "yarn.resourcemanager.webapp.address.rm2")).andReturn(RM_URL2_HOST_PORT);
      expect(cluster.getConfigurationValue("yarn-site", "yarn.resourcemanager.webapp.https.address.rm1")).andReturn(RM_URL1_HOST_PORT);
      expect(cluster.getConfigurationValue("yarn-site", "yarn.resourcemanager.webapp.https.address.rm2")).andReturn(RM_URL2_HOST_PORT);
    }
  
    private void setClusterExpectationInHAWithEmptyWebappConfig(Cluster cluster, String httpPolicy) {
      expect(cluster.getConfigurationValue("yarn-site", "yarn.resourcemanager.ha.enabled")).andReturn("true");
      expect(cluster.getConfigurationValue("yarn-site", "yarn.http.policy")).andReturn(httpPolicy);
      expect(cluster.getConfigurationValue("yarn-site", "yarn.resourcemanager.ha.rm-ids")).andReturn("rm1,rm2");
      expect(cluster.getConfigurationValue("yarn-site", "yarn.resourcemanager.hostname.rm1")).andReturn(RM_URL1_HOST);
      expect(cluster.getConfigurationValue("yarn-site", "yarn.resourcemanager.hostname.rm2")).andReturn(RM_URL2_HOST);
  
    }
  
    private void setClusterExpectationWithEmptyWebappConfig(Cluster cluster, String httpPolicy) {
      expect(cluster.getConfigurationValue("yarn-site", "yarn.resourcemanager.ha.enabled")).andReturn("false");
      expect(cluster.getConfigurationValue("yarn-site", "yarn.http.policy")).andReturn(httpPolicy);
      expect(cluster.getConfigurationValue("yarn-site", "yarn.resourcemanager.hostname")).andReturn(RM_URL1_HOST);
    }
  
    private ViewContext getViewContext(Map<String, String> map) {
      ViewContext viewContextMock = createNiceMock(ViewContext.class);
      expect(viewContextMock.getProperties()).andReturn(map);
      return viewContextMock;
    }
  }
  