Return-Path: X-Original-To: apmail-ambari-commits-archive@www.apache.org Delivered-To: apmail-ambari-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 8C24D11CEA for ; Mon, 9 Jun 2014 16:45:50 +0000 (UTC) Received: (qmail 10100 invoked by uid 500); 9 Jun 2014 16:45:50 -0000 Delivered-To: apmail-ambari-commits-archive@ambari.apache.org Received: (qmail 10073 invoked by uid 500); 9 Jun 2014 16:45:50 -0000 Mailing-List: contact commits-help@ambari.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: ambari-dev@ambari.apache.org Delivered-To: mailing list commits@ambari.apache.org Received: (qmail 10066 invoked by uid 99); 9 Jun 2014 16:45:50 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 09 Jun 2014 16:45:50 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 158B38B2EAC; Mon, 9 Jun 2014 16:45:50 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: ncole@apache.org To: commits@ambari.apache.org Message-Id: <8cb33a75548a43d090f70c55c97ed73f@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: git commit: AMBARI-6056. Agent Custom Command Output Coerces Integers to Floats (Jonathan Hurley via ncole) Date: Mon, 9 Jun 2014 16:45:50 +0000 (UTC) Repository: ambari Updated Branches: refs/heads/trunk 2eb7fcccd -> f1a2af101 AMBARI-6056. Agent Custom Command Output Coerces Integers to Floats (Jonathan Hurley via ncole) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/f1a2af10 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/f1a2af10 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/f1a2af10 Branch: refs/heads/trunk Commit: f1a2af1017213f7dc78d5901d1089ee2bcdc1944 Parents: 2eb7fcc Author: Nate Cole Authored: Mon Jun 9 12:45:34 2014 -0400 Committer: Nate Cole Committed: Mon Jun 9 12:45:34 2014 -0400 ---------------------------------------------------------------------- .../src/main/python/ambari_agent/ActionQueue.py | 2 + .../ambari_agent/CustomServiceOrchestrator.py | 8 +- .../TestCustomServiceOrchestrator.py | 4 +- .../internal/TaskResourceProvider.java | 47 ++++++---- .../main/resources/custom_actions/check_host.py | 26 +++--- .../internal/TaskResourceProviderTest.java | 94 ++++++++++++++++---- ambari-server/src/test/python/TestCheckHost.py | 39 ++++++-- .../resources/custom_actions/invalid_check.json | 42 +++++++++ 8 files changed, 199 insertions(+), 63 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/f1a2af10/ambari-agent/src/main/python/ambari_agent/ActionQueue.py ---------------------------------------------------------------------- diff --git a/ambari-agent/src/main/python/ambari_agent/ActionQueue.py b/ambari-agent/src/main/python/ambari_agent/ActionQueue.py index 749e8c1..9defc7d 100644 --- a/ambari-agent/src/main/python/ambari_agent/ActionQueue.py +++ b/ambari-agent/src/main/python/ambari_agent/ActionQueue.py @@ -191,6 +191,7 @@ class ActionQueue(threading.Thread): roleResult['structuredOut'] = str(json.dumps(commandresult['structuredOut'])) else: roleResult['structuredOut'] = '' + # let ambari know that configuration tags were applied if status == self.COMPLETED_STATUS: configHandler = ActualConfigHandler(self.config, self.configTags) @@ -208,6 +209,7 @@ class ActionQueue(threading.Thread): configHandler.write_actual_component(command['role'], command['configurationTags']) configHandler.write_client_components(command['serviceName'], command['configurationTags']) roleResult['configurationTags'] = configHandler.read_actual_component(command['role']) + self.commandStatuses.put_command_status(command, roleResult) http://git-wip-us.apache.org/repos/asf/ambari/blob/f1a2af10/ambari-agent/src/main/python/ambari_agent/CustomServiceOrchestrator.py ---------------------------------------------------------------------- diff --git a/ambari-agent/src/main/python/ambari_agent/CustomServiceOrchestrator.py b/ambari-agent/src/main/python/ambari_agent/CustomServiceOrchestrator.py index 492e025..ac97626 100644 --- a/ambari-agent/src/main/python/ambari_agent/CustomServiceOrchestrator.py +++ b/ambari-agent/src/main/python/ambari_agent/CustomServiceOrchestrator.py @@ -69,10 +69,10 @@ class CustomServiceOrchestrator(): pass # Ignore fail - def runCommand(self, command, tmpoutfile, tmperrfile, forsed_command_name = None, + def runCommand(self, command, tmpoutfile, tmperrfile, forced_command_name = None, override_output_files = True): """ - forsed_command_name may be specified manually. In this case, value, defined at + forced_command_name may be specified manually. In this case, value, defined at command json, is ignored. """ try: @@ -90,8 +90,8 @@ class CustomServiceOrchestrator(): except KeyError: pass # Status commands have no taskId - if forsed_command_name is not None: # If not supplied as an argument - command_name = forsed_command_name + if forced_command_name is not None: # If not supplied as an argument + command_name = forced_command_name if command_name == self.CUSTOM_ACTION_COMMAND: base_dir = self.file_cache.get_custom_actions_base_dir(server_url_prefix) http://git-wip-us.apache.org/repos/asf/ambari/blob/f1a2af10/ambari-agent/src/test/python/ambari_agent/TestCustomServiceOrchestrator.py ---------------------------------------------------------------------- diff --git a/ambari-agent/src/test/python/ambari_agent/TestCustomServiceOrchestrator.py b/ambari-agent/src/test/python/ambari_agent/TestCustomServiceOrchestrator.py index 00d0c0a..23b9bed 100644 --- a/ambari-agent/src/test/python/ambari_agent/TestCustomServiceOrchestrator.py +++ b/ambari-agent/src/test/python/ambari_agent/TestCustomServiceOrchestrator.py @@ -204,12 +204,12 @@ class TestCustomServiceOrchestrator(TestCase): 'exitcode': 0, } ret = orchestrator.runCommand(command, "out.txt", "err.txt", - forsed_command_name=CustomServiceOrchestrator.COMMAND_NAME_STATUS) + forced_command_name=CustomServiceOrchestrator.COMMAND_NAME_STATUS) ## Check that override_output_files was true only during first call self.assertEquals(run_file_mock.call_args_list[0][0][7], True) self.assertEquals(run_file_mock.call_args_list[1][0][7], False) self.assertEquals(run_file_mock.call_args_list[2][0][7], False) - ## Check that forsed_command_name was taken into account + ## Check that forced_command_name was taken into account self.assertEqual(run_file_mock.call_args_list[0][0][1][0], CustomServiceOrchestrator.COMMAND_NAME_STATUS) http://git-wip-us.apache.org/repos/asf/ambari/blob/f1a2af10/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/TaskResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/TaskResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/TaskResourceProvider.java index 87b915f..0b9a4f6 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/TaskResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/TaskResourceProvider.java @@ -17,8 +17,12 @@ */ package org.apache.ambari.server.controller.internal; -import com.google.gson.Gson; -import com.google.gson.JsonSyntaxException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.controller.AmbariManagementController; import org.apache.ambari.server.controller.TaskStatusRequest; @@ -32,12 +36,7 @@ import org.apache.ambari.server.controller.spi.Resource; import org.apache.ambari.server.controller.spi.SystemException; import org.apache.ambari.server.controller.spi.UnsupportedPropertyException; import org.apache.ambari.server.controller.utilities.PropertyHelper; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import org.codehaus.jackson.map.ObjectMapper; /** * Resource provider for task resources. @@ -65,8 +64,6 @@ class TaskResourceProvider extends AbstractControllerResourceProvider { protected static final String TASK_COMMAND_DET_PROPERTY_ID = PropertyHelper.getPropertyId("Tasks", "command_detail"); protected static final String TASK_CUST_CMD_NAME_PROPERTY_ID = PropertyHelper.getPropertyId("Tasks", "custom_command_name"); - private static final Gson gson = new Gson(); - private static Set pkPropertyIds = new HashSet(Arrays.asList(new String[]{ TASK_ID_PROPERTY_ID})); @@ -151,31 +148,49 @@ class TaskResourceProvider extends AbstractControllerResourceProvider { setResourceProperty(resource, TASK_EXIT_CODE_PROPERTY_ID, response.getExitCode(), requestedIds); setResourceProperty(resource, TASK_STDERR_PROPERTY_ID, response.getStderr(), requestedIds); setResourceProperty(resource, TASK_STOUT_PROPERTY_ID, response.getStdout(), requestedIds); - setResourceProperty(resource, TASK_STRUCT_OUT_PROPERTY_ID, prepareStructuredOutJson(response.getStructuredOut()), requestedIds); + setResourceProperty(resource, TASK_STRUCT_OUT_PROPERTY_ID, parseStructuredOutput(response.getStructuredOut()), requestedIds); setResourceProperty(resource, TASK_START_TIME_PROPERTY_ID, response.getStartTime(), requestedIds); setResourceProperty(resource, TASK_END_TIME_PROPERTY_ID, response.getEndTime(), requestedIds); setResourceProperty(resource, TASK_ATTEMPT_CNT_PROPERTY_ID, response.getAttemptCount(), requestedIds); + if (response.getCustomCommandName() != null) { setResourceProperty(resource, TASK_CUST_CMD_NAME_PROPERTY_ID, response.getCustomCommandName(), requestedIds); } + if (response.getCommandDetail() == null) { setResourceProperty(resource, TASK_COMMAND_DET_PROPERTY_ID, String.format("%s %s", response.getRole(), response.getCommand()), requestedIds); } else { setResourceProperty(resource, TASK_COMMAND_DET_PROPERTY_ID, response.getCommandDetail(), requestedIds); } + resources.add(resource); } } return resources; } - Object prepareStructuredOutJson(String structuredOutStr) { - Object result = null; + /** + * Converts the specified JSON string into a {@link Map}. For now, use Jackson + * instead of gson since none of the integers will convert properly without a + * well-defined first-class object to map to. + * + * @param structuredOutput + * the JSON string to convert. + * @return the converted JSON as key-value pairs, or {@code null} if an + * exception was encountered or if the JSON string was empty. + */ + Map parseStructuredOutput(String structuredOutput) { + if (null == structuredOutput || structuredOutput.isEmpty()) + return null; + + Map result = null; + try { - result = gson.fromJson(structuredOutStr, Map.class); - } catch (JsonSyntaxException exception) { - LOG.warn("Can not parse structured output string " + structuredOutStr); + ObjectMapper mapper = new ObjectMapper(); + result = mapper.readValue(structuredOutput, Map.class); + } catch (Exception excepton) { + LOG.warn("Unable to parse task structured output: {}", structuredOutput); } return result; } http://git-wip-us.apache.org/repos/asf/ambari/blob/f1a2af10/ambari-server/src/main/resources/custom_actions/check_host.py ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/custom_actions/check_host.py b/ambari-server/src/main/resources/custom_actions/check_host.py index f98492b..7128196 100644 --- a/ambari-server/src/main/resources/custom_actions/check_host.py +++ b/ambari-server/src/main/resources/custom_actions/check_host.py @@ -60,7 +60,7 @@ class CheckHost(Script): structured_output[CHECK_JAVA_HOME] = java_home_check_structured_output except Exception, exception: print "There was an unexpected error while checking for the Java home location: " + str(exception) - structured_output[CHECK_JAVA_HOME] = {"exit_code" : "1", "message": str(exception)} + structured_output[CHECK_JAVA_HOME] = {"exit_code" : 1, "message": str(exception)} if CHECK_DB_CONNECTION in check_execute_list: try : @@ -68,7 +68,7 @@ class CheckHost(Script): structured_output[CHECK_DB_CONNECTION] = db_connection_check_structured_output except Exception, exception: print "There was an unknown error while checking database connectivity: " + str(exception) - structured_output[CHECK_DB_CONNECTION] = {"exit_code" : "1", "message": str(exception)} + structured_output[CHECK_DB_CONNECTION] = {"exit_code" : 1, "message": str(exception)} if CHECK_HOST_RESOLUTION in check_execute_list: try : @@ -76,7 +76,7 @@ class CheckHost(Script): structured_output[CHECK_HOST_RESOLUTION] = host_resolution_structured_output except Exception, exception : print "There was an unknown error while checking IP address lookups: " + str(exception) - structured_output[CHECK_HOST_RESOLUTION] = {"exit_code" : "1", "message": str(exception)} + structured_output[CHECK_HOST_RESOLUTION] = {"exit_code" : 1, "message": str(exception)} self.put_structured_out(structured_output) @@ -89,10 +89,10 @@ class CheckHost(Script): if not os.path.isfile(os.path.join(java64_home, "bin", "java")): print "Java home doesn't exist!" - java_home_check_structured_output = {"exit_code" : "1", "message": "Java home doesn't exist!"} + java_home_check_structured_output = {"exit_code" : 1, "message": "Java home doesn't exist!"} else: print "Java home exists!" - java_home_check_structured_output = {"exit_code" : "0", "message": "Java home exists!"} + java_home_check_structured_output = {"exit_code" : 0, "message": "Java home exists!"} return java_home_check_structured_output @@ -131,7 +131,7 @@ class CheckHost(Script): message = "Custom java is not available on host. Please install it. Java home should be the same as on server. " \ "\n" print message - db_connection_check_structured_output = {"exit_code" : "1", "message": message} + db_connection_check_structured_output = {"exit_code" : 1, "message": message} return db_connection_check_structured_output environment = { "no_proxy": format("{ambari_server_hostname}") } @@ -152,7 +152,7 @@ class CheckHost(Script): message = "Error downloading JDK from Ambari Server resources. Check network access to " \ "Ambari Server.\n" + str(e) print message - db_connection_check_structured_output = {"exit_code" : "1", "message": message} + db_connection_check_structured_output = {"exit_code" : 1, "message": message} return db_connection_check_structured_output if jdk_name.endswith(".bin"): @@ -166,7 +166,7 @@ class CheckHost(Script): except Exception, e: message = "Error installing java.\n" + str(e) print message - db_connection_check_structured_output = {"exit_code" : "1", "message": message} + db_connection_check_structured_output = {"exit_code" : 1, "message": message} return db_connection_check_structured_output try: @@ -178,7 +178,7 @@ class CheckHost(Script): message = "Error downloading DBConnectionVerification.jar from Ambari Server resources. Check network access to " \ "Ambari Server.\n" + str(e) print message - db_connection_check_structured_output = {"exit_code" : "1", "message": message} + db_connection_check_structured_output = {"exit_code" : 1, "message": message} return db_connection_check_structured_output # download jdbc driver from ambari-server resources @@ -192,7 +192,7 @@ class CheckHost(Script): "install JDBC connector. Use \"ambari-server setup --help\" for more information. Check network access to " \ "Ambari Server.\n" + str(e) print message - db_connection_check_structured_output = {"exit_code" : "1", "message": message} + db_connection_check_structured_output = {"exit_code" : 1, "message": message} return db_connection_check_structured_output @@ -213,9 +213,9 @@ class CheckHost(Script): print "INFO returncode: " + str(process.returncode) if process.returncode == 0: - db_connection_check_structured_output = {"exit_code" : "0", "message": "DB connection check completed successfully!" } + db_connection_check_structured_output = {"exit_code" : 0, "message": "DB connection check completed successfully!" } else: - db_connection_check_structured_output = {"exit_code" : "1", "message": stdoutdata + stderrdata } + db_connection_check_structured_output = {"exit_code" : 1, "message": stdoutdata + stderrdata } return db_connection_check_structured_output @@ -257,7 +257,7 @@ class CheckHost(Script): print message host_resolution_check_structured_output = { - "exit_code" : "0", + "exit_code" : 0, "message" : message, "failed_count" : failedCount, "success_count" : successCount, http://git-wip-us.apache.org/repos/asf/ambari/blob/f1a2af10/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/TaskResourceProviderTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/TaskResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/TaskResourceProviderTest.java index 537d999..2957683 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/TaskResourceProviderTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/TaskResourceProviderTest.java @@ -18,6 +18,21 @@ package org.apache.ambari.server.controller.internal; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.createNiceMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + import org.apache.ambari.server.controller.AmbariManagementController; import org.apache.ambari.server.controller.RequestStatusResponse; import org.apache.ambari.server.controller.TaskStatusResponse; @@ -29,20 +44,6 @@ import org.apache.ambari.server.controller.utilities.PredicateBuilder; import org.apache.ambari.server.controller.utilities.PropertyHelper; import org.junit.Assert; import org.junit.Test; -import static org.junit.Assert.*; - -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import static org.easymock.EasyMock.createMock; -import static org.easymock.EasyMock.createNiceMock; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.replay; -import static org.easymock.EasyMock.verify; /** * TaskResourceProvider tests. @@ -202,29 +203,84 @@ public class TaskResourceProviderTest { } @Test - public void testPrepareStructuredOutJson() { + public void testParseStructuredOutput() { Resource.Type type = Resource.Type.Task; // Test general case AmbariManagementController managementController = createMock(AmbariManagementController.class); + TaskResourceProvider taskResourceProvider = new TaskResourceProvider( PropertyHelper.getPropertyIds(type), PropertyHelper.getKeyPropertyIds(type), managementController); + replay(managementController); // Check parsing of nested JSON - Map result = (Map) taskResourceProvider.prepareStructuredOutJson("{\"a\":\"b\", \"c\": {\"d\":\"e\",\"f\": [\"g\",\"h\"],\"i\": {\"k\":\"l\"}}}"); + Map result = taskResourceProvider + .parseStructuredOutput("{\"a\":\"b\", \"c\": {\"d\":\"e\",\"f\": [\"g\",\"h\"],\"i\": {\"k\":\"l\"}}}"); assertEquals(result.size(), 2); - Map submap = (Map) result.get("c"); + Map submap = (Map) result.get("c"); assertEquals(submap.size(), 3); List sublist = (List) submap.get("f"); assertEquals(sublist.size(), 2); - Map subsubmap = (Map) submap.get("i"); + Map subsubmap = (Map) submap.get("i"); assertEquals(subsubmap.size(), 1); assertEquals(subsubmap.get("k"), "l"); + // Check negative case - invalid JSON - result = (Map) taskResourceProvider.prepareStructuredOutJson("{\"a\": invalid JSON}"); + result = taskResourceProvider.parseStructuredOutput("{\"a\": invalid JSON}"); assertNull(result); + // ensure that integers come back as integers + result = taskResourceProvider.parseStructuredOutput("{\"a\": 5}"); + assertEquals(result.get("a"), 5); + verify(managementController); } + + @Test + public void testParseStructuredOutputForHostCheck() { + Resource.Type type = Resource.Type.Task; + + // Test general case + AmbariManagementController managementController = createMock(AmbariManagementController.class); + + TaskResourceProvider taskResourceProvider = new TaskResourceProvider( + PropertyHelper.getPropertyIds(type), + PropertyHelper.getKeyPropertyIds(type), managementController); + + replay(managementController); + + Map result = taskResourceProvider.parseStructuredOutput("{\"host_resolution_check\": {\"failures\": [{\"cause\": [-2, \"Name or service not known\"], \"host\": \"foobar\", \"type\": \"FORWARD_LOOKUP\"}], \"message\": \"There were 1 host(s) that could not resolve to an IP address.\", \"failed_count\": 1, \"success_count\": 3, \"exit_code\": 0}}"); + + Assert.assertNotNull(result); + Map host_resolution_check = (Map)result.get("host_resolution_check"); + + assertEquals(host_resolution_check.get("success_count"), 3); + assertEquals(host_resolution_check.get("failed_count"), 1); + + verify(managementController); + } + + @Test + public void testInvalidStructuredOutput() { + Resource.Type type = Resource.Type.Task; + + // Test general case + AmbariManagementController managementController = createMock(AmbariManagementController.class); + + TaskResourceProvider taskResourceProvider = new TaskResourceProvider( + PropertyHelper.getPropertyIds(type), + PropertyHelper.getKeyPropertyIds(type), managementController); + + replay(managementController); + + Map result = taskResourceProvider.parseStructuredOutput(null); + Assert.assertNull(result); + + result = taskResourceProvider.parseStructuredOutput("This is some bad JSON"); + Assert.assertNull(result); + + verify(managementController); + } + } http://git-wip-us.apache.org/repos/asf/ambari/blob/f1a2af10/ambari-server/src/test/python/TestCheckHost.py ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/python/TestCheckHost.py b/ambari-server/src/test/python/TestCheckHost.py index 0ba0386..d84ead4 100644 --- a/ambari-server/src/test/python/TestCheckHost.py +++ b/ambari-server/src/test/python/TestCheckHost.py @@ -44,7 +44,7 @@ class TestCheckHost(TestCase): self.assertEquals(os_isfile_mock.call_args[0][0], 'test_java_home/bin/java') self.assertEquals(structured_out_mock.call_args[0][0], {'java_home_check': {'message': 'Java home exists!', - 'exit_code': '0'}}) + 'exit_code': 0}}) # test, java home doesn't exist os_isfile_mock.reset_mock() os_isfile_mock.return_value = False @@ -53,7 +53,7 @@ class TestCheckHost(TestCase): self.assertEquals(os_isfile_mock.call_args[0][0], 'test_java_home/bin/java') self.assertEquals(structured_out_mock.call_args[0][0], {'java_home_check': {"message": "Java home doesn't exist!", - "exit_code" : "1"}}) + "exit_code" : 1}}) @patch.object(Script, 'get_config') @@ -81,9 +81,11 @@ class TestCheckHost(TestCase): self.assertEquals(structured_out_mock.call_args[0][0], {'db_connection_check': {'message': 'Error downloading ' \ 'DBConnectionVerification.jar from Ambari Server resources. Check network access to Ambari ' \ - 'Server.\ntest exception', 'exit_code': '1'}}) + 'Server.\ntest exception', 'exit_code': 1}}) + self.assertEquals(format_mock.call_args_list[2][0][0], "/bin/sh -c 'cd /usr/lib/ambari-agent/ && curl -kf " \ "--retry 5 {jdk_location}{check_db_connection_jar_name} -o {check_db_connection_jar_name}'") + self.assertEquals(format_mock.call_args_list[3][0][0], "[ -f /usr/lib/ambari-agent/{check_db_connection_jar_name}]") # test, download jdbc driver failed @@ -106,9 +108,11 @@ class TestCheckHost(TestCase): self.assertEquals(structured_out_mock.call_args[0][0], {'db_connection_check': {'message': 'Error downloading JDBC ' \ 'connector from Ambari Server resources. Confirm you ran ambari-server setup to ' \ 'install JDBC connector. Use "ambari-server setup --help" for more information. Check ' \ - 'network access to Ambari Server.\ntest exception', 'exit_code': '1'}}) + 'network access to Ambari Server.\ntest exception', 'exit_code': 1}}) + self.assertEquals(format_mock.call_args_list[4][0][0], "/bin/sh -c 'cd /usr/lib/ambari-agent/ && curl -kf " \ "--retry 5 {jdbc_url} -o {jdbc_name}'") + self.assertEquals(format_mock.call_args_list[5][0][0], "[ -f /usr/lib/ambari-agent/{jdbc_name}]") # test, no connection to remote db @@ -132,7 +136,7 @@ class TestCheckHost(TestCase): checkHost.actionexecute(None) self.assertEquals(structured_out_mock.call_args[0][0], {'db_connection_check': {'message': 'test message', - 'exit_code': '1'}}) + 'exit_code': 1}}) self.assertEquals(format_mock.call_args[0][0],'{java64_home}/bin/java -cp /usr/lib/ambari-agent/{check_db_' \ 'connection_jar_name}:/usr/lib/ambari-agent/{jdbc_name} org.' \ 'apache.ambari.server.DBConnectionVerification {db_connection_url} ' \ @@ -146,7 +150,7 @@ class TestCheckHost(TestCase): checkHost.actionexecute(None) self.assertEquals(structured_out_mock.call_args[0][0], {'db_connection_check': - {'message': 'DB connection check completed successfully!', 'exit_code': '0'}}) + {'message': 'DB connection check completed successfully!', 'exit_code': 0}}) #test jdk_name and java home are not available mock_config.return_value = {"commandParams" : {"check_execute_list" : "db_connection_check", @@ -161,7 +165,7 @@ class TestCheckHost(TestCase): isfile_mock.return_value = False checkHost.actionexecute(None) self.assertEquals(structured_out_mock.call_args[0][0], {'db_connection_check': {'message': 'Custom java is not ' \ - 'available on host. Please install it. Java home should be the same as on server. \n', 'exit_code': '1'}}) + 'available on host. Please install it. Java home should be the same as on server. \n', 'exit_code': 1}}) @@ -187,7 +191,7 @@ class TestCheckHost(TestCase): 'message': 'All hosts resolved to an IP address.', 'failed_count': 0, 'success_count': 5, - 'exit_code': '0'}}) + 'exit_code': 0}}) # try it now with errors mock_socket.side_effect = socket.error @@ -201,4 +205,21 @@ class TestCheckHost(TestCase): {'cause': (), 'host': u'foobar', 'type': 'FORWARD_LOOKUP'}, {'cause': (), 'host': u'!!!', 'type': 'FORWARD_LOOKUP'}], 'message': 'There were 5 host(s) that could not resolve to an IP address.', - 'failed_count': 5, 'success_count': 0, 'exit_code': '0'}}) \ No newline at end of file + 'failed_count': 5, 'success_count': 0, 'exit_code': 0}}) + + @patch.object(Script, 'get_config') + @patch("resource_management.libraries.script.Script.put_structured_out") + def testInvalidCheck(self, structured_out_mock, mock_config): + jsonFilePath = os.path.join("../resources/custom_actions", "invalid_check.json") + + with open(jsonFilePath, "r") as jsonFile: + jsonPayload = json.load(jsonFile) + + mock_config.return_value = ConfigDictionary(jsonPayload) + + checkHost = CheckHost() + checkHost.actionexecute(None) + + # ensure the correct function was called + self.assertTrue(structured_out_mock.called) + structured_out_mock.assert_called_with({}) http://git-wip-us.apache.org/repos/asf/ambari/blob/f1a2af10/ambari-server/src/test/resources/custom_actions/invalid_check.json ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/resources/custom_actions/invalid_check.json b/ambari-server/src/test/resources/custom_actions/invalid_check.json new file mode 100644 index 0000000..8df58d3 --- /dev/null +++ b/ambari-server/src/test/resources/custom_actions/invalid_check.json @@ -0,0 +1,42 @@ +{ + "roleCommand": "ACTIONEXECUTE", + "clusterName": "c1", + "hostname": "c6401.ambari.apache.org", + "passiveInfo": [], + "hostLevelParams": { + "jdk_location": "http://192.168.64.1:8080/resources/", + "ambari_db_rca_password": "mapred", + "java_home": "/usr/jdk64/jdk1.6.0_31", + "ambari_db_rca_url": "jdbc:postgresql://192.168.64.1/ambarirca", + "stack_name": "HDP", + "oracle_jdbc_url": "http://192.168.64.1:8080/resources//ojdbc6.jar", + "stack_version": "2.1", + "db_name": "ambari", + "ambari_db_rca_driver": "org.postgresql.Driver", + "jdk_name": "jdk-6u31-linux-x64.bin", + "ambari_db_rca_username": "mapred", + "db_driver_filename": "mysql-connector-java.jar", + "mysql_jdbc_url": "http://192.168.64.1:8080/resources//mysql-connector-java.jar" + }, + "serviceName": "null", + "role": "check_host", + "commandParams": { + "script": "check_host.py", + "check_execute_list": "bad_check", + "threshold": "20", + "hosts": "c6401.ambari.apache.org, c6402.ambari.apache.org, c6403.ambari.apache.org, foobar, !!!", + "command_timeout": "60", + "script_type": "PYTHON" + }, + "taskId": 158, + "public_hostname": "c6401.ambari.apache.org", + "configurations": {}, + "commandId": "27-1", + "clusterHostInfo": { + "ambari_server_host": [ + "192.168.64.1" + ], + "all_hosts": [], + "all_ping_ports": [] + } +} \ No newline at end of file