Skip to content

Commit

Permalink
cli: refactor refresh to the new approach
Browse files Browse the repository at this point in the history
Signed-off-by: Renan Rodrigo <[email protected]>
  • Loading branch information
renanrodrigo committed Jul 5, 2024
1 parent 13bf603 commit 4b91fd8
Show file tree
Hide file tree
Showing 10 changed files with 142 additions and 138 deletions.
22 changes: 22 additions & 0 deletions features/help.feature
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,28 @@ Feature: Pro Client help text
simulate the output status using a provided token
--all Include unavailable and beta services
"""
When I run `pro status --help` as non-root
Then stdout matches regexp:
"""
usage: pro refresh \[flags\]
Refresh three distinct Ubuntu Pro related artifacts in the system:
* contract: Update contract details from the server.
* config: Reload the config file.
* messages: Update APT and MOTD messages related to UA.
You can individually target any of the three specific actions,
by passing the target name to the command. If no `target`
is specified, all targets are refreshed.
positional arguments:
\{contract,config,messages\}
Target to refresh.
(optional arguments|options):
-h, --help show this help message and exit
"""

Examples: ubuntu release
| release | machine_type |
Expand Down
79 changes: 2 additions & 77 deletions uaclient/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
apt,
apt_news,
config,
contract,
defaults,
entitlements,
event_logger,
Expand All @@ -37,12 +36,12 @@
from uaclient.cli.disable import disable_command
from uaclient.cli.enable import enable_command
from uaclient.cli.fix import fix_command
from uaclient.cli.refresh import refresh_command
from uaclient.cli.security_status import security_status_command
from uaclient.cli.status import status_command
from uaclient.entitlements.entitlement_status import ApplicationStatus
from uaclient.files import state_files
from uaclient.log import get_user_or_root_log_file_path
from uaclient.timer.update_messaging import refresh_motd, update_motd_messages

UA_AUTH_TOKEN_URL = "https://auth.contracts.canonical.com"

Expand All @@ -60,6 +59,7 @@
disable_command,
enable_command,
fix_command,
refresh_command,
security_status_command,
status_command,
]
Expand Down Expand Up @@ -169,26 +169,6 @@ def config_parser(parser):
return parser


def refresh_parser(parser):
"""Build or extend an arg parser for refresh subcommand."""
parser.prog = "refresh"
parser.usage = USAGE_TMPL.format(
name=NAME, command="refresh [contract|config|messages]"
)

parser._optionals.title = messages.CLI_FLAGS
parser.formatter_class = argparse.RawDescriptionHelpFormatter
parser.description = messages.CLI_REFRESH_DESC
parser.add_argument(
"target",
choices=["contract", "config", "messages"],
nargs="?",
default=None,
help=messages.CLI_REFRESH_TARGET,
)
return parser


def help_parser(parser, cfg: config.UAConfig):
"""Build or extend an arg parser for help subcommand."""
usage = USAGE_TMPL.format(name=NAME, command="help [service]")
Expand Down Expand Up @@ -510,12 +490,6 @@ def get_parser(cfg: config.UAConfig):
help_parser(parser_help, cfg=cfg)
parser_help.set_defaults(action=action_help)

parser_refresh = subparsers.add_parser(
"refresh", help=messages.CLI_ROOT_REFRESH
)
parser_refresh.set_defaults(action=action_refresh)
refresh_parser(parser_refresh)

parser_version = subparsers.add_parser(
"version", help=messages.CLI_ROOT_VERSION.format(name=NAME)
)
Expand Down Expand Up @@ -551,55 +525,6 @@ def print_version(_args=None, cfg=None, **kwargs):
print(version.get_version())


def _action_refresh_config(args, cfg: config.UAConfig):
try:
cfg.process_config()
except RuntimeError as exc:
LOG.exception(exc)
raise exceptions.RefreshConfigFailure()
print(messages.REFRESH_CONFIG_SUCCESS)


@cli_util.assert_attached()
def _action_refresh_contract(_args, cfg: config.UAConfig):
try:
contract.refresh(cfg)
except exceptions.ConnectivityError:
raise exceptions.RefreshContractFailure()
print(messages.REFRESH_CONTRACT_SUCCESS)


def _action_refresh_messages(_args, cfg: config.UAConfig):
# Not performing any exception handling here since both of these
# functions should raise UbuntuProError exceptions, which are
# covered by the main_error_handler decorator
try:
update_motd_messages(cfg)
refresh_motd()
if cfg.apt_news:
apt_news.update_apt_news(cfg)
except Exception as exc:
LOG.exception(exc)
raise exceptions.RefreshMessagesFailure()
else:
print(messages.REFRESH_MESSAGES_SUCCESS)


@cli_util.assert_root
@cli_util.assert_lock_file("pro refresh")
def action_refresh(args, *, cfg: config.UAConfig, **kwargs):
if args.target is None or args.target == "config":
_action_refresh_config(args, cfg)

if args.target is None or args.target == "contract":
_action_refresh_contract(args, cfg)

if args.target is None or args.target == "messages":
_action_refresh_messages(args, cfg)

return 0


def configure_apt_proxy(
cfg: config.UAConfig,
scope: AptProxyScope,
Expand Down
79 changes: 79 additions & 0 deletions uaclient/cli/refresh.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import logging

from uaclient import apt_news, config, contract, exceptions, messages, util
from uaclient.cli import cli_util
from uaclient.cli.commands import ProArgument, ProArgumentGroup, ProCommand
from uaclient.timer.update_messaging import refresh_motd, update_motd_messages

LOG = logging.getLogger(util.replace_top_level_logger_name(__name__))


def _action_refresh_config(args, cfg: config.UAConfig):
try:
cfg.process_config()
except RuntimeError as exc:
LOG.exception(exc)
raise exceptions.RefreshConfigFailure()
print(messages.REFRESH_CONFIG_SUCCESS)


@cli_util.assert_attached()
def _action_refresh_contract(_args, cfg: config.UAConfig):
try:
contract.refresh(cfg)
except exceptions.ConnectivityError:
raise exceptions.RefreshContractFailure()
print(messages.REFRESH_CONTRACT_SUCCESS)


def _action_refresh_messages(_args, cfg: config.UAConfig):
# Not performing any exception handling here since both of these
# functions should raise UbuntuProError exceptions, which are
# covered by the main_error_handler decorator
try:
update_motd_messages(cfg)
refresh_motd()
if cfg.apt_news:
apt_news.update_apt_news(cfg)
except Exception as exc:
LOG.exception(exc)
raise exceptions.RefreshMessagesFailure()
else:
print(messages.REFRESH_MESSAGES_SUCCESS)


@cli_util.assert_root
@cli_util.assert_lock_file("pro refresh")
def action_refresh(args, *, cfg: config.UAConfig, **kwargs):
if args.target is None or args.target == "config":
_action_refresh_config(args, cfg)

if args.target is None or args.target == "contract":
_action_refresh_contract(args, cfg)

if args.target is None or args.target == "messages":
_action_refresh_messages(args, cfg)

return 0


refresh_command = ProCommand(
"refresh",
help=messages.CLI_ROOT_REFRESH,
description=messages.CLI_REFRESH_DESC,
action=action_refresh,
preserve_description=True,
argument_groups=[
ProArgumentGroup(
arguments=[
ProArgument(
"target",
help=messages.CLI_REFRESH_TARGET,
nargs="?",
choices=["contract", "config", "messages"],
default=None,
)
]
)
],
)
2 changes: 1 addition & 1 deletion uaclient/cli/tests/test_cli_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

@mock.patch("uaclient.cli.LOG.error")
@mock.patch("uaclient.log.setup_cli_logging")
@mock.patch(M_PATH + "contract.get_available_resources")
@mock.patch("uaclient.contract.get_available_resources")
class TestMainConfig:
@pytest.mark.parametrize("additional_params", ([], ["--help"]))
def test_config_help(
Expand Down
4 changes: 2 additions & 2 deletions uaclient/cli/tests/test_cli_config_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class TestMainConfigSet:
),
),
)
@mock.patch("uaclient.cli.contract.get_available_resources")
@mock.patch("uaclient.contract.get_available_resources")
def test_set_error_with_help_on_invalid_key_value_pair(
self,
_m_resources,
Expand All @@ -92,7 +92,7 @@ def test_set_error_with_help_on_invalid_key_value_pair(


@mock.patch("uaclient.config.user_config_file.user_config.write")
@mock.patch("uaclient.cli.contract.get_available_resources")
@mock.patch("uaclient.contract.get_available_resources")
class TestActionConfigSet:
@mock.patch("uaclient.util.we_are_currently_root", return_value=False)
def test_set_error_on_non_root_user(
Expand Down
2 changes: 1 addition & 1 deletion uaclient/cli/tests/test_cli_config_show.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

@mock.patch("uaclient.cli.logging.error")
@mock.patch("uaclient.log.setup_cli_logging")
@mock.patch(M_PATH + "contract.get_available_resources")
@mock.patch("uaclient.contract.get_available_resources")
class TestMainConfigShow:
def test_config_show_help(
self,
Expand Down
2 changes: 1 addition & 1 deletion uaclient/cli/tests/test_cli_config_unset.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@


@mock.patch("uaclient.log.setup_cli_logging")
@mock.patch("uaclient.cli.contract.get_available_resources")
@mock.patch("uaclient.contract.get_available_resources")
class TestMainConfigUnSet:
@pytest.mark.parametrize(
"kv_pair,err_msg",
Expand Down
2 changes: 1 addition & 1 deletion uaclient/cli/tests/test_cli_disable.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class TestDisable:
@mock.patch("uaclient.cli.disable._enabled_services")
@mock.patch("uaclient.lock.check_lock_info", return_value=(-1, ""))
@mock.patch(
"uaclient.cli.contract.UAContractClient.update_activity_token",
"uaclient.cli.disable.contract.UAContractClient.update_activity_token",
)
@mock.patch("uaclient.cli.entitlements.entitlement_factory")
@mock.patch("uaclient.cli.entitlements.valid_services")
Expand Down
Loading

0 comments on commit 4b91fd8

Please sign in to comment.