def test_env_var_provider_configure_encrypted_value(): def check_env_var_provider_config_local_state(dirname): provider = EnvVarProvider() requirement = _load_env_var_requirement(dirname, "FOO_PASSWORD") assert requirement.encrypted local_state_file = LocalStateFile.load_for_directory(dirname) status = requirement.check_status(dict(), local_state_file, 'default', UserConfigOverrides()) assert dict(source='unset') == status.analysis.config assert local_state_file.get_value(['variables', 'FOO_PASSWORD' ]) is None assert set(keyring.fallback_data().values()) == set() environ = dict(CONDA_DEFAULT_ENV='/pretend/env', CONDA_ENV_PATH='/pretend/env', CONDA_PREFIX='/pretend/env') provider.set_config_values_as_strings(requirement, environ, local_state_file, 'default', UserConfigOverrides(), dict(value="bar")) # should not have affected local state, should use keyring assert local_state_file.get_value(['variables', 'FOO_PASSWORD' ]) is None assert set(keyring.fallback_data().values()) == set(["bar"]) # setting empty string = unset provider.set_config_values_as_strings(requirement, environ, local_state_file, 'default', UserConfigOverrides(), dict(value="")) assert local_state_file.get_value(['variables', 'FOO_PASSWORD' ]) is None assert set(keyring.fallback_data().values()) == set() keyring.enable_fallback_keyring() try: with_directory_contents_completing_project_file( {DEFAULT_PROJECT_FILENAME: """ variables: - FOO_PASSWORD """}, check_env_var_provider_config_local_state) finally: keyring.disable_fallback_keyring()
def test_ask_variables_interactively(monkeypatch): def check(dirname): project_dir_disable_dedicated_env(dirname) def mock_is_interactive(): return True monkeypatch.setattr( 'anaconda_project.internal.cli.console_utils.stdin_is_interactive', mock_is_interactive) inputs = ["foo", "bar"] def mock_console_input(prompt, encrypted): return inputs.pop(0) monkeypatch.setattr( 'anaconda_project.internal.cli.console_utils.console_input', mock_console_input) res = _parse_args_and_run_subcommand( ['anaconda-project', 'prepare', '--directory', dirname]) assert res == 0 local_state = LocalStateFile.load_for_directory(dirname) assert local_state.get_value(['variables', 'FOO']) == 'foo' assert local_state.get_value(['variables', 'BAR_PASSWORD']) is None assert set(keyring.fallback_data().values()) == set(['bar']) keyring.enable_fallback_keyring() try: with_directory_contents_completing_project_file( { DEFAULT_PROJECT_FILENAME: """ variables: FOO: null BAR_PASSWORD: null """ }, check) finally: keyring.disable_fallback_keyring()
def test_prepare_asking_for_password_with_browser(monkeypatch): keyring.reset_keyring_module() # In this scenario, we store a password in the keyring. from tornado.ioloop import IOLoop io_loop = IOLoop() http_results = {} def click_submit(url): from anaconda_project.internal.test.http_utils import http_get_async, http_post_async from tornado import gen @gen.coroutine def do_http(): http_results['get_click_submit'] = get_response = yield http_get_async(url) if get_response.code != 200: raise Exception("got a bad http response " + repr(get_response)) http_results['post_click_submit'] = post_response = yield http_post_async(url, body="") assert 200 == post_response.code assert '</form>' in str(post_response.body) assert 'FOO_PASSWORD' in str(post_response.body) fill_in_password(url, post_response) io_loop.add_callback(do_http) def fill_in_password(url, first_response): from anaconda_project.internal.test.http_utils import http_post_async from anaconda_project.internal.plugin_html import _BEAUTIFUL_SOUP_BACKEND from tornado import gen from bs4 import BeautifulSoup if first_response.code != 200: raise Exception("got a bad http response " + repr(first_response)) # set the FOO_PASSWORD field soup = BeautifulSoup(first_response.body, _BEAUTIFUL_SOUP_BACKEND) password_fields = soup.find_all("input", attrs={'type': 'password'}) if len(password_fields) == 0: print("No password fields in " + repr(soup)) raise Exception("password field not found") else: field = password_fields[0] assert 'name' in field.attrs @gen.coroutine def do_http(): http_results['post_fill_in_password'] = yield http_post_async(url, form={field['name']: 'bloop'}) io_loop.add_callback(do_http) def mock_open_new_tab(url): return click_submit(url) monkeypatch.setattr('webbrowser.open_new_tab', mock_open_new_tab) def prepare_with_browser(dirname): project = project_no_dedicated_env(dirname) environ = minimal_environ() result = prepare_with_browser_ui(project, environ=environ, keep_going_until_success=False, io_loop=io_loop) assert result.errors == [] assert result assert dict(FOO_PASSWORD='******', PROJECT_DIR=project.directory_path) == strip_environ(result.environ) assert dict() == strip_environ(environ) # wait for the results of the POST to come back, # awesome hack-tacular while 'post_fill_in_password' not in http_results: io_loop.call_later(0.01, lambda: io_loop.stop()) io_loop.start() assert 'get_click_submit' in http_results assert 'post_click_submit' in http_results assert 'post_fill_in_password' in http_results assert 200 == http_results['get_click_submit'].code assert 200 == http_results['post_click_submit'].code assert 200 == http_results['post_fill_in_password'].code final_done_html = str(http_results['post_fill_in_password'].body) assert "Done!" in final_done_html assert "Environment variable FOO_PASSWORD is set." in final_done_html local_state_file = LocalStateFile.load_for_directory(project.directory_path) assert local_state_file.get_value(['variables', 'FOO_PASSWORD']) is None # now a no-browser prepare() should read password from the # keyring keyring.enable_fallback_keyring() try: with_directory_contents_completing_project_file( {DEFAULT_PROJECT_FILENAME: """ variables: FOO_PASSWORD: {} """}, prepare_with_browser) finally: keyring.disable_fallback_keyring()
def _with_fallback_keyring(f): try: keyring.enable_fallback_keyring() f() finally: keyring.disable_fallback_keyring()