def test_loading_variables_after_services(self): ''' Test parsing of a Yaml flow with variables referenced before their definition in another file. ''' self.cfg.load_from_stream(''' services: S1: desc: "I'm the service S1" target: "%TARGET_VAR" actions: start: cmd: echo %LUSTRE_FS_LIST --- variables: TARGET_VAR: foo LUSTRE_FS_LIST: store0,work0''') self.cfg.build_graph() srv = service_manager_self().entities['S1'] self.assertTrue('LUSTRE_FS_LIST' in service_manager_self().variables) self.assertTrue('TARGET_VAR' in service_manager_self().variables) self.assertEqual(str(srv.target), "foo") self.assertEqual(srv._actions['start'].command, "echo %LUSTRE_FS_LIST") self.assertTrue(len(self.cfg._flow) == 2)
def test_execute_unknown_exception(self): """CLI return '12' if an unknown exception is raised.""" service_manager_self().call_services = None self._output_check(['S2', 'start'], RC_UNKNOWN_EXCEPTION, "", """[00:00:00] ERROR - Unexpected Exception : 'NoneType'"""\ """ object is not callable """)
def test_parse_with_services_syntax(self): '''Test loading with empty YAML document in flow.''' self.cfg.load_from_stream('''--- services: foo[1-2]: desc: "this is desc" require: [ 'bar' ] actions: start: cmd: run %NAME bar: actions: start: cmd: run_bar''') self.cfg.build_graph() # Get back the manager manager = service_manager_self() self.assertTrue('foo1' in manager.entities) self.assertTrue('foo2' in manager.entities) self.assertTrue('bar' in manager.entities) self.assertTrue(manager.entities['foo1'].has_action('start')) self.assertTrue(manager.entities['foo1'].has_parent_dep('bar')) self.assertTrue(manager.entities['foo2'].has_action('start')) self.assertTrue(manager.entities['foo2'].has_parent_dep('bar')) self.assertTrue(manager.entities['bar'].has_action('start'))
def test_ScannerError_output(self): '''Test command line output on ScannerError''' service_manager_self().call_services = \ lambda services, action, conf=None: raiser(ScannerError) self._output_check(['start'], RC_EXCEPTION, '''''', '''[00:00:00] ERROR - ''')
def test_KeyboardInterrupt_output(self): '''Test command line output on KeybordInterrupt''' service_manager_self().call_services = \ lambda services, action, conf=None : raiser(KeyboardInterrupt) self._output_check(['start'], (128 + SIGINT), '''''', '''[00:00:00] ERROR - Keyboard Interrupt ''')
def test_UnhandledException_output(self): '''Test command line output on UnhandledException''' service_manager_self().call_services = \ lambda services, action, conf=None: raiser(ZeroDivisionError) self._output_check(['start'], RC_UNKNOWN_EXCEPTION, '''''', '''[00:00:00] ERROR - Unexpected Exception : ''')
def test_empty_only_nodes(self): '''Test_apply_config with empty nodeset in only_nodes''' empty_ns = NodeSet() manager = service_manager_self() s1 = Service('S1', target = NodeSet("localhost")) manager.register_services(s1) conf = {'only_nodes': empty_ns} manager._apply_config(conf) self.assertEqual(s1.target, empty_ns)
def test_remove_variable(self): '''Remove a variable, defined or not, is fine.''' manager = service_manager_self() manager.add_var('var', 'foo') self.assertEqual(manager.variables['var'], 'foo') # Remove it manager.remove_var('var') self.assertTrue('foo' not in manager.variables)
def test_ActionNotFound_output(self): '''Test command line output on ActionNotFound''' service_manager_self().call_services = \ lambda services, action, conf=None: raiser( ActionNotFoundError("Test", "Debug")) self._output_check(['start'], RC_EXCEPTION, '''''', '''[00:00:00] ERROR - Action [Debug] not referenced for [Test] ''')
def retcode(self): ''' Determine a retcode from a the last point of the graph RC_OK = 0: Everything went as we expected RC_WARNING = 3: At least one service status is WARNING and all others status is OK RC_ERROR = 6: At least one service status is ERROR Handled by self.execute : RC_EXCEPTION = 9: User error (options or configuration) RC_UNKNOWN_EXCEPTION = 12: Internal error (this is probably a bug) ''' if service_manager_self().source.status in (DEP_ERROR, ERROR): return RC_ERROR elif service_manager_self().has_warnings(): return RC_WARNING else: return RC_OK
def test_empty_excluded_nodes(self): '''Test _apply_config with empty nodeset in excluded_nodes''' localhost_ns = NodeSet("localhost") manager = service_manager_self() s1 = Service('S1', target = localhost_ns) manager.register_services(s1) conf = {'excluded_nodes': NodeSet()} manager._apply_config(conf) self.assertEqual(s1.target, localhost_ns)
def setUp(self): ConfigParser.DEFAULT_FIELDS['config_dir']['value'] = '' ConfigParser.CONFIG_PATH = '/dev/null' ServiceManager._instance = None self.manager = service_manager_self() ActionManager._instance = None # Setup stdout and stderr as a MyOutput file sys.stdout = MyOutput() sys.stderr = MyOutput()
def _lookup_variable(self, varname): ''' Return the value of the specified variable name. If is not found in current object, it searches recursively in the parent object. If it cannot solve the variable name, it raises UndefinedVariableError. ''' from MilkCheck.ServiceManager import service_manager_self if varname in self.variables: return self.variables[varname] elif varname.upper() in self.LOCAL_VARIABLES: value = self.LOCAL_VARIABLES[varname.upper()] return self.resolve_property(value) elif self.parent: return self.parent._lookup_variable(varname) elif varname in service_manager_self().variables: return service_manager_self().variables[varname] else: raise UndefinedVariableError(varname)
def test_call_services_reversed(self): '''Test service_manager with custom reversed actions''' manager = service_manager_self() s1 = Service('S1') s2 = Service('S2') s1.add_action(Action('wait', command='/bin/true')) s2.add_action(Action('wait', command='/bin/true')) s1.add_dep(s2) manager.register_services(s1, s2) manager.call_services(['S1'], 'wait', conf={"reverse_actions": ['wait']}) self.assertTrue(s1._algo_reversed) self.assertTrue(s2._algo_reversed)
def test_service_registration(self): '''Test the resgistration of a service within the manager''' manager = service_manager_self() srvtest = Service('test') manager.register_service(srvtest) self.assertTrue(manager.has_service(srvtest)) self.assertRaises(ServiceAlreadyReferencedError, manager.register_service, Service('test')) srva = Service('A') srvb = Service('B') manager.register_services(srva, srvb) self.assertTrue(manager.has_service(srva)) self.assertTrue(manager.has_service(srvb))
def test_graph(self): '''Test DOT graph output''' manager = service_manager_self() sergrp = ServiceGroup('S1') sergrp.fromdict( {'services': {'srv1': {'target': 'localhost', 'actions': {'start': {'cmd':'/bin/True'}, 'stop': {'cmd': '/bin/False'}}, 'desc': "I'm the service srv1" }, 'subgroup': {'services': {'svcB': {'require_weak':['svcC'], 'actions': {'start': {'cmd': '/bin/True'}, ' stop': {'cmd': '/bin/False'}}, 'desc': 'I am the subservice $NAME'}, 'svcC': {'actions': {'start': {'cmd': '/bin/True'}, 'stop': {'cmd': '/bin/False'}}, 'desc': 'I am the subservice $NAME'}}, 'target': '127.0.0.1', 'desc': "I'm the service $NAME"}}, }) manager.register_services(sergrp) self.assertEqual(manager.output_graph(), """digraph dependency { compound=true; node [style=filled]; subgraph "cluster_S1" { label="S1"; style=rounded; node [style=filled]; "S1.__hook" [style=invis]; "S1.srv1"; subgraph "cluster_S1.subgroup" { label="S1.subgroup"; style=rounded; node [style=filled]; "S1.subgroup.__hook" [style=invis]; "S1.subgroup.svcB" -> "S1.subgroup.svcC" [style=dashed]; "S1.subgroup.svcC"; } } } """)
def test_building_graph(self): '''Test graph building from configuration''' dty = '../tests/MilkCheckTests/ConfigTests/YamlTestFiles/sample_1/' self.cfg.load_from_dir(dty) self.cfg._build_services() # Get back the manager manager = service_manager_self() self.assertTrue('S1' in manager.entities) self.assertTrue('S2' in manager.entities) self.assertTrue('S3' in manager.entities) self.assertTrue('S4' in manager.entities) self.assertTrue(manager.entities['S1'].has_parent_dep('S2')) self.assertTrue(manager.entities['S1'].has_parent_dep('S3')) self.assertTrue(manager.entities['S3'].has_parent_dep('S4')) self.assertTrue(manager.entities['S2'].has_parent_dep('S4')) self.assertTrue(manager.entities['S4'].has_parent_dep('G1'))
def test_call_services_reversed_multiple(self): '''Test service_manager with multiple custom reversed actions''' manager = service_manager_self() s1 = Service('S1') s2 = Service('S2') s1.add_action(Action('stop', command='/bin/true')) s2.add_action(Action('wait', command='/bin/true')) manager.register_services(s1, s2) actions = ['stop', 'wait'] for act in actions: s1._algo_reversed = False s2._algo_reversed = False manager.call_services(['S1'], act, conf={"reverse_actions": actions}) self.assertTrue(s1._algo_reversed) self.assertTrue(s2._algo_reversed)
def test_call_services_retcode6(self): '''Test call_services return 6 whether source is DEP_ERROR''' manager = service_manager_self() s1 = Service('S1') s2 = Service('S2') s3 = Service('S3') s4 = Service('S4') s1.add_action(Action('start', command='/bin/true')) s2.add_action(Action('start', command='/bin/false')) s3.add_action(Action('start', command='/bin/true')) s4.add_action(Action('start', command='/bin/true')) s1.add_dep(target=s2) s2.add_dep(target=s3) s2.add_dep(target=s4) manager.register_services(s1, s2, s3, s4) manager.call_services([], 'start') self.assertTrue(manager.source.status in (ERROR, DEP_ERROR))
def test_call_services_parallelism(self): '''Test services parallelism''' manager = service_manager_self() s1 = Service('S1') s2 = Service('S2') s1.add_action(Action('wait', command='/bin/sleep 0.5')) s2.add_action(Action('wait', command='/bin/sleep 0.5')) manager.register_services(s1, s2) elapsed = time.time() manager.call_services(['S1', 'S2'], 'wait') elapsed = time.time() - elapsed self.assertTrue(elapsed < 0.7, 'Time elapsed too high (%f)' % elapsed) self.assertTrue(manager.source.status not in (ERROR, DEP_ERROR, WARNING)) self.assertEqual(s1.status, DONE) self.assertEqual(s2.status, DONE)
def test_call_services_retcode_weak(self): '''Test call_services return 0 (OK) even with require_weak''' manager = service_manager_self() s1 = Service('S1') s2 = Service('S2') s3 = Service('S3') s4 = Service('S4') s1.add_action(Action('start', command='/bin/true')) s2.add_action(Action('start', command='/bin/false')) s3.add_action(Action('start', command='/bin/true')) s4.add_action(Action('start', command='/bin/true')) s1.add_dep(target=s2, sgth=REQUIRE_WEAK) s2.add_dep(target=s3) s2.add_dep(target=s4) manager.register_services(s1, s2, s3, s4) manager.call_services([], 'start') self.assertEqual(manager.source.status, DONE)
def test_set_variables_before_configuration_parsing(self): ''' Test parsing of Yaml flow with variables prevously defined ''' manager = service_manager_self() manager.add_var('MY_VAR', 'bar') self.cfg.load_from_stream(''' variables: MY_VAR: foo --- services: S1: desc: "I'm the service S1" actions: start: cmd: echo %MY_VAR''') self.cfg.build_graph() self.assertTrue(manager.variables['MY_VAR'] == 'bar')
def test_after_rule_parsing(self): """'after' is supported in configuration""" self.cfg.load_from_stream(''' services: foo: actions: start: cmd: run %NAME bar: after: [ 'foo' ] actions: start: cmd: run_bar''') self.cfg.build_graph() manager = service_manager_self() self.assertTrue('foo' in manager.entities) self.assertTrue('bar' in manager.entities) self.assertTrue(manager.entities['bar'].has_parent_dep('foo'))
def test_forget_service(self): '''The how the manager forgets a service properly''' manager = service_manager_self() s1 = Service('S1') s2 = Service('S2') s3 = Service('S3') s4 = Service('S4') s1.add_dep(target=s2) s2.add_dep(target=s3) s2.add_dep(target=s4) manager.register_services(s1, s2, s3, s4) manager.forget_service(s1) self.assertFalse(manager.has_service(s1)) self.assertFalse(s1.has_parent_dep('S2')) self.assertFalse(s2.has_child_dep('S1')) manager.forget_services(s2, s4) self.assertFalse(manager.has_service(s2)) self.assertFalse(manager.has_service(s4)) self.assertFalse(s4.has_child_dep('S3')) self.assertFalse(s3.has_parent_dep('S4'))
def test_call_services_case_errors(self): '''Test errors generated by call_services''' manager = service_manager_self() s1 = Service('S1') s2 = Service('S2') s3 = Service('S3') s4 = Service('S4') s1.add_action(Action('start', command='%TARGET')) s2.add_action(Action('start', command='/bin/true')) s3.add_action(Action('start', command='/bin/true')) s4.add_action(Action('start', command='/bin/true')) s1.add_dep(target=s2) s2.add_dep(target=s3) s2.add_dep(target=s4) manager.register_services(s1, s2, s3, s4) self.assertRaises(AssertionError, manager.call_services, None, None) self.assertRaises(ServiceNotFoundError, manager.call_services, ['S8'], 'start') self.assertRaises(ServiceNotFoundError, manager.call_services, ['S2', 'S8'], 'start')
def test_graph_service_exlcude(self): """Test the DOT graph output with excluded nodes""" ''' Graph: E3 -> E2 -> E1 -> D0 `-> D1 ''' manager = service_manager_self() entd0 = Service('D0') entd1 = Service('D1') ente1 = Service('E1') ente2 = Service('E2') ente3 = Service('E3') ente3.add_dep(ente2) ente2.add_dep(ente1) ente1.add_dep(entd0) ente1.add_dep(entd1) manager.register_services(entd0, entd1, ente1, ente2, ente3) self.assertEqual(manager.output_graph(excluded=['E2']), """digraph dependency { compound=true; node [style=filled]; "E1" -> "D0"; "E1" -> "D1"; "D0"; "D1"; } """) self.assertEqual(manager.output_graph(excluded=['D0']), """digraph dependency { compound=true; node [style=filled]; "D1"; } """) self.assertEqual(manager.output_graph(excluded=['D0', 'D1']), """digraph dependency { compound=true; node [style=filled]; } """)
def test_deps_between_top_services(self): '''Deps between 2 services in top "services" section are ok''' self.cfg.load_from_stream(''' services: foo: actions: start: cmd: run %NAME --- services: bar: require: [ 'foo' ] actions: start: cmd: run_bar''') self.cfg.build_graph() manager = service_manager_self() self.assertTrue('foo' in manager.entities) self.assertTrue('bar' in manager.entities) self.assertTrue(manager.entities['foo'].has_action('start')) self.assertTrue(manager.entities['bar'].has_action('start')) self.assertTrue(manager.entities['bar'].has_parent_dep('foo'))
def test_call_services_case2(self): '''Test call of required services (start S3, S4)''' manager = service_manager_self() s1 = Service('S1') s2 = Service('S2') s3 = Service('S3') s4 = Service('S4') s1.add_action(Action('start', command='/bin/true')) s2.add_action(Action('start', command='/bin/true')) s3.add_action(Action('start', command='/bin/true')) s4.add_action(Action('start', command='/bin/true')) s1.add_dep(target=s2) s2.add_dep(target=s3) s2.add_dep(target=s4) manager.register_services(s1, s2, s3, s4) manager.call_services(['S3','S4'], 'start') self.assertTrue(manager.source.status not in (ERROR, DEP_ERROR, WARNING)) self.assertEqual(s1.status, NO_STATUS) self.assertEqual(s2.status, NO_STATUS) self.assertEqual(s3.status, DONE) self.assertEqual(s4.status, DONE)
def test_InvalidOptionError_output(self): '''Test command line output on InvalidOption''' service_manager_self().call_services = \ lambda services, action, conf=None: raiser(InvalidOptionError) self._output_check(['start'], RC_EXCEPTION, '''Usage: nosetests [options] [SERVICE...] ACTION Options: --version show program's version number and exit -h, --help show this help message and exit -v, --verbose Increase or decrease verbosity -d, --debug Set debug mode and maximum verbosity -g, --graph Output dependencies graph -s, --summary Display summary of executed actions -c CONFIG_DIR, --config-dir=CONFIG_DIR Change configuration files directory -q, --quiet Enable quiet mode Engine parameters: Those options allow you to configure the behaviour of the engine -n ONLY_NODES, --only-nodes=ONLY_NODES Use only the specified nodes -x EXCLUDED_NODES, --exclude-nodes=EXCLUDED_NODES Exclude the cluster's nodes specified -X EXCLUDED_SVC, --exclude-service=EXCLUDED_SVC Skip the specified services --dry-run Only simulate command execution -D DEFINES, --define=DEFINES, --var=DEFINES Define custom variables --nodeps Do not run dependencies ''', '''[00:00:00] CRITICAL - Invalid options: [00:00:00] CRITICAL - Invalid options: ''')
def test_UnhandledExceptionDebug_output(self): '''Test command line output on UnhandledException in debug mode''' service_manager_self().call_services = \ lambda services, action, conf=None: raiser(ZeroDivisionError) self._output_check(['start', '-d'], RC_UNKNOWN_EXCEPTION, '''Traceback (most recent call last): File "source.py", line 000, in execute manager.call_services(services, action, conf=self._conf) File "source.py", line 000, in <lambda> lambda services, action, conf=None: raiser(ZeroDivisionError) File "source.py", line 000, in raiser raise exception ZeroDivisionError ''', '''[00:00:00] DEBUG - Configuration nodeps: False dryrun: False verbosity: 5 summary: False fanout: 64 reverse_actions: ['stop'] debug: True config_dir: ''')
def tearDown(self): service_manager_self().reset()
def tearDown(self): '''Restore ServiceManager''' CLICommon.tearDown(self) service_manager_self().call_services = self.call_services_backup
def setUp(self): ''' Set up mocking to test exceptions ''' CLICommon.setUp(self) self.call_services_backup = service_manager_self().call_services