Commit 844a6bdb authored by Stavros Sachtouris's avatar Stavros Sachtouris
Browse files

Adjust config cli commands to serve remotes

Refs: #3934

config set remote.smth.option value
  inserts option=value in remote smth
config get remote.smth
  lists the contents (key=val) of remote smth
config delete remote.smth.option
  deletes this specific option from the remote smth
config delete remote.smth
  completely erased the remote smth
parent 362adf50
......@@ -222,6 +222,9 @@ def _check_config_version(cnf):
def _init_session(arguments, is_non_API=False):
"""
:returns: (AuthCachedClient, str) authenticator and cloud remote name
"""
global _help
_help = arguments['help'].value
global _debug
......@@ -242,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
return None, None
cloud = arguments['cloud'].value or 'default'
if not cloud in _cnf.value.keys('remote'):
......@@ -253,26 +256,23 @@ def _init_session(arguments, is_non_API=False):
'single authentication URL and token:',
' kamaki config set remote.%s.url <URL>' % cloud,
' kamaki config set remote.%s.token <t0k3n>' % cloud])
url = _cnf.get_remote(cloud, 'url')
if not url:
kloger.warning(
'WARNING: No remote.%s.url, use service urls instead' % cloud)
return cloud
token = _cnf.get_remote(cloud, 'token')
if not token:
raise CLIError(
'No authentication token provided for %s cloud' % cloud,
importance=3, details=[
'Get and set a token for %s cloud:' % cloud,
' kamaki config set remote.%s.token <t0k3n>' % cloud])
auth_args = dict()
for term in ('url', 'token'):
auth_args[term] = _cnf.get_remote(cloud, term)
if not auth_args[term]:
raise CLIError(
'No authentication %s provided for %s cloud' % (term, cloud),
importance=3, details=[
'Get and set a %s for %s cloud:' % (term, cloud),
' kamaki config set remote.%s.%s <t0k3n>' % (term, cloud)
])
from kamaki.clients.astakos import AstakosClient as AuthCachedClient
try:
return AuthCachedClient(url, token)
return AuthCachedClient(auth_args['url'], auth_args['token']), cloud
except AssertionError as ae:
kloger.warning(
'WARNING: Failed to load auth_url %s [ %s ]' % (url, ae))
return None
kloger.warning('WARNING: Failed to load authenticator [%s]' % ae)
return None, cloud
def _load_spec_module(spec, arguments, module):
......@@ -417,20 +417,20 @@ def set_command_params(parameters):
# CLI Choice:
def run_one_cmd(exe_string, parser, auth_base):
def run_one_cmd(exe_string, parser, auth_base, cloud):
global _history
_history = History(
parser.arguments['config'].get_global('history_file'))
_history.add(' '.join([exe_string] + argv[1:]))
from kamaki.cli import one_command
one_command.run(auth_base, parser, _help)
one_command.run(auth_base, cloud, parser, _help)
def run_shell(exe_string, parser, auth_base):
def run_shell(exe_string, parser, auth_base, cloud):
from command_shell import _init_shell
shell = _init_shell(exe_string, parser)
_load_all_commands(shell.cmd_tree, parser.arguments)
shell.run(auth_base, parser)
shell.run(auth_base, cloud, parser)
def is_non_API(parser):
......@@ -458,18 +458,18 @@ def main():
filelog = logger.add_file_logger(__name__.split('.')[0])
filelog.info('* Initial Call *\n%s\n- - -' % ' '.join(argv))
remote_base = _init_session(parser.arguments, is_non_API(parser))
auth_base, cloud = _init_session(parser.arguments, is_non_API(parser))
from kamaki.cli.utils import suggest_missing
suggest_missing()
if parser.unparsed:
run_one_cmd(exe, parser, remote_base)
run_one_cmd(exe, parser, auth_base, cloud)
elif _help:
parser.parser.print_help()
_groups_help(parser.arguments)
else:
run_shell(exe, parser, remote_base)
run_shell(exe, parser, auth_base, cloud)
except CLIError as err:
print_error_message(err)
if _debug:
......
......@@ -298,8 +298,9 @@ class Shell(Cmd):
hdr = tmp_partition[0].strip()
return '%s commands:' % hdr
def run(self, auth_base, parser, path=''):
def run(self, auth_base, cloud, parser, path=''):
self.auth_base = auth_base
self.cloud = cloud
self._parser = parser
self._history = History(
parser.arguments['config'].get_global('history_file'))
......
......@@ -34,15 +34,13 @@
from kamaki.cli.logger import get_logger
from kamaki.cli.utils import print_json, print_items
from kamaki.cli.argument import FlagArgument
from kamaki.cli.errors import CLIError
from kamaki.clients import Client
log = get_logger(__name__)
class _command_init(object):
def __init__(self, arguments={}, auth_base_or_remote=None):
def __init__(self, arguments={}, auth_base=None, cloud=None):
if hasattr(self, 'arguments'):
arguments.update(self.arguments)
if isinstance(self, _optional_output_cmd):
......@@ -54,12 +52,8 @@ class _command_init(object):
self.config = self['config']
except KeyError:
pass
if isinstance(auth_base_or_remote, Client):
self.auth_base = auth_base_or_remote
elif not getattr(self, 'auth_base', None):
self.remote = auth_base_or_remote
if not self.remote:
raise CLIError('CRITICAL: No cloud specified', 3)
self.auth_base = auth_base or getattr(self, 'auth_base', None)
self.cloud = cloud or getattr(self, 'cloud', None)
def _set_log_params(self):
try:
......
......@@ -31,10 +31,13 @@
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
from sys import stdout
from kamaki.cli import command
from kamaki.cli.argument import FlagArgument
from kamaki.cli.commands import _command_init, errors
from kamaki.cli.command_tree import CommandTree
from kamaki.cli.errors import CLIError, CLISyntaxError
config_cmds = CommandTree('config', 'Kamaki configurations')
_commands = [config_cmds]
......@@ -64,7 +67,12 @@ class config_list(_command_init):
for section in sorted(self.config.sections()):
items = self.config.items(section)
for key, val in sorted(items):
print('%s.%s = %s' % (section, key, val))
if section in ('remote',):
prefix = '%s.%s' % (section, key)
for k, v in val.items():
print('%s..%s = %s' % (prefix, k, v))
else:
print('%s.%s = %s' % (section, key, val))
def main(self):
self._run()
......@@ -79,9 +87,25 @@ class config_get(_command_init):
@errors.generic.all
def _run(self, option):
section, sep, key = option.rpartition('.')
section = section or 'global'
value = self.config.get(section, key)
if value:
if not sep:
match = False
for k in self.config.keys(key):
match = True
if option != 'remote':
stdout.write('%s.%s =' % (option, k))
self._run('%s.%s' % (option, k))
if match:
return
section = 'global'
prefix = 'remote.'
get, section = (
self.config.get_remote, section[len(prefix):]) if (
section.startswith(prefix)) else (self.config.get, section)
value = get(section, key)
if isinstance(value, dict):
for k, v in value.items():
print('%s.%s.%s = %s' % (section, key, k, v))
elif value:
print(value)
def main(self, option):
......@@ -97,8 +121,19 @@ class config_set(_command_init):
@errors.generic.all
def _run(self, option, value):
section, sep, key = option.rpartition('.')
section = section or 'global'
self.config.set(section, key, value)
prefix = 'remote.'
if section.startswith(prefix):
self.config.set_remote(section[len(prefix):], key, value)
elif section in ('remote',):
raise CLISyntaxError(
'Invalid syntax for cloud definition', importance=2, details=[
'To define a cloud remote "%s"' % key,
'set the cloud\'s authentication url and token:',
' /config set remote.%s.url <URL>' % key,
' /config set remote.%s.token <t0k3n>' % key])
else:
section = section or 'global'
self.config.set(section, key, value)
self.config.write()
self.config.reload()
......@@ -123,7 +158,15 @@ class config_delete(_command_init):
def _run(self, option):
section, sep, key = option.rpartition('.')
section = section or 'global'
self.config.remove_option(section, key, self['default'])
prefix = 'remote.'
if section.startswith(prefix):
remote = section[len(prefix):]
try:
self.config.remove_from_remote(remote, key)
except KeyError:
raise CLIError('Field %s does not exist' % option)
else:
self.config.remove_option(section, key, self['default'])
self.config.write()
self.config.reload()
......
......@@ -50,7 +50,9 @@ class generic(object):
if _debug:
print_stack()
print_exc(e)
raiseCLIError(e)
if isinstance(e, CLIError):
raiseCLIError(e)
raiseCLIError(e, details=['%s, -d for debug info' % type(e)])
return _raise
@classmethod
......
......@@ -248,9 +248,9 @@ class Config(RawConfigParser):
def set_remote(self, remote, option, value):
try:
d = self.get('remote', remote)
d = self.get('remote', remote) or dict()
except KeyError:
pass
d = dict()
d[option] = value
self.set('remote', remote, d)
......@@ -299,6 +299,11 @@ class Config(RawConfigParser):
except NoSectionError:
pass
def remove_from_remote(self, remote, option):
d = self.get('remote', remote)
if isinstance(d, dict):
d.pop(option)
def keys(self, section, include_defaults=True):
d = self._get_dict(section, include_defaults)
return d.keys()
......
......@@ -55,7 +55,7 @@ def _get_best_match_from_cmd_tree(cmd_tree, unparsed):
return None
def run(remote_base, parser, _help):
def run(remote_base, cloud, parser, _help):
group = get_command_group(list(parser.unparsed), parser.arguments)
if not group:
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