def test_bootstrap(self): """ Verify Transport().bootstrap works as expected. """ with patch('commissaire.transport.ansibleapi.TaskQueueManager') as _tqm: _tqm().run.return_value = 0 transport = ansibleapi.Transport() transport.variable_manager._fact_cache = {} oscmd = MagicMock(OSCmdBase) config = Config( etcd={ 'uri': urlparse('http://127.0.0.1:2379'), }, kubernetes={ 'uri': urlparse('http://127.0.0.1:8080'), 'token': 'token', } ) result, facts = transport.bootstrap( '10.2.0.2', 'test/fake_key', config, oscmd) # We should have a successful response self.assertEquals(0, result) # We should see expected calls self.assertEquals(1, oscmd.install_docker.call_count) self.assertEquals(1, oscmd.install_kube.call_count)
def test_bootstrap(self): """ Verify Transport().bootstrap works as expected. """ with patch( 'commissaire.transport.ansibleapi.TaskQueueManager') as _tqm: _tqm().run.return_value = 0 transport = ansibleapi.Transport() transport.variable_manager._fact_cache = {} oscmd = MagicMock(OSCmdBase) config = Config(etcd={ 'uri': urlparse('http://127.0.0.1:2379'), }, kubernetes={ 'uri': urlparse('http://127.0.0.1:8080'), 'token': 'token', }) result, facts = transport.bootstrap('10.2.0.2', 'test/fake_key', config, oscmd) # We should have a successful response self.assertEquals(0, result) # We should see expected calls self.assertEquals(1, oscmd.install_docker.call_count) self.assertEquals(1, oscmd.install_kube.call_count)
def test_bootstrap(self): """ Verify Transport().bootstrap works as expected. """ with patch( 'commissaire.transport.ansibleapi.TaskQueueManager') as _tqm: _tqm().run.return_value = 0 transport = ansibleapi.Transport() transport.variable_manager._fact_cache = {} oscmd = MagicMock(OSCmdBase) config = Config(etcd={ 'uri': urlparse('http://127.0.0.1:2379'), }, kubernetes={ 'uri': urlparse('http://127.0.0.1:8080'), 'token': 'token', }) result, facts = transport.bootstrap('10.2.0.2', 'test/fake_key', config, oscmd) # We should have a successful response self.assertEquals(0, result) # We should see expected calls self.assertEquals(1, oscmd.install_docker.call_count) self.assertEquals(1, oscmd.install_kube.call_count) # Check 'commissaire_enable_pkg_repos' playbook variable # for various operating systems. transport = ansibleapi.Transport() transport._run = MagicMock() transport._run.return_value = (0, {}) needs_enable_repos = ('redhat', 'rhel') for os_type in available_os_types: oscmd = get_oscmd(os_type) result, facts = transport.bootstrap('10.2.0.2.', 'test/fake_key', config, oscmd) play_vars = transport._run.call_args[0][4] command = play_vars['commissaire_enable_pkg_repos'] if os_type in needs_enable_repos: self.assertIn('subscription-manager repos', command) else: self.assertEqual('true', command) # no-op command
def test_bootstrap(self): """ Verify Transport().bootstrap works as expected. """ with patch('commissaire.transport.ansibleapi.TaskQueueManager') as _tqm: _tqm().run.return_value = 0 transport = ansibleapi.Transport() transport.variable_manager._fact_cache = {} oscmd = MagicMock(OSCmdBase) config = Config( etcd={ 'uri': urlparse('http://127.0.0.1:2379'), }, kubernetes={ 'uri': urlparse('http://127.0.0.1:8080'), 'token': 'token', } ) result, facts = transport.bootstrap( '10.2.0.2', 'test/fake_key', config, oscmd) # We should have a successful response self.assertEquals(0, result) # We should see expected calls self.assertEquals(1, oscmd.install_docker.call_count) self.assertEquals(1, oscmd.install_kube.call_count) # Check 'commissaire_enable_pkg_repos' playbook variable # for various operating systems. transport = ansibleapi.Transport() transport._run = MagicMock() transport._run.return_value = (0, {}) needs_enable_repos = ('redhat', 'rhel') for os_type in available_os_types: oscmd = get_oscmd(os_type) result, facts = transport.bootstrap( '10.2.0.2.', 'test/fake_key', config, oscmd) play_vars = transport._run.call_args[0][4] command = play_vars['commissaire_enable_pkg_repos'] if os_type in needs_enable_repos: self.assertIn('subscription-manager repos', command) else: self.assertEqual('true', command) # no-op command
def test_investigator(self): """ Verify the investigator. """ with mock.patch('commissaire.transport.ansibleapi.Transport') as _tp, \ mock.patch('etcd.Client.get') as _etcd_get, \ mock.patch('etcd.Client.write') as _etcd_write: _tp().get_info.return_value = ( 0, { 'os': 'fedora', 'cpus': 2, 'memory': 11989228, 'space': 487652, } ) q = Queue() _etcd_get.return_value = MagicMock( 'etcd.EtcdResult', value=self.etcd_host) to_investigate = { 'address': '10.0.0.2', } ssh_priv_key = 'dGVzdAo=' connection_config = { 'etcd': { 'uri': urlparse('http://127.0.0.1:2379'), }, 'kubernetes': { 'uri': urlparse('http://127.0.0.1:8080'), 'token': 'token', } } q.put_nowait((to_investigate, ssh_priv_key, 'root')) investigator(q, connection_config, run_once=True) self.assertEquals(1, _etcd_get.call_count) self.assertEquals(2, _etcd_write.call_count)
def test_investigator(self): """ Verify the investigator. """ with contextlib.nested( mock.patch('cherrypy.engine.publish'), mock.patch('commissaire.transport.ansibleapi.Transport'), mock.patch('etcd.Client')) as (_publish, _tp, _store): _tp().get_info.return_value = ( 0, { 'os': 'fedora', 'cpus': 2, 'memory': 11989228, 'space': 487652, } ) q = Queue() _publish.return_value = [[ MagicMock('etcd.EtcdResult', value=self.etcd_host), None]] to_investigate = { 'address': '10.0.0.2', } ssh_priv_key = 'dGVzdAo=' connection_config = { 'etcd': { 'uri': urlparse('http://127.0.0.1:2379'), }, 'kubernetes': { 'uri': urlparse('http://127.0.0.1:8080'), 'token': 'token', } } q.put_nowait((to_investigate, ssh_priv_key)) investigator(q, connection_config, True) self.assertEquals(3, _publish.call_count)
def test_investigator(self): """ Verify the investigator. """ with mock.patch('commissaire.transport.ansibleapi.Transport') as _tp: _tp().get_info.return_value = ( 0, { 'os': 'fedora', 'cpus': 2, 'memory': 11989228, 'space': 487652, } ) q = Queue() to_investigate = { 'address': '10.0.0.2', } ssh_priv_key = 'dGVzdAo=' connection_config = { 'etcd': { 'uri': urlparse('http://127.0.0.1:2379'), }, 'kubernetes': { 'uri': urlparse('http://127.0.0.1:8080'), 'token': 'token', } } manager = MagicMock(StoreHandlerManager) manager.get.return_value = Host(**json.loads(self.etcd_host)) q.put_nowait((manager, to_investigate, ssh_priv_key, 'root')) investigator(q, connection_config, run_once=True) self.assertEquals(1, manager.get.call_count) self.assertEquals(2, manager.save.call_count)
def test_investigator(self): """ Verify the investigator. """ with mock.patch('commissaire.transport.ansibleapi.Transport') as _tp: _tp().get_info.return_value = (0, { 'os': 'fedora', 'cpus': 2, 'memory': 11989228, 'space': 487652, }) q = Queue() client = etcd.Client() client.get = MagicMock('get') client.get.return_value = MagicMock(value=self.etcd_host) client.set = MagicMock('set') client.set.return_value = self.etcd_host to_investigate = { 'address': '10.0.0.2', } ssh_priv_key = 'dGVzdAo=' connection_config = { 'etcd': { 'uri': urlparse('http://127.0.0.1:2379'), }, 'kubernetes': { 'uri': urlparse('http://127.0.0.1:8080'), 'token': 'token', } } q.put_nowait((to_investigate, ssh_priv_key)) investigator(q, connection_config, client, True) self.assertEquals(1, client.get.call_count) self.assertEquals(2, client.set.call_count)
def test_investigator(self): """ Verify the investigator. """ with contextlib.nested( mock.patch('cherrypy.engine.publish'), mock.patch('commissaire.transport.ansibleapi.Transport'), mock.patch('etcd.Client')) as (_publish, _tp, _store): _tp().get_info.return_value = (0, { 'os': 'fedora', 'cpus': 2, 'memory': 11989228, 'space': 487652, }) q = Queue() _publish.return_value = [[ MagicMock('etcd.EtcdResult', value=self.etcd_host), None ]] to_investigate = { 'address': '10.0.0.2', } ssh_priv_key = 'dGVzdAo=' connection_config = { 'etcd': { 'uri': urlparse('http://127.0.0.1:2379'), }, 'kubernetes': { 'uri': urlparse('http://127.0.0.1:8080'), 'token': 'token', } } q.put_nowait((to_investigate, ssh_priv_key)) investigator(q, connection_config, True) self.assertEquals(3, _publish.call_count)
def test_node_registered(self): """ Verify that KuberContainerManager().node_registered() works as expected. """ config = Config( etcd={ 'uri': urlparse('http://127.0.0.1:2379'), }, kubernetes={ 'uri': urlparse('http://127.0.0.1:8080'), 'token': 'token', } ) kube_container_mgr = KubeContainerManager(config) # First call should return True. The rest should be False. kube_container_mgr.con = MagicMock() kube_container_mgr.con.get = MagicMock(side_effect=( MagicMock(status_code=200), MagicMock(status_code=404), MagicMock(status_code=500))) self.assertTrue(kube_container_mgr.node_registered('test')) self.assertFalse(kube_container_mgr.node_registered('test')) self.assertFalse(kube_container_mgr.node_registered('test'))
def check_config(cls, config): """ Examines the configuration parameters for a KubernetesStoreHandler and throws a ConfigurationError if any parameters are invalid. """ url = urlparse(config.get('server_url', cls.DEFAULT_SERVER_URL)) if (bool(config.get('certificate-path')) ^ bool(config.get('certificate-key-path'))): raise ConfigurationError( 'Both "certificate_path" and "certificate_key_path" ' 'must be provided to use a client side certificate') if config.get('certificate-path'): if url.scheme != 'https': raise ConfigurationError( 'Server URL scheme must be "https" when using client ' 'side certificates (got "{0}")'.format(url.scheme))
def __init__(self, config): """ Creates a new instance of EtcdStoreHandler. :param config: Configuration details :type config: dict """ url = urlparse(config.get('server_url', self.DEFAULT_SERVER_URL)) client_args = {'host': url.hostname, 'protocol': url.scheme} if url.port is not None: client_args['port'] = url.port if config.get('certificate-path'): client_args['cert'] = (config['certificate-path'], config['certificate-key-path']) self._store = etcd.Client(**client_args) self._etcd_namespace = '/commissaire'
def parse_uri(uri, name): """ Parses and returns a parsed URI. :param uri: The URI to parse. :type uri: str :param name: The name to use for errors. :type name: str :returns: A parsed URI. :rtype: ParseResult :raises: Exception """ parsed = urlparse(uri) # Verify we have what we need if not uri or None in (parsed.port, parsed.hostname, parsed.scheme): raise Exception( ('You must provide a full {0} URI. ' 'EX: http://127.0.0.1:2379'.format(name))) return parsed
""" import contextlib import etcd import mock import cherrypy from . import TestCase from commissaire.jobs.clusterexec import clusterexec from commissaire.config import Config from commissaire.compat.urlparser import urlparse from mock import MagicMock cherrypy.config['commissaire.config'] = Config( etcd={'uri': urlparse('http://127.0.0.1:2379')}) class Test_JobsClusterExec(TestCase): """ Tests for the clusterexec job. """ etcd_host = ('{"address": "10.2.0.2", "ssh_priv_key": "dGVzdAo=",' ' "status": "available", "os": "atomic",' ' "cpus": 2, "memory": 11989228, "space": 487652,' ' "last_check": "2015-12-17T15:48:18.710454", ' '"cluster": "default"}') etcd_cluster = '{"status": "ok", "hostset": ["10.2.0.2"]}'
def main(): # pragma: no cover """ Main script entry point. """ import argparse from commissaire.config import Config config = Config() epilog = ('Example: ./commissaire -e http://127.0.0.1:2379' ' -k http://127.0.0.1:8080') parser = argparse.ArgumentParser(epilog=epilog) parser.add_argument( '--listen-interface', '-i', type=str, help='Interface to listen on') parser.add_argument( '--listen-port', '-p', type=int, help='Port to listen on') parser.add_argument( '--etcd-uri', '-e', type=str, required=True, help='Full URI for etcd EX: http://127.0.0.1:2379') parser.add_argument( '--kube-uri', '-k', type=str, required=True, help='Full URI for kubernetes EX: http://127.0.0.1:8080') args = parser.parse_args() try: config.etcd['uri'] = parse_uri(args.etcd_uri, 'etcd') config.kubernetes['uri'] = parse_uri(args.kube_uri, 'kube') except Exception: _, ex, _ = exception.raise_if_not(Exception) parser.error(ex) ds = etcd.Client( host=config.etcd['uri'].hostname, port=config.etcd['uri'].port) try: logging.config.dictConfig( json.loads(ds.get('/commissaire/config/logger').value)) logging.info('Using Etcd for logging configuration.') except etcd.EtcdKeyNotFound: with open('./conf/logger.json', 'r') as logging_default_cfg: logging.config.dictConfig(json.loads(logging_default_cfg.read())) logging.warn('No logger configuration in Etcd. Using defaults.') except etcd.EtcdConnectionFailed: _, ecf, _ = exception.raise_if_not(etcd.EtcdConnectionFailed) err = 'Unable to connect to Etcd: {0}. Exiting ...'.format(ecf) logging.fatal(err) parser.error('{0}\n'.format(err)) raise SystemExit(1) interface = cli_etcd_or_default( 'listeninterface', args.listen_interface, '0.0.0.0', ds) port = cli_etcd_or_default('listenport', args.listen_port, 8000, ds) config.etcd['listen'] = urlparse('http://{0}:{1}'.format( interface, port)) try: config.kubernetes['token'] = ds.get( '/commissaire/config/kubetoken').value logging.debug('Config: {0}'.format(config)) POOLS['investigator'].spawn( investigator, INVESTIGATE_QUEUE, config, ds) except etcd.EtcdKeyNotFound: parser.error('"/commissaire/config/kubetoken" must be set in etcd!') # watch_thread = gevent.spawn(host_watcher, ROUTER_QUEUE, ds) # router_thread = gevent.spawn(router, ROUTER_QUEUE) app = create_app(ds) try: WSGIServer((interface, int(port)), app).serve_forever() except KeyboardInterrupt: pass POOLS['investigator'].kill()