def test_failure_roles_not_a_list(self): stderr = MagicMock() tmpdir, bundle_file = create_temp_bundle( strip_margin("""|nrOfCpus = {} |memory = {} |diskSpace = {} |roles = {} |""").format(self.nr_of_cpus, self.memory, self.disk_space, '-'.join(self.roles))) resolve_bundle_mock = MagicMock(return_value=(self.bundle_file_name, bundle_file)) with patch('conductr_cli.resolver.resolve_bundle', resolve_bundle_mock): args = self.default_args.copy() args.update({'bundle': bundle_file}) logging_setup.configure_logging(MagicMock(**args), err_output=stderr) result = conduct_load.load(MagicMock(**args)) self.assertFalse(result) resolve_bundle_mock.assert_called_with(self.custom_settings, self.bundle_resolve_cache_dir, bundle_file, self.offline_mode) self.assertEqual( as_error( strip_margin("""|Error: Unable to parse bundle.conf. |Error: roles has type 'str' rather than 'list'. |""")), self.output(stderr)) shutil.rmtree(tmpdir)
def test_failure_roles_not_a_list(self): stderr = MagicMock() tmpdir, bundle_file = create_temp_bundle( strip_margin("""|nrOfCpus = {} |memory = {} |diskSpace = {} |roles = {} |""").format(self.nr_of_cpus, self.memory, self.disk_space, '-'.join(self.roles))) resolve_bundle_mock = MagicMock(return_value=(self.bundle_name, bundle_file)) with patch('conductr_cli.resolver.resolve_bundle', resolve_bundle_mock): args = self.default_args.copy() args.update({'bundle': bundle_file}) logging_setup.configure_logging(MagicMock(**args), err_output=stderr) result = conduct_load.load(MagicMock(**args)) self.assertFalse(result) resolve_bundle_mock.assert_called_with(self.custom_settings, self.bundle_resolve_cache_dir, bundle_file) self.assertEqual( as_error(strip_margin("""|Error: Unable to parse bundle.conf. |Error: roles has type 'str' rather than 'list'. |""")), self.output(stderr)) shutil.rmtree(tmpdir)
def test_cannot_stop_containers(self): stdout = MagicMock() stderr = MagicMock() mock_docker_rm = MagicMock( side_effect=CalledProcessError(-1, 'test only')) containers = ['cond-0', 'cond-1'] with patch('conductr_cli.sandbox_common.resolve_running_docker_containers', return_value=containers), \ patch('conductr_cli.terminal.docker_rm', mock_docker_rm): logging_setup.configure_logging(MagicMock(**self.default_args), stdout, stderr) sandbox_stop_docker.stop(MagicMock(**self.default_args)) self.assertEqual( strip_margin("""||------------------------------------------------| || Stopping ConductR | ||------------------------------------------------| |"""), self.output(stdout)) self.assertEqual( as_error( strip_margin( """|Error: ConductR containers could not be stopped |Error: Please stop the Docker containers manually |""")), self.output(stderr)) mock_docker_rm.assert_called_once_with(containers)
def test_failure_no_disk_space(self): stderr = MagicMock() tmpdir, bundle_file = create_temp_bundle( strip_margin( """|nrOfCpus = {} |memory = {} |roles = [{}] |""" ).format(self.nr_of_cpus, self.memory, ", ".join(self.roles)) ) resolve_bundle_mock = MagicMock(return_value=(self.bundle_file_name, bundle_file)) with patch("conductr_cli.resolver.resolve_bundle", resolve_bundle_mock): args = self.default_args.copy() args.update({"bundle": bundle_file}) logging_setup.configure_logging(MagicMock(**args), err_output=stderr) result = conduct_load.load(MagicMock(**args)) self.assertFalse(result) resolve_bundle_mock.assert_called_with(self.custom_settings, self.bundle_resolve_cache_dir, bundle_file) self.assertEqual( as_error( strip_margin( """|Error: Unable to parse bundle.conf. |Error: No configuration setting found for key diskSpace. |""" ) ), self.output(stderr), ) shutil.rmtree(tmpdir)
def test_ip(self): args = {} args.update(self.default_args) args.pop('host') args.update({'ip': '10.0.0.1'}) default_url = 'http://10.0.0.1:9005/bundles/{}/events?count=1'.format(self.bundle_id_urlencoded) http_method = self.respond_with(text='{}') quote_method = MagicMock(return_value=self.bundle_id_urlencoded) stdout = MagicMock() input_args = MagicMock(**args) with patch('requests.get', http_method), \ patch('urllib.parse.quote', quote_method): logging_setup.configure_logging(input_args, stdout) result = conduct_events.events(input_args) self.assertTrue(result) http_method.assert_called_with(default_url, auth=self.conductr_auth, verify=self.server_verification_file, timeout=DEFAULT_HTTP_TIMEOUT, headers={'Host': '10.0.0.1'}) self.assertEqual( strip_margin("""|TIME EVENT DESC |"""), self.output(stdout))
def default_output(self, command='conduct', params='', bundle_id='45e0c47', downloading_configuration='', verbose=''): return strip_margin(self.output_template.format(**{ 'command': command, 'params': params, 'bundle_id': bundle_id, 'downloading_configuration': downloading_configuration, 'verbose': verbose}))
def test_failure_no_bundle_conf(self): resolve_bundle_mock = MagicMock(return_value=(self.bundle_file_name, self.bundle_file)) conf_mock = MagicMock(return_value=None) stderr = MagicMock() with patch('conductr_cli.resolver.resolve_bundle', resolve_bundle_mock), \ patch('conductr_cli.bundle_utils.conf', conf_mock): args = self.default_args.copy() logging_setup.configure_logging(MagicMock(**args), err_output=stderr) result = conduct_load.load(MagicMock(**args)) self.assertFalse(result) resolve_bundle_mock.assert_called_with(self.custom_settings, self.bundle_resolve_cache_dir, self.bundle_file, self.offline_mode) self.assertEqual( as_error( strip_margin( """|Error: Problem with the bundle: Unable to find bundle.conf within the bundle file |""")), self.output(stderr)) conf_mock.assert_called_with(self.bundle_file)
def test_default_settings(self): stdout = MagicMock() is_tty_mock = MagicMock(return_value=True) stderr = MagicMock() logging_setup.configure_logging(MagicMock(), stdout, stderr) with patch('sys.stdout.isatty', is_tty_mock): log = logging.getLogger('conductr_cli') log.debug('this is debug') log.verbose('this is verbose') log.info('this is info') log.progress('this is progress', flush=True) log.quiet('this is quiet') log.warning('this is warning') log.error('this is error') log.screen('this is screen') self.assertFalse(log.is_debug_enabled()) self.assertFalse(log.is_verbose_enabled()) self.assertTrue(log.is_info_enabled()) self.assertTrue(log.is_progress_enabled()) self.assertTrue(log.is_quiet_enabled()) self.assertTrue(log.is_warn_enabled()) self.assertEqual( as_warn( strip_margin("""|this is info |this is progress |this is quiet |Warning: this is warning |this is screen |""")), self.output(stdout)) self.assertEqual(as_error('Error: this is error\n'), self.output(stderr))
def test_with_custom_args_v1(self): stdout = MagicMock() image_version = '1.1.0' conductr_roles = [['role1', 'role2']] envs = ['key1=value1', 'key2=value2'] image = 'my-image' log_level = 'debug' nr_of_containers = 1 ports = [3000, 3001] features = [['visualization'], ['logging']] with \ patch('conductr_cli.terminal.docker_images', return_value='some-image'), \ patch('conductr_cli.terminal.docker_ps', return_value=''), \ patch('conductr_cli.terminal.docker_inspect', return_value='10.10.10.10'), \ patch('conductr_cli.terminal.docker_run', return_value='') as mock_docker_run, \ patch('conductr_cli.sandbox_common.resolve_running_docker_containers', return_value=[]), \ patch('conductr_cli.sandbox_run.wait_for_conductr') as mock_wait_for_conductr: args = self.default_args.copy() args.update({ 'image_version': image_version, 'conductr_roles': conductr_roles, 'envs': envs, 'image': image, 'log_level': log_level, 'nr_of_containers': nr_of_containers, 'ports': ports, 'bundle_http_port': 7222, 'features': features }) input_args = MagicMock(**args) logging_setup.configure_logging(input_args, stdout) sandbox_run.run(input_args) expected_stdout = strip_margin("""||------------------------------------------------| || Starting ConductR | ||------------------------------------------------| |Starting container cond-0 exposing 127.0.0.1:3000, 127.0.0.1:3001, 127.0.0.1:5601, 127.0.0.1:9200, 127.0.0.1:9999.. ||------------------------------------------------| || Summary | ||------------------------------------------------| |ConductR has been started |Check resource consumption of Docker container that run the ConductR node with: | docker stats cond-0 |Check current bundle status with: | conduct info |""") self.assertEqual(expected_stdout, self.output(stdout)) mock_docker_run.assert_called_once_with( ['-d', '--name', 'cond-0', '-e', 'key1=value1', '-e', 'key2=value2', '-e', 'CONDUCTR_INSTANCE=0', '-e', 'CONDUCTR_NR_OF_INSTANCES=1', '-e', 'AKKA_LOGLEVEL=debug', '-e', 'CONDUCTR_FEATURES=visualization,logging', '-e', 'CONDUCTR_ROLES=role1,role2', '-p', '5601:5601', '-p', '9004:9004', '-p', '9005:9005', '-p', '9006:9006', '-p', '9999:9999', '-p', '9200:9200', '-p', '7222:7222', '-p', '3000:3000', '-p', '3001:3001'], '{}:{}'.format(image, image_version), self.default_positional_args ) mock_wait_for_conductr.assert_called_once_with(input_args, 0, DEFAULT_WAIT_RETRIES, DEFAULT_WAIT_RETRY_INTERVAL)
def base_test_failure_no_configuration(self): resolve_bundle_mock = MagicMock( side_effect=[(self.bundle_name, self.bundle_file), BundleResolutionError('some message')]) stdout = MagicMock() stderr = MagicMock() with patch('conductr_cli.resolver.resolve_bundle', resolve_bundle_mock): args = self.default_args.copy() args.update({'configuration': 'no_such.conf'}) logging_setup.configure_logging(MagicMock(**args), stdout, stderr) result = conduct_load.load(MagicMock(**args)) self.assertFalse(result) self.assertEqual(resolve_bundle_mock.call_args_list, [ call(self.custom_settings, self.bundle_resolve_cache_dir, self.bundle_file), call(self.custom_settings, self.bundle_resolve_cache_dir, 'no_such.conf') ]) self.assertEqual( as_error( strip_margin("""|Error: Bundle not found: some message |""")), self.output(stderr))
def test_stopped_bundle(self): request_headers_mock = MagicMock(return_value=self.mock_headers) http_method = self.respond_with(text="""[ { "attributes": { "bundleName": "test-bundle" }, "bundleId": "45e0c477d3e5ea92aa8d85c0d8f3e25c", "bundleExecutions": [], "bundleInstallations": [1] } ]""") stdout = MagicMock() input_args = MagicMock(**self.default_args) with patch('requests.get', http_method), \ patch('conductr_cli.conduct_url.request_headers', request_headers_mock): logging_setup.configure_logging(input_args, stdout) result = conduct_info.info(input_args) self.assertTrue(result) request_headers_mock.assert_called_with(input_args) http_method.assert_called_with(self.default_url, timeout=DEFAULT_HTTP_TIMEOUT, headers=self.mock_headers) self.assertEqual( strip_margin("""|ID NAME #REP #STR #RUN |45e0c47 test-bundle 1 0 0 |"""), self.output(stdout))
def test_one_running_one_starting_one_stopped(self): http_method = self.respond_with(text="""[ { "attributes": { "bundleName": "test-bundle-1" }, "bundleId": "45e0c477d3e5ea92aa8d85c0d8f3e25c", "bundleExecutions": [{"isStarted": true}], "bundleInstallations": [1] }, { "attributes": { "bundleName": "test-bundle-2" }, "bundleId": "45e0c477d3e5ea92aa8d85c0d8f3e25c-c52e3f8d0c58d8aa29ae5e3d774c0e54", "bundleExecutions": [{"isStarted": false}], "bundleInstallations": [1] }, { "attributes": { "bundleName": "test-bundle-3" }, "bundleId": "45e0c477d3e5ea92aa8d85c0d8f3e25c", "bundleExecutions": [], "bundleInstallations": [1] } ]""") stdout = MagicMock() with patch('requests.get', http_method), patch('sys.stdout', stdout): conduct_info.info(MagicMock(**self.default_args)) http_method.assert_called_with(self.default_url) self.assertEqual( strip_margin("""|ID NAME #REP #STR #RUN |45e0c47 test-bundle-1 1 0 1 |45e0c47-c52e3f8 test-bundle-2 1 1 0 |45e0c47 test-bundle-3 1 0 0 |"""), self.output(stdout))
def test_multiple_acls_sorted(self): request_headers_mock = MagicMock(return_value=self.mock_headers) http_method = self.respond_with_file_contents( 'data/bundle_with_acls/multiple_bundles_tcp.json') stdout = MagicMock() input_args = MagicMock(**self.default_args) with patch('requests.get', http_method), \ patch('conductr_cli.conduct_url.request_headers', request_headers_mock): logging_setup.configure_logging(input_args, stdout) result = conduct_acls.acls(input_args) self.assertTrue(result) request_headers_mock.assert_called_with(input_args) http_method.assert_called_with(self.default_url, timeout=DEFAULT_HTTP_TIMEOUT, headers=self.mock_headers) self.assertEqual( strip_margin( """|TCP/PORT SYSTEM SYSTEM VERSION ENDPOINT NAME BUNDLE ID BUNDLE NAME STATUS |7101 other-bundle-1.0.0 1.0.0 tunnel aaa4d64 other-bundle-1.0.0 Starting |9006 my-bundle-1.0.0 1.0.0 bin-one f804d64 my-bundle-1.0.0 Starting |19001 some-bundle-1.0.0 1.0.0 streamer bbb4d64 some-bundle-1.0.0 Starting |"""), self.output(stdout))
def test_one_bundle_starting_long_ids(self): request_headers_mock = MagicMock(return_value=self.mock_headers) http_method = self.respond_with_file_contents('data/bundle_with_services/one_bundle_starting.json') stdout = MagicMock() args = self.default_args.copy() args.update({'long_ids': True}) input_args = MagicMock(**args) with patch('requests.get', http_method), \ patch('conductr_cli.conduct_url.request_headers', request_headers_mock): logging_setup.configure_logging(input_args, stdout) result = conduct_services.services(input_args) self.assertTrue(result) request_headers_mock.assert_called_with(input_args) http_method.assert_called_with(self.default_url, timeout=DEFAULT_HTTP_TIMEOUT, headers=self.mock_headers) self.assertEqual( strip_margin( """|SERVICE BUNDLE ID BUNDLE NAME STATUS |http://:8010/comp1-endp1 f804d644a01a5ab9f679f76939f5c7e2 multi-comp-multi-endp-1.0.0 Starting |http://:8011/comp1-endp2 f804d644a01a5ab9f679f76939f5c7e2 multi-comp-multi-endp-1.0.0 Starting |http://:9010/comp2-endp1 f804d644a01a5ab9f679f76939f5c7e2 multi-comp-multi-endp-1.0.0 Starting |http://:9011/comp2-endp2 f804d644a01a5ab9f679f76939f5c7e2 multi-comp-multi-endp-1.0.0 Starting |http://my.service f804d644a01a5ab9f679f76939f5c7e2 multi-comp-multi-endp-1.0.0 Starting |"""), self.output(stdout))
def test_two_bundles_mult_components_endpoints_no_path(self): request_headers_mock = MagicMock(return_value=self.mock_headers) http_method = self.respond_with_file_contents('data/bundle_with_services/two_bundles_no_path.json') stdout = MagicMock() input_args = MagicMock(**self.default_args) with patch('requests.get', http_method), \ patch('conductr_cli.conduct_url.request_headers', request_headers_mock): logging_setup.configure_logging(input_args, stdout) result = conduct_services.services(input_args) self.assertTrue(result) request_headers_mock.assert_called_with(input_args) http_method.assert_called_with(self.default_url, timeout=DEFAULT_HTTP_TIMEOUT, headers=self.mock_headers) self.assertEqual( strip_margin("""|SERVICE BUNDLE ID BUNDLE NAME STATUS |http://:6011 6e4560e multi2-comp-multi-endp-1.0.0 Running |http://:7010/comp3-endp1 6e4560e multi2-comp-multi-endp-1.0.0 Running |http://:7011/comp3-endp2 6e4560e multi2-comp-multi-endp-1.0.0 Running |http://:8010/comp1-endp1 f804d64 multi-comp-multi-endp-1.0.0 Running |http://:8011/comp1-endp2 f804d64 multi-comp-multi-endp-1.0.0 Running |http://:9010/comp2-endp1 f804d64 multi-comp-multi-endp-1.0.0 Running |http://:9010/comp2-endp1 6e4560e multi2-comp-multi-endp-1.0.0 Running |http://:9011 f804d64 multi-comp-multi-endp-1.0.0 Running |"""), self.output(stdout))
def test_multiple_events(self): http_method = self.respond_with(text="""[ { "timestamp":"2015-08-24T01:16:22.327Z", "host":"10.0.1.232", "message":"[WARN] [04/21/2015 12:54:30.079] [doc-renderer-cluster-1-akka.remote.default-remote-dispatcher-22] Association with remote system has failed." }, { "timestamp":"2015-08-24T01:16:25.327Z", "host":"10.0.1.232", "message":"[WARN] [04/21/2015 12:54:36.079] [doc-renderer-cluster-1-akka.remote.default-remote-dispatcher-26] Association with remote system has failed." } ]""") stdout = MagicMock() with patch('requests.get', http_method), patch('sys.stdout', stdout): conduct_logs.logs(MagicMock(**self.default_args)) http_method.assert_called_with(self.default_url) self.assertEqual( strip_margin("""|TIME HOST LOG |2015-08-24T01:16:22Z 10.0.1.232 [WARN] [04/21/2015 12:54:30.079] [doc-renderer-cluster-1-akka.remote.default-remote-dispatcher-22] Association with remote system has failed. |2015-08-24T01:16:25Z 10.0.1.232 [WARN] [04/21/2015 12:54:36.079] [doc-renderer-cluster-1-akka.remote.default-remote-dispatcher-26] Association with remote system has failed. |"""), self.output(stdout))
def test_has_error(self): http_method = self.respond_with(text="""[ { "attributes": { "bundleName": "test-bundle" }, "bundleId": "45e0c477d3e5ea92aa8d85c0d8f3e25c", "bundleExecutions": [], "bundleInstallations": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], "hasError": true } ]""") stdout = MagicMock() input_args = MagicMock(**self.default_args) with patch('requests.get', http_method): logging_setup.configure_logging(input_args, stdout) result = conduct_info.info(input_args) self.assertTrue(result) http_method.assert_called_with(self.default_url, auth=self.conductr_auth, verify=self.server_verification_file, timeout=DEFAULT_HTTP_TIMEOUT, headers={'Host': '127.0.0.1'}) self.assertEqual( strip_margin("""|ID NAME #REP #STR #RUN |! 45e0c47 test-bundle 10 0 0 |There are errors: use `conduct events` or `conduct logs` for further information |"""), self.output(stdout))
def test_long_ids(self): http_method = self.respond_with(text="""[ { "attributes": { "bundleName": "test-bundle" }, "bundleId": "45e0c477d3e5ea92aa8d85c0d8f3e25c", "bundleExecutions": [], "bundleInstallations": [1] } ]""") stdout = MagicMock() args = self.default_args.copy() args.update({'long_ids': True}) input_args = MagicMock(**args) with patch('requests.get', http_method): logging_setup.configure_logging(input_args, stdout) result = conduct_info.info(input_args) self.assertTrue(result) http_method.assert_called_with(self.default_url, auth=self.conductr_auth, verify=self.server_verification_file, timeout=DEFAULT_HTTP_TIMEOUT, headers={'Host': '127.0.0.1'}) self.assertEqual( strip_margin("""|ID NAME #REP #STR #RUN |45e0c477d3e5ea92aa8d85c0d8f3e25c test-bundle 1 0 0 |"""), self.output(stdout))
def test_ip(self): args = {} args.update(self.default_args) args.pop('host') args.update({'ip': '10.0.0.1'}) default_url = 'http://10.0.0.1:9005/bundles' http_method = self.respond_with_file_contents( 'data/bundle_with_acls/one_bundle_tcp.json') stdout = MagicMock() input_args = MagicMock(**args) with patch('requests.get', http_method): logging_setup.configure_logging(input_args, stdout) result = conduct_acls.acls(input_args) self.assertTrue(result) http_method.assert_called_with(default_url, timeout=DEFAULT_HTTP_TIMEOUT, headers={'Host': '10.0.0.1'}) self.assertEqual( strip_margin( """|TCP/PORT BUNDLE ID BUNDLE NAME STATUS |9001 f804d64 multi-comp-multi-endp-1.0.0 Starting |"""), self.output(stdout))
def base_test_failure_no_configuration(self): resolve_bundle_mock = MagicMock(side_effect=[(self.bundle_name, self.bundle_file), BundleResolutionError('some message')]) stdout = MagicMock() stderr = MagicMock() with patch('conductr_cli.resolver.resolve_bundle', resolve_bundle_mock): args = self.default_args.copy() args.update({'configuration': 'no_such.conf'}) logging_setup.configure_logging(MagicMock(**args), stdout, stderr) result = conduct_load.load(MagicMock(**args)) self.assertFalse(result) self.assertEqual( resolve_bundle_mock.call_args_list, [ call(self.custom_settings, self.bundle_resolve_cache_dir, self.bundle_file), call(self.custom_settings, self.bundle_resolve_cache_dir, 'no_such.conf') ] ) self.assertEqual( as_error(strip_margin("""|Error: Bundle not found: some message |""")), self.output(stderr))
def base_test_failure(self): request_headers_mock = MagicMock(return_value=self.mock_headers) resolve_bundle_mock = MagicMock(return_value=(self.bundle_name, self.bundle_file)) http_method = self.respond_with(404) stdout = MagicMock() stderr = MagicMock() open_mock = MagicMock(return_value=1) input_args = MagicMock(**self.default_args) with patch('conductr_cli.resolver.resolve_bundle', resolve_bundle_mock), \ patch('conductr_cli.conduct_url.request_headers', request_headers_mock), \ patch('requests.post', http_method), \ patch('builtins.open', open_mock): logging_setup.configure_logging(input_args, stdout, stderr) result = conduct_load.load(input_args) self.assertFalse(result) open_mock.assert_called_with(self.bundle_file, 'rb') resolve_bundle_mock.assert_called_with(self.custom_settings, self.bundle_resolve_cache_dir, self.bundle_file) request_headers_mock.assert_called_with(input_args) http_method.assert_called_with(self.default_url, files=self.default_files, timeout=LOAD_HTTP_TIMEOUT, headers=self.mock_headers) self.assertEqual( as_error( strip_margin("""|Error: 404 Not Found |""")), self.output(stderr))
def test_hung_processes(self): ps_output = [{ 'id': 58002, 'type': 'core' }, { 'id': 58003, 'type': 'agent' }] stdout = MagicMock() stderr = MagicMock() mock_os_kill = MagicMock() mock_time_sleep = MagicMock() mock_find_pids = MagicMock(return_value=ps_output) with patch('os.kill', mock_os_kill), \ patch('time.sleep', mock_time_sleep), \ patch('conductr_cli.sandbox_common.find_pids', mock_find_pids): logging_setup.configure_logging(MagicMock(**self.default_args), stdout, stderr) sandbox_stop_jvm.stop(MagicMock(**self.default_args)) self.assertEqual(h1('Stopping ConductR') + '\n', self.output(stdout)) self.assertEqual( strip_margin( as_error( """|Error: ConductR core pid 58002 could not be stopped |Error: ConductR agent pid 58003 could not be stopped |Error: Please stop the processes manually |""")), self.output(stderr)) mock_os_kill.assert_has_calls( [call(58002, signal.SIGTERM), call(58003, signal.SIGTERM)])
def test_duplicate_endpoints(self): request_headers_mock = MagicMock(return_value=self.mock_headers) http_method = self.respond_with_file_contents( 'data/bundle_with_acls/duplicate_endpoints_tcp.json') stdout = MagicMock() input_args = MagicMock(**self.default_args) with patch('requests.get', http_method), \ patch('conductr_cli.conduct_url.request_headers', request_headers_mock): logging_setup.configure_logging(input_args, stdout) result = conduct_acls.acls(input_args) self.assertTrue(result) request_headers_mock.assert_called_with(input_args) http_method.assert_called_with(self.default_url, timeout=DEFAULT_HTTP_TIMEOUT, headers=self.mock_headers) self.maxDiff = None self.assertEqual( as_warn( strip_margin( """|TCP/PORT SYSTEM SYSTEM VERSION ENDPOINT NAME BUNDLE ID BUNDLE NAME STATUS |12001 dup-system 1 duplicate f804d64 dup-bundle-1 Running |12002 dup-system 1 duplicate a904d64 dup-bundle-2 Running | |Warning: Multiple endpoints found: dup-system/1/duplicate |Warning: Unable to expose these endpoint via ConductR HAProxy. |Warning: Please ensure the ENDPOINT NAME is unique within a particular SYSTEM and SYSTEM VERSION. |""")), self.output(stdout))
def base_test_failure_install_timeout(self): resolve_bundle_mock = MagicMock(return_value=(self.bundle_name, self.bundle_file)) http_method = self.respond_with(200, self.default_response) stderr = MagicMock() open_mock = MagicMock(return_value=1) wait_for_installation_mock = MagicMock(side_effect=WaitTimeoutError('test timeout')) input_args = MagicMock(**self.default_args) with patch('conductr_cli.resolver.resolve_bundle', resolve_bundle_mock), \ patch('requests.post', http_method), \ patch('builtins.open', open_mock), \ patch('conductr_cli.bundle_installation.wait_for_installation', wait_for_installation_mock): logging_setup.configure_logging(input_args, err_output=stderr) result = conduct_load.load(input_args) self.assertFalse(result) open_mock.assert_called_with(self.bundle_file, 'rb') resolve_bundle_mock.assert_called_with(self.custom_settings, self.bundle_resolve_cache_dir, self.bundle_file) http_method.assert_called_with(self.default_url, files=self.default_files, timeout=LOAD_HTTP_TIMEOUT) wait_for_installation_mock.assert_called_with(self.bundle_id, input_args) self.assertEqual( as_error(strip_margin("""|Error: Timed out: test timeout |""")), self.output(stderr))
def base_test_failure_scale_timeout(self): http_method = self.respond_with(200, self.default_response) wait_for_scale_mock = MagicMock( side_effect=WaitTimeoutError('test wait timeout error')) stderr = MagicMock() input_args = MagicMock(**self.default_args) with patch('requests.put', http_method), \ patch('conductr_cli.bundle_scale.wait_for_scale', wait_for_scale_mock): logging_setup.configure_logging(input_args, err_output=stderr) result = conduct_run.run(input_args) self.assertFalse(result) http_method.assert_called_with(self.default_url, auth=self.conductr_auth, verify=self.server_verification_file, headers={'Host': '127.0.0.1'}) wait_for_scale_mock.assert_called_with(self.bundle_id, self.scale, wait_for_is_active=True, args=input_args) self.assertEqual( as_error( strip_margin("""|Error: Timed out: test wait timeout error |""")), self.output(stderr))
def test_display_with_long_id(self): request_headers_mock = MagicMock(return_value=self.mock_headers) http_method = self.respond_with_file_contents( 'data/bundle_with_acls/one_bundle_http.json') stdout = MagicMock() args = self.default_args.copy() args.update({'long_ids': True}) input_args = MagicMock(**args) with patch('requests.get', http_method), \ patch('conductr_cli.conduct_url.request_headers', request_headers_mock): logging_setup.configure_logging(input_args, stdout) result = conduct_acls.acls(input_args) self.assertTrue(result) request_headers_mock.assert_called_with(input_args) http_method.assert_called_with(self.default_url, timeout=DEFAULT_HTTP_TIMEOUT, headers=self.mock_headers) self.assertEqual( strip_margin( """|METHOD PATH REWRITE SYSTEM SYSTEM VERSION ENDPOINT NAME BUNDLE ID BUNDLE NAME STATUS |* /foo multi-comp-multi-endp-1.0.0 1.0.0 comp1-endp1 f804d644a01a5ab9f679f76939f5c7e2 multi-comp-multi-endp-1.0.0 Starting |"""), self.output(stdout))
def test_multiple_events(self): request_headers_mock = MagicMock(return_value=self.mock_headers) http_method = self.respond_with(text="""[ { "timestamp":"2015-08-24T01:16:22.327Z", "host":"10.0.1.232", "message":"[WARN] [04/21/2015 12:54:30.079] [doc-renderer-cluster-1-akka.remote.default-remote-dispatcher-22] Association with remote system has failed." }, { "timestamp":"2015-08-24T01:16:25.327Z", "host":"10.0.1.232", "message":"[WARN] [04/21/2015 12:54:36.079] [doc-renderer-cluster-1-akka.remote.default-remote-dispatcher-26] Association with remote system has failed." } ]""") quote_method = MagicMock(return_value=self.bundle_id_urlencoded) stdout = MagicMock() input_args = MagicMock(**self.default_args) with patch('requests.get', http_method), \ patch('conductr_cli.conduct_url.request_headers', request_headers_mock), \ patch('urllib.parse.quote', quote_method): logging_setup.configure_logging(input_args, stdout) result = conduct_logs.logs(input_args) self.assertTrue(result) request_headers_mock.assert_called_with(input_args) http_method.assert_called_with(self.default_url, timeout=DEFAULT_HTTP_TIMEOUT, headers=self.mock_headers) self.assertEqual( strip_margin("""|TIME HOST LOG |2015-08-24T01:16:22Z 10.0.1.232 [WARN] [04/21/2015 12:54:30.079] [doc-renderer-cluster-1-akka.remote.default-remote-dispatcher-22] Association with remote system has failed. |2015-08-24T01:16:25Z 10.0.1.232 [WARN] [04/21/2015 12:54:36.079] [doc-renderer-cluster-1-akka.remote.default-remote-dispatcher-26] Association with remote system has failed. |"""), self.output(stdout))
def test_multiple_acls_sorted(self): request_headers_mock = MagicMock(return_value=self.mock_headers) http_method = self.respond_with_file_contents( 'data/bundle_with_acls/multiple_bundles_http.json') stdout = MagicMock() input_args = MagicMock(**self.default_args) with patch('requests.get', http_method), \ patch('conductr_cli.conduct_url.request_headers', request_headers_mock): logging_setup.configure_logging(input_args, stdout) result = conduct_acls.acls(input_args) self.assertTrue(result) request_headers_mock.assert_called_with(input_args) http_method.assert_called_with(self.default_url, timeout=DEFAULT_HTTP_TIMEOUT, headers=self.mock_headers) self.assertEqual( strip_margin( """|METHOD PATH REWRITE SYSTEM SYSTEM VERSION ENDPOINT NAME BUNDLE ID BUNDLE NAME STATUS |* /user/(.*)/item/(.*) /my-items/\\1-\\2 my-endp-1.0.0 1.0.0 dostat bbb4d64 my-endp-1.0.0 Running |POST ^/baz/boom /foo multi-comp-multi-endp-1.0.0 1.0.0 comp1-endp1 f804d64 multi-comp-multi-endp-1.0.0 Starting |* ^/bar multi-comp-multi-endp-1.0.0 1.0.0 comp1-endp1 f804d64 multi-comp-multi-endp-1.0.0 Starting |* /foo multi-comp-multi-endp-1.0.0 1.0.0 comp1-endp1 f804d64 multi-comp-multi-endp-1.0.0 Starting |"""), self.output(stdout))
def test_multiple_events(self): http_method = self.respond_with(text="""[ { "timestamp":"2015-08-24T01:16:22.327Z", "event":"conductr.loadScheduler.loadBundleRequested", "description":"Load bundle requested: requestId=cba938cd-860e-41a4-9cbe-2c677feaca20, bundleName=visualizer" }, { "timestamp":"2015-08-24T01:16:25.327Z", "event":"conductr.loadExecutor.bundleWritten", "description":"Bundle written: requestId=cba938cd-860e-41a4-9cbe-2c677feaca20, bundleName=visualizer" } ]""") stdout = MagicMock() with patch('requests.get', http_method), patch('sys.stdout', stdout): conduct_events.events(MagicMock(**self.default_args)) http_method.assert_called_with(self.default_url) self.assertEqual( strip_margin("""|TIME EVENT DESC |2015-08-24T01:16:22Z conductr.loadScheduler.loadBundleRequested Load bundle requested: requestId=cba938cd-860e-41a4-9cbe-2c677feaca20, bundleName=visualizer |2015-08-24T01:16:25Z conductr.loadExecutor.bundleWritten Bundle written: requestId=cba938cd-860e-41a4-9cbe-2c677feaca20, bundleName=visualizer |"""), self.output(stdout))
def test_wait_timeout_all_events(self): count_installations_mock = MagicMock(return_value=1) url_mock = MagicMock(return_value='/bundle-events/endpoint') get_events_mock = MagicMock(return_value=[ create_test_event('bundleInstallationAdded'), create_test_event('bundleInstallationAdded'), create_test_event('bundleInstallationAdded') ]) stdout = MagicMock() bundle_id = 'a101449418187d92c789d1adc240b6d6' args = MagicMock(**{ 'wait_timeout': 10 }) with patch('conductr_cli.conduct_url.url', url_mock), \ patch('conductr_cli.bundle_installation.count_installations', count_installations_mock), \ patch('conductr_cli.sse_client.get_events', get_events_mock): logging_setup.configure_logging(args, stdout) self.assertRaises(WaitTimeoutError, bundle_installation.wait_for_uninstallation, bundle_id, args) self.assertEqual(count_installations_mock.call_args_list, [ call(bundle_id, args), call(bundle_id, args), call(bundle_id, args), call(bundle_id, args) ]) url_mock.assert_called_with('bundles/events', args) self.assertEqual(strip_margin("""|Bundle a101449418187d92c789d1adc240b6d6 waiting to be uninstalled |Bundle a101449418187d92c789d1adc240b6d6 still waiting to be uninstalled |Bundle a101449418187d92c789d1adc240b6d6 still waiting to be uninstalled |Bundle a101449418187d92c789d1adc240b6d6 still waiting to be uninstalled |"""), self.output(stdout))
def base_test_failure_no_response(self): resolve_bundle_mock = MagicMock(return_value=(self.bundle_file_name, self.bundle_file)) create_multipart_mock = MagicMock(return_value=self.multipart_mock) http_method = self.raise_read_timeout_error('test reason', self.default_url) stdout = MagicMock() stderr = MagicMock() open_mock = MagicMock(return_value=1) input_args = MagicMock(**self.default_args) with patch('conductr_cli.resolver.resolve_bundle', resolve_bundle_mock), \ patch('conductr_cli.conduct_load.create_multipart', create_multipart_mock), \ patch('requests.post', http_method), \ patch('builtins.open', open_mock): logging_setup.configure_logging(input_args, stdout, stderr) result = conduct_load.load(input_args) self.assertFalse(result) open_mock.assert_called_with(self.bundle_file, 'rb') resolve_bundle_mock.assert_called_with(self.custom_settings, self.bundle_resolve_cache_dir, self.bundle_file) create_multipart_mock.assert_called_with(self.conduct_load_logger, self.default_files) http_method.assert_called_with(self.default_url, data=self.multipart_mock, auth=self.conductr_auth, verify=self.server_verification_file, headers={'Content-Type': self.multipart_content_type, 'Host': '127.0.0.1'}) self.assertEqual( as_error( strip_margin("""|Error: Timed out waiting for response from the server: test reason |Error: One possible issue may be that there are not enough resources or machines with the roles that your bundle requires |""")), self.output(stderr))
def base_test_failure_scale_timeout(self): request_headers_mock = MagicMock(return_value=self.mock_headers) http_method = self.respond_with(200, self.default_response) wait_for_scale_mock = MagicMock( side_effect=WaitTimeoutError('test wait timeout error')) stderr = MagicMock() input_args = MagicMock(**self.default_args) with patch('requests.put', http_method), \ patch('conductr_cli.conduct_url.request_headers', request_headers_mock), \ patch('conductr_cli.bundle_scale.wait_for_scale', wait_for_scale_mock): logging_setup.configure_logging(input_args, err_output=stderr) result = conduct_run.run(input_args) self.assertFalse(result) request_headers_mock.assert_called_with(input_args) http_method.assert_called_with(self.default_url, headers=self.mock_headers) wait_for_scale_mock.assert_called_with(self.bundle_id, self.scale, input_args) self.assertEqual( as_error( strip_margin("""|Error: Timed out: test wait timeout error |""")), self.output(stderr))
def base_test_failure_install_timeout(self): resolve_bundle_mock = MagicMock(return_value=(self.bundle_file_name, self.bundle_file)) create_multipart_mock = MagicMock(return_value=self.multipart_mock) http_method = self.respond_with(200, self.default_response) stderr = MagicMock() open_mock = MagicMock(return_value=1) wait_for_installation_mock = MagicMock(side_effect=WaitTimeoutError('test timeout')) input_args = MagicMock(**self.default_args) with patch('conductr_cli.resolver.resolve_bundle', resolve_bundle_mock), \ patch('conductr_cli.conduct_load.create_multipart', create_multipart_mock), \ patch('requests.post', http_method), \ patch('builtins.open', open_mock), \ patch('conductr_cli.bundle_installation.wait_for_installation', wait_for_installation_mock): logging_setup.configure_logging(input_args, err_output=stderr) result = conduct_load.load(input_args) self.assertFalse(result) open_mock.assert_called_with(self.bundle_file, 'rb') create_multipart_mock.assert_called_with(self.conduct_load_logger, self.default_files) http_method.assert_called_with(self.default_url, data=self.multipart_mock, auth=self.conductr_auth, verify=self.server_verification_file, headers={'Content-Type': self.multipart_content_type, 'Host': '127.0.0.1'}) wait_for_installation_mock.assert_called_with(self.bundle_id, input_args) self.assertEqual( as_error(strip_margin("""|Error: Timed out: test timeout |""")), self.output(stderr))
def test_boot2docker_shellinit(self): output = strip_margin( """|Writing /Users/mj/.boot2docker/certs/boot2docker-vm/ca.pem |Writing /Users/mj/.boot2docker/certs/boot2docker-vm/cert.pem |Writing /Users/mj/.boot2docker/certs/boot2docker-vm/key.pem | export DOCKER_HOST=tcp://192.168.59.103:2376 | export DOCKER_CERT_PATH=/Users/mj/.boot2docker/certs/boot2docker-vm | export DOCKER_TLS_VERIFY=1 |""") check_output_mock = MagicMock(return_value=output) with patch('subprocess.check_output', check_output_mock): result = terminal.boot2docker_shellinit() expected_result = [ 'Writing /Users/mj/.boot2docker/certs/boot2docker-vm/ca.pem', 'Writing /Users/mj/.boot2docker/certs/boot2docker-vm/cert.pem', 'Writing /Users/mj/.boot2docker/certs/boot2docker-vm/key.pem', 'export DOCKER_HOST=tcp://192.168.59.103:2376', 'export DOCKER_CERT_PATH=/Users/mj/.boot2docker/certs/boot2docker-vm', 'export DOCKER_TLS_VERIFY=1' ] self.assertEqual(result, expected_result) check_output_mock.assert_called_with(['boot2docker', 'shellinit'], universal_newlines=True)
def test_macos_ipv6(self): mock_loopback_device_name = MagicMock( return_value=self.loopback_device_name) mock_is_linux = MagicMock(return_value=False) mock_is_macos = MagicMock(return_value=True) with patch('conductr_cli.host.loopback_device_name', mock_loopback_device_name), \ patch('conductr_cli.host.is_linux', mock_is_linux), \ patch('conductr_cli.host.is_macos', mock_is_macos): result = host.addr_alias_setup_instructions( self.addrs_ipv6, self.subnet_mask_ipv6) expected_result = strip_margin( """|Whoops. Network address aliases are required so that the sandbox can operate as a cluster of machines. | |Please run the following and then try your command again: | |sudo ifconfig ix0 alias 0000:0000:0000:0000:0000:ffff:c0a8:0101 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff |sudo ifconfig ix0 alias 0000:0000:0000:0000:0000:ffff:c0a8:0102 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff |""") self.assertEqual(expected_result, result) mock_loopback_device_name.assert_called_once_with() mock_is_linux.assert_called_once_with() mock_is_macos.assert_called_once_with()
def test_docker_machine_env(self): vm_name = 'default' output = strip_margin("""|export DOCKER_TLS_VERIFY="1" |export DOCKER_HOST="tcp://192.168.99.100:2376" |export DOCKER_CERT_PATH="/Users/mj/.docker/machine/machines/default" |export DOCKER_MACHINE_NAME="default" |# Run this command to configure your shell: |# eval "$(docker-machine env default) |""") check_output_mock = MagicMock(return_value=output) with patch('subprocess.check_output', check_output_mock): result = terminal.docker_machine_env(vm_name) expected_result = [ 'export DOCKER_TLS_VERIFY="1"', 'export DOCKER_HOST="tcp://192.168.99.100:2376"', 'export DOCKER_CERT_PATH="/Users/mj/.docker/machine/machines/default"', 'export DOCKER_MACHINE_NAME="default"', '# Run this command to configure your shell:', '# eval "$(docker-machine env default)' ] self.assertEqual(result, expected_result) check_output_mock.assert_called_with( ['docker-machine', 'env', vm_name], universal_newlines=True)
def test_multiple_events(self): http_method = self.respond_with(text="""[ { "timestamp":"2015-08-24T01:16:22.327Z", "event":"conductr.loadScheduler.loadBundleRequested", "description":"Load bundle requested: requestId=cba938cd-860e-41a4-9cbe-2c677feaca20, bundleName=visualizer" }, { "timestamp":"2015-08-24T01:16:25.327Z", "event":"conductr.loadExecutor.bundleWritten", "description":"Bundle written: requestId=cba938cd-860e-41a4-9cbe-2c677feaca20, bundleName=visualizer" } ]""") quote_method = MagicMock(return_value=self.bundle_id_urlencoded) stdout = MagicMock() input_args = MagicMock(**self.default_args) with patch('requests.get', http_method), \ patch('urllib.parse.quote', quote_method): logging_setup.configure_logging(input_args, stdout) result = conduct_events.events(input_args) self.assertTrue(result) http_method.assert_called_with(self.default_url, auth=self.conductr_auth, verify=self.server_verification_file, timeout=DEFAULT_HTTP_TIMEOUT, headers={'Host': '127.0.0.1'}) self.assertEqual( strip_margin("""|TIME EVENT DESC |2015-08-24T01:16:22Z conductr.loadScheduler.loadBundleRequested Load bundle requested: requestId=cba938cd-860e-41a4-9cbe-2c677feaca20, bundleName=visualizer |2015-08-24T01:16:25Z conductr.loadExecutor.bundleWritten Bundle written: requestId=cba938cd-860e-41a4-9cbe-2c677feaca20, bundleName=visualizer |"""), self.output(stdout))
def test_basic_usage(self): self.maxDiff = None http_method = self.respond_with(text=self.fake_output) stdout = MagicMock() input_args = MagicMock(**self.default_args) with patch('requests.get', http_method): logging_setup.configure_logging(input_args, stdout) result = conduct_members.members(input_args) self.assertTrue(result) http_method.assert_called_with(self.default_url, auth=self.conductr_auth, verify=self.server_verification_file, timeout=DEFAULT_HTTP_TIMEOUT, headers={'Host': '127.0.0.1'}) self.assertEqual( strip_margin( """|UID ADDRESS ROLES STATUS REACHABLE |-916664159 akka.tcp://[email protected]:9004 replicator Up Yes |1129598726 akka.tcp://[email protected]:9004 replicator Up Yes |-543773917 akka.tcp://[email protected]:9004 replicator Up Yes |"""), self.output(stdout))
def __init__(self, method_name): super().__init__(method_name) self.bundle_id = '45e0c477d3e5ea92aa8d85c0d8f3e25c' self.nr_of_cpus = 1.0 self.memory = 200 self.disk_space = 100 self.roles = ['web-server'] self.bundle_file_name = 'bundle.zip' self.system = 'bundle' self.custom_settings = Mock() self.bundle_resolve_cache_dir = 'bundle-resolve-cache-dir' self.tmpdir, self.bundle_file = create_temp_bundle( strip_margin("""|nrOfCpus = {}, |memory = {}, |diskSpace = {}, |roles = [{}], |name = {}, |system = {}, |""").format(self.nr_of_cpus, self.memory, self.disk_space, ', '.join(self.roles), self.bundle_file_name, self.system)) self.default_args = { 'dcos_mode': False, 'scheme': 'http', 'host': '127.0.0.1', 'port': 9005, 'base_path': '/', 'api_version': '1', 'disable_instructions': False, 'verbose': False, 'quiet': False, 'no_wait': False, 'offline_mode': False, 'long_ids': False, 'command': 'conduct', 'cli_parameters': '', 'custom_settings': self.custom_settings, 'resolve_cache_dir': self.bundle_resolve_cache_dir, 'bundle': self.bundle_file, 'configuration': None, 'conductr_auth': self.conductr_auth, 'server_verification_file': self.server_verification_file } self.default_url = 'http://127.0.0.1:9005/bundles' self.default_files = [ ('nrOfCpus', str(self.nr_of_cpus)), ('memory', str(self.memory)), ('diskSpace', str(self.disk_space)), ('roles', ' '.join(self.roles)), ('bundleName', self.bundle_file_name), ('system', self.system), ('bundle', (self.bundle_file_name, 1)) ]
def test_sse(self): raw_sse = strip_margin("""|data: | |event:My Test Event |data:My Test Data | |data: | |""") raw_sse_iterators = [iter(list(raw_sse))] iter_content_mock = MagicMock(side_effect=raw_sse_iterators) raise_for_status_mock = MagicMock() response_mock = MagicMock() response_mock.raise_for_status = raise_for_status_mock response_mock.iter_content = iter_content_mock request_get_mock = MagicMock(return_value=response_mock) result = [] with patch('requests.get', request_get_mock): events = sse_client.get_events(False, '127.0.0.1', 'http://host.com') for event in events: result.append(event) self.assertEqual([ sse_client.Event(event=None, data=''), sse_client.Event(event='My Test Event', data='My Test Data'), sse_client.Event(event=None, data='') ], result) request_get_mock.assert_called_with('http://host.com', stream=True, **sse_client.SSE_REQUEST_INPUT) raise_for_status_mock.assert_called_with() iter_content_mock.assert_called_with(decode_unicode=True)
def base_test_failure_no_response(self): request_headers_mock = MagicMock(return_value=self.mock_headers) resolve_bundle_mock = MagicMock(return_value=(self.bundle_name, self.bundle_file)) http_method = self.raise_read_timeout_error('test reason', self.default_url) stdout = MagicMock() stderr = MagicMock() open_mock = MagicMock(return_value=1) input_args = MagicMock(**self.default_args) with patch('conductr_cli.resolver.resolve_bundle', resolve_bundle_mock), \ patch('conductr_cli.conduct_url.request_headers', request_headers_mock), \ patch('requests.post', http_method), \ patch('builtins.open', open_mock): logging_setup.configure_logging(input_args, stdout, stderr) result = conduct_load.load(input_args) self.assertFalse(result) open_mock.assert_called_with(self.bundle_file, 'rb') resolve_bundle_mock.assert_called_with(self.custom_settings, self.bundle_resolve_cache_dir, self.bundle_file) request_headers_mock.assert_called_with(input_args) http_method.assert_called_with(self.default_url, files=self.default_files, timeout=LOAD_HTTP_TIMEOUT, headers=self.mock_headers) self.assertEqual( as_error( strip_margin( """|Error: Timed out waiting for response from the server: test reason |Error: One possible issue may be that there are not enough resources or machines with the roles that your bundle requires |""")), self.output(stderr))
def test_jvm_validation_java_version_parse_error(self): conductr_version = '2.0.0' stdout = MagicMock() stderr = MagicMock() mock_feature = MagicMock() features = [mock_feature] mock_collect_features = MagicMock(return_value=features) mock_sandbox_run_jvm = MagicMock(side_effect=JavaVersionParseError('this is the output from java -version')) args = self.default_args.copy() args.update({ 'image_version': conductr_version }) input_args = MagicMock(**args) with \ patch('conductr_cli.sandbox_features.collect_features', mock_collect_features), \ patch('conductr_cli.sandbox_run_jvm.run', mock_sandbox_run_jvm): logging_setup.configure_logging(input_args, stdout, stderr) self.assertFalse(sandbox_run.run(input_args)) mock_sandbox_run_jvm.assert_called_once_with(input_args, features) expected_output = strip_margin(as_error("""|Error: Unable to obtain java version from the `java -version` command. |Error: Please ensure Oracle JVM 1.8 and above is installed. |""")) self.assertEqual(expected_output, self.output(stderr))
def test_duplicate_endpoints(self): request_headers_mock = MagicMock(return_value=self.mock_headers) http_method = self.respond_with_file_contents('data/bundle_with_acls/duplicate_endpoints_tcp.json') stdout = MagicMock() input_args = MagicMock(**self.default_args) with patch('requests.get', http_method), \ patch('conductr_cli.conduct_url.request_headers', request_headers_mock): logging_setup.configure_logging(input_args, stdout) result = conduct_acls.acls(input_args) self.assertTrue(result) request_headers_mock.assert_called_with(input_args) http_method.assert_called_with(self.default_url, timeout=DEFAULT_HTTP_TIMEOUT, headers=self.mock_headers) self.maxDiff = None self.assertEqual( as_warn(strip_margin( """|TCP/PORT SYSTEM SYSTEM VERSION ENDPOINT NAME BUNDLE ID BUNDLE NAME STATUS |12001 dup-system 1 duplicate f804d64 dup-bundle-1 Running |12002 dup-system 1 duplicate a904d64 dup-bundle-2 Running | |Warning: Multiple endpoints found: dup-system/1/duplicate |Warning: Unable to expose these endpoint via ConductR HAProxy. |Warning: Please ensure the ENDPOINT NAME is unique within a particular SYSTEM and SYSTEM VERSION. |""")), self.output(stdout))
def test_containers_already_running(self): stdout = MagicMock() features = [] running_containers = ['cond-0'] input_args = MagicMock(**self.default_args) with \ patch('conductr_cli.terminal.docker_images', return_value='some-image'), \ patch('conductr_cli.terminal.docker_pull', return_value=''), \ patch('conductr_cli.terminal.docker_ps', return_value=''), \ patch('conductr_cli.terminal.docker_inspect', return_value='10.10.10.10'), \ patch('conductr_cli.terminal.docker_run', return_value=''), \ patch('conductr_cli.sandbox_common.resolve_running_docker_containers', return_value=running_containers), \ patch('conductr_cli.sandbox_proxy.stop_proxy') as mock_stop_proxy, \ patch('conductr_cli.terminal.docker_rm') as mock_docker_rm: logging_setup.configure_logging(input_args, stdout) sandbox_run_docker.run(input_args, features) expected_stdout = strip_margin( """||------------------------------------------------| || Stopping ConductR | ||------------------------------------------------| |ConductR has been successfully stopped ||------------------------------------------------| || Starting ConductR | ||------------------------------------------------| |Starting container cond-0.. |""") self.assertEqual(expected_stdout, self.output(stdout)) mock_stop_proxy.assert_called_once_with() mock_docker_rm.assert_called_once_with(running_containers)
def test_return_immediately_if_scale_is_met(self): conductr_host = '10.0.0.1' conductr_host_mock = MagicMock(return_value=conductr_host) get_events_mock = MagicMock(return_value=[]) get_scale_mock = MagicMock(side_effect=[3]) stdout = MagicMock() bundle_id = 'a101449418187d92c789d1adc240b6d6' dcos_mode = False args = MagicMock(**{ 'dcos_mode': dcos_mode, 'wait_timeout': 10, 'conductr_auth': self.conductr_auth, 'server_verification_file': self.server_verification_file }) with patch('conductr_cli.bundle_scale.get_scale', get_scale_mock), \ patch('conductr_cli.conduct_url.conductr_host', conductr_host_mock), \ patch('conductr_cli.sse_client.get_events', get_events_mock): logging_setup.configure_logging(args, stdout) bundle_scale.wait_for_scale(bundle_id, 3, args) self.assertEqual(get_scale_mock.call_args_list, [ call(bundle_id, args) ]) conductr_host_mock.assert_not_called() get_events_mock.assert_not_called() self.assertEqual(strip_margin("""|Bundle a101449418187d92c789d1adc240b6d6 expected scale 3 is met |"""), self.output(stdout))
def test_no_wait(self): stdout = MagicMock() mock_wait_for_conductr = MagicMock() with \ patch('conductr_cli.terminal.docker_images', return_value=''), \ patch('conductr_cli.terminal.docker_pull', return_value=''), \ patch('conductr_cli.terminal.docker_ps', return_value=''), \ patch('conductr_cli.terminal.docker_inspect', return_value='10.10.10.10'), \ patch('conductr_cli.terminal.docker_run', return_value='') as mock_docker_run, \ patch('conductr_cli.sandbox_common.resolve_running_docker_containers', return_value=[]), \ patch('conductr_cli.sandbox_run.wait_for_conductr', mock_wait_for_conductr): args = self.default_args.copy() args.update({'no_wait': True}) input_args = MagicMock(**args) logging_setup.configure_logging(input_args, stdout) sandbox_run.run(input_args) expected_stdout = strip_margin("""|Pulling down the ConductR development image.. ||------------------------------------------------| || Starting ConductR | ||------------------------------------------------| |Starting container cond-0.. |""") expected_optional_args = self.default_general_args('cond-0') + self.default_env_args + self.default_port_args expected_image = '{}:{}'.format(CONDUCTR_DEV_IMAGE, LATEST_CONDUCTR_VERSION) expected_positional_args = self.default_positional_args self.assertEqual(expected_stdout, self.output(stdout)) mock_docker_run.assert_called_once_with(expected_optional_args, expected_image, expected_positional_args) mock_wait_for_conductr.assert_not_called()
def test_two_bundles_mult_components_endpoints(self): http_method = self.respond_with_file_contents('data/two_bundles.json') stdout = MagicMock() with patch('requests.get', http_method): logging_setup.configure_logging(MagicMock(**self.default_args), stdout) result = conduct_services.services(MagicMock(**self.default_args)) self.assertTrue(result) http_method.assert_called_with(self.default_url, timeout=DEFAULT_HTTP_TIMEOUT) self.assertEqual( as_warn(strip_margin("""|SERVICE BUNDLE ID BUNDLE NAME STATUS |http://:6011/comp2-endp2 6e4560e multi2-comp-multi-endp-1.0.0 Running |http://:7010/comp3-endp1 6e4560e multi2-comp-multi-endp-1.0.0 Running |http://:7011/comp3-endp2 6e4560e multi2-comp-multi-endp-1.0.0 Running |http://:8010/comp1-endp1 f804d64 multi-comp-multi-endp-1.0.0 Running |http://:8011/comp1-endp2 f804d64 multi-comp-multi-endp-1.0.0 Running |http://:9010/comp2-endp1 f804d64 multi-comp-multi-endp-1.0.0 Running |http://:9010/comp2-endp1 6e4560e multi2-comp-multi-endp-1.0.0 Running |http://:9011/comp2-endp2 f804d64 multi-comp-multi-endp-1.0.0 Running | |Warning: Multiple endpoints found for the following services: /comp2-endp2 |Warning: Service resolution for these services is undefined. |""")), self.output(stdout))
def test_quiet_settings(self): stdout = MagicMock() stderr = MagicMock() logging_setup.configure_logging(MagicMock(**{'quiet': True}), stdout, stderr) log = logging.getLogger('conductr_cli') log.debug('this is debug') log.verbose('this is verbose') log.info('this is info') log.progress('this is progress', flush=True) log.quiet('this is quiet') log.warning('this is warning') log.error('this is error') log.screen('this is screen') self.assertFalse(log.is_debug_enabled()) self.assertFalse(log.is_verbose_enabled()) self.assertFalse(log.is_info_enabled()) self.assertFalse(log.is_progress_enabled()) self.assertTrue(log.is_quiet_enabled()) self.assertTrue(log.is_warn_enabled()) self.assertEqual(as_warn(strip_margin("""|this is quiet |Warning: this is warning |this is screen |""")), self.output(stdout)) self.assertEqual(as_error('Error: this is error\n'), self.output(stderr))
def test_wait_timeout_all_events(self): get_scale_mock = MagicMock(return_value=0) url_mock = MagicMock(return_value='/bundle-events/endpoint') get_events_mock = MagicMock(return_value=[ self.create_test_event('bundleExecutionAdded'), self.create_test_event('bundleExecutionAdded'), self.create_test_event('bundleExecutionAdded') ]) stdout = MagicMock() bundle_id = 'a101449418187d92c789d1adc240b6d6' args = MagicMock(**{ 'wait_timeout': 10 }) with patch('conductr_cli.conduct_url.url', url_mock), \ patch('conductr_cli.bundle_scale.get_scale', get_scale_mock), \ patch('conductr_cli.sse_client.get_events', get_events_mock): logging_setup.configure_logging(args, stdout) self.assertRaises(WaitTimeoutError, bundle_scale.wait_for_scale, bundle_id, 3, args) self.assertEqual(get_scale_mock.call_args_list, [ call(bundle_id, args), call(bundle_id, args), call(bundle_id, args), call(bundle_id, args) ]) url_mock.assert_called_with('bundles/events', args) self.assertEqual(strip_margin("""|Bundle a101449418187d92c789d1adc240b6d6 waiting to reach expected scale 3 |Bundle a101449418187d92c789d1adc240b6d6 has scale 0, expected 3 |Bundle a101449418187d92c789d1adc240b6d6 has scale 0, expected 3 |Bundle a101449418187d92c789d1adc240b6d6 has scale 0, expected 3 |"""), self.output(stdout))
def test_multiple_events(self): http_method = self.respond_with(text="""[ { "timestamp":"2015-08-24T01:16:22.327Z", "event":"conductr.loadScheduler.loadBundleRequested", "description":"Load bundle requested: requestId=cba938cd-860e-41a4-9cbe-2c677feaca20, bundleName=visualizer" }, { "timestamp":"2015-08-24T01:16:25.327Z", "event":"conductr.loadExecutor.bundleWritten", "description":"Bundle written: requestId=cba938cd-860e-41a4-9cbe-2c677feaca20, bundleName=visualizer" } ]""") quote_method = MagicMock(return_value=self.bundle_id_urlencoded) stdout = MagicMock() input_args = MagicMock(**self.default_args) with patch('requests.get', http_method), \ patch('urllib.parse.quote', quote_method): logging_setup.configure_logging(input_args, stdout) result = conduct_events.events(input_args) self.assertTrue(result) http_method.assert_called_with(self.default_url, auth=self.conductr_auth, verify=self.server_verification_file, timeout=DEFAULT_HTTP_TIMEOUT, headers={'Host': '127.0.0.1'}) self.assertEqual( strip_margin( """|TIME EVENT DESC |2015-08-24T01:16:22Z conductr.loadScheduler.loadBundleRequested Load bundle requested: requestId=cba938cd-860e-41a4-9cbe-2c677feaca20, bundleName=visualizer |2015-08-24T01:16:25Z conductr.loadExecutor.bundleWritten Bundle written: requestId=cba938cd-860e-41a4-9cbe-2c677feaca20, bundleName=visualizer |"""), self.output(stdout))
def test_role_match(self): self.maxDiff = None filtered_by_role_web_args = self.default_args.copy() filtered_by_role_web_args.update({'role': 'web'}) http_method = self.respond_with(text=self.fake_output) stdout = MagicMock() input_args = MagicMock(**filtered_by_role_web_args) with patch('requests.get', http_method): logging_setup.configure_logging(input_args, stdout) result = conduct_agents.agents(input_args) self.assertTrue(result) http_method.assert_called_with(self.default_url, auth=self.conductr_auth, verify=self.server_verification_file, timeout=DEFAULT_HTTP_TIMEOUT, headers={'Host': '127.0.0.1'}) self.assertEqual( strip_margin("""|ADDRESS ROLES OBSERVED BY |akka.tcp://[email protected]:2552/user/reaper/cluster-client#-596247188 web,data akka.tcp://[email protected]:9004 |akka.tcp://[email protected]:2552/user/reaper/cluster-client#-775189131 web akka.tcp://[email protected]:9004 |akka.tcp://[email protected]:2552/user/reaper/cluster-client#1858099110 web,data akka.tcp://[email protected]:9004 |"""), self.output(stdout))
def test_stop(self): stdout = MagicMock() mock_is_docker_present = MagicMock(return_value=True) mock_get_running_haproxy = MagicMock(return_value='sandbox-haproxy') mock_docker_rm = MagicMock() args = MagicMock(**{}) with patch('conductr_cli.docker.is_docker_present', mock_is_docker_present), \ patch('conductr_cli.sandbox_proxy.get_running_haproxy', mock_get_running_haproxy), \ patch('conductr_cli.terminal.docker_rm', mock_docker_rm): logging_setup.configure_logging(args, stdout) self.assertTrue(sandbox_proxy.stop_proxy()) mock_get_running_haproxy.assert_called_once_with() mock_docker_rm.assert_called_once_with(['sandbox-haproxy']) expected_output = strip_margin( """||------------------------------------------------| || Stopping HAProxy | ||------------------------------------------------| |HAProxy has been successfully stopped |""") self.assertEqual(expected_output, self.output(stdout))
def test_error_with_affinity_switch(self): args = { 'host': '127.0.0.1', 'port': 9005, 'api_version': '1', 'verbose': False, 'no_wait': False, 'long_ids': False, 'cli_parameters': '', 'bundle': self.bundle_id, 'scale': self.scale, 'affinity': 'other-bundle' } stderr = MagicMock() logging_setup.configure_logging(MagicMock(**args), err_output=stderr) result = conduct_run.run(MagicMock(**args)) self.assertFalse(result) self.assertEqual( as_error( strip_margin( """|Error: Affinity feature is only available for v1.1 onwards of ConductR |""")), self.output(stderr))
def base_test_failure(self): resolve_bundle_mock = MagicMock(return_value=(self.bundle_file_name, self.bundle_file)) create_multipart_mock = MagicMock(return_value=self.multipart_mock) http_method = self.respond_with(404) stdout = MagicMock() stderr = MagicMock() open_mock = MagicMock(return_value=1) input_args = MagicMock(**self.default_args) with patch('conductr_cli.resolver.resolve_bundle', resolve_bundle_mock), \ patch('conductr_cli.conduct_load.create_multipart', create_multipart_mock), \ patch('requests.post', http_method), \ patch('builtins.open', open_mock): logging_setup.configure_logging(input_args, stdout, stderr) result = conduct_load.load(input_args) self.assertFalse(result) open_mock.assert_called_with(self.bundle_file, 'rb') resolve_bundle_mock.assert_called_with(self.custom_settings, self.bundle_resolve_cache_dir, self.bundle_file) create_multipart_mock.assert_called_with(self.conduct_load_logger, self.default_files) http_method.assert_called_with(self.default_url, data=self.multipart_mock, auth=self.conductr_auth, verify=self.server_verification_file, headers={'Content-Type': self.multipart_content_type, 'Host': '127.0.0.1'}) self.assertEqual( as_error(strip_margin("""|Error: 404 Not Found |""")), self.output(stderr))
def test_wait_timeout(self): count_installations_mock = MagicMock(side_effect=[1, 1, 1]) url_mock = MagicMock(return_value='/bundle-events/endpoint') get_events_mock = MagicMock(return_value=[ create_test_event('bundleInstallationAdded'), create_test_event('bundleInstallationAdded'), create_test_event('bundleInstallationAdded') ]) stdout = MagicMock() bundle_id = 'a101449418187d92c789d1adc240b6d6' args = MagicMock(**{ # Purposely set no timeout to invoke the error 'wait_timeout': -1 }) with patch('conductr_cli.conduct_url.url', url_mock), \ patch('conductr_cli.bundle_installation.count_installations', count_installations_mock), \ patch('conductr_cli.sse_client.get_events', get_events_mock): logging_setup.configure_logging(args, stdout) self.assertRaises(WaitTimeoutError, bundle_installation.wait_for_uninstallation, bundle_id, args) self.assertEqual(count_installations_mock.call_args_list, [call(bundle_id, args)]) url_mock.assert_called_with('bundles/events', args) self.assertEqual( strip_margin( """|Bundle a101449418187d92c789d1adc240b6d6 waiting to be uninstalled |"""), self.output(stdout))
def test_create_dir(self): args = MagicMock() stdout = MagicMock() remove = MagicMock() makedirs = MagicMock() symlink = MagicMock() logging_setup.configure_logging(args, stdout) with patch('shutil.which', lambda x: '/somefile'), \ patch('os.path.exists', lambda x: False), \ patch('os.remove', remove), \ patch('os.makedirs', makedirs), \ patch('os.symlink', symlink): result = conduct_dcos.setup(args) self.assertTrue(result) remove.assert_not_called() makedirs.assert_called_with('{}/.dcos/subcommands/conductr/env/bin'.format(os.path.expanduser('~')), exist_ok=True) symlink.assert_called_with('/somefile', '{}/.dcos/subcommands/conductr/env/bin/dcos-conduct'.format(os.path.expanduser('~'))) self.assertEqual( strip_margin("""|The DC/OS CLI is now configured. |Prefix \'conduct\' with \'dcos\' when you want to contact ConductR on DC/OS e.g. \'dcos conduct info\' |"""), self.output(stdout))
def test_multiple_events(self): http_method = self.respond_with(text="""[ { "timestamp":"2015-08-24T01:16:22.327Z", "host":"10.0.1.232", "message":"[WARN] [04/21/2015 12:54:30.079] [doc-renderer-cluster-1-akka.remote.default-remote-dispatcher-22] Association with remote system has failed." }, { "timestamp":"2015-08-24T01:16:25.327Z", "host":"10.0.1.232", "message":"[WARN] [04/21/2015 12:54:36.079] [doc-renderer-cluster-1-akka.remote.default-remote-dispatcher-26] Association with remote system has failed." } ]""") quote_method = MagicMock(return_value=self.bundle_id_urlencoded) stdout = MagicMock() input_args = MagicMock(**self.default_args) with patch('requests.get', http_method), \ patch('urllib.parse.quote', quote_method): logging_setup.configure_logging(input_args, stdout) result = conduct_logs.logs(input_args) self.assertTrue(result) http_method.assert_called_with(self.default_url, auth=self.conductr_auth, verify=self.server_verification_file, timeout=DEFAULT_HTTP_TIMEOUT, headers={'Host': '127.0.0.1'}) self.assertEqual( strip_margin("""|TIME HOST LOG |2015-08-24T01:16:22Z 10.0.1.232 [WARN] [04/21/2015 12:54:30.079] [doc-renderer-cluster-1-akka.remote.default-remote-dispatcher-22] Association with remote system has failed. |2015-08-24T01:16:25Z 10.0.1.232 [WARN] [04/21/2015 12:54:36.079] [doc-renderer-cluster-1-akka.remote.default-remote-dispatcher-26] Association with remote system has failed. |"""), self.output(stdout))
def test_custom_settings_no_resolver_config(self): custom_settings = ConfigFactory.parse_string( strip_margin("""|dummy = foo |""")) result = resolver.resolver_chain(custom_settings, False) expected_result = [stdin_resolver, uri_resolver, bintray_resolver] self.assertEqual(expected_result, result)
def test_ip(self): args = {} args.update(self.default_args) args.pop('host') args.update({'ip': '10.0.0.1'}) default_url = 'http://10.0.0.1:9005/bundles/{}/logs?count=1'.format(self.bundle_id_urlencoded) http_method = self.respond_with(text='{}') quote_method = MagicMock(return_value=self.bundle_id_urlencoded) stdout = MagicMock() input_args = MagicMock(**args) with patch('requests.get', http_method), \ patch('urllib.parse.quote', quote_method): logging_setup.configure_logging(input_args, stdout) result = conduct_logs.logs(input_args) self.assertTrue(result) http_method.assert_called_with(default_url, auth=self.conductr_auth, verify=self.server_verification_file, timeout=DEFAULT_HTTP_TIMEOUT, headers={'Host': '10.0.0.1'}) self.assertEqual( strip_margin("""|TIME HOST LOG |"""), self.output(stdout))
def __init__(self, method_name): super().__init__(method_name) self.bundle_id = "45e0c477d3e5ea92aa8d85c0d8f3e25c" self.nr_of_cpus = 1.0 self.memory = 200 self.disk_space = 100 self.roles = ["web-server"] self.bundle_file_name = "bundle.zip" self.system = "bundle" self.custom_settings = Mock() self.bundle_resolve_cache_dir = "bundle-resolve-cache-dir" self.tmpdir, self.bundle_file = create_temp_bundle( strip_margin( """|nrOfCpus = {}, |memory = {}, |diskSpace = {}, |roles = [{}], |name = {}, |system = {}, |""" ).format( self.nr_of_cpus, self.memory, self.disk_space, ", ".join(self.roles), self.bundle_file_name, self.system ) ) self.default_args = { "dcos_mode": False, "scheme": "http", "host": "127.0.0.1", "port": 9005, "base_path": "/", "api_version": "1", "disable_instructions": False, "verbose": False, "quiet": False, "no_wait": False, "long_ids": False, "command": "conduct", "cli_parameters": "", "custom_settings": self.custom_settings, "resolve_cache_dir": self.bundle_resolve_cache_dir, "bundle": self.bundle_file, "configuration": None, "conductr_auth": self.conductr_auth, "server_verification_file": self.server_verification_file, } self.default_url = "http://127.0.0.1:9005/bundles" self.default_files = [ ("nrOfCpus", str(self.nr_of_cpus)), ("memory", str(self.memory)), ("diskSpace", str(self.disk_space)), ("roles", " ".join(self.roles)), ("bundleName", self.bundle_file_name), ("system", self.system), ("bundle", (self.bundle_file_name, 1)), ]