def test_process_met_end(self): """ Test _process_met method when setting 'end' parameter """ m = mox.Mox() midnight = '00:00:00' one = '01:00:00' p1 = TimeWindow('test', {}, begin=None, end=one, weekdays=None, parent=None, interval=0.1) p2 = TimeWindow('test', {}, begin=None, end=midnight, weekdays=None, parent=None, interval=0.1) mid_time = datetime.datetime.strptime(midnight, '%H:%M:%S').time() one_time = datetime.datetime.strptime(one, '%H:%M:%S').time() m.StubOutWithMock(p1, '_get_comparison') p1._get_comparison(p1.end).AndReturn(mid_time) # pretend it's midnight m.StubOutWithMock(p2, '_get_comparison') p2._get_comparison(p2.end).AndReturn(one_time) # pretend it's one m.ReplayAll() p1._process_met() p2._process_met() # should be 'met' if end is one and it is midnight self.assertEqual(p1.met, True) # should not be 'met' if end is midnight and it is one self.assertEqual(p2.met, False) m.VerifyAll() m.UnsetStubs()
def test_process_met_weekdays(self): """ Test _process_met method when setting weekdays parameter """ m = mox.Mox() m_to_fri = '0-4' p1 = TimeWindow('test', {}, begin=None, end=None, weekdays=m_to_fri, parent=None, interval=0.1) p2 = TimeWindow('test', {}, begin=None, end=None, weekdays=m_to_fri, parent=None, interval=0.1) m.StubOutWithMock(p1, 'weekday') p1.weekday().AndReturn(1) # pretend it's Tuesday m.StubOutWithMock(p2, 'weekday') p2.weekday().AndReturn(6) # pretend it's Sunday m.ReplayAll() p1._process_met() p2._process_met() # should be 'met' if weekdays = mon-fri and it is Tuesday self.assertEqual(p1.met, True) # should not be 'met' if weekdays = mon-fri and it is Sunday self.assertEqual(p2.met, False) m.VerifyAll() m.UnsetStubs()
def test_get_datetime_object(self): """ Test get_datetime_object method creates proper datetime.datetime or datetime.time object given the proper string """ # test full date date_test = '1970-01-02 03:04:05' exp_dt_obj = datetime.datetime(1970, 1, 2, 3, 4, 5) result = TimeWindow.get_datetime_object(date_test) self.assertEqual(exp_dt_obj, result) # test timestamp with hours, minutes seconds time_test1 = '01:02:03' exp_tm_obj1 = datetime.time(1, 2, 3) result = TimeWindow.get_datetime_object(time_test1) self.assertEqual(exp_tm_obj1, result) # test timestamp with hours, minutes time_test2 = '03:04' exp_tm_obj2 = datetime.time(3, 4) result = TimeWindow.get_datetime_object(time_test2) self.assertEqual(exp_tm_obj2, result) # test timestamp with single-digit hour, minutes time_test3 = '5:06' exp_tm_obj3 = datetime.time(5, 6) result = TimeWindow.get_datetime_object(time_test3) self.assertEqual(exp_tm_obj3, result)
def test_create_datetime_dict(self): """ Test create_datetime_dict method creates proper dictionary """ # test full date date_test = '1970-01-02 03:04:05' result = TimeWindow.create_datetime_dict(date_test) exp_date_dict = {'second': 5, 'hour': 3, 'year': 1970, 'day': 2, 'minute': 4, 'month': 1} self.assertEqual(exp_date_dict, result) # test timestamp with hours, minutes seconds time_test1 = '01:02:03' result = TimeWindow.create_datetime_dict(time_test1) exp_time1_dict = {'second': 3, 'hour': 1, 'year': None, 'day': None, 'minute': 2, 'month': None} self.assertEqual(exp_time1_dict, result) # test timestamp with hours, minutes time_test2 = '03:04' result = TimeWindow.create_datetime_dict(time_test2) exp_time2_dict = {'second': None, 'hour': 3, 'year': None, 'day': None, 'minute': 4, 'month': None} self.assertEqual(exp_time2_dict, result) # test timestamp with single-digit hour, minutes time_test3 = '5:06' result = TimeWindow.create_datetime_dict(time_test3) exp_time3_dict = {'second': None, 'hour': 5, 'year': None, 'day': None, 'minute': 6, 'month': None} self.assertEqual(exp_time3_dict, result)
def test_process_met_attributes_all_none(self): """ Test that when all parameters are None 'met' is False """ p = TimeWindow('test', {}, begin=None, end=None, weekdays=None, parent=None, interval=0.1) p._process_met() self.assertEqual(p.met, False)
def test_create_datetime_dict(self): """ Test create_datetime_dict method creates proper dictionary """ # test full date date_test = '1970-01-02 03:04:05' result = TimeWindow.create_datetime_dict(date_test) exp_date_dict = { 'second': 5, 'hour': 3, 'year': 1970, 'day': 2, 'minute': 4, 'month': 1 } self.assertEqual(exp_date_dict, result) # test timestamp with hours, minutes seconds time_test1 = '01:02:03' result = TimeWindow.create_datetime_dict(time_test1) exp_time1_dict = { 'second': 3, 'hour': 1, 'year': None, 'day': None, 'minute': 2, 'month': None } self.assertEqual(exp_time1_dict, result) # test timestamp with hours, minutes time_test2 = '03:04' result = TimeWindow.create_datetime_dict(time_test2) exp_time2_dict = { 'second': None, 'hour': 3, 'year': None, 'day': None, 'minute': 4, 'month': None } self.assertEqual(exp_time2_dict, result) # test timestamp with single-digit hour, minutes time_test3 = '5:06' result = TimeWindow.create_datetime_dict(time_test3) exp_time3_dict = { 'second': None, 'hour': 5, 'year': None, 'day': None, 'minute': 6, 'month': None } self.assertEqual(exp_time3_dict, result)
def test_process_met_attributes_all_none(self): """ Test that when all parameters are None 'met' is False """ p = TimeWindow('test', begin=None, end=None, weekdays=None, parent=None, interval=0.1) p._process_met() self.assertEqual(p.met, False)
def test_inequality(self): """ Test object inequality between two objects """ p1 = TimeWindow('test', begin='00:00:00', end='11:11:11', weekdays='6', parent=None, interval=0.1) p2 = TimeWindow('test', begin='11:11:11', end='12:22:22', weekdays=None, parent=None, interval=5.0) self.assertNotEquals(p1, p2)
def _parse_data(self, gut_data): """ :type gut_data: dict """ start_data = gut_data.get(u'start', None) self._log.debug('raw start from zk is "{0}"'.format(start_data)) if start_data is not None: self._start = TimeWindow.get_datetime_object(start_data) stop_data = gut_data.get(u'stop', None) self._log.debug('raw stop from zk is "{0}"'.format(stop_data)) if stop_data is not None: self._stop = TimeWindow.get_datetime_object(stop_data) if start_data is None and stop_data is None: self._log.error('Start and Stop time not specified!') self._log.info('The current time is: {0}. Start time is: {1}. ' 'Stop time is: {2}' .format(self.current_time, self._start, self._stop))
def test_parse_range(self): """ Test that the parse_range method returns the correct list of ints """ # test comma-delimited one_three_five_str = '1,3,5' one_three_five_lst = [1, 3, 5] result = TimeWindow.parse_range(one_three_five_str) self.assertEqual(one_three_five_lst, result, msg='Could not parse comma-delimeted str.') # test range one_to_three_str = '1-3' one_to_three_lst = [1, 2, 3] result = TimeWindow.parse_range(one_to_three_str) self.assertEqual(one_to_three_lst, result, msg='Could not parse range str.') # test mix of commas and ranges one_three_four_to_six_str = '1,3,4-6' one_three_four_to_six_lst = [1, 3, 4, 5, 6] result = TimeWindow.parse_range(one_three_four_to_six_str) self.assertEqual( one_three_four_to_six_lst, result, msg='Could not parse mix of comma-delimited and range str.') # test invalid range zero_to_10_str = '0-10' zero_to_6_lst = [0, 1, 2, 3, 4, 5, 6] result = TimeWindow.parse_range(zero_to_10_str) self.assertEqual(zero_to_6_lst, result) # test invalid single eleven_str = '11' empty_lst = [] result = TimeWindow.parse_range(eleven_str) self.assertEqual(empty_lst, result)
def test_parse_range(self): """ Test that the parse_range method returns the correct list of ints """ # test comma-delimited one_three_five_str = '1,3,5' one_three_five_lst = [1, 3, 5] result = TimeWindow.parse_range(one_three_five_str) self.assertEqual(one_three_five_lst, result, msg='Could not parse comma-delimeted str.') # test range one_to_three_str = '1-3' one_to_three_lst = [1, 2, 3] result = TimeWindow.parse_range(one_to_three_str) self.assertEqual(one_to_three_lst, result, msg='Could not parse range str.') # test mix of commas and ranges one_three_four_to_six_str = '1,3,4-6' one_three_four_to_six_lst = [1, 3, 4, 5, 6] result = TimeWindow.parse_range(one_three_four_to_six_str) self.assertEqual(one_three_four_to_six_lst, result, msg='Could not parse mix of comma-delimited and range str.') # test invalid range zero_to_10_str = '0-10' zero_to_6_lst = [0, 1, 2, 3, 4, 5, 6] result = TimeWindow.parse_range(zero_to_10_str) self.assertEqual(zero_to_6_lst, result) # test invalid single eleven_str = '11' empty_lst = [] result = TimeWindow.parse_range(eleven_str) self.assertEqual(empty_lst, result)
def test_process_met_end(self): """ Test _process_met method when setting 'end' parameter """ m = mox.Mox() midnight = '00:00:00' one = '01:00:00' p1 = TimeWindow('test', begin=None, end=one, weekdays=None, parent=None, interval=0.1) p2 = TimeWindow('test', begin=None, end=midnight, weekdays=None, parent=None, interval=0.1) mid_time = datetime.datetime.strptime(midnight, '%H:%M:%S').time() one_time = datetime.datetime.strptime(one, '%H:%M:%S').time() m.StubOutWithMock(p1, '_get_comparison') p1._get_comparison(p1.end).AndReturn(mid_time) # pretend it's midnight m.StubOutWithMock(p2, '_get_comparison') p2._get_comparison(p2.end).AndReturn(one_time) # pretend it's one m.ReplayAll() p1._process_met() p2._process_met() # should be 'met' if end is one and it is midnight self.assertEqual(p1.met, True) # should not be 'met' if end is midnight and it is one self.assertEqual(p2.met, False) m.VerifyAll() m.UnsetStubs()
def test_process_met_weekdays(self): """ Test _process_met method when setting weekdays parameter """ m = mox.Mox() m_to_fri = '0-4' p1 = TimeWindow('test', begin=None, end=None, weekdays=m_to_fri, parent=None, interval=0.1) p2 = TimeWindow('test', begin=None, end=None, weekdays=m_to_fri, parent=None, interval=0.1) m.StubOutWithMock(p1, 'weekday') p1.weekday().AndReturn(1) # pretend it's Tuesday m.StubOutWithMock(p2, 'weekday') p2.weekday().AndReturn(6) # pretend it's Sunday m.ReplayAll() p1._process_met() p2._process_met() # should be 'met' if weekdays = mon-fri and it is Tuesday self.assertEqual(p1.met, True) # should not be 'met' if weekdays = mon-fri and it is Sunday self.assertEqual(p2.met, False) m.VerifyAll() m.UnsetStubs()
def _parse_dependencies(self, action): """ Parse dependencies out of XML :type action: xml.etree.ElementTree.Element :rtype: list """ # TODO: rename 'path' when it really isn't a path. this is a hack... # prev_was_not keeps track of whether the outer class was 'not' dependencies = [] prev_was_not = False for predicate in action.iter('Predicate'): pred_type = predicate.get('type').lower() pred_path = predicate.get('path', None) # pred_oper = predicate.get('operational', False) pred_oper = bool( verify_attribute(predicate, 'operational', none_allowed=True)) if pred_type == PredicateType.ZOOKEEPERHASCHILDREN: dependencies.append({ 'type': pred_type, 'path': pred_path, 'operational': pred_oper }) prev_was_not = False elif pred_type == PredicateType.ZOOKEEPERHASGRANDCHILDREN: dependencies.append({ 'type': pred_type, 'path': pred_path, 'operational': pred_oper }) prev_was_not = False elif pred_type == PredicateType.ZOOKEEPERGOODUNTILTIME: if len(pred_path.split('gut/')) > 1: dependencies.append({ 'type': pred_type, 'path': ("I should be up between: {0}".format( pred_path.split("gut/")[1])), 'operational': pred_oper }) else: logging.debug('Invalid GUT path: {0}'.format(pred_path)) prev_was_not = False elif pred_type == PredicateType.HOLIDAY: dependencies.append({ 'type': pred_type, 'path': ("Does NOT run on holidays" if prev_was_not else "Runs on holidays"), 'operational': pred_oper }) prev_was_not = False elif pred_type == PredicateType.WEEKEND: dependencies.append({ 'type': pred_type, 'path': ("Does NOT run on weekends" if prev_was_not else "Runs on weekends"), 'operational': pred_oper }) prev_was_not = False elif pred_type == PredicateType.TIMEWINDOW: begin = predicate.get('begin', None) end = predicate.get('end', None) weekdays = predicate.get('weekdays', None) msg = 'I should be up ' if begin is not None: msg += 'after: {0} '.format(begin) if end is not None: msg += 'until: {0}'.format(end) # only send dependency if there is something to send if begin is not None or end is not None: dependencies.append({ 'type': pred_type, 'path': msg, 'operational': pred_oper }) # pretend this is a weekend predicate for convenience if weekdays is not None: day_range = TimeWindow.parse_range(weekdays) if Weekdays.SATURDAY in day_range or Weekdays.SUNDAY in day_range: wk_msg = 'Runs on weekends' else: wk_msg = 'Does NOT run on weekends' dependencies.append({ 'type': PredicateType.WEEKEND, 'path': wk_msg, 'operational': pred_oper }) elif pred_type == PredicateType.NOT: prev_was_not = True return dependencies
def create(self, xmlpart, callback=None, parent=None): """ :type xmlpart: xml.etree.ElementTree.Element :type callback: types.FunctionType or None :type parent: str or None """ if xmlpart is None: # A dummy predicate will be returned if there are no predicates # met is true b/c we don't want to block on no predicates return create_dummy(comp=self._component_name, parent=self._action, met=True) if isinstance(xmlpart, str): root = ElementTree.fromstring(xmlpart) else: root = xmlpart if parent is None: parent = self._action ptype = verify_attribute(root, 'type').lower() operational = bool( verify_attribute(root, 'operational', none_allowed=True)) if ptype == 'simple': return self._ensure_new(SimplePredicate(self._component_name, operational=operational, parent=parent), callback=callback) elif ptype == PredicateType.ZOOKEEPERNODEEXISTS: return self._ensure_new(ZookeeperNodeExists( self._component_name, self.zkclient, verify_attribute(root, 'path'), operational=operational, parent=parent), callback=callback) elif ptype == PredicateType.ZOOKEEPERHASCHILDREN: return self._ensure_new(ZookeeperHasChildren( self._component_name, self.zkclient, verify_attribute(root, 'path'), ephemeral_only=verify_attribute(root, 'ephemeral_only', none_allowed=True, default=True), operational=operational, parent=parent), callback=callback) elif ptype == PredicateType.ZOOKEEPERHASGRANDCHILDREN: return self._ensure_new(ZookeeperHasGrandChildren( self._component_name, self.zkclient, verify_attribute(root, 'path'), ephemeral_only=verify_attribute(root, 'ephemeral_only', none_allowed=True, default=True), operational=operational, parent=parent), callback=callback) elif ptype == PredicateType.ZOOKEEPERGLOB: return self._ensure_new(ZookeeperGlob( self._component_name, self.zkclient, verify_attribute(root, 'path'), ephemeral_only=verify_attribute(root, 'ephemeral_only', none_allowed=True, default=True), operational=operational, parent=parent), callback=callback) elif ptype == PredicateType.ZOOKEEPERGOODUNTILTIME: return self._ensure_new(ZookeeperGoodUntilTime( self._component_name, self.zkclient, verify_attribute(root, 'path'), operational=operational, parent=parent), callback=callback) elif ptype == PredicateType.PROCESS: return self._ensure_new(PredicateProcess(self._component_name, self._proc_client, verify_attribute( root, 'interval', cast=float), operational=operational, parent=parent), callback=callback) elif ptype == PredicateType.API: return self._ensure_new(APIPredicate( self._component_name, verify_attribute(root, 'url'), verb=verify_attribute(root, 'verb', none_allowed=True, default='GET'), expected_code=verify_attribute(root, 'expected_code', none_allowed=True, cast=int, default=200), interval=verify_attribute(root, 'interval', cast=float), operational=operational, parent=parent), callback=callback) elif ptype == PredicateType.HEALTH: return self._ensure_new(PredicateHealth( self._component_name, verify_attribute(root, 'command'), verify_attribute(root, 'interval', cast=float), self._system, operational=operational, parent=parent), callback=callback) elif ptype == PredicateType.HOLIDAY: return self._ensure_new(PredicateHoliday(self._component_name, self.zkclient, path=self._holiday_path, operational=operational, parent=parent), callback=callback) elif ptype == PredicateType.WEEKEND: return self._ensure_new(PredicateWeekend(self._component_name, operational=operational, parent=parent), callback=callback) elif ptype == PredicateType.TIMEWINDOW: return self._ensure_new(TimeWindow( self._component_name, begin=verify_attribute(root, 'begin', none_allowed=True), end=verify_attribute(root, 'end', none_allowed=True), weekdays=verify_attribute(root, 'weekdays', none_allowed=True), operational=operational, parent=parent), callback=callback) # below, use recursion to get nested predicates elif ptype == PredicateType.NOT: for element in root.findall('Predicate'): dep = self.create(element, callback=callback) return self._ensure_new( PredicateNot(self._component_name, dep, parent=self._parent_name(parent, 'not'))) elif ptype == PredicateType.AND: deps = list() for element in root.findall('Predicate'): deps.append( self.create(element, callback=callback, parent=self._parent_name(parent, 'and'))) return self._ensure_new( PredicateAnd(self._component_name, deps, parent=parent)) elif ptype == PredicateType.OR: deps = list() for element in root.findall('Predicate'): deps.append( self.create(element, callback=callback, parent=self._parent_name(parent, 'or'))) return self._ensure_new( PredicateOr(self._component_name, deps, parent=parent)) else: self._log.error( 'Unknown predicate type "{0}". Ignoring'.format(ptype)) # create dummy if it is an unknown predicate type. # met is set to true b/c we don't want to block on error return create_dummy(comp=self._component_name, parent=self._action, met=True)