|
@@ -0,0 +1,672 @@
|
|
|
+/**
|
|
|
+ * 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.controller.logging;
|
|
|
+
|
|
|
+import org.apache.ambari.server.security.credential.PrincipalKeyCredential;
|
|
|
+import org.apache.ambari.server.security.encryption.CredentialStoreService;
|
|
|
+import org.apache.ambari.server.state.Cluster;
|
|
|
+import org.apache.ambari.server.state.Config;
|
|
|
+import org.apache.commons.codec.binary.Base64;
|
|
|
+import org.easymock.Capture;
|
|
|
+import org.easymock.EasyMockSupport;
|
|
|
+import org.junit.Test;
|
|
|
+
|
|
|
+import java.net.HttpURLConnection;
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Set;
|
|
|
+
|
|
|
+import static org.easymock.EasyMock.capture;
|
|
|
+import static org.easymock.EasyMock.eq;
|
|
|
+import static org.easymock.EasyMock.expect;
|
|
|
+
|
|
|
+import static org.junit.Assert.assertEquals;
|
|
|
+import static org.junit.Assert.assertNotNull;
|
|
|
+import static org.junit.Assert.assertSame;
|
|
|
+import static org.junit.Assert.assertTrue;
|
|
|
+
|
|
|
+
|
|
|
+public class LoggingRequestHelperImplTest {
|
|
|
+
|
|
|
+ private static final String TEST_JSON_INPUT_TWO_LIST_ENTRIES =
|
|
|
+ "{" +
|
|
|
+ " \"startIndex\" : 0," +
|
|
|
+ " \"pageSize\" : 5," +
|
|
|
+ " \"totalCount\" : 10452," +
|
|
|
+ " \"resultSize\" : 5," +
|
|
|
+ " \"queryTimeMS\" : 1458148754113," +
|
|
|
+ " \"logList\" : [ {" +
|
|
|
+ " \"cluster\" : \"clusterone\"," +
|
|
|
+ " \"method\" : \"chooseUnderReplicatedBlocks\"," +
|
|
|
+ " \"level\" : \"INFO\"," +
|
|
|
+ " \"event_count\" : 1," +
|
|
|
+ " \"ip\" : \"192.168.1.1\"," +
|
|
|
+ " \"type\" : \"hdfs_namenode\"," +
|
|
|
+ " \"seq_num\" : 10584," +
|
|
|
+ " \"path\" : \"/var/log/hadoop/hdfs/hadoop-hdfs-namenode-c6401.ambari.apache.org.log\"," +
|
|
|
+ " \"file\" : \"UnderReplicatedBlocks.java\"," +
|
|
|
+ " \"line_number\" : 394," +
|
|
|
+ " \"host\" : \"c6401.ambari.apache.org\"," +
|
|
|
+ " \"log_message\" : \"chooseUnderReplicatedBlocks selected 2 blocks at priority level 0; Total=2 Reset bookmarks? false\"," +
|
|
|
+ " \"logger_name\" : \"BlockStateChange\"," +
|
|
|
+ " \"id\" : \"9c5562fb-123f-47c8-aaf5-b5e407326c08\"," +
|
|
|
+ " \"message_md5\" : \"-3892769501348410581\"," +
|
|
|
+ " \"logtime\" : 1458148749036," +
|
|
|
+ " \"event_md5\" : \"1458148749036-2417481968206345035\"," +
|
|
|
+ " \"logfile_line_number\" : 2084," +
|
|
|
+ " \"_ttl_\" : \"+7DAYS\"," +
|
|
|
+ " \"_expire_at_\" : 1458753550322," +
|
|
|
+ " \"_version_\" : 1528979784023932928" +
|
|
|
+ " }, {" +
|
|
|
+ " \"cluster\" : \"clusterone\"," +
|
|
|
+ " \"method\" : \"putMetrics\"," +
|
|
|
+ " \"level\" : \"WARN\"," +
|
|
|
+ " \"event_count\" : 1," +
|
|
|
+ " \"ip\" : \"192.168.1.1\"," +
|
|
|
+ " \"type\" : \"yarn_resourcemanager\"," +
|
|
|
+ " \"seq_num\" : 10583," +
|
|
|
+ " \"path\" : \"/var/log/hadoop-yarn/yarn/yarn-yarn-resourcemanager-c6401.ambari.apache.org.log\"," +
|
|
|
+ " \"file\" : \"HadoopTimelineMetricsSink.java\"," +
|
|
|
+ " \"line_number\" : 262," +
|
|
|
+ " \"host\" : \"c6401.ambari.apache.org\"," +
|
|
|
+ " \"log_message\" : \"Unable to send metrics to collector by address:http://c6401.ambari.apache.org:6188/ws/v1/timeline/metrics\"," +
|
|
|
+ " \"logger_name\" : \"timeline.HadoopTimelineMetricsSink\"," +
|
|
|
+ " \"id\" : \"8361c5a9-5b1c-4f44-bc8f-4c6f07d94228\"," +
|
|
|
+ " \"message_md5\" : \"5942185045779825717\"," +
|
|
|
+ " \"logtime\" : 1458148746937," +
|
|
|
+ " \"event_md5\" : \"14581487469371427138486123628676\"," +
|
|
|
+ " \"logfile_line_number\" : 549," +
|
|
|
+ " \"_ttl_\" : \"+7DAYS\"," +
|
|
|
+ " \"_expire_at_\" : 1458753550322," +
|
|
|
+ " \"_version_\" : 1528979784022884357" +
|
|
|
+ " }" +
|
|
|
+ "]" +
|
|
|
+ "}";
|
|
|
+
|
|
|
+ private static final String TEST_JSON_INPUT_LOG_LEVEL_QUERY =
|
|
|
+ "{\"pageSize\":\"0\",\"queryTimeMS\":\"1459970731998\",\"resultSize\":\"6\",\"startIndex\":\"0\",\"totalCount\":\"0\"," +
|
|
|
+ "\"vNameValues\":[{\"name\":\"FATAL\",\"value\":\"0\"},{\"name\":\"ERROR\",\"value\":\"0\"}," +
|
|
|
+ "{\"name\":\"WARN\",\"value\":\"41\"},{\"name\":\"INFO\",\"value\":\"186\"},{\"name\":\"DEBUG\",\"value\":\"0\"}," +
|
|
|
+ "{\"name\":\"TRACE\",\"value\":\"0\"}]}";
|
|
|
+
|
|
|
+
|
|
|
+ private final String EXPECTED_HOST_NAME = "c6401.ambari.apache.org";
|
|
|
+
|
|
|
+ private final String EXPECTED_PORT_NUMBER = "61888";
|
|
|
+
|
|
|
+ private static final String EXPECTED_USER_NAME = "admin-user";
|
|
|
+
|
|
|
+ private static final String EXPECTED_ADMIN_PASSWORD = "admin-pwd";
|
|
|
+
|
|
|
+ private static final String EXPECTED_ENCODED_CREDENTIALS =
|
|
|
+ Base64.encodeBase64String((EXPECTED_USER_NAME + ":" + EXPECTED_ADMIN_PASSWORD).getBytes());
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testLogQueryRequestBasic() throws Exception {
|
|
|
+ EasyMockSupport mockSupport =
|
|
|
+ new EasyMockSupport();
|
|
|
+
|
|
|
+ CredentialStoreService credentialStoreServiceMock =
|
|
|
+ mockSupport.createMock(CredentialStoreService.class);
|
|
|
+
|
|
|
+ Cluster clusterMock =
|
|
|
+ mockSupport.createMock(Cluster.class);
|
|
|
+
|
|
|
+ LoggingRequestHelperImpl.NetworkConnection networkConnectionMock =
|
|
|
+ mockSupport.createMock(LoggingRequestHelperImpl.NetworkConnection.class);
|
|
|
+
|
|
|
+ Config adminPropertiesConfigMock =
|
|
|
+ mockSupport.createMock(Config.class);
|
|
|
+
|
|
|
+ Map<String, String> testConfigProperties =
|
|
|
+ new HashMap<String, String>();
|
|
|
+
|
|
|
+ testConfigProperties.put("logsearch_admin_username", EXPECTED_USER_NAME);
|
|
|
+ testConfigProperties.put("logsearch_admin_password", EXPECTED_ADMIN_PASSWORD);
|
|
|
+ testConfigProperties = Collections.unmodifiableMap(testConfigProperties);
|
|
|
+
|
|
|
+ Capture<HttpURLConnection> captureURLConnection = new Capture<HttpURLConnection>();
|
|
|
+ Capture<HttpURLConnection> captureURLConnectionForAuthentication = new Capture<HttpURLConnection>();
|
|
|
+
|
|
|
+ expect(clusterMock.getDesiredConfigByType("logsearch-admin-properties")).andReturn(adminPropertiesConfigMock).atLeastOnce();
|
|
|
+ expect(adminPropertiesConfigMock.getProperties()).andReturn(testConfigProperties).atLeastOnce();
|
|
|
+ expect(networkConnectionMock.readQueryResponseFromServer(capture(captureURLConnection))).andReturn(new StringBuffer(TEST_JSON_INPUT_TWO_LIST_ENTRIES)).atLeastOnce();
|
|
|
+
|
|
|
+ // expect that basic authentication is setup, with the expected encoded credentials
|
|
|
+ networkConnectionMock.setupBasicAuthentication(capture(captureURLConnectionForAuthentication), eq(EXPECTED_ENCODED_CREDENTIALS));
|
|
|
+
|
|
|
+ mockSupport.replayAll();
|
|
|
+
|
|
|
+ LoggingRequestHelper helper =
|
|
|
+ new LoggingRequestHelperImpl(EXPECTED_HOST_NAME, EXPECTED_PORT_NUMBER, credentialStoreServiceMock, clusterMock, networkConnectionMock);
|
|
|
+
|
|
|
+ // invoke query request
|
|
|
+ LogQueryResponse result =
|
|
|
+ helper.sendQueryRequest(Collections.<String,String>emptyMap());
|
|
|
+
|
|
|
+ // verify that the HttpURLConnection was created with the proper values
|
|
|
+ HttpURLConnection httpURLConnection =
|
|
|
+ captureURLConnection.getValue();
|
|
|
+
|
|
|
+ assertEquals("URLConnection did not have the correct hostname information",
|
|
|
+ EXPECTED_HOST_NAME, httpURLConnection.getURL().getHost());
|
|
|
+ assertEquals("URLConnection did not have the correct port information",
|
|
|
+ EXPECTED_PORT_NUMBER, httpURLConnection.getURL().getPort() + "");
|
|
|
+ assertEquals("URLConnection did not have the expected http protocol scheme",
|
|
|
+ "http", httpURLConnection.getURL().getProtocol());
|
|
|
+ assertEquals("URLConnection did not have the expected method set",
|
|
|
+ "GET", httpURLConnection.getRequestMethod());
|
|
|
+
|
|
|
+ assertSame("HttpUrlConnection instances passed into NetworkConnection mock should have been the same instance",
|
|
|
+ httpURLConnection, captureURLConnectionForAuthentication.getValue());
|
|
|
+
|
|
|
+
|
|
|
+ assertNotNull("Response object should not be null",
|
|
|
+ result);
|
|
|
+
|
|
|
+ // verify that the JSON response returned from the simulated server
|
|
|
+ // is parsed properly, and has the expected values
|
|
|
+ assertEquals("startIndex not parsed properly",
|
|
|
+ "0", result.getStartIndex());
|
|
|
+ assertEquals("pageSize not parsed properly",
|
|
|
+ "5", result.getPageSize());
|
|
|
+ assertEquals("totalCount not parsed properly",
|
|
|
+ "10452", result.getTotalCount());
|
|
|
+ assertEquals("resultSize not parsed properly",
|
|
|
+ "5", result.getResultSize());
|
|
|
+ assertEquals("queryTimeMS not parsed properly",
|
|
|
+ "1458148754113", result.getQueryTimeMS());
|
|
|
+
|
|
|
+ assertEquals("incorrect number of LogLineResult items parsed",
|
|
|
+ 2, result.getListOfResults().size());
|
|
|
+
|
|
|
+ List<LogLineResult> listOfLineResults =
|
|
|
+ result.getListOfResults();
|
|
|
+
|
|
|
+ {
|
|
|
+ LogLineResult resultOne = listOfLineResults.get(0);
|
|
|
+ // verify that all fields in this class are parsed as expected
|
|
|
+ assertEquals("Cluster name not parsed properly",
|
|
|
+ "clusterone", resultOne.getClusterName());
|
|
|
+ assertEquals("Method Name not parsed properly",
|
|
|
+ "chooseUnderReplicatedBlocks", resultOne.getLogMethod());
|
|
|
+ assertEquals("Log Level not parsed properly",
|
|
|
+ "INFO", resultOne.getLogLevel());
|
|
|
+ assertEquals("event_count not parsed properly",
|
|
|
+ "1", resultOne.getEventCount());
|
|
|
+ assertEquals("ip address not parsed properly",
|
|
|
+ "192.168.1.1", resultOne.getIpAddress());
|
|
|
+ assertEquals("component type not parsed properly",
|
|
|
+ "hdfs_namenode", resultOne.getComponentType());
|
|
|
+ assertEquals("sequence number not parsed properly",
|
|
|
+ "10584", resultOne.getSequenceNumber());
|
|
|
+ assertEquals("log file path not parsed properly",
|
|
|
+ "/var/log/hadoop/hdfs/hadoop-hdfs-namenode-c6401.ambari.apache.org.log", resultOne.getLogFilePath());
|
|
|
+ assertEquals("log src file name not parsed properly",
|
|
|
+ "UnderReplicatedBlocks.java", resultOne.getSourceFile());
|
|
|
+ assertEquals("log src line number not parsed properly",
|
|
|
+ "394", resultOne.getSourceFileLineNumber());
|
|
|
+ assertEquals("host name not parsed properly",
|
|
|
+ "c6401.ambari.apache.org", resultOne.getHostName());
|
|
|
+ assertEquals("log message not parsed properly",
|
|
|
+ "chooseUnderReplicatedBlocks selected 2 blocks at priority level 0; Total=2 Reset bookmarks? false", resultOne.getLogMessage());
|
|
|
+ assertEquals("logger name not parsed properly",
|
|
|
+ "BlockStateChange", resultOne.getLoggerName());
|
|
|
+ assertEquals("id not parsed properly",
|
|
|
+ "9c5562fb-123f-47c8-aaf5-b5e407326c08", resultOne.getId());
|
|
|
+ assertEquals("message MD5 not parsed properly",
|
|
|
+ "-3892769501348410581", resultOne.getMessageMD5());
|
|
|
+ assertEquals("log time not parsed properly",
|
|
|
+ "1458148749036", resultOne.getLogTime());
|
|
|
+ assertEquals("event MD5 not parsed properly",
|
|
|
+ "1458148749036-2417481968206345035", resultOne.getEventMD5());
|
|
|
+ assertEquals("logfile line number not parsed properly",
|
|
|
+ "2084", resultOne.getLogFileLineNumber());
|
|
|
+ assertEquals("ttl not parsed properly",
|
|
|
+ "+7DAYS", resultOne.getTtl());
|
|
|
+ assertEquals("expire at not parsed properly",
|
|
|
+ "1458753550322", resultOne.getExpirationTime());
|
|
|
+ assertEquals("version not parsed properly",
|
|
|
+ "1528979784023932928", resultOne.getVersion());
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ LogLineResult resultTwo = listOfLineResults.get(1);
|
|
|
+ // verify second log line record's data is parsed correctly
|
|
|
+ assertEquals("Cluster name not parsed properly",
|
|
|
+ "clusterone", resultTwo.getClusterName());
|
|
|
+ assertEquals("Method Name not parsed properly",
|
|
|
+ "putMetrics", resultTwo.getLogMethod());
|
|
|
+ assertEquals("Log Level not parsed properly",
|
|
|
+ "WARN", resultTwo.getLogLevel());
|
|
|
+ assertEquals("event_count not parsed properly",
|
|
|
+ "1", resultTwo.getEventCount());
|
|
|
+ assertEquals("ip address not parsed properly",
|
|
|
+ "192.168.1.1", resultTwo.getIpAddress());
|
|
|
+ assertEquals("component type not parsed properly",
|
|
|
+ "yarn_resourcemanager", resultTwo.getComponentType());
|
|
|
+ assertEquals("sequence number not parsed properly",
|
|
|
+ "10583", resultTwo.getSequenceNumber());
|
|
|
+ assertEquals("log file path not parsed properly",
|
|
|
+ "/var/log/hadoop-yarn/yarn/yarn-yarn-resourcemanager-c6401.ambari.apache.org.log", resultTwo.getLogFilePath());
|
|
|
+ assertEquals("log src file name not parsed properly",
|
|
|
+ "HadoopTimelineMetricsSink.java", resultTwo.getSourceFile());
|
|
|
+ assertEquals("log src line number not parsed properly",
|
|
|
+ "262", resultTwo.getSourceFileLineNumber());
|
|
|
+ assertEquals("host name not parsed properly",
|
|
|
+ "c6401.ambari.apache.org", resultTwo.getHostName());
|
|
|
+ assertEquals("log message not parsed properly",
|
|
|
+ "Unable to send metrics to collector by address:http://c6401.ambari.apache.org:6188/ws/v1/timeline/metrics", resultTwo.getLogMessage());
|
|
|
+ assertEquals("logger name not parsed properly",
|
|
|
+ "timeline.HadoopTimelineMetricsSink", resultTwo.getLoggerName());
|
|
|
+ assertEquals("id not parsed properly",
|
|
|
+ "8361c5a9-5b1c-4f44-bc8f-4c6f07d94228", resultTwo.getId());
|
|
|
+ assertEquals("message MD5 not parsed properly",
|
|
|
+ "5942185045779825717", resultTwo.getMessageMD5());
|
|
|
+ assertEquals("log time not parsed properly",
|
|
|
+ "1458148746937", resultTwo.getLogTime());
|
|
|
+ assertEquals("event MD5 not parsed properly",
|
|
|
+ "14581487469371427138486123628676", resultTwo.getEventMD5());
|
|
|
+ assertEquals("logfile line number not parsed properly",
|
|
|
+ "549", resultTwo.getLogFileLineNumber());
|
|
|
+ assertEquals("ttl not parsed properly",
|
|
|
+ "+7DAYS", resultTwo.getTtl());
|
|
|
+ assertEquals("expire at not parsed properly",
|
|
|
+ "1458753550322", resultTwo.getExpirationTime());
|
|
|
+ assertEquals("version not parsed properly",
|
|
|
+ "1528979784022884357", resultTwo.getVersion());
|
|
|
+ }
|
|
|
+
|
|
|
+ mockSupport.verifyAll();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testLogLevelRequestBasic() throws Exception {
|
|
|
+ EasyMockSupport mockSupport =
|
|
|
+ new EasyMockSupport();
|
|
|
+
|
|
|
+ CredentialStoreService credentialStoreServiceMock =
|
|
|
+ mockSupport.createMock(CredentialStoreService.class);
|
|
|
+
|
|
|
+ Cluster clusterMock =
|
|
|
+ mockSupport.createMock(Cluster.class);
|
|
|
+
|
|
|
+ LoggingRequestHelperImpl.NetworkConnection networkConnectionMock =
|
|
|
+ mockSupport.createMock(LoggingRequestHelperImpl.NetworkConnection.class);
|
|
|
+
|
|
|
+ Config adminPropertiesConfigMock =
|
|
|
+ mockSupport.createMock(Config.class);
|
|
|
+
|
|
|
+ Map<String, String> testConfigProperties =
|
|
|
+ new HashMap<String, String>();
|
|
|
+ testConfigProperties.put("logsearch_admin_username", "admin-user");
|
|
|
+ testConfigProperties.put("logsearch_admin_password", "admin-pwd");
|
|
|
+ testConfigProperties = Collections.unmodifiableMap(testConfigProperties);
|
|
|
+
|
|
|
+ Capture<HttpURLConnection> captureURLConnection = new Capture<HttpURLConnection>();
|
|
|
+ Capture<HttpURLConnection> captureURLConnectionForAuthentication = new Capture<HttpURLConnection>();
|
|
|
+
|
|
|
+ expect(clusterMock.getDesiredConfigByType("logsearch-admin-properties")).andReturn(adminPropertiesConfigMock).atLeastOnce();
|
|
|
+ expect(adminPropertiesConfigMock.getProperties()).andReturn(testConfigProperties).atLeastOnce();
|
|
|
+ expect(networkConnectionMock.readQueryResponseFromServer(capture(captureURLConnection))).andReturn(new StringBuffer(TEST_JSON_INPUT_LOG_LEVEL_QUERY)).atLeastOnce();
|
|
|
+
|
|
|
+ // expect that basic authentication is setup, with the expected encoded credentials
|
|
|
+ networkConnectionMock.setupBasicAuthentication(capture(captureURLConnectionForAuthentication), eq(EXPECTED_ENCODED_CREDENTIALS));
|
|
|
+
|
|
|
+
|
|
|
+ mockSupport.replayAll();
|
|
|
+
|
|
|
+
|
|
|
+ LoggingRequestHelper helper =
|
|
|
+ new LoggingRequestHelperImpl(EXPECTED_HOST_NAME, EXPECTED_PORT_NUMBER, credentialStoreServiceMock, clusterMock, networkConnectionMock);
|
|
|
+
|
|
|
+ // invoke query request
|
|
|
+ LogLevelQueryResponse result =
|
|
|
+ helper.sendLogLevelQueryRequest("hdfs_datanode", EXPECTED_HOST_NAME);
|
|
|
+
|
|
|
+ // verify that the HttpURLConnection was created with the proper values
|
|
|
+ HttpURLConnection httpURLConnection =
|
|
|
+ captureURLConnection.getValue();
|
|
|
+
|
|
|
+ assertEquals("URLConnection did not have the correct hostname information",
|
|
|
+ EXPECTED_HOST_NAME, httpURLConnection.getURL().getHost());
|
|
|
+ assertEquals("URLConnection did not have the correct port information",
|
|
|
+ EXPECTED_PORT_NUMBER, httpURLConnection.getURL().getPort() + "");
|
|
|
+ assertEquals("URLConnection did not have the expected http protocol scheme",
|
|
|
+ "http", httpURLConnection.getURL().getProtocol());
|
|
|
+ assertEquals("URLConnection did not have the expected method set",
|
|
|
+ "GET", httpURLConnection.getRequestMethod());
|
|
|
+
|
|
|
+ assertSame("HttpUrlConnection instances passed into NetworkConnection mock should have been the same instance",
|
|
|
+ httpURLConnection, captureURLConnectionForAuthentication.getValue());
|
|
|
+
|
|
|
+ assertNotNull("Response object should not be null",
|
|
|
+ result);
|
|
|
+
|
|
|
+ // expected values taken from JSON input string declared above
|
|
|
+ assertEquals("startIndex not parsed properly",
|
|
|
+ "0", result.getStartIndex());
|
|
|
+ assertEquals("pageSize not parsed properly",
|
|
|
+ "0", result.getPageSize());
|
|
|
+ assertEquals("totalCount not parsed properly",
|
|
|
+ "0", result.getTotalCount());
|
|
|
+ assertEquals("resultSize not parsed properly",
|
|
|
+ "6", result.getResultSize());
|
|
|
+ assertEquals("queryTimeMS not parsed properly",
|
|
|
+ "1459970731998", result.getQueryTimeMS());
|
|
|
+
|
|
|
+ assertEquals("Incorrect number of log level count items parsed",
|
|
|
+ 6, result.getNameValueList().size());
|
|
|
+
|
|
|
+ List<NameValuePair> resultList =
|
|
|
+ result.getNameValueList();
|
|
|
+ assertNameValuePair("FATAL", "0", resultList.get(0));
|
|
|
+ assertNameValuePair("ERROR", "0", resultList.get(1));
|
|
|
+ assertNameValuePair("WARN", "41", resultList.get(2));
|
|
|
+ assertNameValuePair("INFO", "186", resultList.get(3));
|
|
|
+ assertNameValuePair("DEBUG", "0", resultList.get(4));
|
|
|
+ assertNameValuePair("TRACE", "0", resultList.get(5));
|
|
|
+
|
|
|
+ mockSupport.verifyAll();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testLogFileNameRequestBasic() throws Exception {
|
|
|
+ final String expectedComponentName = "hdfs_namenode";
|
|
|
+
|
|
|
+ EasyMockSupport mockSupport =
|
|
|
+ new EasyMockSupport();
|
|
|
+
|
|
|
+ CredentialStoreService credentialStoreServiceMock =
|
|
|
+ mockSupport.createMock(CredentialStoreService.class);
|
|
|
+
|
|
|
+ Cluster clusterMock =
|
|
|
+ mockSupport.createMock(Cluster.class);
|
|
|
+
|
|
|
+ LoggingRequestHelperImpl.NetworkConnection networkConnectionMock =
|
|
|
+ mockSupport.createMock(LoggingRequestHelperImpl.NetworkConnection.class);
|
|
|
+
|
|
|
+ Config adminPropertiesConfigMock =
|
|
|
+ mockSupport.createMock(Config.class);
|
|
|
+
|
|
|
+ Map<String, String> testConfigProperties =
|
|
|
+ new HashMap<String, String>();
|
|
|
+ testConfigProperties.put("logsearch_admin_username", "admin-user");
|
|
|
+ testConfigProperties.put("logsearch_admin_password", "admin-pwd");
|
|
|
+ testConfigProperties = Collections.unmodifiableMap(testConfigProperties);
|
|
|
+
|
|
|
+ Capture<HttpURLConnection> captureURLConnection = new Capture<HttpURLConnection>();
|
|
|
+ Capture<HttpURLConnection> captureURLConnectionForAuthentication = new Capture<HttpURLConnection>();
|
|
|
+
|
|
|
+ expect(clusterMock.getDesiredConfigByType("logsearch-admin-properties")).andReturn(adminPropertiesConfigMock).atLeastOnce();
|
|
|
+ expect(adminPropertiesConfigMock.getProperties()).andReturn(testConfigProperties).atLeastOnce();
|
|
|
+ expect(networkConnectionMock.readQueryResponseFromServer(capture(captureURLConnection))).andReturn(new StringBuffer(TEST_JSON_INPUT_TWO_LIST_ENTRIES)).atLeastOnce();
|
|
|
+
|
|
|
+ // expect that basic authentication is setup, with the expected encoded credentials
|
|
|
+ networkConnectionMock.setupBasicAuthentication(capture(captureURLConnectionForAuthentication), eq(EXPECTED_ENCODED_CREDENTIALS));
|
|
|
+
|
|
|
+ mockSupport.replayAll();
|
|
|
+
|
|
|
+ LoggingRequestHelper helper =
|
|
|
+ new LoggingRequestHelperImpl(EXPECTED_HOST_NAME, EXPECTED_PORT_NUMBER, credentialStoreServiceMock, clusterMock, networkConnectionMock);
|
|
|
+
|
|
|
+ // invoke query request
|
|
|
+ Set<String> result =
|
|
|
+ helper.sendGetLogFileNamesRequest(expectedComponentName, EXPECTED_HOST_NAME);
|
|
|
+
|
|
|
+ // verify that the HttpURLConnection was created with the propert values
|
|
|
+ HttpURLConnection httpURLConnection =
|
|
|
+ captureURLConnection.getValue();
|
|
|
+
|
|
|
+ assertEquals("URLConnection did not have the correct hostname information",
|
|
|
+ EXPECTED_HOST_NAME, httpURLConnection.getURL().getHost());
|
|
|
+ assertEquals("URLConnection did not have the correct port information",
|
|
|
+ EXPECTED_PORT_NUMBER, httpURLConnection.getURL().getPort() + "");
|
|
|
+ assertEquals("URLConnection did not have the expected http protocol scheme",
|
|
|
+ "http", httpURLConnection.getURL().getProtocol());
|
|
|
+ assertEquals("URLConnection did not have the expected method set",
|
|
|
+ "GET", httpURLConnection.getRequestMethod());
|
|
|
+
|
|
|
+ assertSame("HttpUrlConnection instances passed into NetworkConnection mock should have been the same instance",
|
|
|
+ httpURLConnection, captureURLConnectionForAuthentication.getValue());
|
|
|
+
|
|
|
+ final String resultQuery =
|
|
|
+ httpURLConnection.getURL().getQuery();
|
|
|
+
|
|
|
+ // verify that the query contains the three required parameters
|
|
|
+ assertTrue("host parameter was not included in query",
|
|
|
+ resultQuery.contains("host=c6401.ambari.apache.org"));
|
|
|
+ assertTrue("components_name parameter was not included in the query",
|
|
|
+ resultQuery.contains("components_name=" + expectedComponentName));
|
|
|
+ assertTrue("pageSize parameter was not included in query",
|
|
|
+ resultQuery.contains("pageSize=1"));
|
|
|
+
|
|
|
+ assertNotNull("Response object should not be null",
|
|
|
+ result);
|
|
|
+ assertEquals("Response Set was not of the expected size",
|
|
|
+ 1, result.size());
|
|
|
+ assertEquals("Response did not include the expected file name",
|
|
|
+ "/var/log/hadoop/hdfs/hadoop-hdfs-namenode-c6401.ambari.apache.org.log",
|
|
|
+ result.iterator().next());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Verifies that if the LogSearch admin configuration for user/password credentials
|
|
|
+ * is not available, the integration layer will attempt to locate the LogSearch credential
|
|
|
+ * in the CredentialStoreService as a fallback mechanism.
|
|
|
+ *
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ @Test
|
|
|
+ public void testLogQueryRequestBasicCredentialsNotInConfig() throws Exception {
|
|
|
+ final String expectedClusterName = "my-test-cluster";
|
|
|
+
|
|
|
+ EasyMockSupport mockSupport =
|
|
|
+ new EasyMockSupport();
|
|
|
+
|
|
|
+ CredentialStoreService credentialStoreServiceMock =
|
|
|
+ mockSupport.createMock(CredentialStoreService.class);
|
|
|
+
|
|
|
+ Cluster clusterMock =
|
|
|
+ mockSupport.createMock(Cluster.class);
|
|
|
+
|
|
|
+ LoggingRequestHelperImpl.NetworkConnection networkConnectionMock =
|
|
|
+ mockSupport.createMock(LoggingRequestHelperImpl.NetworkConnection.class);
|
|
|
+
|
|
|
+ Config adminPropertiesConfigMock =
|
|
|
+ mockSupport.createMock(Config.class);
|
|
|
+
|
|
|
+ Capture<HttpURLConnection> captureURLConnection = new Capture<HttpURLConnection>();
|
|
|
+ Capture<HttpURLConnection> captureURLConnectionForAuthentication = new Capture<HttpURLConnection>();
|
|
|
+
|
|
|
+ expect(clusterMock.getDesiredConfigByType("logsearch-admin-properties")).andReturn(adminPropertiesConfigMock).atLeastOnce();
|
|
|
+ expect(clusterMock.getClusterName()).andReturn(expectedClusterName).atLeastOnce();
|
|
|
+ expect(adminPropertiesConfigMock.getProperties()).andReturn(Collections.<String, String>emptyMap()).atLeastOnce();
|
|
|
+ expect(networkConnectionMock.readQueryResponseFromServer(capture(captureURLConnection))).andReturn(new StringBuffer(TEST_JSON_INPUT_TWO_LIST_ENTRIES)).atLeastOnce();
|
|
|
+ // the credential store service should be consulted in this case, in order
|
|
|
+ // to attempt to obtain the LogSearch credential from the store
|
|
|
+ expect(credentialStoreServiceMock.getCredential(expectedClusterName, "logsearch.admin.credential")).andReturn(new PrincipalKeyCredential(EXPECTED_USER_NAME, EXPECTED_ADMIN_PASSWORD)).atLeastOnce();
|
|
|
+
|
|
|
+ // expect that basic authentication is setup, with the expected encoded credentials
|
|
|
+ networkConnectionMock.setupBasicAuthentication(capture(captureURLConnectionForAuthentication), eq(EXPECTED_ENCODED_CREDENTIALS));
|
|
|
+
|
|
|
+ mockSupport.replayAll();
|
|
|
+
|
|
|
+ LoggingRequestHelper helper =
|
|
|
+ new LoggingRequestHelperImpl(EXPECTED_HOST_NAME, EXPECTED_PORT_NUMBER, credentialStoreServiceMock, clusterMock, networkConnectionMock);
|
|
|
+
|
|
|
+ // invoke query request
|
|
|
+ LogQueryResponse result =
|
|
|
+ helper.sendQueryRequest(Collections.<String,String>emptyMap());
|
|
|
+
|
|
|
+ // verify that the HttpURLConnection was created with the proper values
|
|
|
+ HttpURLConnection httpURLConnection =
|
|
|
+ captureURLConnection.getValue();
|
|
|
+
|
|
|
+ assertEquals("URLConnection did not have the correct hostname information",
|
|
|
+ EXPECTED_HOST_NAME, httpURLConnection.getURL().getHost());
|
|
|
+ assertEquals("URLConnection did not have the correct port information",
|
|
|
+ EXPECTED_PORT_NUMBER, httpURLConnection.getURL().getPort() + "");
|
|
|
+ assertEquals("URLConnection did not have the expected http protocol scheme",
|
|
|
+ "http", httpURLConnection.getURL().getProtocol());
|
|
|
+ assertEquals("URLConnection did not have the expected method set",
|
|
|
+ "GET", httpURLConnection.getRequestMethod());
|
|
|
+
|
|
|
+ assertSame("HttpUrlConnection instances passed into NetworkConnection mock should have been the same instance",
|
|
|
+ httpURLConnection, captureURLConnectionForAuthentication.getValue());
|
|
|
+
|
|
|
+
|
|
|
+ assertNotNull("Response object should not be null",
|
|
|
+ result);
|
|
|
+
|
|
|
+ // verify that the JSON response returned from the simulated server
|
|
|
+ // is parsed properly, and has the expected values
|
|
|
+ assertEquals("startIndex not parsed properly",
|
|
|
+ "0", result.getStartIndex());
|
|
|
+ assertEquals("pageSize not parsed properly",
|
|
|
+ "5", result.getPageSize());
|
|
|
+ assertEquals("totalCount not parsed properly",
|
|
|
+ "10452", result.getTotalCount());
|
|
|
+ assertEquals("resultSize not parsed properly",
|
|
|
+ "5", result.getResultSize());
|
|
|
+ assertEquals("queryTimeMS not parsed properly",
|
|
|
+ "1458148754113", result.getQueryTimeMS());
|
|
|
+
|
|
|
+ assertEquals("incorrect number of LogLineResult items parsed",
|
|
|
+ 2, result.getListOfResults().size());
|
|
|
+
|
|
|
+ List<LogLineResult> listOfLineResults =
|
|
|
+ result.getListOfResults();
|
|
|
+
|
|
|
+ {
|
|
|
+ LogLineResult resultOne = listOfLineResults.get(0);
|
|
|
+ // verify that all fields in this class are parsed as expected
|
|
|
+ assertEquals("Cluster name not parsed properly",
|
|
|
+ "clusterone", resultOne.getClusterName());
|
|
|
+ assertEquals("Method Name not parsed properly",
|
|
|
+ "chooseUnderReplicatedBlocks", resultOne.getLogMethod());
|
|
|
+ assertEquals("Log Level not parsed properly",
|
|
|
+ "INFO", resultOne.getLogLevel());
|
|
|
+ assertEquals("event_count not parsed properly",
|
|
|
+ "1", resultOne.getEventCount());
|
|
|
+ assertEquals("ip address not parsed properly",
|
|
|
+ "192.168.1.1", resultOne.getIpAddress());
|
|
|
+ assertEquals("component type not parsed properly",
|
|
|
+ "hdfs_namenode", resultOne.getComponentType());
|
|
|
+ assertEquals("sequence number not parsed properly",
|
|
|
+ "10584", resultOne.getSequenceNumber());
|
|
|
+ assertEquals("log file path not parsed properly",
|
|
|
+ "/var/log/hadoop/hdfs/hadoop-hdfs-namenode-c6401.ambari.apache.org.log", resultOne.getLogFilePath());
|
|
|
+ assertEquals("log src file name not parsed properly",
|
|
|
+ "UnderReplicatedBlocks.java", resultOne.getSourceFile());
|
|
|
+ assertEquals("log src line number not parsed properly",
|
|
|
+ "394", resultOne.getSourceFileLineNumber());
|
|
|
+ assertEquals("host name not parsed properly",
|
|
|
+ "c6401.ambari.apache.org", resultOne.getHostName());
|
|
|
+ assertEquals("log message not parsed properly",
|
|
|
+ "chooseUnderReplicatedBlocks selected 2 blocks at priority level 0; Total=2 Reset bookmarks? false", resultOne.getLogMessage());
|
|
|
+ assertEquals("logger name not parsed properly",
|
|
|
+ "BlockStateChange", resultOne.getLoggerName());
|
|
|
+ assertEquals("id not parsed properly",
|
|
|
+ "9c5562fb-123f-47c8-aaf5-b5e407326c08", resultOne.getId());
|
|
|
+ assertEquals("message MD5 not parsed properly",
|
|
|
+ "-3892769501348410581", resultOne.getMessageMD5());
|
|
|
+ assertEquals("log time not parsed properly",
|
|
|
+ "1458148749036", resultOne.getLogTime());
|
|
|
+ assertEquals("event MD5 not parsed properly",
|
|
|
+ "1458148749036-2417481968206345035", resultOne.getEventMD5());
|
|
|
+ assertEquals("logfile line number not parsed properly",
|
|
|
+ "2084", resultOne.getLogFileLineNumber());
|
|
|
+ assertEquals("ttl not parsed properly",
|
|
|
+ "+7DAYS", resultOne.getTtl());
|
|
|
+ assertEquals("expire at not parsed properly",
|
|
|
+ "1458753550322", resultOne.getExpirationTime());
|
|
|
+ assertEquals("version not parsed properly",
|
|
|
+ "1528979784023932928", resultOne.getVersion());
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ LogLineResult resultTwo = listOfLineResults.get(1);
|
|
|
+ // verify second log line record's data is parsed correctly
|
|
|
+ assertEquals("Cluster name not parsed properly",
|
|
|
+ "clusterone", resultTwo.getClusterName());
|
|
|
+ assertEquals("Method Name not parsed properly",
|
|
|
+ "putMetrics", resultTwo.getLogMethod());
|
|
|
+ assertEquals("Log Level not parsed properly",
|
|
|
+ "WARN", resultTwo.getLogLevel());
|
|
|
+ assertEquals("event_count not parsed properly",
|
|
|
+ "1", resultTwo.getEventCount());
|
|
|
+ assertEquals("ip address not parsed properly",
|
|
|
+ "192.168.1.1", resultTwo.getIpAddress());
|
|
|
+ assertEquals("component type not parsed properly",
|
|
|
+ "yarn_resourcemanager", resultTwo.getComponentType());
|
|
|
+ assertEquals("sequence number not parsed properly",
|
|
|
+ "10583", resultTwo.getSequenceNumber());
|
|
|
+ assertEquals("log file path not parsed properly",
|
|
|
+ "/var/log/hadoop-yarn/yarn/yarn-yarn-resourcemanager-c6401.ambari.apache.org.log", resultTwo.getLogFilePath());
|
|
|
+ assertEquals("log src file name not parsed properly",
|
|
|
+ "HadoopTimelineMetricsSink.java", resultTwo.getSourceFile());
|
|
|
+ assertEquals("log src line number not parsed properly",
|
|
|
+ "262", resultTwo.getSourceFileLineNumber());
|
|
|
+ assertEquals("host name not parsed properly",
|
|
|
+ "c6401.ambari.apache.org", resultTwo.getHostName());
|
|
|
+ assertEquals("log message not parsed properly",
|
|
|
+ "Unable to send metrics to collector by address:http://c6401.ambari.apache.org:6188/ws/v1/timeline/metrics", resultTwo.getLogMessage());
|
|
|
+ assertEquals("logger name not parsed properly",
|
|
|
+ "timeline.HadoopTimelineMetricsSink", resultTwo.getLoggerName());
|
|
|
+ assertEquals("id not parsed properly",
|
|
|
+ "8361c5a9-5b1c-4f44-bc8f-4c6f07d94228", resultTwo.getId());
|
|
|
+ assertEquals("message MD5 not parsed properly",
|
|
|
+ "5942185045779825717", resultTwo.getMessageMD5());
|
|
|
+ assertEquals("log time not parsed properly",
|
|
|
+ "1458148746937", resultTwo.getLogTime());
|
|
|
+ assertEquals("event MD5 not parsed properly",
|
|
|
+ "14581487469371427138486123628676", resultTwo.getEventMD5());
|
|
|
+ assertEquals("logfile line number not parsed properly",
|
|
|
+ "549", resultTwo.getLogFileLineNumber());
|
|
|
+ assertEquals("ttl not parsed properly",
|
|
|
+ "+7DAYS", resultTwo.getTtl());
|
|
|
+ assertEquals("expire at not parsed properly",
|
|
|
+ "1458753550322", resultTwo.getExpirationTime());
|
|
|
+ assertEquals("version not parsed properly",
|
|
|
+ "1528979784022884357", resultTwo.getVersion());
|
|
|
+ }
|
|
|
+
|
|
|
+ mockSupport.verifyAll();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Convenience method for asserting on the values of NameValuePair instances
|
|
|
+ *
|
|
|
+ * @param expectedName the expected name
|
|
|
+ * @param expectedValue the expected value
|
|
|
+ * @param nameValuePair the NameValuePair instance to test
|
|
|
+ */
|
|
|
+ static void assertNameValuePair(String expectedName, String expectedValue, NameValuePair nameValuePair) {
|
|
|
+ assertEquals("Unexpected name found in this pair",
|
|
|
+ expectedName, nameValuePair.getName());
|
|
|
+ assertEquals("Unexpected value found in this pair",
|
|
|
+ expectedValue, nameValuePair.getValue());
|
|
|
+ }
|
|
|
+
|
|
|
+}
|