You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by dm...@apache.org on 2015/04/17 15:05:55 UTC

ambari git commit: AMBARI-10565. Alerts: test cases for python code, AlertSchedulerHandler (dlysnichenko)

Repository: ambari
Updated Branches:
  refs/heads/trunk 52fe9f77f -> 51b2c338b


AMBARI-10565. Alerts: test cases for python code, AlertSchedulerHandler (dlysnichenko)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/51b2c338
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/51b2c338
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/51b2c338

Branch: refs/heads/trunk
Commit: 51b2c338bf1489dd0223a6e2bf105a737676495c
Parents: 52fe9f7
Author: Lisnichenko Dmitro <dl...@hortonworks.com>
Authored: Fri Apr 17 16:05:25 2015 +0300
Committer: Lisnichenko Dmitro <dl...@hortonworks.com>
Committed: Fri Apr 17 16:05:25 2015 +0300

----------------------------------------------------------------------
 .../python/ambari_agent/alerts/base_alert.py    |   4 +-
 .../python/ambari_agent/alerts/port_alert.py    |   5 +-
 .../python/ambari_agent/TestAlertCollector.py   | 205 +++++++++++
 .../ambari_agent/TestAlertSchedulerHandler.py   | 210 +++++++++++
 .../test/python/ambari_agent/TestBaseAlert.py   |  85 +++++
 .../test/python/ambari_agent/TestHeartbeat.py   |   1 +
 .../test/python/ambari_agent/TestMetricAlert.py | 212 +++++++++++
 .../test/python/ambari_agent/TestPortAlert.py   | 361 +++++++++++++++++++
 .../test/python/ambari_agent/TestScriptAlert.py |  67 ++++
 .../resource_management/TestUserResource.py     |   2 +-
 10 files changed, 1148 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/51b2c338/ambari-agent/src/main/python/ambari_agent/alerts/base_alert.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/main/python/ambari_agent/alerts/base_alert.py b/ambari-agent/src/main/python/ambari_agent/alerts/base_alert.py
index ec30570..08fb8a9 100644
--- a/ambari-agent/src/main/python/ambari_agent/alerts/base_alert.py
+++ b/ambari-agent/src/main/python/ambari_agent/alerts/base_alert.py
@@ -433,7 +433,9 @@ class BaseAlert(object):
     Low level function to collect alert data.  The result is a tuple as:
     res[0] = the result code
     res[1] = the list of arguments supplied to the reporting text for the result code
-    """  
+    """
+    #TODO: After implementation uncomment /src/test/python/ambari_agent/TestMetricAlert.py:194
+    # and /src/test/python/ambari_agent/TestScriptAlert.py:52
     raise NotImplementedError
 
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/51b2c338/ambari-agent/src/main/python/ambari_agent/alerts/port_alert.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/main/python/ambari_agent/alerts/port_alert.py b/ambari-agent/src/main/python/ambari_agent/alerts/port_alert.py
index 1dbd450..848da65 100644
--- a/ambari-agent/src/main/python/ambari_agent/alerts/port_alert.py
+++ b/ambari-agent/src/main/python/ambari_agent/alerts/port_alert.py
@@ -118,7 +118,8 @@ class PortAlert(BaseAlert):
     if logger.isEnabledFor(logging.DEBUG):
       logger.debug("[Alert][{0}] Checking {1} on port {2}".format(
         self.get_name(), host, str(port)))
-    
+
+    s = None
     try:
       s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
       s.settimeout(self.critical_timeout)
@@ -163,4 +164,4 @@ class PortAlert(BaseAlert):
     if state == self.RESULT_OK or state == self.RESULT_WARNING:
       return 'TCP OK - {0:.4f} response on port {1}'
 
-    return 'Connection failed: {0} to {1}:{2}'
\ No newline at end of file
+    return 'Connection failed: {0} to {1}:{2}'

http://git-wip-us.apache.org/repos/asf/ambari/blob/51b2c338/ambari-agent/src/test/python/ambari_agent/TestAlertCollector.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/ambari_agent/TestAlertCollector.py b/ambari-agent/src/test/python/ambari_agent/TestAlertCollector.py
new file mode 100644
index 0000000..5ee1171
--- /dev/null
+++ b/ambari-agent/src/test/python/ambari_agent/TestAlertCollector.py
@@ -0,0 +1,205 @@
+#!/usr/bin/env python
+
+'''
+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.
+'''
+
+from ambari_agent.alerts.collector import AlertCollector
+
+from mock.mock import patch
+from unittest import TestCase
+
+class TestAlertCollector(TestCase):
+
+  def test_put_noCluster(self):
+    cluster = 'TestCluster'
+    alert = {
+      'name': 'AlertName',
+      'uuid': '12'
+    }
+    collector = AlertCollector()
+    collector._AlertCollector__buckets = {
+      'TestCluster2': {}
+    }
+    collector.put(cluster, alert)
+
+    self.assertEquals(collector._AlertCollector__buckets, {'TestCluster': {'AlertName': alert}, 'TestCluster2': {}})
+
+  def test_put_clusterExists(self):
+    cluster = 'TestCluster'
+    alert = {
+      'name': 'AlertName',
+      'uuid': '12'
+    }
+    collector = AlertCollector()
+    collector._AlertCollector__buckets = {
+      'TestCluster': {}
+    }
+    collector.put(cluster, alert)
+
+    self.assertEquals(collector._AlertCollector__buckets, {'TestCluster': {'AlertName': alert}})
+
+  def test_put_alertExists(self):
+    cluster = 'TestCluster'
+    alert = {
+      'name': 'AlertName',
+      'uuid': '12'
+    }
+    collector = AlertCollector()
+    collector._AlertCollector__buckets = {
+      'TestCluster': {
+        'AlertName': {
+          'smth': 'some_value'
+        }
+      }
+    }
+    collector.put(cluster, alert)
+
+    self.assertEquals(collector._AlertCollector__buckets, {'TestCluster': {'AlertName': alert}})
+
+  def test_remove(self):
+    alert1 = {
+      'name': 'AlertName1',
+      'uuid': 11
+    }
+    alert2 = {
+      'name': 'AlertName2',
+      'uuid': '12'
+    }
+    controller = AlertCollector()
+    controller._AlertCollector__buckets = {
+      'TestCluster': {
+        'AlertName1': alert1,
+        'AlertName2': alert2
+      }
+    }
+    controller.remove('TestCluster', 'AlertName1')
+
+    self.assertEquals(controller._AlertCollector__buckets, {'TestCluster': {'AlertName2': alert2}})
+
+  def test_remove_noCluster(self):
+    alert1 = {
+      'name': 'AlertName1',
+      'uuid': 11
+    }
+    alert2 = {
+      'name': 'AlertName2',
+      'uuid': '12'
+    }
+    controller = AlertCollector()
+    controller._AlertCollector__buckets = {
+      'TestCluster2': {
+        'AlertName1': alert1,
+        'AlertName2': alert2
+      }
+    }
+    controller.remove('TestCluster', 'AlertName1')
+
+    self.assertEquals(controller._AlertCollector__buckets, {'TestCluster2': {'AlertName1': alert1, 'AlertName2': alert2}})
+
+  def test_remove_noAlert(self):
+    alert2 = {
+      'name': 'AlertName2',
+      'uuid': '12'
+    }
+    controller = AlertCollector()
+    controller._AlertCollector__buckets = {
+      'TestCluster2': {
+        'AlertName2': alert2
+      }
+    }
+    controller.remove('TestCluster', 'AlertName1')
+
+    self.assertEquals(controller._AlertCollector__buckets, {'TestCluster2': {'AlertName2': alert2}})
+
+  def test_remove_by_uuid(self):
+    alert1 = {
+      'name': 'AlertName1',
+      'uuid': '11'
+    }
+    alert2 = {
+      'name': 'AlertName2',
+      'uuid': '12'
+    }
+    controller = AlertCollector()
+    controller._AlertCollector__buckets = {
+      'TestCluster2': {
+        'AlertName1': alert1,
+        'AlertName2': alert2
+      }
+    }
+    controller.remove_by_uuid('11')
+
+    self.assertEquals(controller._AlertCollector__buckets, {'TestCluster2': {'AlertName2': alert2}})
+
+  def test_remove_by_uuid_absent(self):
+    alert1 = {
+      'name': 'AlertName1',
+      'uuid': '11'
+    }
+    alert2 = {
+      'name': 'AlertName2',
+      'uuid': '12'
+    }
+    controller = AlertCollector()
+    controller._AlertCollector__buckets = {
+      'TestCluster': {
+        'AlertName1': alert1,
+        'AlertName2': alert2
+      }
+    }
+    controller.remove_by_uuid('13')
+
+    self.assertEquals(controller._AlertCollector__buckets, {'TestCluster': {'AlertName1': alert1, 'AlertName2': alert2}})
+
+  def test_alerts(self):
+    alert1 = {
+      'name': 'AlertName1',
+      'uuid': '11'
+    }
+    alert2 = {
+      'name': 'AlertName2',
+      'uuid': '12'
+    }
+    alert3 = {
+      'name': 'AlertName3',
+      'uuid': '13'
+    }
+    alert4 = {
+      'name': 'AlertName4',
+      'uuid': '14'
+    }
+    controller = AlertCollector()
+    controller._AlertCollector__buckets = {
+      'TestCluster1': {
+        'AlertName1': alert1,
+        'AlertName2': alert2
+      },
+      'TestCluster2': {
+        'AlertName3': alert3,
+        'AlertName4': alert4
+      }
+    }
+    list = controller.alerts()
+
+    self.assertEquals(controller._AlertCollector__buckets, {})
+    self.assertEquals(list.sort(), [alert1, alert2, alert3, alert4].sort())
+
+
+
+
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/51b2c338/ambari-agent/src/test/python/ambari_agent/TestAlertSchedulerHandler.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/ambari_agent/TestAlertSchedulerHandler.py b/ambari-agent/src/test/python/ambari_agent/TestAlertSchedulerHandler.py
new file mode 100644
index 0000000..d15cd32
--- /dev/null
+++ b/ambari-agent/src/test/python/ambari_agent/TestAlertSchedulerHandler.py
@@ -0,0 +1,210 @@
+#!/usr/bin/env python
+
+'''
+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.
+'''
+
+import copy
+import os
+
+from ambari_agent.AlertSchedulerHandler import AlertSchedulerHandler
+from ambari_agent.alerts.metric_alert import MetricAlert
+from ambari_agent.alerts.port_alert import PortAlert
+from ambari_agent.alerts.script_alert import ScriptAlert
+from ambari_agent.alerts.web_alert import WebAlert
+
+from mock.mock import patch, Mock, MagicMock
+from unittest import TestCase
+
+TEST_PATH = os.path.join('ambari_agent', 'dummy_files')
+
+class TestAlertSchedulerHandler(TestCase):
+
+  def test_load_definitions(self):
+    scheduler = AlertSchedulerHandler(TEST_PATH, TEST_PATH, TEST_PATH, TEST_PATH, None)
+
+    definitions = scheduler._AlertSchedulerHandler__load_definitions()
+
+    self.assertEquals(len(definitions), 1)
+
+  def test_json_to_callable_metric(self):
+    scheduler = AlertSchedulerHandler(TEST_PATH, TEST_PATH, TEST_PATH, TEST_PATH, None, None)
+    json_definition = {
+      'source': {
+        'type': 'METRIC'
+      }
+    }
+
+    callable_result = scheduler._AlertSchedulerHandler__json_to_callable('cluster', 'host', copy.deepcopy(json_definition))
+
+    self.assertTrue(callable_result is not None)
+    self.assertTrue(isinstance(callable_result, MetricAlert))
+    self.assertEquals(callable_result.alert_meta, json_definition)
+    self.assertEquals(callable_result.alert_source_meta, json_definition['source'])
+
+  def test_json_to_callable_port(self):
+    json_definition = {
+      'source': {
+        'type': 'PORT'
+      }
+    }
+
+    scheduler = AlertSchedulerHandler(TEST_PATH, TEST_PATH, TEST_PATH, TEST_PATH, None, None)
+    callable_result = scheduler._AlertSchedulerHandler__json_to_callable('cluster', 'host', copy.deepcopy(json_definition))
+
+    self.assertTrue(callable_result is not None)
+    self.assertTrue(isinstance(callable_result, PortAlert))
+    self.assertEquals(callable_result.alert_meta, json_definition)
+    self.assertEquals(callable_result.alert_source_meta, json_definition['source'])
+
+  def test_json_to_callable_web(self):
+
+    json_definition = {
+      'source': {
+        'type': 'WEB'
+      }
+    }
+
+    scheduler = AlertSchedulerHandler(TEST_PATH, TEST_PATH, TEST_PATH, TEST_PATH, None, None)
+    callable_result = scheduler._AlertSchedulerHandler__json_to_callable('cluster', 'host', copy.deepcopy(json_definition))
+
+    self.assertTrue(callable_result is not None)
+    self.assertTrue(isinstance(callable_result, WebAlert))
+    self.assertEquals(callable_result.alert_meta, json_definition)
+    self.assertEquals(callable_result.alert_source_meta, json_definition['source'])
+
+  def test_json_to_callable_none(self):
+    json_definition = {
+      'source': {
+        'type': 'SOMETHING'
+      }
+    }
+
+    scheduler = AlertSchedulerHandler(TEST_PATH, TEST_PATH, TEST_PATH, TEST_PATH, None, None)
+    callable_result = scheduler._AlertSchedulerHandler__json_to_callable('cluster', 'host', copy.deepcopy(json_definition))
+
+    self.assertTrue(callable_result is None)
+
+  def test_execute_alert_noneScheduler(self):
+    execution_commands = []
+
+    scheduler = AlertSchedulerHandler(TEST_PATH, TEST_PATH, TEST_PATH, TEST_PATH, None, None)
+    scheduler._AlertSchedulerHandler__scheduler = None
+    alert_mock = Mock()
+    scheduler._AlertSchedulerHandler__json_to_callable = Mock(return_value=alert_mock)
+
+    scheduler.execute_alert(execution_commands)
+
+    self.assertFalse(alert_mock.collect.called)
+
+  def test_execute_alert_noneCommands(self):
+    execution_commands = None
+
+    scheduler = AlertSchedulerHandler(TEST_PATH, TEST_PATH, TEST_PATH, TEST_PATH, None, None)
+    alert_mock = Mock()
+    scheduler._AlertSchedulerHandler__json_to_callable = Mock(return_value=alert_mock)
+
+    scheduler.execute_alert(execution_commands)
+
+    self.assertFalse(alert_mock.collect.called)
+
+  def test_execute_alert_emptyCommands(self):
+    execution_commands = []
+
+    scheduler = AlertSchedulerHandler(TEST_PATH, TEST_PATH, TEST_PATH, TEST_PATH, None, None)
+    alert_mock = Mock()
+    scheduler._AlertSchedulerHandler__json_to_callable = Mock(return_value=alert_mock)
+
+    scheduler.execute_alert(execution_commands)
+
+    self.assertFalse(alert_mock.collect.called)
+
+  def test_execute_alert(self):
+    execution_commands = [
+      {
+        'clusterName': 'cluster',
+        'hostName': 'host',
+        'alertDefinition': {
+          'name': 'alert1'
+        }
+      }
+    ]
+
+    scheduler = AlertSchedulerHandler(TEST_PATH, TEST_PATH, TEST_PATH, TEST_PATH, None, None)
+    alert_mock = MagicMock()
+    alert_mock.collect = Mock()
+    alert_mock.set_helpers = Mock()
+    scheduler._AlertSchedulerHandler__json_to_callable = Mock(return_value=alert_mock)
+    scheduler._AlertSchedulerHandler__config_maps = {
+      'cluster': {}
+    }
+
+    scheduler.execute_alert(execution_commands)
+
+    scheduler._AlertSchedulerHandler__json_to_callable.assert_called_with('cluster', 'host', {'name': 'alert1'})
+    self.assertTrue(alert_mock.collect.called)
+
+  def test_load_definitions(self):
+    scheduler = AlertSchedulerHandler(TEST_PATH, TEST_PATH, TEST_PATH, TEST_PATH, None, None)
+    scheduler._AlertSchedulerHandler__config_maps = {
+      'cluster': {}
+    }
+
+    definitions = scheduler._AlertSchedulerHandler__load_definitions()
+
+    alert_def = definitions[0]
+    self.assertTrue(isinstance(alert_def, PortAlert))
+
+  def test_load_definitions_noFile(self):
+    scheduler = AlertSchedulerHandler('wrong_path', 'wrong_path', 'wrong_path', 'wrong_path', None, None)
+    scheduler._AlertSchedulerHandler__config_maps = {
+      'cluster': {}
+    }
+
+    definitions = scheduler._AlertSchedulerHandler__load_definitions()
+
+    self.assertEquals(definitions, [])
+
+  def test_start(self):
+    execution_commands = [
+      {
+        'clusterName': 'cluster',
+        'hostName': 'host',
+        'alertDefinition': {
+          'name': 'alert1'
+        }
+      }
+    ]
+
+    scheduler = AlertSchedulerHandler(TEST_PATH, TEST_PATH, TEST_PATH, TEST_PATH, None, None)
+    alert_mock = MagicMock()
+    alert_mock.interval = Mock(return_value=5)
+    alert_mock.collect = Mock()
+    alert_mock.set_helpers = Mock()
+    scheduler.schedule_definition = MagicMock()
+    scheduler._AlertSchedulerHandler__scheduler = MagicMock()
+    scheduler._AlertSchedulerHandler__scheduler.running = False
+    scheduler._AlertSchedulerHandler__scheduler.start = Mock()
+    scheduler._AlertSchedulerHandler__json_to_callable = Mock(return_value=alert_mock)
+    scheduler._AlertSchedulerHandler__config_maps = {
+      'cluster': {}
+    }
+
+    scheduler.start()
+
+    self.assertTrue(scheduler._AlertSchedulerHandler__scheduler.start.called)
+    scheduler.schedule_definition.assert_called_with(alert_mock)

http://git-wip-us.apache.org/repos/asf/ambari/blob/51b2c338/ambari-agent/src/test/python/ambari_agent/TestBaseAlert.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/ambari_agent/TestBaseAlert.py b/ambari-agent/src/test/python/ambari_agent/TestBaseAlert.py
new file mode 100644
index 0000000..e67c894
--- /dev/null
+++ b/ambari-agent/src/test/python/ambari_agent/TestBaseAlert.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python
+
+'''
+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.
+'''
+
+from unittest import TestCase
+from alerts.base_alert import BaseAlert
+
+alert = BaseAlert({}, {})
+
+class TestBaseAlert(TestCase):
+
+  def test_interval_noData(self):
+    alert_meta = {}
+    alert_source_meta = {}
+
+    alert = BaseAlert(alert_meta, alert_source_meta)
+    interval = alert.interval()
+    self.assertEquals(interval, 1)
+
+  def test_interval_zero(self):
+    alert_meta = {'interval': 0}
+    alert_source_meta = {}
+
+    alert = BaseAlert(alert_meta, alert_source_meta)
+    interval = alert.interval()
+    self.assertEquals(interval, 1)
+
+  def test_interval(self):
+    alert_meta = {'interval': 5}
+    alert_source_meta = {}
+
+    alert = BaseAlert(alert_meta, alert_source_meta)
+    interval = alert.interval()
+    self.assertEquals(interval, 5)
+
+  def test_isEnabled(self):
+    alert_meta = {'enabled': 'true'}
+    alert_source_meta = {}
+
+    alert = BaseAlert(alert_meta, alert_source_meta)
+    enabled = alert.is_enabled()
+    self.assertEquals(enabled, 'true')
+
+  def test_getName(self):
+    alert_meta = {'name': 'ambari'}
+    alert_source_meta = {}
+
+    alert = BaseAlert(alert_meta, alert_source_meta)
+    name = alert.get_name()
+    self.assertEquals(name, 'ambari')
+
+  def test_getUuid(self):
+    alert_meta = {'uuid': '123'}
+    alert_source_meta = {}
+
+    alert = BaseAlert(alert_meta, alert_source_meta)
+    uuid = alert.get_uuid()
+    self.assertEquals(uuid, '123')
+
+  def test_setCluster(self):
+    alert_meta = {}
+    alert_source_meta = {}
+    cluster = 'cluster'
+    host = 'host'
+
+    alert = BaseAlert(alert_meta, alert_source_meta)
+    alert.set_cluster(cluster, host)
+    self.assertEquals(alert.cluster_name, cluster)
+    self.assertEquals(alert.host_name, host)

http://git-wip-us.apache.org/repos/asf/ambari/blob/51b2c338/ambari-agent/src/test/python/ambari_agent/TestHeartbeat.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/ambari_agent/TestHeartbeat.py b/ambari-agent/src/test/python/ambari_agent/TestHeartbeat.py
index 11a4182..2f13ef5 100644
--- a/ambari-agent/src/test/python/ambari_agent/TestHeartbeat.py
+++ b/ambari-agent/src/test/python/ambari_agent/TestHeartbeat.py
@@ -216,6 +216,7 @@ class TestHeartbeat(TestCase):
       "commandType" : "STATUS_COMMAND",
       "clusterName" : "c1",
       "componentName" : "DATANODE",
+      "role" : "DATANODE",
       'configurations':{'global' : {}}
     }
     actionQueue.put_status([statusCommand])

http://git-wip-us.apache.org/repos/asf/ambari/blob/51b2c338/ambari-agent/src/test/python/ambari_agent/TestMetricAlert.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/ambari_agent/TestMetricAlert.py b/ambari-agent/src/test/python/ambari_agent/TestMetricAlert.py
new file mode 100644
index 0000000..e3fe32a
--- /dev/null
+++ b/ambari-agent/src/test/python/ambari_agent/TestMetricAlert.py
@@ -0,0 +1,212 @@
+#!/usr/bin/env python
+
+'''
+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.
+'''
+
+from unittest import TestCase
+from alerts.metric_alert import MetricAlert
+from mock.mock import Mock, MagicMock, patch
+import os
+
+class TestMetricAlert(TestCase):
+
+  @patch("urllib2.urlopen")
+  def test_collect(self, urllib):
+    alert_meta = {
+      'name': 'alert1',
+      'label': 'label1',
+      'serviceName': 'service1',
+      'componentName': 'component1',
+      'uuid': '123',
+      'enabled': 'true'
+    }
+    alert_source_meta = {
+      'jmx': {
+        'property_list': [
+          'x/y'
+        ]
+      },
+      'uri': {
+        'http': '192.168.0.10:8080',
+        'https_property': '{{hdfs-site/dfs.http.policy}}',
+        'https_property_value': 'HTTPS_ONLY'
+      },
+      "reporting": {
+        "ok": {
+          "text": "OK: {0}"
+        },
+        "warning": {
+          "text": "Warn: {0}",
+          "value": 2
+        },
+        "critical": {
+          "text": "Crit: {0}",
+          "value": 5
+        }
+      }
+    }
+    cluster = 'c1'
+    host = 'host1'
+    expected_text = 'OK: 1'
+
+    def collector_side_effect(clus, data):
+      self.assertEquals(data['name'], alert_meta['name'])
+      self.assertEquals(data['label'], alert_meta['label'])
+      self.assertEquals(data['text'], expected_text)
+      self.assertEquals(data['service'], alert_meta['serviceName'])
+      self.assertEquals(data['component'], alert_meta['componentName'])
+      self.assertEquals(data['uuid'], alert_meta['uuid'])
+      self.assertEquals(data['enabled'], alert_meta['enabled'])
+      self.assertEquals(data['cluster'], cluster)
+      self.assertEquals(clus, cluster)
+
+    response = Mock()
+    urllib.return_value = response
+    response.read = Mock(return_value='{"beans": [{"y": 1}]}')
+    mock_collector = MagicMock()
+    mock_collector.put = Mock(side_effect=collector_side_effect)
+
+    alert = MetricAlert(alert_meta, alert_source_meta)
+    alert.set_helpers(mock_collector, {'foo-site/bar': 12, 'foo-site/baz': 'asd'})
+    alert.set_cluster(cluster, host)
+
+    alert.collect()
+
+  @patch("urllib2.urlopen")
+  def test_collect(self, urllib):
+    alert_meta = {
+      'name': 'alert1',
+      'label': 'label1',
+      'serviceName': 'service1',
+      'componentName': 'component1',
+      'uuid': '123',
+      'enabled': 'true'
+    }
+    alert_source_meta = {
+      'jmx': {
+        'property_list': [
+          'x/y'
+        ]
+      },
+      'uri': {
+        'http': '192.168.0.10:8080',
+        'https_property': '{{hdfs-site/dfs.http.policy}}',
+        'https_property_value': 'HTTPS_ONLY'
+      },
+      "reporting": {
+        "ok": {
+          "text": "OK: {0}"
+        },
+        "warning": {
+          "text": "Warn: {0}",
+          "value": 2
+        },
+        "critical": {
+          "text": "Crit: {0}",
+          "value": 5
+        }
+      }
+    }
+    cluster = 'c1'
+    host = 'host1'
+    expected_text = 'Warn: 4'
+
+    def collector_side_effect(clus, data):
+      self.assertEquals(data['name'], alert_meta['name'])
+      self.assertEquals(data['label'], alert_meta['label'])
+      self.assertEquals(data['text'], expected_text)
+      self.assertEquals(data['service'], alert_meta['serviceName'])
+      self.assertEquals(data['component'], alert_meta['componentName'])
+      self.assertEquals(data['uuid'], alert_meta['uuid'])
+      self.assertEquals(data['enabled'], alert_meta['enabled'])
+      self.assertEquals(data['cluster'], cluster)
+      self.assertEquals(clus, cluster)
+
+    response = Mock()
+    urllib.return_value = response
+    response.read = Mock(return_value='{"beans": [{"y": 4}]}')
+    mock_collector = MagicMock()
+    mock_collector.put = Mock(side_effect=collector_side_effect)
+
+    alert = MetricAlert(alert_meta, alert_source_meta)
+    alert.set_helpers(mock_collector, {'foo-site/bar': 12, 'foo-site/baz': 'asd'})
+    alert.set_cluster(cluster, host)
+
+    alert.collect()
+
+  @patch("urllib2.urlopen")
+  def test_collect(self, urllib):
+    alert_meta = {
+      'name': 'alert1',
+      'label': 'label1',
+      'serviceName': 'service1',
+      'componentName': 'component1',
+      'uuid': '123',
+      'enabled': 'true'
+    }
+    alert_source_meta = {
+      'jmx': {
+        'property_list': [
+          'x/y'
+        ]
+      },
+      'uri': {
+        'http': '192.168.0.10:8080',
+        'https_property': '{{hdfs-site/dfs.http.policy}}',
+        'https_property_value': 'HTTPS_ONLY'
+      },
+      "reporting": {
+        "ok": {
+          "text": "OK: {0}"
+        },
+        "warning": {
+          "text": "Warn: {0}",
+          "value": 2
+        },
+        "critical": {
+          "text": "Crit: {0}",
+          "value": 5
+        }
+      }
+    }
+    cluster = 'c1'
+    host = 'host1'
+    expected_text = 'Crit: 12'
+
+    def collector_side_effect(clus, data):
+      self.assertEquals(data['name'], alert_meta['name'])
+      self.assertEquals(data['label'], alert_meta['label'])
+      #self.assertEquals(data['text'], expected_text)
+      self.assertEquals(data['service'], alert_meta['serviceName'])
+      self.assertEquals(data['component'], alert_meta['componentName'])
+      self.assertEquals(data['uuid'], alert_meta['uuid'])
+      self.assertEquals(data['enabled'], alert_meta['enabled'])
+      self.assertEquals(data['cluster'], cluster)
+      self.assertEquals(clus, cluster)
+
+    response = Mock()
+    urllib.return_value = response
+    response.read = Mock(return_value='{"beans": [{"y": 12}]}')
+    mock_collector = MagicMock()
+    mock_collector.put = Mock(side_effect=collector_side_effect)
+
+    alert = MetricAlert(alert_meta, alert_source_meta)
+    alert.set_helpers(mock_collector, {'foo-site/bar': 12, 'foo-site/baz': 'asd'})
+    alert.set_cluster(cluster, host)
+
+    alert.collect()

http://git-wip-us.apache.org/repos/asf/ambari/blob/51b2c338/ambari-agent/src/test/python/ambari_agent/TestPortAlert.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/ambari_agent/TestPortAlert.py b/ambari-agent/src/test/python/ambari_agent/TestPortAlert.py
new file mode 100644
index 0000000..195cc63
--- /dev/null
+++ b/ambari-agent/src/test/python/ambari_agent/TestPortAlert.py
@@ -0,0 +1,361 @@
+#!/usr/bin/env python
+
+'''
+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.
+'''
+
+from unittest import TestCase
+from alerts.port_alert import PortAlert
+from mock.mock import Mock, MagicMock, patch
+
+class TestPortAlert(TestCase):
+
+  @patch("socket.socket")
+  @patch("time.time")
+  def test_collect_defaultPort(self, time, socket):
+    alert_meta = {
+      'name': 'alert1',
+      'label': 'label1',
+      'serviceName': 'service1',
+      'componentName': 'component1',
+      'uuid': '123',
+      'enabled': 'true'
+    }
+    alert_source_meta = {
+      'uri': 'http://192.168.0.1',
+      'default_port': 80
+    }
+    cluster = 'c1'
+    host = 'host1'
+    expected_state = 'OK'
+    expected_text = 'TCP OK - 0.2010 response on port 80'
+    time.side_effect = [123, 324, 567]
+    alert = PortAlert(alert_meta, alert_source_meta)
+    alert.set_cluster(cluster, host)
+
+    def collector_side_effect(clus, data):
+      self.assertEquals(data['name'], alert_meta['name'])
+      self.assertEquals(data['label'], alert_meta['label'])
+      self.assertEquals(data['service'], alert_meta['serviceName'])
+      self.assertEquals(data['component'], alert_meta['componentName'])
+      self.assertEquals(data['uuid'], alert_meta['uuid'])
+      self.assertEquals(data['enabled'], alert_meta['enabled'])
+      self.assertEquals(data['state'], expected_state)
+      self.assertEquals(data['text'], expected_text)
+      self.assertEquals(data['cluster'], cluster)
+      self.assertEquals(clus, cluster)
+
+    alert.collector = MagicMock()
+    alert.collector.put = Mock(side_effect=collector_side_effect)
+
+    alert.collect()
+
+  @patch("socket.socket")
+  @patch("time.time")
+  def test_collect_warning(self, time, socket):
+    alert_meta = {
+      'name': 'alert1',
+      'label': 'label1',
+      'serviceName': 'service1',
+      'componentName': 'component1',
+      'uuid': '123',
+      'enabled': 'true'
+    }
+    alert_source_meta = {
+      'uri': 'http://192.168.0.1:8080',
+      'default_port': 80
+    }
+    cluster = 'c1'
+    host = 'host1'
+    expected_state = 'WARNING'
+    expected_text = 'TCP OK - 3.1170 response on port 8080'
+    time.side_effect = [123, 3240, 567]
+    alert = PortAlert(alert_meta, alert_source_meta)
+    alert.set_cluster(cluster, host)
+
+    def collector_side_effect(clus, data):
+      self.assertEquals(data['name'], alert_meta['name'])
+      self.assertEquals(data['label'], alert_meta['label'])
+      self.assertEquals(data['service'], alert_meta['serviceName'])
+      self.assertEquals(data['component'], alert_meta['componentName'])
+      self.assertEquals(data['uuid'], alert_meta['uuid'])
+      self.assertEquals(data['enabled'], alert_meta['enabled'])
+      self.assertEquals(data['state'], expected_state)
+      self.assertEquals(data['text'], expected_text)
+      self.assertEquals(data['cluster'], cluster)
+      self.assertEquals(clus, cluster)
+
+    alert.collector = MagicMock()
+    alert.collector.put = Mock(side_effect=collector_side_effect)
+
+    alert.collect()
+
+  @patch("socket.socket")
+  @patch("time.time")
+  def test_collect_connectionTimeout(self, time, socket):
+    alert_meta = {
+      'name': 'alert1',
+      'label': 'label1',
+      'serviceName': 'service1',
+      'componentName': 'component1',
+      'uuid': '123',
+      'enabled': 'true'
+    }
+    alert_source_meta = {
+      'uri': 'http://192.168.0.1:8080',
+      'default_port': 80
+    }
+    cluster = 'c1'
+    host = 'host1'
+    expected_state = 'CRITICAL'
+    expected_text = 'Connection failed: Socket Timeout to 192.168.0.1:8080'
+    time.side_effect = [123, 5240, 567]
+    alert = PortAlert(alert_meta, alert_source_meta)
+    alert.set_cluster(cluster, host)
+
+    def collector_side_effect(clus, data):
+      self.assertEquals(data['name'], alert_meta['name'])
+      self.assertEquals(data['label'], alert_meta['label'])
+      self.assertEquals(data['service'], alert_meta['serviceName'])
+      self.assertEquals(data['component'], alert_meta['componentName'])
+      self.assertEquals(data['uuid'], alert_meta['uuid'])
+      self.assertEquals(data['enabled'], alert_meta['enabled'])
+      self.assertEquals(data['state'], expected_state)
+      self.assertEquals(data['text'], expected_text)
+      self.assertEquals(data['cluster'], cluster)
+      self.assertEquals(clus, cluster)
+
+    alert.collector = MagicMock()
+    alert.collector.put = Mock(side_effect=collector_side_effect)
+
+    alert.collect()
+
+  @patch("socket.socket")
+  @patch("time.time")
+  def test_collect_noUrl(self, time, socket):
+    alert_meta = {
+      'name': 'alert1',
+      'label': 'label1',
+      'serviceName': 'service1',
+      'componentName': 'component1',
+      'uuid': '123',
+      'enabled': 'true'
+    }
+    alert_source_meta = {
+      'default_port': 80
+    }
+    cluster = 'c1'
+    host = 'host1'
+    expected_state = 'CRITICAL'
+    expected_text = 'Connection failed: Socket Timeout to host1:80'
+    time.side_effect = [123, 5240, 567]
+    alert = PortAlert(alert_meta, alert_source_meta)
+    alert.set_cluster(cluster, host)
+
+    def collector_side_effect(clus, data):
+      self.assertEquals(data['name'], alert_meta['name'])
+      self.assertEquals(data['label'], alert_meta['label'])
+      self.assertEquals(data['service'], alert_meta['serviceName'])
+      self.assertEquals(data['component'], alert_meta['componentName'])
+      self.assertEquals(data['uuid'], alert_meta['uuid'])
+      self.assertEquals(data['enabled'], alert_meta['enabled'])
+      self.assertEquals(data['state'], expected_state)
+      self.assertEquals(data['text'], expected_text)
+      self.assertEquals(data['cluster'], cluster)
+      self.assertEquals(clus, cluster)
+
+    alert.collector = MagicMock()
+    alert.collector.put = Mock(side_effect=collector_side_effect)
+
+    alert.collect()
+
+  @patch("socket.socket")
+  @patch("time.time")
+  def test_collect_exception(self, time, socket):
+    alert_meta = {
+      'name': 'alert1',
+      'label': 'label1',
+      'serviceName': 'service1',
+      'componentName': 'component1',
+      'uuid': '123',
+      'enabled': 'true'
+    }
+    alert_source_meta = {
+      'uri': 'http://192.168.0.1:8080',
+      'default_port': 80
+    }
+    cluster = 'c1'
+    host = 'host1'
+    expected_state = 'CRITICAL'
+    expected_text = 'Connection failed: exception message to 192.168.0.1:8080'
+    time.side_effect = [123, 345, 567]
+    socket.side_effect = Exception('exception message')
+    alert = PortAlert(alert_meta, alert_source_meta)
+    alert.set_cluster(cluster, host)
+
+    def collector_side_effect(clus, data):
+      self.assertEquals(data['name'], alert_meta['name'])
+      self.assertEquals(data['label'], alert_meta['label'])
+      self.assertEquals(data['service'], alert_meta['serviceName'])
+      self.assertEquals(data['component'], alert_meta['componentName'])
+      self.assertEquals(data['uuid'], alert_meta['uuid'])
+      self.assertEquals(data['enabled'], alert_meta['enabled'])
+      self.assertEquals(data['state'], expected_state)
+      self.assertEquals(data['text'], expected_text)
+      self.assertEquals(data['cluster'], cluster)
+      self.assertEquals(clus, cluster)
+
+    alert.collector = MagicMock()
+    alert.collector.put = Mock(side_effect=collector_side_effect)
+
+    alert.collect()
+
+  @patch("socket.socket")
+  @patch("time.time")
+  def test_collect_warningTimeoutChanged(self, time, socket):
+    alert_meta = {
+      'name': 'alert1',
+      'label': 'label1',
+      'serviceName': 'service1',
+      'componentName': 'component1',
+      'uuid': '123',
+      'enabled': 'true'
+    }
+    alert_source_meta = {
+      'uri': 'http://192.168.0.1:8080',
+      'default_port': 80,
+      'reporting': {
+        'warning': {
+          'value': 4
+        }
+      }
+    }
+    cluster = 'c1'
+    host = 'host1'
+    expected_state = 'OK'
+    expected_text = 'TCP OK - 3.1170 response on port 8080'
+    time.side_effect = [123, 3240, 567]
+    alert = PortAlert(alert_meta, alert_source_meta)
+    alert.set_cluster(cluster, host)
+
+    def collector_side_effect(clus, data):
+      self.assertEquals(data['name'], alert_meta['name'])
+      self.assertEquals(data['label'], alert_meta['label'])
+      self.assertEquals(data['service'], alert_meta['serviceName'])
+      self.assertEquals(data['component'], alert_meta['componentName'])
+      self.assertEquals(data['uuid'], alert_meta['uuid'])
+      self.assertEquals(data['enabled'], alert_meta['enabled'])
+      self.assertEquals(data['state'], expected_state)
+      self.assertEquals(data['text'], expected_text)
+      self.assertEquals(data['cluster'], cluster)
+      self.assertEquals(clus, cluster)
+
+    alert.collector = MagicMock()
+    alert.collector.put = Mock(side_effect=collector_side_effect)
+
+    alert.collect()
+
+  @patch("socket.socket")
+  @patch("time.time")
+  def test_collect_criticalTimeoutChanged(self, time, socket):
+    alert_meta = {
+      'name': 'alert1',
+      'label': 'label1',
+      'serviceName': 'service1',
+      'componentName': 'component1',
+      'uuid': '123',
+      'enabled': 'true'
+    }
+    alert_source_meta = {
+      'uri': 'http://192.168.0.1:8080',
+      'default_port': 80,
+      'reporting': {
+        'critical': {
+          'value': 3
+        }
+      }
+    }
+    cluster = 'c1'
+    host = 'host1'
+    expected_state = 'CRITICAL'
+    expected_text = 'Connection failed: Socket Timeout to 192.168.0.1:8080'
+    time.side_effect = [123, 3240, 567]
+    alert = PortAlert(alert_meta, alert_source_meta)
+    alert.set_cluster(cluster, host)
+
+    def collector_side_effect(clus, data):
+      self.assertEquals(data['name'], alert_meta['name'])
+      self.assertEquals(data['label'], alert_meta['label'])
+      self.assertEquals(data['service'], alert_meta['serviceName'])
+      self.assertEquals(data['component'], alert_meta['componentName'])
+      self.assertEquals(data['uuid'], alert_meta['uuid'])
+      self.assertEquals(data['enabled'], alert_meta['enabled'])
+      self.assertEquals(data['state'], expected_state)
+      self.assertEquals(data['text'], expected_text)
+      self.assertEquals(data['cluster'], cluster)
+      self.assertEquals(clus, cluster)
+
+    alert.collector = MagicMock()
+    alert.collector.put = Mock(side_effect=collector_side_effect)
+
+    alert.collect()
+
+  @patch("socket.socket")
+  @patch("time.time")
+  def test_collect_criticalTimeoutTooBig(self, time, socket):
+    alert_meta = {
+      'name': 'alert1',
+      'label': 'label1',
+      'serviceName': 'service1',
+      'componentName': 'component1',
+      'uuid': '123',
+      'enabled': 'true'
+    }
+    alert_source_meta = {
+      'uri': 'http://192.168.0.1:8080',
+      'default_port': 80,
+      'reporting': {
+        'critical': {
+          'value': 33
+        }
+      }
+    }
+    cluster = 'c1'
+    host = 'host1'
+    expected_state = 'CRITICAL'
+    expected_text = 'Connection failed: Socket Timeout to 192.168.0.1:8080'
+    time.side_effect = [120, 123, 5240, 567]
+    alert = PortAlert(alert_meta, alert_source_meta)
+    alert.set_cluster(cluster, host)
+
+    def collector_side_effect(clus, data):
+      self.assertEquals(data['name'], alert_meta['name'])
+      self.assertEquals(data['label'], alert_meta['label'])
+      self.assertEquals(data['service'], alert_meta['serviceName'])
+      self.assertEquals(data['component'], alert_meta['componentName'])
+      self.assertEquals(data['uuid'], alert_meta['uuid'])
+      self.assertEquals(data['enabled'], alert_meta['enabled'])
+      self.assertEquals(data['state'], expected_state)
+      self.assertEquals(data['text'], expected_text)
+      self.assertEquals(data['cluster'], cluster)
+      self.assertEquals(clus, cluster)
+
+    alert.collector = MagicMock()
+    alert.collector.put = Mock(side_effect=collector_side_effect)
+
+    alert.collect()
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/51b2c338/ambari-agent/src/test/python/ambari_agent/TestScriptAlert.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/ambari_agent/TestScriptAlert.py b/ambari-agent/src/test/python/ambari_agent/TestScriptAlert.py
new file mode 100644
index 0000000..7201a10
--- /dev/null
+++ b/ambari-agent/src/test/python/ambari_agent/TestScriptAlert.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python
+
+'''
+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.
+'''
+
+from unittest import TestCase
+from alerts.script_alert import ScriptAlert
+from mock.mock import Mock, MagicMock, patch
+import os
+
+DUMMY_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'dummy_files')
+
+class TestScriptAlert(TestCase):
+
+  def test_collect(self):
+    alert_meta = {
+      'name': 'alert1',
+      'label': 'label1',
+      'serviceName': 'service1',
+      'componentName': 'component1',
+      'uuid': '123',
+      'enabled': 'true'
+    }
+    alert_source_meta = {
+      'stacks_directory': DUMMY_PATH,
+      'path': os.path.join(DUMMY_PATH, 'test_script.py'),
+      'common_services_directory': DUMMY_PATH,
+      'host_scripts_directory': DUMMY_PATH,
+    }
+    cluster = 'c1'
+    host = 'host1'
+    expected_text = 'bar is 12, baz is asd'
+
+    def collector_side_effect(clus, data):
+      self.assertEquals(data['name'], alert_meta['name'])
+      self.assertEquals(data['label'], alert_meta['label'])
+      #self.assertEquals(data['text'], expected_text)
+      self.assertEquals(data['service'], alert_meta['serviceName'])
+      self.assertEquals(data['component'], alert_meta['componentName'])
+      self.assertEquals(data['uuid'], alert_meta['uuid'])
+      self.assertEquals(data['enabled'], alert_meta['enabled'])
+      self.assertEquals(data['cluster'], cluster)
+      self.assertEquals(clus, cluster)
+
+    mock_collector = MagicMock()
+    mock_collector.put = Mock(side_effect=collector_side_effect)
+
+    alert = ScriptAlert(alert_meta, alert_source_meta, {})
+    alert.set_helpers(mock_collector, {'foo-site/bar': 12, 'foo-site/baz': 'asd'})
+    alert.set_cluster(cluster, host)
+
+    alert.collect()

http://git-wip-us.apache.org/repos/asf/ambari/blob/51b2c338/ambari-agent/src/test/python/resource_management/TestUserResource.py
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/python/resource_management/TestUserResource.py b/ambari-agent/src/test/python/resource_management/TestUserResource.py
index 800e823..4d83073 100644
--- a/ambari-agent/src/test/python/resource_management/TestUserResource.py
+++ b/ambari-agent/src/test/python/resource_management/TestUserResource.py
@@ -183,7 +183,7 @@ class TestUserResource(TestCase):
       user = User("mapred", action = "create", groups = ['1','2','3'], 
           shell = "/bin/bash")
 
-    popen_mock.assert_called_with(['/bin/bash', '--login', '--noprofile', '-c', 'ambari-sudo.sh  PATH=/bin -H -E usermod -G 1,2,3 -s /bin/bash mapred'], shell=False, preexec_fn=None, stderr=-2, stdout=5, env={'PATH': '/bin'}, bufsize=1, cwd=None, close_fds=True)
+    popen_mock.assert_called_with(['/bin/bash', '--login', '--noprofile', '-c', 'ambari-sudo.sh  PATH=/bin -H -E usermod -G 1,2,3,hadoop -s /bin/bash mapred'], shell=False, preexec_fn=None, env={'PATH': '/bin'}, close_fds=True, stdout=5, stderr=-2, bufsize=1, cwd=None)
     self.assertEqual(popen_mock.call_count, 1)
 
   @patch.object(subprocess, "Popen")