Skip to content

Commit

Permalink
Added bucket subcommands (#1022)
Browse files Browse the repository at this point in the history
* added bucket subcommands

* use bucket subcommands

* use bucket subcommands

* use bucket subcommands

* updated docs

* nox -s format

* added bucket notification-rule

* nox -s format

* use bucket notification-rule subcommand

* nox -s format

* replace notification-rules with notification-rule in comments

* unit tests for deprecated notification-rules command

* nox -s format

* fixed typo

* added unit test for deprecated bucket commands

* nested replaced by

* updated expected stderr messages

* PR changes
  • Loading branch information
adal-chiriliuc-reef authored Apr 25, 2024
1 parent a11c1b6 commit e5cafd6
Show file tree
Hide file tree
Showing 14 changed files with 434 additions and 213 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,17 +126,17 @@ but make sure to explicitly use `b2v3` command from the docker image as shown be

#### Authorization

User can either authorize on each command (`list-buckets` is just a example here)
User can either authorize on each command (`bucket list` is just a example here)

```bash
B2_APPLICATION_KEY=<key> B2_APPLICATION_KEY_ID=<key-id> docker run --rm -e B2_APPLICATION_KEY -e B2_APPLICATION_KEY_ID backblazeit/b2:latest b2v3 list-buckets
B2_APPLICATION_KEY=<key> B2_APPLICATION_KEY_ID=<key-id> docker run --rm -e B2_APPLICATION_KEY -e B2_APPLICATION_KEY_ID backblazeit/b2:latest b2v3 bucket list
```

or authorize once and keep the credentials persisted:

```bash
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
docker run --rm -v b2:/root backblazeit/b2:latest b2v3 bucket list # remember to include `-v` - authorization details are there
```

#### Downloading and uploading
Expand Down
1 change: 1 addition & 0 deletions b2/_internal/_b2v4/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,4 @@
B2.register_subcommand(Key)
B2.register_subcommand(Replication)
B2.register_subcommand(Account)
B2.register_subcommand(BucketCmd)
1 change: 1 addition & 0 deletions b2/_internal/b2v3/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,4 @@ class Ls(B2URIBucketNFolderNameArgMixin, BaseLs):
B2.register_subcommand(Key)
B2.register_subcommand(Replication)
B2.register_subcommand(Account)
B2.register_subcommand(BucketCmd)
182 changes: 143 additions & 39 deletions b2/_internal/console_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -1548,7 +1548,7 @@ def _determine_source_metadata(
return source_file_version.file_info, source_file_version.content_type


class CreateBucket(DefaultSseMixin, LifecycleRulesMixin, Command):
class BucketCreateBase(DefaultSseMixin, LifecycleRulesMixin, Command):
"""
Creates a new bucket. Prints the ID of the bucket created.
Expand Down Expand Up @@ -1672,7 +1672,7 @@ def _run(self, args):
return 0


class DeleteBucket(Command):
class BucketDeleteBase(Command):
"""
Deletes the bucket with the given name.
Expand Down Expand Up @@ -1995,7 +1995,7 @@ def _run(self, args):
return 0


class GetBucket(Command):
class BucketGetBase(Command):
"""
Prints all of the information about the bucket, including
bucket info, CORS rules and lifecycle rules.
Expand Down Expand Up @@ -2080,7 +2080,7 @@ class GetFileInfo(CmdReplacedByMixin, B2URIFileIDArgMixin, FileInfoBase):
replaced_by_cmd = FileInfo


class GetDownloadAuth(Command):
class BucketGetDownloadAuthBase(Command):
"""
Prints an authorization token that is valid only for downloading
files from the given bucket.
Expand Down Expand Up @@ -2171,7 +2171,7 @@ def _run(self, args):
return 0


class ListBuckets(Command):
class BucketListBase(Command):
"""
Lists all of the buckets in the current account.
Expand Down Expand Up @@ -3157,7 +3157,7 @@ def get_synchronizer_from_args(
)


class UpdateBucket(DefaultSseMixin, LifecycleRulesMixin, Command):
class BucketUpdateBase(DefaultSseMixin, LifecycleRulesMixin, Command):
"""
Updates the ``bucketType`` of an existing bucket. Prints the ID
of the bucket updated.
Expand Down Expand Up @@ -4254,7 +4254,7 @@ def _run(self, args):
return 0


class NotificationRulesWarningMixin(Described):
class BucketNotificationRuleWarningMixin(Described):
"""
.. warning::
Expand All @@ -4263,40 +4263,40 @@ class NotificationRulesWarningMixin(Described):
"""


class NotificationRules(NotificationRulesWarningMixin, Command):
class BucketNotificationRuleBase(BucketNotificationRuleWarningMixin, Command):
"""
Bucket notification rules management subcommands.
{NotificationRulesWarningMixin}
{BucketNotificationRuleWarningMixin}
For more information on each subcommand, use ``{NAME} notification-rules SUBCOMMAND --help``.
For more information on each subcommand, use ``{NAME} bucket notification-rule SUBCOMMAND --help``.
Examples:
.. code-block::
{NAME} notification-rules create b2://bucketName/optionalSubPath/ ruleName --event-type "b2:ObjectCreated:*" --webhook-url https://example.com/webhook
{NAME} notification-rules list b2://bucketName
{NAME} notification-rules update b2://bucketName/newPath/ ruleName --disable --event-type "b2:ObjectCreated:*" --event-type "b2:ObjectHidden:*"
{NAME} notification-rules delete b2://bucketName ruleName
{NAME} bucket notification-rule create b2://bucketName/optionalSubPath/ ruleName --event-type "b2:ObjectCreated:*" --webhook-url https://example.com/webhook
{NAME} bucket notification-rule list b2://bucketName
{NAME} bucket notification-rule update b2://bucketName/newPath/ ruleName --disable --event-type "b2:ObjectCreated:*" --event-type "b2:ObjectHidden:*"
{NAME} bucket notification-rule delete b2://bucketName ruleName
"""
subcommands_registry = ClassRegistry(attr_name='COMMAND_NAME')


@NotificationRules.subcommands_registry.register
class NotificationRulesList(JSONOptionMixin, NotificationRulesWarningMixin, Command):
@BucketNotificationRuleBase.subcommands_registry.register
class BucketNotificationRuleList(JSONOptionMixin, BucketNotificationRuleWarningMixin, Command):
"""
Allows listing bucket notification rules of the given bucket.
{NotificationRulesWarningMixin}
{BucketNotificationRuleWarningMixin}
{JSONOptionMixin}
Examples:
.. code-block::
{NAME} notification-rules list b2://bucketName
{NAME} notification-rule list b2://bucketName
Requires capability:
Expand Down Expand Up @@ -4334,7 +4334,9 @@ def _run(self, args):
return 0


class NotificationRulesCreateBase(JSONOptionMixin, NotificationRulesWarningMixin, Command):
class BucketNotificationRuleCreateBase(
JSONOptionMixin, BucketNotificationRuleWarningMixin, Command
):
@classmethod
def _validate_secret(cls, value: str) -> str:
if not re.match(r'^[a-zA-Z0-9]{32}$', value):
Expand Down Expand Up @@ -4418,7 +4420,7 @@ def print_rule(self, args, rule):
self._print_human_readable_structure(rule)


class NotificationRulesUpdateBase(NotificationRulesCreateBase):
class BucketNotificationRuleUpdateBase(BucketNotificationRuleCreateBase):
def _run(self, args):
bucket = self.api.get_bucket_by_name(args.B2_URI.bucket_name)
rules_by_name = {rule["name"]: rule for rule in bucket.get_notification_rules()}
Expand All @@ -4442,18 +4444,18 @@ def _run(self, args):
return 0


@NotificationRules.subcommands_registry.register
class NotificationRulesCreate(NotificationRulesCreateBase):
@BucketNotificationRuleBase.subcommands_registry.register
class BucketNotificationRuleCreate(BucketNotificationRuleCreateBase):
"""
Allows creating bucket notification rules for the given bucket.
{NotificationRulesWarningMixin}
{BucketNotificationRuleWarningMixin}
Examples:
.. code-block::
{NAME} notification-rules create b2://bucketName/optionalSubPath/ ruleName --event-type "b2:ObjectCreated:*" --webhook-url https://example.com/webhook
{NAME} notification-rule create b2://bucketName/optionalSubPath/ ruleName --event-type "b2:ObjectCreated:*" --webhook-url https://example.com/webhook
Requires capability:
Expand Down Expand Up @@ -4501,19 +4503,19 @@ def _run(self, args):
return 0


@NotificationRules.subcommands_registry.register
class NotificationRulesUpdate(NotificationRulesUpdateBase):
@BucketNotificationRuleBase.subcommands_registry.register
class BucketNotificationRuleUpdate(BucketNotificationRuleUpdateBase):
"""
Allows updating notification rule of the given bucket.
{NotificationRulesWarningMixin}
{BucketNotificationRuleWarningMixin}
Examples:
.. code-block::
{NAME} notification-rules update b2://bucketName/newPath/ ruleName --disable --event-type "b2:ObjectCreated:*" --event-type "b2:ObjectHidden:*"
{NAME} notification-rules update b2://bucketName/newPath/ ruleName --enable
{NAME} notification-rule update b2://bucketName/newPath/ ruleName --disable --event-type "b2:ObjectCreated:*" --event-type "b2:ObjectHidden:*"
{NAME} notification-rule update b2://bucketName/newPath/ ruleName --enable
Requires capability:
Expand All @@ -4530,18 +4532,18 @@ def _setup_parser(cls, parser):
super()._setup_parser(parser)


@NotificationRules.subcommands_registry.register
class NotificationRulesEnable(NotificationRulesUpdateBase):
@BucketNotificationRuleBase.subcommands_registry.register
class BucketNotificationRuleEnable(BucketNotificationRuleUpdateBase):
"""
Allows enabling notification rule of the given bucket.
{NotificationRulesWarningMixin}
{BucketNotificationRuleWarningMixin}
Examples:
.. code-block::
{NAME} notification-rules enable b2://bucketName/ ruleName
{NAME} notification-rule enable b2://bucketName/ ruleName
Requires capability:
Expand All @@ -4565,18 +4567,18 @@ def get_rule_from_args(self, args):
return {'name': args.ruleName, 'isEnabled': True}


@NotificationRules.subcommands_registry.register
class NotificationRulesDisable(NotificationRulesUpdateBase):
@BucketNotificationRuleBase.subcommands_registry.register
class BucketNotificationRuleDisable(BucketNotificationRuleUpdateBase):
"""
Allows disabling notification rule of the given bucket.
{NotificationRulesWarningMixin}
{BucketNotificationRuleWarningMixin}
Examples:
.. code-block::
{NAME} notification-rules disable b2://bucketName/ ruleName
{NAME} notification-rule disable b2://bucketName/ ruleName
Requires capability:
Expand All @@ -4600,8 +4602,8 @@ def get_rule_from_args(self, args):
return {'name': args.ruleName, 'isEnabled': False}


@NotificationRules.subcommands_registry.register
class NotificationRulesDelete(Command):
@BucketNotificationRuleBase.subcommands_registry.register
class BucketNotificationRuleDelete(Command):
"""
Allows deleting bucket notification rule of the given bucket.
Expand Down Expand Up @@ -4813,6 +4815,108 @@ class ClearAccount(CmdReplacedByMixin, AccountClearBase):
replaced_by_cmd = (Account, AccountClear)


class BucketCmd(Command):
"""
Bucket management subcommands.
For more information on each subcommand, use ``{NAME} key SUBCOMMAND --help``.
Examples:
.. code-block::
{NAME} bucket list
{NAME} bucket get
{NAME} bucket create
{NAME} bucket update
{NAME} bucket delete
{NAME} bucket get-download-auth
"""
# to avoid conflicts with the Bucket class this class is named BucketCmd
COMMAND_NAME = "bucket"

subcommands_registry = ClassRegistry(attr_name='COMMAND_NAME')


@BucketCmd.subcommands_registry.register
class BucketList(BucketListBase):
__doc__ = BucketListBase.__doc__
COMMAND_NAME = 'list'


@BucketCmd.subcommands_registry.register
class BucketGet(BucketGetBase):
__doc__ = BucketGetBase.__doc__
COMMAND_NAME = 'get'


@BucketCmd.subcommands_registry.register
class BucketCreate(BucketCreateBase):
__doc__ = BucketCreateBase.__doc__
COMMAND_NAME = 'create'


@BucketCmd.subcommands_registry.register
class BucketUpdate(BucketUpdateBase):
__doc__ = BucketUpdateBase.__doc__
COMMAND_NAME = 'update'


@BucketCmd.subcommands_registry.register
class BucketDelete(BucketDeleteBase):
__doc__ = BucketDeleteBase.__doc__
COMMAND_NAME = 'delete'


@BucketCmd.subcommands_registry.register
class BucketGetDownloadAuth(BucketGetDownloadAuthBase):
__doc__ = BucketGetDownloadAuthBase.__doc__
# TODO we can't use 'get-download-auth', gets transformed to 'get--download--auth'
COMMAND_NAME = 'GetDownloadAuth'


@BucketCmd.subcommands_registry.register
class BucketNotificationRule(BucketNotificationRuleBase):
__doc__ = BucketNotificationRuleBase.__doc__
# TODO we can't use 'notification-rule', gets transformed to 'notification--rule'
COMMAND_NAME = 'NotificationRule'


class ListBuckets(CmdReplacedByMixin, BucketListBase):
__doc__ = BucketListBase.__doc__
replaced_by_cmd = (BucketCmd, BucketList)


class GetBucket(CmdReplacedByMixin, BucketGetBase):
__doc__ = BucketGetBase.__doc__
replaced_by_cmd = (BucketCmd, BucketGet)


class CreateBucket(CmdReplacedByMixin, BucketCreateBase):
__doc__ = BucketCreateBase.__doc__
replaced_by_cmd = (BucketCmd, BucketCreate)


class UpdateBucket(CmdReplacedByMixin, BucketUpdateBase):
__doc__ = BucketUpdateBase.__doc__
replaced_by_cmd = (BucketCmd, BucketUpdate)


class DeleteBucket(CmdReplacedByMixin, BucketDeleteBase):
__doc__ = BucketDeleteBase.__doc__
replaced_by_cmd = (BucketCmd, BucketDelete)


class GetDownloadAuth(CmdReplacedByMixin, BucketGetDownloadAuthBase):
__doc__ = BucketGetDownloadAuthBase.__doc__
replaced_by_cmd = (BucketCmd, BucketGetDownloadAuth)


class NotificationRules(CmdReplacedByMixin, BucketNotificationRuleBase):
__doc__ = BucketNotificationRuleBase.__doc__
replaced_by_cmd = (BucketCmd, BucketNotificationRule)


class ConsoleTool:
"""
Implements the commands available in the B2 command-line tool
Expand Down
1 change: 1 addition & 0 deletions changelog.d/+command-bucket.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add `bucket {list|get|create|update|delete|get-download-auth|notification-rule}` commands.
1 change: 1 addition & 0 deletions changelog.d/+command-bucket.deprecated.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Deprecated `list-buckets`, `get-bucket`, `create-bucket`, `update-bucket`, `delete-bucket`, `get-download-auth` and `notification-rules`, use `bucket {list|get|create|update|delete|get-download-auth|notification-rule}` instead.
Loading

0 comments on commit e5cafd6

Please sign in to comment.