Skip to content

Commit aadfdd4

Browse files
areeseAllen Reese
andauthored
Add a --token-file flag to the databricks configure command (#330)
* Add a --token-file flag to the databricks configure command This flag causes the databricks configure command to read the token from the specified file instead of from stdin. This can be used for places where the token is exposed as a secret in a file, but a complete configuration is not. * Fix whitespace formatting after merge to please lint again * Fix merge bug where configure_cli_token was being called right after _configure_cli_token_file Co-authored-by: Allen Reese <areese999@apple.com>
1 parent fb7eca2 commit aadfdd4

1 file changed

Lines changed: 61 additions & 26 deletions

File tree

  • databricks_cli/configure

databricks_cli/configure/cli.py

Lines changed: 61 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,59 +20,83 @@
2020
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2121
# See the License for the specific language governing permissions and
2222
# limitations under the License.
23-
23+
import io
2424
import os
25-
import click
25+
from os import path
2626

27+
import click
2728
from click import ParamType
2829

30+
from databricks_cli.configure.config import profile_option, get_profile_from_context, debug_option
2931
from databricks_cli.configure.provider import DatabricksConfig, update_and_persist_config, \
3032
ProfileConfigProvider
3133
from databricks_cli.utils import CONTEXT_SETTINGS
32-
from databricks_cli.configure.config import profile_option, get_profile_from_context, debug_option
3334

3435
PROMPT_HOST = 'Databricks Host (should begin with https://)'
3536
PROMPT_USERNAME = 'Username'
36-
PROMPT_PASSWORD = 'Password' # NOQA
37-
PROMPT_TOKEN = 'Token' # NOQA
37+
PROMPT_PASSWORD = 'Password' # NOQA
38+
PROMPT_TOKEN = 'Token' # NOQA
3839
ENV_AAD_TOKEN = 'DATABRICKS_AAD_TOKEN'
3940

4041

41-
def _configure_cli_token(profile, insecure):
42+
def _configure_cli_token_file(profile, token_file, host, insecure):
43+
if not path.exists(token_file):
44+
raise RuntimeError('Unable to read token from "{}"'.format(token_file))
45+
46+
with io.open(token_file, encoding='utf-8') as f:
47+
token = f.readline().strip()
48+
49+
config = ProfileConfigProvider(profile).get_config() or DatabricksConfig.empty()
50+
if not host:
51+
host = click.prompt(PROMPT_HOST, default=config.host, type=_DbfsHost())
52+
53+
new_config = DatabricksConfig.from_token(host, token, insecure)
54+
update_and_persist_config(profile, new_config)
55+
56+
57+
def _configure_cli_token(profile, insecure, host=None):
4258
config = ProfileConfigProvider(profile).get_config() or DatabricksConfig.empty()
43-
host = click.prompt(PROMPT_HOST, default=config.host, type=_DbfsHost())
44-
token = click.prompt(PROMPT_TOKEN, default=config.token)
59+
60+
if not host:
61+
host = click.prompt(PROMPT_HOST, default=config.host, type=_DbfsHost())
62+
63+
token = click.prompt(PROMPT_TOKEN, default=config.token, hide_input=True)
4564
new_config = DatabricksConfig.from_token(host, token, insecure)
4665
update_and_persist_config(profile, new_config)
4766

4867

49-
def _configure_cli_aad_token(profile, insecure):
68+
def _configure_cli_aad_token(profile, insecure, host=None):
5069
config = ProfileConfigProvider(profile).get_config() or DatabricksConfig.empty()
5170

5271
if ENV_AAD_TOKEN not in os.environ:
53-
print('[ERROR] Set Environment Variable \'%s\' with your '
54-
'AAD Token and run again.\n' % ENV_AAD_TOKEN)
55-
print('Commands to run to get your AAD token:\n'
56-
'\t az login\n'
57-
'\t token_response=$(az account get-access-token '
58-
'--resource 2ff814a6-3304-4ab8-85cb-cd0e6f879c1d)\n'
59-
'\t export %s=$(jq .accessToken -r <<< "$token_response")\n' % ENV_AAD_TOKEN
60-
)
72+
click.echo('[ERROR] Set Environment Variable \'%s\' with your '
73+
'AAD Token and run again.\n' % ENV_AAD_TOKEN)
74+
click.echo('Commands to run to get your AAD token:\n'
75+
'\t az login\n'
76+
'\t token_response=$(az account get-access-token '
77+
'--resource 2ff814a6-3304-4ab8-85cb-cd0e6f879c1d)\n'
78+
'\t export %s=$(jq .accessToken -r <<< "$token_response")\n' % ENV_AAD_TOKEN
79+
)
6180
return
6281

63-
host = click.prompt(PROMPT_HOST, default=config.host, type=_DbfsHost())
82+
if not host:
83+
host = click.prompt(PROMPT_HOST, default=config.host, type=_DbfsHost())
84+
6485
aad_token = os.environ.get(ENV_AAD_TOKEN)
6586
new_config = DatabricksConfig.from_token(host, aad_token, insecure)
6687
update_and_persist_config(profile, new_config)
6788

6889

69-
def _configure_cli_password(profile, insecure):
90+
def _configure_cli_password(profile, insecure, host):
7091
config = ProfileConfigProvider(profile).get_config() or DatabricksConfig.empty()
7192
if config.password:
7293
default_password = '*' * len(config.password)
7394
else:
7495
default_password = None
75-
host = click.prompt(PROMPT_HOST, default=config.host, type=_DbfsHost())
96+
97+
if not host:
98+
host = click.prompt(PROMPT_HOST, default=config.host, type=_DbfsHost())
99+
76100
username = click.prompt(PROMPT_USERNAME, default=config.username)
77101
password = click.prompt(PROMPT_PASSWORD, default=default_password, hide_input=True,
78102
confirmation_prompt=True)
@@ -84,29 +108,40 @@ def _configure_cli_password(profile, insecure):
84108

85109
@click.command(context_settings=CONTEXT_SETTINGS,
86110
short_help='Configures host and authentication info for the CLI.')
87-
@click.option('--token', show_default=True, is_flag=True, default=False)
111+
@click.option('--token', '-t', 'token', show_default=True, is_flag=True, default=False)
112+
@click.option('--token-file', '-f', 'token_file', default=None,
113+
help='Instead of reading the token from stdin, ' +
114+
'read the token from a file provided by a secret store.')
115+
@click.option('--host', show_default=True, default=None,
116+
help='Host to connect to.')
88117
@click.option('--aad-token', show_default=True, is_flag=True, default=False)
89-
@click.option('--insecure', show_default=True, is_flag=True, default=None)
118+
@click.option('--insecure', show_default=True, is_flag=True, default=None,
119+
help='DO NOT verify SSL Certificates')
90120
@debug_option
91121
@profile_option
92-
def configure_cli(token, aad_token, insecure):
122+
def configure_cli(token, aad_token, insecure, host, token_file):
93123
"""
94124
Configures host and authentication info for the CLI.
95125
"""
96126
profile = get_profile_from_context()
97127
insecure_str = str(insecure) if insecure is not None else None
128+
98129
if token:
99-
_configure_cli_token(profile, insecure_str)
130+
_configure_cli_token(profile=profile, insecure=insecure_str, host=host)
131+
elif token_file:
132+
_configure_cli_token_file(profile=profile, insecure=insecure_str, host=host,
133+
token_file=token_file)
100134
elif aad_token:
101-
_configure_cli_aad_token(profile, insecure_str)
135+
_configure_cli_aad_token(profile=profile, insecure=insecure_str, host=host)
102136
else:
103-
_configure_cli_password(profile, insecure_str)
137+
_configure_cli_password(profile=profile, insecure=insecure_str, host=host)
104138

105139

106140
class _DbfsHost(ParamType):
107141
"""
108142
Used to validate the configured host
109143
"""
144+
110145
def convert(self, value, param, ctx):
111146
if value.startswith('https://'):
112147
return value

0 commit comments

Comments
 (0)