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_success_with_affinity(self): args = { 'ip': '127.0.0.1', 'port': 9005, 'api_version': '2', 'verbose': False, 'quiet': False, 'no_wait': False, 'long_ids': False, 'cli_parameters': '', 'bundle': self.bundle_id, 'scale': self.scale, 'affinity': 'other-bundle' } expected_url = \ 'http://127.0.0.1:9005/v2/bundles/45e0c477d3e5ea92aa8d85c0d8f3e25c?scale=3&affinity=other-bundle' http_method = self.respond_with(200, self.default_response) wait_for_scale_mock = MagicMock() stdout = MagicMock() input_args = MagicMock(**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, stdout) result = conduct_run.run(input_args) self.assertTrue(result) http_method.assert_called_with(expected_url) wait_for_scale_mock.assert_called_with(self.bundle_id, self.scale, input_args) self.assertEqual(self.default_output(), self.output(stdout))
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_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 base_test_success_long_ids(self): http_method = self.respond_with(200, self.default_response) wait_for_scale_mock = MagicMock() stdout = MagicMock() args = self.default_args.copy() args.update({'long_ids': True}) input_args = MagicMock(**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, stdout) result = conduct_run.run(input_args) self.assertTrue(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( self.default_output(bundle_id='45e0c477d3e5ea92aa8d85c0d8f3e25c'), self.output(stdout))
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_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_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_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_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_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 base_test_success_verbose(self): resolve_bundle_mock = MagicMock(return_value=(self.bundle_name, self.bundle_file)) http_method = self.respond_with(200, self.default_response) stdout = MagicMock() open_mock = MagicMock(return_value=1) wait_for_installation_mock = MagicMock() args = self.default_args.copy() args.update({'verbose': True}) input_args = MagicMock(**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, stdout) result = conduct_load.load(input_args) self.assertTrue(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(self.default_output(verbose=self.default_response), 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_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_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 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_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 run(): # Parse arguments parser = build_parser() argcomplete.autocomplete(parser) args = parser.parse_args() # Print help or execute subparser function if not vars(args).get('func'): parser.print_help() # Validate image_version elif vars(args).get('func').__name__ == 'run' and not args.image_version: parser.exit('The version of the ConductR Docker image must be set.\n' 'Please visit https://www.lightbend.com/product/conductr/developer ' 'to obtain the current version information.') # Call sandbox function elif vars(args).get('func').__name__ == 'version': logging_setup.configure_logging(args) args.func(args) else: logging_setup.configure_logging(args) # Check that all feature arguments are valid if vars(args).get('func').__name__ == 'run': if args.features and args.no_wait: parser.exit('Option --no-wait is not allowed when starting ConductR with option --feature') invalid_features = [f for f, *a in args.features if f not in feature_names] if invalid_features: parser.exit('Invalid features: %s (choose from %s)' % (', '.join("'%s'" % f for f in invalid_features), ', '.join("'%s'" % f for f in feature_names))) # Docker VM validation args.vm_type = docker.vm_type() validate_docker_vm(args.vm_type) args.func(args)
def base_test_success(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(200, self.default_response) stdout = MagicMock() open_mock = MagicMock(return_value=1) wait_for_installation_mock = MagicMock() 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.conduct_url.request_headers', request_headers_mock), \ patch('conductr_cli.bundle_installation.wait_for_installation', wait_for_installation_mock): logging_setup.configure_logging(input_args, stdout) result = conduct_load.load(input_args) self.assertTrue(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) wait_for_installation_mock.assert_called_with(self.bundle_id, input_args) self.assertEqual(self.default_output(), 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_success_with_configuration(self): request_headers_mock = MagicMock(return_value=self.mock_headers) http_method = self.respond_with(200, self.default_response) wait_for_scale_mock = MagicMock() stdout = MagicMock() args = self.default_args.copy() cli_parameters = ' --ip 127.0.1.1 --port 9006' args.update({'cli_parameters': cli_parameters}) input_args = MagicMock(**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, stdout) result = conduct_run.run(input_args) self.assertTrue(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( self.default_output(params=cli_parameters), 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/45e0c477d3e5ea92aa8d85c0d8f3e25c?scale=0' http_method = self.respond_with(200, self.default_response) wait_for_scale_mock = MagicMock() stdout = MagicMock() input_args = MagicMock(**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, stdout) result = conduct_stop.stop(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'}) wait_for_scale_mock.assert_called_with(self.bundle_id, 0, input_args) self.assertEqual(self.default_output(), self.output(stdout))
def base_test_success_with_custom_host_port(self): http_method = self.respond_with(200, self.default_response) wait_for_scale_mock = MagicMock() stdout = MagicMock() args = self.default_args.copy() cli_parameters = ' --host 127.0.1.1 --port 9006' args.update({'cli_parameters': cli_parameters}) input_args = MagicMock(**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, stdout) result = conduct_run.run(input_args) self.assertTrue(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(self.default_output(params=cli_parameters), self.output(stdout))
def base_test_success_with_configuration(self): request_headers_mock = MagicMock(return_value=self.mock_headers) http_method = self.respond_with(200, self.default_response) wait_for_scale_mock = MagicMock() stdout = MagicMock() args = self.default_args.copy() cli_parameters = ' --ip 127.0.1.1 --port 9006' args.update({'cli_parameters': cli_parameters}) input_args = MagicMock(**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, stdout) result = conduct_run.run(input_args) self.assertTrue(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(self.default_output(params=cli_parameters), self.output(stdout))
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 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 test_no_ref(self): tmpdir = tempfile.mkdtemp() with tempfile.NamedTemporaryFile() as output: attributes = create_attributes_object({ 'name': 'test', 'source': tmpdir, 'format': 'oci-image', 'tag': 'latest', 'output': output.name }) stdout_mock = MagicMock() stderr_mock = MagicMock() logging_setup.configure_logging(MagicMock(), stdout_mock, stderr_mock) os.mkdir(os.path.join(tmpdir, 'refs')) open(os.path.join(tmpdir, 'oci-layout'), 'w').close() with \ patch('sys.stdin', MagicMock(**{'buffer': BytesIO(b'')})), \ patch('sys.stdout.buffer.write', stdout_mock): bndl_create.bndl_create(attributes) self.assertEqual( self.output(stderr_mock), as_error( 'Error: bndl: Invalid OCI Image. Cannot find requested tag "latest" in OCI Image\n' ))
def base_test_success_long_ids(self): request_headers_mock = MagicMock(return_value=self.mock_headers) http_method = self.respond_with(200, self.default_response) wait_for_scale_mock = MagicMock() stdout = MagicMock() args = self.default_args.copy() args.update({'long_ids': True}) input_args = MagicMock(**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, stdout) result = conduct_run.run(input_args) self.assertTrue(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( self.default_output(bundle_id='45e0c477d3e5ea92aa8d85c0d8f3e25c'), 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_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 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_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_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_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 base_test_failure_invalid_address(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_connection_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( self.default_connection_error.format(self.default_url), self.output(stderr))
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 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_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_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_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_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_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_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_start(self): stdout = MagicMock() mock_is_docker_present = MagicMock(return_value=True) mock_setup_haproxy_dirs = MagicMock() mock_stop_proxy = MagicMock() mock_start_docker_instance = MagicMock() mock_start_conductr_haproxy = MagicMock() args = MagicMock(**{}) with patch('conductr_cli.docker.is_docker_present', mock_is_docker_present), \ patch('conductr_cli.sandbox_proxy.setup_haproxy_dirs', mock_setup_haproxy_dirs), \ patch('conductr_cli.sandbox_proxy.stop_proxy', mock_stop_proxy), \ patch('conductr_cli.sandbox_proxy.start_docker_instance', mock_start_docker_instance), \ patch('conductr_cli.sandbox_proxy.start_conductr_haproxy', mock_start_conductr_haproxy): logging_setup.configure_logging(args, stdout) sandbox_proxy.start_proxy(ipaddress.ip_address('192.168.1.1'), 9000, [3003], [9999, 9200]) mock_is_docker_present.assert_called_once_with() mock_setup_haproxy_dirs.assert_called_once_with() mock_stop_proxy.assert_called_once_with() mock_start_docker_instance.assert_called_once_with( ipaddress.ip_address('192.168.1.1'), 9000, [3003], [9999, 9200]) mock_start_conductr_haproxy.assert_called_once_with() self.assertEqual('', self.output(stdout))
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_success_with_configuration(self): tmpdir, config_file = create_temp_bundle_with_contents({ 'bundle.conf': '{name="overlaid-name"}', 'config.sh': 'echo configuring' }) request_headers_mock = MagicMock(return_value=self.mock_headers) resolve_bundle_mock = MagicMock(side_effect=[(self.bundle_name, self.bundle_file), ('config.zip', config_file)]) zip_entry_mock = MagicMock(side_effect=['mock bundle.conf', 'mock bundle.conf overlay']) http_method = self.respond_with(200, self.default_response) stdout = MagicMock() open_mock = MagicMock(return_value=1) wait_for_installation_mock = MagicMock() args = self.default_args.copy() args.update({'configuration': config_file}) input_args = MagicMock(**args) with patch('conductr_cli.resolver.resolve_bundle', resolve_bundle_mock), \ patch('conductr_cli.bundle_utils.zip_entry', zip_entry_mock), \ patch('conductr_cli.conduct_url.request_headers', request_headers_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, stdout) result = conduct_load.load(input_args) self.assertTrue(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, config_file) ] ) self.assertEqual( open_mock.call_args_list, [call(self.bundle_file, 'rb'), call(config_file, 'rb')] ) request_headers_mock.assert_called_with(input_args) expected_files = [ ('bundleConf', ('bundle.conf', 'mock bundle.conf')), ('bundleConfOverlay', ('bundle.conf', 'mock bundle.conf overlay')), ('bundle', ('bundle.zip', 1)), ('configuration', ('config.zip', 1)) ] http_method.assert_called_with(self.default_url, files=expected_files, timeout=LOAD_HTTP_TIMEOUT, headers=self.mock_headers) wait_for_installation_mock.assert_called_with(self.bundle_id, input_args) self.assertEqual(self.default_output(downloading_configuration='Retrieving configuration...\n'), self.output(stdout)) self.assertEqual( zip_entry_mock.call_args_list, [call('bundle.conf', self.bundle_file), call('bundle.conf', config_file)] )
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 run(): # Parse arguments parser = build_parser() argcomplete.autocomplete(parser) args = parser.parse_args() # Print help or execute subparser function if vars(args).get('func') is None: parser.print_help() # Exit with sandbox debug error message elif vars(args).get('func') == 'debug': parser.exit( 'Debugging a ConductR cluster is not supported by the \'conductr-cli\'.\n' 'Use the sbt plugin \'sbt-conductr-sandbox\' instead.') # Validate host IP address elif args.resolve_ip and not sandbox_common.resolve_host_ip(): return # Validate image_version elif vars(args).get('func').__name__ == 'run' and not args.image_version: parser.exit( 'The version of the ConductR Docker image must be set.\n' 'Please visit https://www.typesafe.com/product/conductr/developer ' 'to obtain the current version information.') # Call sandbox function else: logging_setup.configure_logging(args) args.func(args)
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_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_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_invalid_address(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_connection_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( self.default_connection_error.format(self.default_url), self.output(stderr))
def run(): # Parse arguments parser = build_parser() argcomplete.autocomplete(parser) args = parser.parse_args() if not vars(args).get('func'): parser.print_help() else: # Add custom plugin dir to import path custom_plugins_dir = vars(args).get('custom_plugins_dir') if custom_plugins_dir: sys.path.append(custom_plugins_dir) # Resolve default ip if the --ip argument hasn't been specified if not vars(args).get('ip'): # Returns None if an error has occurred args.ip = host.resolve_default_ip() if not args.ip: return else: args.local_connection = False args.cli_parameters = get_cli_parameters(args) args.custom_settings = get_custom_settings(args) logging_setup.configure_logging(args) is_completed_without_error = args.func(args) if not is_completed_without_error: exit(1)
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 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 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_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 base_test_success(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) stdout = MagicMock() open_mock = MagicMock(return_value=1) wait_for_installation_mock = MagicMock() cleanup_old_bundles_mock = MagicMock() 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('conductr_cli.conduct_load.cleanup_old_bundles', cleanup_old_bundles_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, stdout) result = conduct_load.load(input_args) self.assertTrue(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'}) wait_for_installation_mock.assert_called_with(self.bundle_id, input_args) cleanup_old_bundles_mock.assert_called_with(self.bundle_resolve_cache_dir, self.bundle_file_name, excluded=self.bundle_file) self.assertEqual(self.default_output(), self.output(stdout))
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_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)