Skip to content

Commit

Permalink
Added key, replication, account subcommands (#1020)
Browse files Browse the repository at this point in the history
* added key {list|create|delete} commands

* updated tests and docs to use new key subcommands

* nox -s format

* added changelog.d files

* fixed changelog file

* updated key example

* added tests for deprecated key commands

* nox -s format

* fixed deprecated commands tests

* fixed deprecated command integration tests

* fixed deprecated integration tests

* added Subcommand suffix

* added replication subcommands

* combine changelog.d files.

* updated tests to use both commands and subcommands

* fixed deprecated integration tests

* renamed changelog files

* added account subcommands

* updated documentation

* use account subcommands in tests

* use `account authorize` subcommand in tests

* use `account authorize` subcommand in tests

* nox -s format

* fixed tests

* fixed typo

* add commands to v3 registry

* reverted README.md change

* reverted README.md change

* fixed tests

* added deprecated account commands tests
  • Loading branch information
adal-chiriliuc-reef authored Apr 24, 2024
1 parent 8999f91 commit 6146f70
Show file tree
Hide file tree
Showing 16 changed files with 499 additions and 135 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ B2_APPLICATION_KEY=<key> B2_APPLICATION_KEY_ID=<key-id> docker run --rm -e B2_AP
or authorize once and keep the credentials persisted:

```bash
docker run --rm -it -v b2:/root backblazeit/b2:latest b2v3 authorize-account
docker run --rm -it -v b2:/root backblazeit/b2:latest b2v3 account authorize
docker run --rm -v b2:/root backblazeit/b2:latest b2v3 list-buckets # remember to include `-v` - authorization details are there
```

Expand Down
3 changes: 3 additions & 0 deletions b2/_internal/_b2v4/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,6 @@
B2.register_subcommand(License)
B2.register_subcommand(InstallAutocomplete)
B2.register_subcommand(NotificationRules)
B2.register_subcommand(Key)
B2.register_subcommand(Replication)
B2.register_subcommand(Account)
3 changes: 3 additions & 0 deletions b2/_internal/b2v3/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,6 @@ class Ls(B2URIBucketNFolderNameArgMixin, BaseLs):
B2.register_subcommand(License)
B2.register_subcommand(InstallAutocomplete)
B2.register_subcommand(NotificationRules)
B2.register_subcommand(Key)
B2.register_subcommand(Replication)
B2.register_subcommand(Account)
214 changes: 194 additions & 20 deletions b2/_internal/console_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -1145,7 +1145,7 @@ class B2(Command):
There are two flows of authorization:
* call ``{NAME} authorize-account`` and have the credentials cached in sqlite
* call ``{NAME} account authorize`` and have the credentials cached in sqlite
* set ``{B2_APPLICATION_KEY_ID_ENV_VAR}`` and ``{B2_APPLICATION_KEY_ENV_VAR}`` environment
variables when running this program
Expand All @@ -1166,7 +1166,7 @@ class B2(Command):
If the directory ``{XDG_CONFIG_HOME_ENV_VAR}/b2`` does not exist (and is needed), it is created.
Please note that the above rules may be changed in next versions of b2sdk, and in order to get
reliable authentication file location you should use ``b2 get-account-info``.
reliable authentication file location you should use ``b2 account get``.
Control characters escaping is turned on if running under terminal.
You can override it by explicitly using `--escape-control-chars`/`--no-escape-control-chars`` option,
Expand Down Expand Up @@ -1206,7 +1206,7 @@ def _run(self, args):
return args.command_class


class AuthorizeAccount(Command):
class AccountAuthorizeBase(Command):
"""
Prompts for Backblaze ``applicationKeyId`` and ``applicationKey`` (unless they are given
on the command line).
Expand All @@ -1218,7 +1218,7 @@ class AuthorizeAccount(Command):
application key from the ``B2 Cloud Storage Buckets`` page on
the web site: https://secure.backblaze.com/b2_buckets.htm
To use a normal application key, created with the ``create-key``
To use a normal application key, created with the ``key create``
command or on the web site, provide the application key ID
and the application key itself.
Expand Down Expand Up @@ -1383,7 +1383,7 @@ def _run(self, args):
return 0


class ClearAccount(Command):
class AccountClearBase(Command):
"""
Erases everything in local cache.
Expand Down Expand Up @@ -1599,7 +1599,7 @@ def _run(self, args):
return 0


class CreateKey(Command):
class KeyCreateBase(Command):
"""
Creates a new application key. Prints the application key information. This is the only
time the application key itself will be returned. Listing application keys will show
Expand All @@ -1618,7 +1618,7 @@ class CreateKey(Command):
The ``namePrefix`` restricts file access to files whose names start with the prefix.
The output is the new application key ID, followed by the application key itself.
The two values returned are the two that you pass to ``authorize-account`` to use the key.
The two values returned are the two that you pass to ``account authorize`` to use the key.
Requires capability:
Expand Down Expand Up @@ -1717,7 +1717,7 @@ def _run(self, args):
return 0


class DeleteKey(Command):
class KeyDeleteBase(Command):
"""
Deletes the specified application key by its ID.
Expand Down Expand Up @@ -1977,7 +1977,7 @@ def _run(self, args):
return 0


class GetAccountInfo(Command):
class AccountGetBase(Command):
"""
Shows the account ID, key, auth token, URLs, and what capabilities
the current application keys has.
Expand Down Expand Up @@ -2204,7 +2204,7 @@ def run_list_buckets(cls, command: Command, *, json_: bool) -> int:
return 0


class ListKeys(Command):
class KeyListBase(Command):
"""
Lists the application keys for the current account.
Expand Down Expand Up @@ -3653,7 +3653,7 @@ def _run(self, args):
return 0


class ReplicationSetup(Command):
class ReplicationSetupBase(Command):
"""
Sets up replication between two buckets (potentially from different accounts), creating and replacing keys if necessary.
Expand Down Expand Up @@ -3779,7 +3779,7 @@ def alter_one_rule(cls, rule: ReplicationRule) -> ReplicationRule | None:
pass


class ReplicationDelete(ReplicationRuleChanger):
class ReplicationDeleteBase(ReplicationRuleChanger):
"""
Deletes a replication rule
Expand All @@ -3795,7 +3795,7 @@ def alter_one_rule(cls, rule: ReplicationRule) -> ReplicationRule | None:
return None


class ReplicationPause(ReplicationRuleChanger):
class ReplicationPauseBase(ReplicationRuleChanger):
"""
Pauses a replication rule
Expand All @@ -3812,7 +3812,7 @@ def alter_one_rule(cls, rule: ReplicationRule) -> ReplicationRule | None:
return rule


class ReplicationUnpause(ReplicationRuleChanger):
class ReplicationUnpauseBase(ReplicationRuleChanger):
"""
Unpauses a replication rule
Expand All @@ -3829,7 +3829,7 @@ def alter_one_rule(cls, rule: ReplicationRule) -> ReplicationRule | None:
return rule


class ReplicationStatus(Command):
class ReplicationStatusBase(Command):
"""
Inspects files in only source or both source and destination buckets
(potentially from different accounts) and provides detailed replication statistics.
Expand Down Expand Up @@ -4633,6 +4633,180 @@ def _run(self, args):
return 0


class Key(Command):
"""
Application keys management subcommands.
For more information on each subcommand, use ``{NAME} key SUBCOMMAND --help``.
Examples:
.. code-block::
{NAME} key list
{NAME} key create my-key listFiles,deleteFiles
{NAME} key delete 005c398ac3212400000000010
"""
subcommands_registry = ClassRegistry(attr_name='COMMAND_NAME')


@Key.subcommands_registry.register
class KeyListSubcommand(KeyListBase):
__doc__ = KeyListBase.__doc__
COMMAND_NAME = 'list'


@Key.subcommands_registry.register
class KeyCreateSubcommand(KeyCreateBase):
__doc__ = KeyCreateBase.__doc__
COMMAND_NAME = 'create'


@Key.subcommands_registry.register
class KeyDeleteSubcommand(KeyDeleteBase):
__doc__ = KeyDeleteBase.__doc__
COMMAND_NAME = 'delete'


class ListKeys(CmdReplacedByMixin, KeyListBase):
__doc__ = KeyListBase.__doc__
replaced_by_cmd = Key


class CreateKey(CmdReplacedByMixin, KeyCreateBase):
__doc__ = KeyCreateBase.__doc__
replaced_by_cmd = Key


class DeleteKey(CmdReplacedByMixin, KeyDeleteBase):
__doc__ = KeyDeleteBase.__doc__
replaced_by_cmd = Key


class Replication(Command):
"""
Replication rule management subcommands.
For more information on each subcommand, use ``{NAME} key SUBCOMMAND --help``.
Examples:
.. code-block::
{NAME} replication setup --name=my-repl-rule src-bucket dest-bucket
{NAME} replication status --rule=my-repl-rule src-bucket
{NAME} replication pause src-bucket my-repl-rule
{NAME} replication unpause src-bucket my-repl-rule
{NAME} replication delete src-bucket my-repl-rule
"""
subcommands_registry = ClassRegistry(attr_name='COMMAND_NAME')


@Replication.subcommands_registry.register
class ReplicationSetupSubcommand(ReplicationSetupBase):
__doc__ = ReplicationSetupBase.__doc__
COMMAND_NAME = 'setup'


@Replication.subcommands_registry.register
class ReplicationStatusSubcommand(ReplicationStatusBase):
__doc__ = ReplicationStatusBase.__doc__
COMMAND_NAME = 'status'


@Replication.subcommands_registry.register
class ReplicationPauseSubcommand(ReplicationPauseBase):
__doc__ = ReplicationPauseBase.__doc__
COMMAND_NAME = 'pause'


@Replication.subcommands_registry.register
class ReplicationUnpauseSubcommand(ReplicationUnpauseBase):
__doc__ = ReplicationUnpauseBase.__doc__
COMMAND_NAME = 'unpause'


@Replication.subcommands_registry.register
class ReplicationDeleteSubcommand(ReplicationDeleteBase):
__doc__ = ReplicationDeleteBase.__doc__
COMMAND_NAME = 'delete'


class ReplicationSetup(CmdReplacedByMixin, ReplicationSetupBase):
__doc__ = ReplicationSetupBase.__doc__
replaced_by_cmd = Replication


class ReplicationStatus(CmdReplacedByMixin, ReplicationStatusBase):
__doc__ = ReplicationStatusBase.__doc__
replaced_by_cmd = Replication


class ReplicationPause(CmdReplacedByMixin, ReplicationPauseBase):
__doc__ = ReplicationPauseBase.__doc__
replaced_by_cmd = Replication


class ReplicationUnpause(CmdReplacedByMixin, ReplicationUnpauseBase):
__doc__ = ReplicationUnpauseBase.__doc__
replaced_by_cmd = Replication


class ReplicationDelete(CmdReplacedByMixin, ReplicationDeleteBase):
__doc__ = ReplicationDeleteBase.__doc__
replaced_by_cmd = Replication


class Account(Command):
"""
Account management subcommands.
For more information on each subcommand, use ``{NAME} key SUBCOMMAND --help``.
Examples:
.. code-block::
{NAME} account authorize [applicationKeyId] [applicationKey]
{NAME} account get
{NAME} account clear
"""
subcommands_registry = ClassRegistry(attr_name='COMMAND_NAME')


@Account.subcommands_registry.register
class AccountAuthorize(AccountAuthorizeBase):
__doc__ = AccountAuthorizeBase.__doc__
COMMAND_NAME = 'authorize'


@Account.subcommands_registry.register
class AccountGet(AccountGetBase):
__doc__ = AccountGetBase.__doc__
COMMAND_NAME = 'get'


@Account.subcommands_registry.register
class AccountClear(AccountClearBase):
__doc__ = AccountClearBase.__doc__
COMMAND_NAME = 'clear'


class AuthorizeAccount(CmdReplacedByMixin, AccountAuthorizeBase):
__doc__ = AccountAuthorizeBase.__doc__
replaced_by_cmd = Account


class GetAccountInfo(CmdReplacedByMixin, AccountGetBase):
__doc__ = AccountGetBase.__doc__
replaced_by_cmd = Account


class ClearAccount(CmdReplacedByMixin, AccountClearBase):
__doc__ = AccountClearBase.__doc__
replaced_by_cmd = Account


class ConsoleTool:
"""
Implements the commands available in the B2 command-line tool
Expand Down Expand Up @@ -4702,7 +4876,7 @@ def run_command(self, argv):
except MissingAccountData as e:
logger.exception('ConsoleTool missing account data error')
self._print_stderr(
f'ERROR: {e} Use: {self.b2_binary_name} authorize-account or provide auth data with '
f'ERROR: {e} Use: \'{self.b2_binary_name} account authorize\' or provide auth data with '
f'{B2_APPLICATION_KEY_ID_ENV_VAR!r} and {B2_APPLICATION_KEY_ENV_VAR!r} environment variables'
)
return 1
Expand Down Expand Up @@ -4735,8 +4909,8 @@ def _initialize_b2_api(cls, args: argparse.Namespace, kwargs: dict) -> B2Api:
except MissingAccountData:
is_same_key_on_disk = False

if not is_same_key_on_disk and args.command_class not in (
AuthorizeAccount, ClearAccount
if not is_same_key_on_disk and not issubclass(
args.command_class, (AccountAuthorizeBase, AccountClearBase)
):
# when user specifies keys via env variables, we switch to in-memory account info
return _get_inmemory_b2api(**kwargs)
Expand All @@ -4760,8 +4934,8 @@ def authorize_from_env(self) -> int:
if self.api.account_info.is_same_key(key_id, realm or 'production'):
return 0

logger.info('authorize-account is being run from env variables')
return AuthorizeAccount(self).authorize(key_id, key, realm)
logger.info('`account authorize` is being run from env variables')
return AccountAuthorizeBase(self).authorize(key_id, key, realm)

def _print(self, *args, **kwargs):
print(*args, file=self.stdout, **kwargs)
Expand Down
1 change: 1 addition & 0 deletions changelog.d/+command-account.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add `account {authorize|get|clear}` commands.
1 change: 1 addition & 0 deletions changelog.d/+command-account.deprecated.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Deprecated `authorize-account`, `get-account-info` and `clear-account`, use `account {authorize|get|clear}` instead.
1 change: 1 addition & 0 deletions changelog.d/+command-key.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add `key {list|create|delete}` commands.
1 change: 1 addition & 0 deletions changelog.d/+command-key.deprecated.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Deprecated `list-keys`, `create-key` and `delete-key`, use `key {list|create|delete}` instead.
1 change: 1 addition & 0 deletions changelog.d/+command-replication.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add `replication {setup|delete|pause|unpause|status}` commands.
1 change: 1 addition & 0 deletions changelog.d/+command-replication.deprecated.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Deprecated `replication-{setup|delete|pause|unpause|status}`, use `replication {setup|delete|pause|unpause|status}` instead.
Loading

0 comments on commit 6146f70

Please sign in to comment.