Skip to content

Commit b660824

Browse files
committed
Add a "cloud cache delete" command
Authentication is cached in the keyring when cache.auth is enabled in clouds.yaml, and nothing removes it. Add a command that deletes what is cached for a cloud, so that the next command authenticates again. That is what is wanted when the cached credential has been revoked, or belongs to an account no longer being used. The command does not authenticate itself. The credential it clears may be the one that authentication would fail with. Depends-On: https://review.opendev.org/c/openstack/openstacksdk/+/1001431/ Change-Id: Ie6bd39f1a67aba8d59be4cbabcd3d2f7dde168b9 Signed-off-by: Doug Goldstein <cardoe@cardoe.com> Assisted-By: Claude Opus 5
1 parent 01668c8 commit b660824

5 files changed

Lines changed: 112 additions & 0 deletions

File tree

doc/source/cli/command-objects/common/index.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,19 @@ compute and network services.
1313
:command: availability zone list
1414

1515

16+
cloud cache
17+
-----------
18+
19+
Authentication is cached in the keyring between invocations when the
20+
``cache.auth`` setting is enabled in ``clouds.yaml``. This deletes what is
21+
cached for a cloud, so that the next command authenticates again. For a plugin
22+
that authenticates in a browser, such as ``v3websso``, that means logging in
23+
again.
24+
25+
.. autoprogram-cliff:: openstack.common
26+
:command: cloud cache delete
27+
28+
1629
command
1730
-------
1831

openstackclient/common/cloud.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
2+
# not use this file except in compliance with the License. You may obtain
3+
# a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
#
13+
14+
"""Cloud action implementations"""
15+
16+
import argparse
17+
18+
from openstackclient import command
19+
from openstackclient.i18n import _
20+
21+
22+
class DeleteCloudCache(command.Command):
23+
_description = _("Delete the authentication cached for a cloud")
24+
25+
# Authenticating in order to throw away the credential that would have
26+
# been used to do it makes no sense, and would defeat the point when the
27+
# cached credential is the broken thing being cleared.
28+
auth_required = False
29+
30+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
31+
parser = super().get_parser(prog_name)
32+
parser.epilog = _(
33+
"Authentication is only cached when the 'cache.auth' setting is "
34+
"enabled in clouds.yaml. Without it there is nothing stored and "
35+
"nothing to delete."
36+
)
37+
return parser
38+
39+
def take_action(self, parsed_args: argparse.Namespace) -> None:
40+
self.app.client_manager._cli_options.clear_auth_cache()
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
2+
# not use this file except in compliance with the License. You may obtain
3+
# a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
#
13+
14+
from unittest import mock
15+
16+
import fixtures
17+
18+
from openstackclient.common import cloud
19+
from openstackclient.tests.unit import utils
20+
21+
22+
class TestDeleteCloudCache(utils.TestCommand):
23+
def setUp(self):
24+
super().setUp()
25+
26+
self.cmd = cloud.DeleteCloudCache(self.app, None)
27+
# The fake client manager has no cloud region of its own.
28+
self.cloud_region = self.useFixture(
29+
fixtures.MockPatchObject(
30+
self.app.client_manager,
31+
'_cli_options',
32+
mock.Mock(),
33+
create=True,
34+
)
35+
).mock
36+
37+
def test_delete(self):
38+
parsed_args = self.check_parser(self.cmd, [], [])
39+
40+
self.cmd.take_action(parsed_args)
41+
42+
self.cloud_region.clear_auth_cache.assert_called_once_with()
43+
44+
def test_does_not_authenticate(self):
45+
# Authenticating in order to discard the credential that would be used
46+
# to do it is pointless, and impossible when that credential is the
47+
# broken thing being cleared.
48+
self.assertFalse(self.cmd.auth_required)

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ volume = "openstackclient.volume.client"
4747

4848
[project.entry-points."openstack.common"]
4949
availability_zone_list = "openstackclient.common.availability_zone:ListAvailabilityZone"
50+
cloud_cache_delete = "openstackclient.common.cloud:DeleteCloudCache"
5051
configuration_show = "openstackclient.common.configuration:ShowConfiguration"
5152
extension_list = "openstackclient.common.extension:ListExtension"
5253
extension_show = "openstackclient.common.extension:ShowExtension"
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
features:
3+
- |
4+
Added the ``cloud cache delete`` command, which deletes the authentication
5+
cached in the keyring for a cloud so that the next command authenticates
6+
again. Use it when the cached credential has been revoked, or to switch to
7+
a different account with a plugin that authenticates in a browser.
8+
9+
Authentication is only cached when the ``cache.auth`` setting is enabled
10+
in ``clouds.yaml``.

0 commit comments

Comments
 (0)