Revision 144b3551

b/kamaki/cli/__init__.py
223 223

  
224 224
def _init_session(arguments, is_non_API=False):
225 225
    """
226
    :returns: (AuthCachedClient, str) authenticator and cloud remote name
226
    :returns: (AuthCachedClient, str) authenticator and cloud name
227 227
    """
228 228
    global _help
229 229
    _help = arguments['help'].value
......
248 248
        return None, None
249 249

  
250 250
    cloud = arguments['cloud'].value or 'default'
251
    if not cloud in _cnf.value.keys('remote'):
251
    if not cloud in _cnf.value.keys('cloud'):
252 252
        raise CLIError(
253
            'No cloud remote "%s" is configured' % cloud,
253
            'No cloud "%s" is configured' % cloud,
254 254
            importance=3, details=[
255
                'To configure a new cloud remote, find and set the',
255
                'To configure a new cloud, find and set the',
256 256
                'single authentication URL and token:',
257
                '  kamaki config set remote.%s.url <URL>' % cloud,
258
                '  kamaki config set remote.%s.token <t0k3n>' % cloud])
257
                '  kamaki config set cloud.%s.url <URL>' % cloud,
258
                '  kamaki config set cloud.%s.token <t0k3n>' % cloud])
259 259
    auth_args = dict()
260 260
    for term in ('url', 'token'):
261
        auth_args[term] = _cnf.get_remote(cloud, term)
261
        auth_args[term] = _cnf.get_cloud(cloud, term)
262 262
        if not auth_args[term]:
263 263
            raise CLIError(
264 264
                'No authentication %s provided for %s cloud' % (term, cloud),
265 265
                importance=3, details=[
266 266
                    'Get and set a %s for %s cloud:' % (term, cloud),
267
                    '  kamaki config set remote.%s.%s <t0k3n>' % (term, cloud)
267
                    '  kamaki config set cloud.%s.%s <t0k3n>' % (term, cloud)
268 268
                ])
269 269

  
270 270
    from kamaki.clients.astakos import AstakosClient as AuthCachedClient
b/kamaki/cli/argument.py
181 181
    def get_global(self, option):
182 182
        return self.value.get_global(option)
183 183

  
184
    def get_remote(self, remote, option):
185
        return self.value.get_remote(remote, option)
184
    def get_cloud(self, cloud, option):
185
        return self.value.get_cloud(cloud, option)
186 186

  
187 187
_config_arg = ConfigArgument(
188 188
    1, 'Path to configuration file', ('-c', '--config'))
......
409 409

  
410 410
_arguments = dict(
411 411
    config=_config_arg,
412
    cloud=ValueArgument('Chose a remote cloud to connect to', ('--cloud')),
412
    cloud=ValueArgument('Chose a cloud to connect to', ('--cloud')),
413 413
    help=Argument(0, 'Show help message', ('-h', '--help')),
414 414
    debug=FlagArgument('Include debug output', ('-d', '--debug')),
415 415
    include=FlagArgument(
b/kamaki/cli/commands/__init__.py
76 76

  
77 77
    @DontRaiseKeyError
78 78
    def _custom_url(self, service):
79
        return self.config.get_remote(self.cloud, '%s_url' % service)
79
        return self.config.get_cloud(self.cloud, '%s_url' % service)
80 80

  
81 81
    @DontRaiseKeyError
82 82
    def _custom_token(self, service):
83
        return self.config.get_remote(self.cloud, '%s_token' % service)
83
        return self.config.get_cloud(self.cloud, '%s_token' % service)
84 84

  
85 85
    @DontRaiseKeyError
86 86
    def _custom_type(self, service):
87
        return self.config.get_remote(self.cloud, '%s_type' % service)
87
        return self.config.get_cloud(self.cloud, '%s_type' % service)
88 88

  
89 89
    @DontRaiseKeyError
90 90
    def _custom_version(self, service):
91
        return self.config.get_remote(self.cloud, '%s_version' % service)
91
        return self.config.get_cloud(self.cloud, '%s_version' % service)
92 92

  
93 93
    def _set_log_params(self):
94 94
        try:
b/kamaki/cli/commands/astakos.py
53 53
            base_url = self._custom_url('astakos')
54 54
            if base_url:
55 55
                token = self._custom_token('astakos')\
56
                    or self.config.get_remote(self.cloud, 'token')
56
                    or self.config.get_cloud(self.cloud, 'token')
57 57
                self.client = AstakosClient(base_url=base_url, token=token)
58 58
                return
59 59
        else:
......
72 72
    """Authenticate a user
73 73
    Get user information (e.g. unique account name) from token
74 74
    Token should be set in settings:
75
    *  check if a token is set    /config get remote.default.token
76
    *  permanently set a token    /config set remote.default.token <token>
75
    *  check if a token is set    /config get cloud.default.token
76
    *  permanently set a token    /config set cloud.default.token <token>
77 77
    Token can also be provided as a parameter
78
    (In case of another named cloud remote, use its name instead of default)
78
    (In case of another named cloud, use its name instead of default)
79 79
    """
80 80

  
81 81
    @staticmethod
b/kamaki/cli/commands/config.py
50 50
    \n.   [group]\
51 51
    \n.   option=value\
52 52
    \n.   (more options can be set per group)\
53
    \n. special case: named cloud remotes.\
53
    \n. special case: named clouds.\
54 54
    \n. E.g. for a cloud "demo":\
55
    \n.   [remote "demo"]\
55
    \n.   [cloud "demo"]\
56 56
    \n.   url = <http://single/authentication/url/for/demo/site>\
57 57
    \n.   token = <auth_token_from_demo_site>\
58
    \n. which are referenced as remote.demo.url , remote.demo.token'
58
    \n. which are referenced as cloud.demo.url , cloud.demo.token'
59 59

  
60 60

  
61 61
@command(config_cmds)
......
73 73
        for section in sorted(self.config.sections()):
74 74
            items = self.config.items(section)
75 75
            for key, val in sorted(items):
76
                if section in ('remote',):
76
                if section in ('cloud',):
77 77
                    prefix = '%s.%s' % (section, key)
78 78
                    for k, v in val.items():
79 79
                        print('%s..%s = %s' % (prefix, k, v))
......
97 97
            match = False
98 98
            for k in self.config.keys(key):
99 99
                match = True
100
                if option != 'remote':
100
                if option != 'cloud':
101 101
                    stdout.write('%s.%s =' % (option, k))
102 102
                self._run('%s.%s' % (option, k))
103 103
            if match:
104 104
                return
105 105
            section = 'global'
106
        prefix = 'remote.'
106
        prefix = 'cloud.'
107 107
        get, section = (
108
            self.config.get_remote, section[len(prefix):]) if (
108
            self.config.get_cloud, section[len(prefix):]) if (
109 109
                section.startswith(prefix)) else (self.config.get, section)
110 110
        value = get(section, key)
111 111
        if isinstance(value, dict):
......
127 127
    @errors.generic.all
128 128
    def _run(self, option, value):
129 129
        section, sep, key = option.rpartition('.')
130
        prefix = 'remote.'
130
        prefix = 'cloud.'
131 131
        if section.startswith(prefix):
132
            self.config.set_remote(section[len(prefix):], key, value)
133
        elif section in ('remote',):
132
            self.config.set_cloud(section[len(prefix):], key, value)
133
        elif section in ('cloud',):
134 134
            raise CLISyntaxError(
135 135
                'Invalid syntax for cloud definition', importance=2, details=[
136
                    'To define a cloud remote "%s"' % key,
136
                    'To define a cloud "%s"' % key,
137 137
                    'set the cloud\'s authentication url and token:',
138
                    '  /config set remote.%s.url <URL>' % key,
139
                    '  /config set remote.%s.token <t0k3n>' % key])
138
                    '  /config set cloud.%s.url <URL>' % key,
139
                    '  /config set cloud.%s.token <t0k3n>' % key])
140 140
        else:
141 141
            section = section or 'global'
142 142
            self.config.set(section, key, value)
......
164 164
    def _run(self, option):
165 165
        section, sep, key = option.rpartition('.')
166 166
        section = section or 'global'
167
        prefix = 'remote.'
167
        prefix = 'cloud.'
168 168
        if section.startswith(prefix):
169
            remote = section[len(prefix):]
169
            cloud = section[len(prefix):]
170 170
            try:
171
                self.config.remove_from_remote(remote, key)
171
                self.config.remove_from_cloud(cloud, key)
172 172
            except KeyError:
173 173
                raise CLIError('Field %s does not exist' % option)
174 174
        else:
b/kamaki/cli/commands/cyclades.py
53 53

  
54 54
about_authentication = '\nUser Authentication:\
55 55
    \n* to check authentication: /user authenticate\
56
    \n* to set authentication token: /config set remote.default.token <token>'
56
    \n* to set authentication token: /config set cloud.default.token <token>'
57 57

  
58 58
howto_personality = [
59 59
    'Defines a file to be injected to VMs personality.',
......
75 75
            if base_url:
76 76
                token = self._custom_token(service)\
77 77
                    or self._custom_token('cyclades')\
78
                    or self.config.get_remote('token')
78
                    or self.config.get_cloud('token')
79 79
                self.client = CycladesClient(
80 80
                    base_url=base_url, token=token)
81 81
                return
b/kamaki/cli/commands/errors.py
39 39
from kamaki.cli.utils import format_size
40 40

  
41 41
CLOUDNAME = [
42
    'Note: If you use a named cloud remote, use its name',
43
    'instead of "default"']
42
    'Note: If you use a named cloud, use its name instead of "default"']
44 43

  
45 44

  
46 45
class generic(object):
......
71 70
                        'Make sure a valid token is provided:',
72 71
                        '  to check if token is valid: /user authenticate',
73 72
                        '  to set token:',
74
                        '    /config set remote.default.token <token>',
73
                        '    /config set cloud.default.token <token>',
75 74
                        '  to get current token:',
76
                        '    /config get remote.default.token'] + CLOUDNAME)
75
                        '    /config get cloud.default.token'] + CLOUDNAME)
77 76
                elif ce.status in range(-12, 200) + [302, 401, 403, 500]:
78 77
                    raiseCLIError(ce, importance=3, details=[
79 78
                        'Check if service is up'])
......
86 85
                    raiseCLIError(ce, msg, details=[
87 86
                        'Check if authentication url is correct',
88 87
                        '  check current url:',
89
                        '    /config get remote.default.url',
88
                        '    /config get cloud.default.url',
90 89
                        '  set new auth. url:',
91
                        '    /config set remote.default.url'] + CLOUDNAME)
90
                        '    /config set cloud.default.url'] + CLOUDNAME)
92 91
                raise
93 92
        return _raise
94 93

  
......
96 95
class user(object):
97 96

  
98 97
    _token_details = [
99
        'To check default token: /config get remote.default.token',
98
        'To check default token: /config get cloud.default.token',
100 99
        'If set/update a token:',
101
        '*  (permanent):  /config set remote.default.token <token>',
100
        '*  (permanent):  /config set cloud.default.token <token>',
102 101
        '*  (temporary):  re-run with <token> parameter'] + CLOUDNAME
103 102

  
104 103
    @classmethod
......
112 111
            if not getattr(client, 'token', False):
113 112
                kloger.warning(
114 113
                    'No permanent token (try:'
115
                    ' kamaki config set remote.default.token <tkn>)')
114
                    ' kamaki config set cloud.default.token <tkn>)')
116 115
            if not getattr(client, 'base_url', False):
117 116
                msg = 'Missing synnefo authentication URL'
118 117
                raise CLIError(msg, importance=3, details=[
119 118
                    'Check if authentication url is correct',
120 119
                        '  check current url:',
121
                        '    /config get remote.default.url',
120
                        '    /config get cloud.default.url',
122 121
                        '  set new auth. url:',
123
                        '    /config set remote.default.url'] + CLOUDNAME)
122
                        '    /config set cloud.default.url'] + CLOUDNAME)
124 123
            return r
125 124
        return _raise
126 125

  
b/kamaki/cli/commands/image.py
80 80
            if img_url:
81 81
                token = self._custom_token('image')\
82 82
                    or self._custom_token('plankton')\
83
                    or self.config.get_remote(self.cloud, 'token')
83
                    or self.config.get_cloud(self.cloud, 'token')
84 84
                self.client = ImageClient(base_url=img_url, token=token)
85 85
                return
86 86
        if getattr(self, 'auth_base', False):
b/kamaki/cli/commands/pithos.py
153 153

  
154 154
    @DontRaiseKeyError
155 155
    def _custom_container(self):
156
        return self.config.get_remote(self.cloud, 'pithos_container')
156
        return self.config.get_cloud(self.cloud, 'pithos_container')
157 157

  
158 158
    @DontRaiseKeyError
159 159
    def _custom_uuid(self):
160
        return self.config.get_remote(self.cloud, 'pithos_uuid')
160
        return self.config.get_cloud(self.cloud, 'pithos_uuid')
161 161

  
162 162
    def _set_account(self):
163 163
        self.account = self._custom_uuid()
b/kamaki/cli/commands/snf-astakos.py
61 61
    def _run(self):
62 62
        self.cloud = self.cloud if self.cloud else 'default'
63 63
        self.token = self['token'] or self._custom_token('astakos')\
64
            or self.config.get_remote(self.cloud, 'token')
64
            or self.config.get_cloud(self.cloud, 'token')
65 65
        if getattr(self, 'auth_base', False):
66 66
            astakos_endpoints = self.auth_base.get_service_endpoints(
67 67
                self._custom_type('astakos') or 'identity',
......
82 82
    """Authenticate a user
83 83
    Get user information (e.g. unique account name) from token
84 84
    Token should be set in settings:
85
    *  check if a token is set    /config get remote.default.token
86
    *  permanently set a token    /config set remote.default.token <token>
85
    *  check if a token is set    /config get cloud.default.token
86
    *  permanently set a token    /config set cloud.default.token <token>
87 87
    Token can also be provided as a parameter
88
    (To use a named cloud remote, use its name instead of "default")
88
    (To use a named cloud, use its name instead of "default")
89 89
    """
90 90

  
91 91
    arguments = dict(
b/kamaki/cli/config.py
39 39
from re import match
40 40

  
41 41
from kamaki.cli.errors import CLISyntaxError
42
from kamaki import __version__
42 43

  
43 44
try:
44 45
    from collections import OrderedDict
......
55 56
# Name of a shell variable to bypass the CONFIG_PATH value
56 57
CONFIG_ENV = 'KAMAKI_CONFIG'
57 58

  
58
HEADER = """
59
# Kamaki configuration file v3 (kamaki >= v0.9)
60
"""
59
version = ''
60
for c in '%s' % __version__:
61
    if c not in '0.123456789':
62
        break
63
    version += c
64
HEADER = '# Kamaki configuration file v%s' % version
61 65

  
62 66
DEFAULTS = {
63 67
    'global': {
68
        'default_cloud': '',
64 69
        'colors': 'off',
65 70
        'log_file': os.path.expanduser('~/.kamaki.log'),
66 71
        'log_token': 'off',
......
79 84
        #  'livetest_cli': 'livetest',
80 85
        #  'astakos_cli': 'snf-astakos'
81 86
    },
82
    'remote':
87
    'cloud':
83 88
    {
84
        'default': {
85
            'url': '',
86
            'token': ''
87
            #'pithos_type': 'object-store',
88
            #'pithos_version': 'v1',
89
            #'cyclades_type': 'compute',
90
            #'cyclades_version': 'v2.0',
91
            #'plankton_type': 'image',
92
            #'plankton_version': '',
93
            #'astakos_type': 'identity',
94
            #'astakos_version': 'v2.0'
95
        }
89
        #'default': {
90
        #    'url': '',
91
        #    'token': ''
92
        #    'pithos_type': 'object-store',
93
        #    'pithos_version': 'v1',
94
        #    'cyclades_type': 'compute',
95
        #    'cyclades_version': 'v2.0',
96
        #    'plankton_type': 'image',
97
        #    'plankton_version': '',
98
        #    'astakos_type': 'identity',
99
        #    'astakos_version': 'v2.0'
100
        #}
96 101
    }
97 102
}
98 103

  
......
107 112
        self.read(self.path)
108 113

  
109 114
        for section in self.sections():
110
            r = self._remote_name(section)
115
            r = self._cloud_name(section)
111 116
            if r:
112 117
                for k, v in self.items(section):
113
                    self.set_remote(r, k, v)
118
                    self.set_cloud(r, k, v)
114 119
                self.remove_section(section)
115 120

  
116 121
    @staticmethod
117
    def _remote_name(full_section_name):
118
        matcher = match('remote "(\w+)"', full_section_name)
122
    def _cloud_name(full_section_name):
123
        matcher = match('cloud "(\w+)"', full_section_name)
119 124
        return matcher.groups()[0] if matcher else None
120 125

  
121 126
    def rescue_old_file(self):
......
139 144
            user=dict(serv='astakos', cmd='user'),
140 145
        )
141 146

  
147
        self.set('global', 'default_cloud', 'default')
142 148
        for s in self.sections():
143 149
            if s in ('global'):
144 150
                # global.url, global.token -->
145
                # remote.default.url, remote.default.token
151
                # cloud.default.url, cloud.default.token
146 152
                for term in set(self.keys(s)).difference(global_terms):
147 153
                    if term not in ('url', 'token'):
148 154
                        lost_terms.append('%s.%s = %s' % (
......
150 156
                        self.remove_option(s, term)
151 157
                        continue
152 158
                    gval = self.get(s, term)
153
                    cval = self.get_remote('default', term)
159
                    cval = self.get_cloud('default', term)
154 160
                    if gval and cval and (
155 161
                        gval.lower().strip('/') != cval.lower().strip('/')):
156 162
                            raise CLISyntaxError(
157 163
                                'Conflicting values for default %s' % term,
158 164
                                importance=2, details=[
159 165
                                    ' global.%s:  %s' % (term, gval),
160
                                    ' remote.default.%s:  %s' % (term, cval),
166
                                    ' cloud.default.%s:  %s' % (term, cval),
161 167
                                    'Please remove one of them manually:',
162 168
                                    ' /config delete global.%s' % term,
163 169
                                    ' or'
164
                                    ' /config delete remote.default.%s' % term,
170
                                    ' /config delete cloud.default.%s' % term,
165 171
                                    'and try again'])
166 172
                    elif gval:
167
                        print('... rescue %s.%s => remote.default.%s' % (
173
                        print('... rescue %s.%s => cloud.default.%s' % (
168 174
                            s, term, term))
169
                        self.set_remote('default', term, gval)
175
                        self.set_cloud('default', term, gval)
170 176
                    self.remove_option(s, term)
171 177
            # translation for <service> or <command> settings
172 178
            # <service> or <command group> settings --> translation --> global
......
186 192
                    if v and k in ('cli',):
187 193
                        print('... rescue %s.%s => global.%s_cli' % (
188 194
                            s, k, trn['cmd']))
189
                        self.set('global', 'file_cli', v)
190
                    elif (k in ('container', 'uuid')) and (
191
                            trn['serv'] in ('pithos',)):
192
                        print(
193
                            '... rescue %s.%s => remote.default.pithos_%s' % (
195
                        self.set('global', '%s_cli' % trn['cmd'], v)
196
                    elif k in ('container',) and trn['serv'] in ('pithos',):
197
                        print('... rescue %s.%s => cloud.default.pithos_%s' % (
194 198
                                    s, k, k))
195
                        self.set_remote('default', 'pithos_%s' % k, v)
196
                    elif v:
199
                        self.set_cloud('default', 'pithos_%s' % k, v)
200
                    else:
197 201
                        lost_terms.append('%s.%s = %s' % (s, k, v))
198 202
                self.remove_section(s)
199 203
        #  self.pretty_print()
......
212 216
                    print '\t', k, '=>', v
213 217

  
214 218
    def guess_version(self):
219
        """
220
        :returns: (float) version of the config file or 0.0 if unrecognized
221
        """
215 222
        checker = Config(self.path, with_defaults=False)
216 223
        sections = checker.sections()
217
        log.warning('Config file heuristic 1: global section ?')
224
        log.warning('Config file heuristic 1: old global section ?')
218 225
        if 'global' in sections:
219 226
            if checker.get('global', 'url') or checker.get('global', 'token'):
220 227
                log.warning('..... config file has an old global section')
221
                return 2.0
222
        log.warning('........ nope')
223
        log.warning('Config file heuristic 2: at least 1 remote section ?')
224
        if 'remote' in sections:
225
            for r in self.keys('remote'):
226
                log.warning('... found remote "%s"' % r)
227
                return 3.0
228
                return 8.0
228 229
        log.warning('........ nope')
230
        log.warning('Config file heuristic 2: missing all cloud sections ?')
231
        if 'cloud' in sections:
232
            for r in self.keys('cloud'):
233
                log.warning('... found cloud "%s"' % r)
234
                return 9.0
235
        log.warning('........ yep')
229 236
        log.warning('All heuristics failed, cannot decide')
230 237
        return 0.0
231 238

  
232
    def get_remote(self, remote, option):
239
    def get_cloud(self, cloud, option):
233 240
        """
234
        :param remote: (str) remote cloud alias
241
        :param cloud: (str) cloud alias
235 242

  
236
        :param option: (str) option in remote cloud section
243
        :param option: (str) option in cloud section
237 244

  
238 245
        :returns: (str) the value assigned on this option
239 246

  
240
        :raises KeyError: if remote or remote's option does not exist
247
        :raises KeyError: if cloud or cloud's option does not exist
241 248
        """
242
        r = self.get('remote', remote)
249
        r = self.get('cloud', cloud)
243 250
        if not r:
244
            raise KeyError('Remote "%s" does not exist' % remote)
251
            raise KeyError('Cloud "%s" does not exist' % cloud)
245 252
        return r[option]
246 253

  
247 254
    def get_global(self, option):
248 255
        return self.get('global', option)
249 256

  
250
    def set_remote(self, remote, option, value):
257
    def set_cloud(self, cloud, option, value):
251 258
        try:
252
            d = self.get('remote', remote) or dict()
259
            d = self.get('cloud', cloud) or dict()
253 260
        except KeyError:
254 261
            d = dict()
255 262
        d[option] = value
256
        self.set('remote', remote, d)
263
        self.set('cloud', cloud, d)
257 264

  
258 265
    def set_global(self, option, value):
259 266
        self.set('global', option, value)
......
279 286

  
280 287
    def get(self, section, option):
281 288
        """
282
        :param section: (str) HINT: for remotes, use remote.<section>
289
        :param section: (str) HINT: for clouds, use cloud.<section>
283 290

  
284 291
        :param option: (str)
285 292

  
......
288 295
        value = self._overrides.get(section, {}).get(option)
289 296
        if value is not None:
290 297
            return value
291
        if section.startswith('remote.'):
292
            return self.get_remote(section[len('remote.'):], option)
298
        prefix = 'cloud.'
299
        if section.startswith(prefix):
300
            return self.get_cloud(section[len(prefix):], option)
293 301
        try:
294 302
            return RawConfigParser.get(self, section, option)
295 303
        except (NoSectionError, NoOptionError):
......
297 305

  
298 306
    def set(self, section, option, value):
299 307
        """
300
        :param section: (str) HINT: for remotes use remote.<section>
308
        :param section: (str) HINT: for remotes use cloud.<section>
301 309

  
302 310
        :param option: (str)
303 311

  
304 312
        :param value: str
305 313
        """
306
        if section.startswith('remote.'):
307
            return self.set_remote(section[len('remote.')], option, value)
314
        prefix = 'cloud.'
315
        if section.startswith(prefix):
316
            return self.set_cloud(section[len(prefix)], option, value)
308 317
        if section not in RawConfigParser.sections(self):
309 318
            self.add_section(section)
310 319
        RawConfigParser.set(self, section, option, value)
......
317 326
        except NoSectionError:
318 327
            pass
319 328

  
320
    def remove_from_remote(self, remote, option):
321
        d = self.get('remote', remote)
329
    def remote_from_cloud(self, cloud, option):
330
        d = self.get('cloud', cloud)
322 331
        if isinstance(d, dict):
323 332
            d.pop(option)
324 333

  
......
334 343
        self._overrides[section][option] = value
335 344

  
336 345
    def write(self):
337
        for r, d in self.items('remote'):
346
        for r, d in self.items('cloud'):
338 347
            for k, v in d.items():
339
                self.set('remote "%s"' % r, k, v)
340
        self.remove_section('remote')
348
                self.set('cloud "%s"' % r, k, v)
349
        self.remove_section('cloud')
341 350

  
342 351
        with open(self.path, 'w') as f:
343 352
            os.chmod(self.path, 0600)
b/kamaki/cli/errors.py
78 78
            'Two options to resolve this:',
79 79
            'A. (recommended) Let kamaki discover the endpoint URLs for all',
80 80
            'services by setting a single Authentication URL and token:',
81
            '  /config set remote.default.url <AUTH_URL>',
82
            '  /config set remote.default.token <t0k3n>',
81
            '  /config set cloud.default.url <AUTH_URL>',
82
            '  /config set cloud.default.token <t0k3n>',
83 83
            'B. (advanced users) Explicitly set a valid %s endpoint URL' % (
84 84
                service.upper()),
85 85
            'Note: url option has a higher priority, so delete it to',
86 86
            'make that work',
87
            '  /config delete remote.default.url',
88
            '  /config set remote.%s.url <%s_URL>' % (
87
            '  /config delete cloud.default.url',
88
            '  /config set cloud.%s.url <%s_URL>' % (
89 89
                service, service.upper())]
90 90
        super(CLIBaseUrlError, self).__init__(message, details, importance)
91 91

  
b/kamaki/cli/one_command.py
55 55
    return None
56 56

  
57 57

  
58
def run(remote_base, cloud, parser, _help):
58
def run(auth_base, cloud, parser, _help):
59 59
    group = get_command_group(list(parser.unparsed), parser.arguments)
60 60
    if not group:
61 61
        parser.parser.print_help()
......
96 96
        exit(0)
97 97

  
98 98
    cls = cmd.get_class()
99
    executable = cls(parser.arguments, remote_base, cloud)
99
    executable = cls(parser.arguments, auth_base, cloud)
100 100
    parser.update_arguments(executable.arguments)
101 101
    #parsed, unparsed = parse_known_args(parser, executable.arguments)
102 102
    for term in _best_match:

Also available in: Unified diff