Commit db03f805 authored by Stavros Sachtouris's avatar Stavros Sachtouris
Browse files

Make authentication lazy

Refs: #4300

Authentication (a.k.a. POST /tokens) is performed only if needed, therefore a
syntax query will not request for authentication.

A new method is introduced in kamaki.cli: init_chached_authenticator. This
method authenticated the resolved URL and TOKEN(s).

Until now, this functionality was part of the _init_session method located at
kamaki.cli entry point. Now, this method call has been pushed down.

In case of an interactive shell, the method is called during the shell setup
In case of a one_command, the method is called right before a new executable
command is initialized. This also means that a non-executable command name
space will not cause the execution of init_cached_authenticator.
parent 7f869771
......@@ -229,7 +229,7 @@ def _check_config_version(cnf):
def _init_session(arguments, is_non_API=False):
:returns: (AuthCachedClient, str) authenticator and cloud name
:returns: cloud name
global _help
_help = arguments['help'].value
......@@ -245,7 +245,7 @@ def _init_session(arguments, is_non_API=False):
_setup_logging(_silent, _debug, _verbose, _include)
if _help or is_non_API:
return None, None
return None
......@@ -299,32 +299,34 @@ def _init_session(arguments, is_non_API=False):
'Set a %s for cloud %s:' % (term.upper(), cloud),
' kamaki config set cloud.%s.%s <%s>' % (
cloud, term, term.upper())])
return cloud
def init_cached_authenticator(url, tokens, config_module, logger):
auth_base = None
for token in reversed(auth_args['token'].split()):
for token in reversed(tokens):
if auth_base:
auth_base = AuthCachedClient(
auth_args['url'], auth_args['token'])
auth_base = AuthCachedClient(url, tokens)
from kamaki.cli.commands import _command_init
fake_cmd = _command_init(arguments)
fake_cmd = _command_init(dict(config=config_module))
fake_cmd.client = auth_base
except ClientError as ce:
if ce.status in (401, ):
'WARNING: Failed to authorize token %s' % token)
'WARNING: Failed to authenticate token %s' % token)
return auth_base, cloud
return auth_base
except AssertionError as ae:
kloger.warning('WARNING: Failed to load authenticator [%s]' % ae)
return None, cloud
logger.warning('WARNING: Failed to load authenticator [%s]' % ae)
return None
def _load_spec_module(spec, arguments, module):
......@@ -475,17 +477,21 @@ def set_command_params(parameters):
# CLI Choice:
def run_one_cmd(exe_string, parser, auth_base, cloud):
def run_one_cmd(exe_string, parser, cloud):
global _history
_history = History(
_history = History(parser.arguments['config'].get_global('history_file'))
_history.add(' '.join([exe_string] + argv[1:]))
from kamaki.cli import one_command, cloud, parser, _help), parser, _help)
def run_shell(exe_string, parser, auth_base, cloud):
def run_shell(exe_string, parser, cloud):
from command_shell import _init_shell
global kloger
_cnf = parser.arguments['config']
auth_base = init_cached_authenticator(
_cnf.get_cloud(cloud, 'url'), _cnf.get_cloud(cloud, 'token').split(),
_cnf, kloger)
username, userid = (
auth_base.user_term('name'), auth_base.user_term('id'))
......@@ -514,27 +520,27 @@ def main():
if parser.arguments['version'].value:
log_file = parser.arguments['config'].get_global('log_file')
_cnf = parser.arguments['config']
log_file = _cnf.get_global('log_file')
if log_file:
global filelog
filelog = logger.add_file_logger(__name__.split('.')[0])'* Initial Call *\n%s\n- - -' % ' '.join(argv))
auth_base, cloud = _init_session(parser.arguments, is_non_API(parser))
cloud = _init_session(parser.arguments, is_non_API(parser))
from kamaki.cli.utils import suggest_missing
global _colors
exclude = ['ansicolors'] if not _colors == 'on' else []
if parser.unparsed:
run_one_cmd(exe, parser, auth_base, cloud)
run_one_cmd(exe, parser, cloud)
elif _help:
run_shell(exe, parser, auth_base, cloud)
run_shell(exe, parser, cloud)
except CLIError as err:
if _debug:
......@@ -31,10 +31,10 @@
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.command
from kamaki.cli import get_command_group, set_command_params
from kamaki.cli import print_subcommands_help, exec_cmd, update_parser_help
from kamaki.cli import _groups_help, _load_spec_module
from kamaki.cli import kloger
from kamaki.cli import (
get_command_group, set_command_params, print_subcommands_help, exec_cmd,
update_parser_help, _groups_help, _load_spec_module,
init_cached_authenticator, kloger)
from kamaki.cli.errors import CLIUnknownCommand
......@@ -55,7 +55,7 @@ def _get_best_match_from_cmd_tree(cmd_tree, unparsed):
return None
def run(auth_base, cloud, parser, _help):
def run(cloud, parser, _help):
group = get_command_group(list(parser.unparsed), parser.arguments)
if not group:
......@@ -68,7 +68,8 @@ def run(auth_base, cloud, parser, _help):
global _best_match
_best_match = []
group_spec = parser.arguments['config'].get('global', '%s_cli' % group)
_cnf = parser.arguments['config']
group_spec = _cnf.get('global', '%s_cli' % group)
spec_module = _load_spec_module(group_spec, parser.arguments, '_commands')
if spec_module is None:
raise CLIUnknownCommand(
......@@ -98,9 +99,11 @@ def run(auth_base, cloud, parser, _help):
cls = cmd.cmd_class
auth_base = init_cached_authenticator(
_cnf.get_cloud(cloud, 'url'), _cnf.get_cloud(cloud, 'token').split(),
_cnf, kloger)
executable = cls(parser.arguments, auth_base, cloud)
#parsed, unparsed = parse_known_args(parser, executable.arguments)
for term in _best_match:
exec_cmd(executable, parser.unparsed, parser.parser.print_help)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment