Add configuration show command
Create a `configuration show` command that displays the current configuration of the CLI. Different configurations can be displayed using options such as --os-cloud. Passwords and tokens are redacted by default unless the --unmask option is specified. Closes-Bug: #1476729 Change-Id: I0792365d0c5fa526cd09c0ed88c6bb1e2cb813a7
This commit is contained in:
parent
64334c0dc9
commit
43942871a9
18
doc/source/command-objects/configuration.rst
Normal file
18
doc/source/command-objects/configuration.rst
Normal file
@ -0,0 +1,18 @@
|
||||
=============
|
||||
configuration
|
||||
=============
|
||||
|
||||
Available for all services
|
||||
|
||||
configuration show
|
||||
------------------
|
||||
|
||||
Show the current openstack client configuration. This command is a little
|
||||
different from other show commands because it does not take a resource name
|
||||
or id to show. The command line options, such as --os-cloud, can be used to
|
||||
show different configurations.
|
||||
|
||||
.. program:: configuration show
|
||||
.. code:: bash
|
||||
|
||||
os configuration show
|
@ -137,3 +137,9 @@ that appears in :file:`clouds.yaml`
|
||||
rackspace:
|
||||
auth:
|
||||
auth_url: 'https://identity.api.rackspacecloud.com/v2.0/'
|
||||
|
||||
Debugging
|
||||
~~~~~~~~~
|
||||
You may find the :doc:`config show <command-objects/config>`
|
||||
helpful to debug configuration issues. It will display your current
|
||||
configuration.
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
"""Manage access to the clients, including authenticating when needed."""
|
||||
|
||||
import copy
|
||||
import logging
|
||||
import pkg_resources
|
||||
import sys
|
||||
@ -203,6 +204,9 @@ class ClientManager(object):
|
||||
interface=interface)
|
||||
return endpoint
|
||||
|
||||
def get_configuration(self):
|
||||
return copy.deepcopy(self._cli_options.config)
|
||||
|
||||
|
||||
# Plugin Support
|
||||
|
||||
|
58
openstackclient/common/configuration.py
Normal file
58
openstackclient/common/configuration.py
Normal file
@ -0,0 +1,58 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
"""Configuration action implementations"""
|
||||
|
||||
import logging
|
||||
|
||||
from cliff import show
|
||||
import six
|
||||
|
||||
REDACTED = "<redacted>"
|
||||
|
||||
|
||||
class ShowConfiguration(show.ShowOne):
|
||||
"""Display configuration details"""
|
||||
|
||||
log = logging.getLogger(__name__ + '.ShowConfiguration')
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowConfiguration, self).get_parser(prog_name)
|
||||
mask_group = parser.add_mutually_exclusive_group()
|
||||
mask_group.add_argument(
|
||||
"--mask",
|
||||
dest="mask",
|
||||
action="store_true",
|
||||
default=True,
|
||||
help="Attempt to mask passwords (default)",
|
||||
)
|
||||
mask_group.add_argument(
|
||||
"--unmask",
|
||||
dest="mask",
|
||||
action="store_false",
|
||||
help="Show password in clear text",
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.log.debug('take_action(%s)', parsed_args)
|
||||
|
||||
info = self.app.client_manager.get_configuration()
|
||||
for key, value in six.iteritems(info.pop('auth', {})):
|
||||
if parsed_args.mask:
|
||||
if 'password' in key.lower():
|
||||
value = REDACTED
|
||||
if 'token' in key.lower():
|
||||
value = REDACTED
|
||||
info['auth.' + key] = value
|
||||
return zip(*sorted(six.iteritems(info)))
|
79
openstackclient/tests/common/test_configuration.py
Normal file
79
openstackclient/tests/common/test_configuration.py
Normal file
@ -0,0 +1,79 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
from openstackclient.common import configuration
|
||||
from openstackclient.tests import fakes
|
||||
from openstackclient.tests import utils
|
||||
|
||||
|
||||
class TestConfiguration(utils.TestCommand):
|
||||
|
||||
def test_show(self):
|
||||
arglist = []
|
||||
verifylist = [('mask', True)]
|
||||
cmd = configuration.ShowConfiguration(self.app, None)
|
||||
parsed_args = self.check_parser(cmd, arglist, verifylist)
|
||||
|
||||
columns, data = cmd.take_action(parsed_args)
|
||||
|
||||
collist = ('auth.password', 'auth.token', 'auth.username',
|
||||
'identity_api_version', 'region')
|
||||
self.assertEqual(collist, columns)
|
||||
datalist = (
|
||||
configuration.REDACTED,
|
||||
configuration.REDACTED,
|
||||
fakes.USERNAME,
|
||||
fakes.VERSION,
|
||||
fakes.REGION_NAME,
|
||||
)
|
||||
self.assertEqual(datalist, tuple(data))
|
||||
|
||||
def test_show_unmask(self):
|
||||
arglist = ['--unmask']
|
||||
verifylist = [('mask', False)]
|
||||
cmd = configuration.ShowConfiguration(self.app, None)
|
||||
parsed_args = self.check_parser(cmd, arglist, verifylist)
|
||||
|
||||
columns, data = cmd.take_action(parsed_args)
|
||||
|
||||
collist = ('auth.password', 'auth.token', 'auth.username',
|
||||
'identity_api_version', 'region')
|
||||
self.assertEqual(collist, columns)
|
||||
datalist = (
|
||||
fakes.PASSWORD,
|
||||
fakes.AUTH_TOKEN,
|
||||
fakes.USERNAME,
|
||||
fakes.VERSION,
|
||||
fakes.REGION_NAME,
|
||||
)
|
||||
self.assertEqual(datalist, tuple(data))
|
||||
|
||||
def test_show_mask(self):
|
||||
arglist = ['--mask']
|
||||
verifylist = [('mask', True)]
|
||||
cmd = configuration.ShowConfiguration(self.app, None)
|
||||
parsed_args = self.check_parser(cmd, arglist, verifylist)
|
||||
|
||||
columns, data = cmd.take_action(parsed_args)
|
||||
|
||||
collist = ('auth.password', 'auth.token', 'auth.username',
|
||||
'identity_api_version', 'region')
|
||||
self.assertEqual(collist, columns)
|
||||
datalist = (
|
||||
configuration.REDACTED,
|
||||
configuration.REDACTED,
|
||||
fakes.USERNAME,
|
||||
fakes.VERSION,
|
||||
fakes.REGION_NAME,
|
||||
)
|
||||
self.assertEqual(datalist, tuple(data))
|
@ -28,6 +28,7 @@ PASSWORD = "scratchy"
|
||||
PROJECT_NAME = "poochie"
|
||||
REGION_NAME = "richie"
|
||||
INTERFACE = "catchy"
|
||||
VERSION = "3"
|
||||
|
||||
TEST_RESPONSE_DICT = fixture.V2Token(token_id=AUTH_TOKEN,
|
||||
user_name=USERNAME)
|
||||
@ -102,6 +103,17 @@ class FakeClientManager(object):
|
||||
self.auth_ref = None
|
||||
self.auth_plugin_name = None
|
||||
|
||||
def get_configuration(self):
|
||||
return {
|
||||
'auth': {
|
||||
'username': USERNAME,
|
||||
'password': PASSWORD,
|
||||
'token': AUTH_TOKEN,
|
||||
},
|
||||
'region': REGION_NAME,
|
||||
'identity_api_version': VERSION,
|
||||
}
|
||||
|
||||
|
||||
class FakeModule(object):
|
||||
def __init__(self, name, version):
|
||||
|
@ -44,6 +44,7 @@ openstack.cli.base =
|
||||
volume = openstackclient.volume.client
|
||||
|
||||
openstack.common =
|
||||
configuration_show = openstackclient.common.configuration:ShowConfiguration
|
||||
extension_list = openstackclient.common.extension:ListExtension
|
||||
limits_show = openstackclient.common.limits:ShowLimits
|
||||
quota_set = openstackclient.common.quota:SetQuota
|
||||
|
Loading…
Reference in New Issue
Block a user