Skip to content

Commit c33a28b

Browse files
committed
MB-70102 Add 3 new flags to the repo-add command
The new flags are --worm, --default-retention, --cloud-retention-delete-versions. They to correspond to the body parameters with the same name of the AddActiveRepository endpoint. Change-Id: I87dfdc871a40683d8d44c68456590d60246455b7 Reviewed-on: https://review.couchbase.org/c/couchbase-cli/+/238417 Reviewed-by: Safian Ali <safian.ali@couchbase.com> Tested-by: Build Bot <build@couchbase.com>
1 parent abe127f commit c33a28b

3 files changed

Lines changed: 88 additions & 1 deletion

File tree

cbmgr.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7349,6 +7349,9 @@ def __init__(self, subparser):
73497349
group.add_argument('--location', metavar='<location>', help='The location to store the backups in',
73507350
required=True)
73517351
group.add_argument('--bucket-name', metavar='<bucket_name>', help='The bucket to backup')
7352+
group.add_argument('--worm', type=int, metavar='<days>', help='The WORM compliance period in days')
7353+
group.add_argument('--default-retention', type=int, metavar='<days>',
7354+
help='The default retention period in days')
73527355

73537356
# the cloud arguments are given the own group so that the short help is a bit more readable
73547357
cloud_group = repository_parser.add_argument_group('Backup repository cloud arguments')
@@ -7368,6 +7371,9 @@ def __init__(self, subparser):
73687371
'Use for object store compatible third party solutions')
73697372
cloud_group.add_argument('--cloud-force-path-style', action='store_true',
73707373
help='When using S3 or S3 compatible storage it will use the old path style.')
7374+
cloud_group.add_argument('--cloud-retention-delete-versions', action='store_true',
7375+
help='Pruning expired backups will also delete old object versions. (This applies to'
7376+
'backups in a versioning-enabled object store)')
73717377

73727378
@rest_initialiser(version_check=True, enterprise_check=True, cluster_init_check=True)
73737379
def execute(self, opts):
@@ -7406,6 +7412,17 @@ def execute(self, opts):
74067412
if opts.cloud_force_path_style is not None:
74077413
request_body["cloud_force_path_style"] = opts.cloud_force_path_style
74087414

7415+
if opts.worm is not None:
7416+
if opts.worm < 3 or opts.worm > 36525:
7417+
_exit_if_errors(['the provided WORM period must be in the [3, 36525] range'])
7418+
request_body["worm"] = opts.worm
7419+
7420+
if opts.default_retention is not None:
7421+
request_body["default_retention"] = opts.default_retention
7422+
7423+
if opts.cloud_retention_delete_versions is not None:
7424+
request_body["cloud_retention_delete_versions"] = opts.cloud_retention_delete_versions
7425+
74097426
_, errors = self.rest.add_backup_active_repository(opts.id, request_body)
74107427
_exit_if_errors(errors)
74117428
_success('Added repository')

docs/modules/cli/pages/cbcli/couchbase-cli-backup-service-repo-add.adoc

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ _couchbase-cli backup-service_ [--cluster <url>] [--username <user>]
2020
[--cloud-credentials-name <name>] [--cloud-staging-dir <path>]
2121
[--cloud-credentials-id <id>] [--cloud-credentials-key <key>]
2222
[--cloud-credentials-refresh-token <token>] [--cloud-region <region>]
23-
[--cloud-endpoint <endpoint>] [--cloud-force-path-style]
23+
[--cloud-endpoint <endpoint>] [--cloud-force-path-style] [--worm <days>]
24+
[--default-retention <days>] [--cloud-retention-delete-versions]
2425

2526
== DESCRIPTION
2627

@@ -50,6 +51,16 @@ directly in object storage such as S3, Azure, GCP or compatible stores.
5051
Optionally specify a single bucket to back up. If not provided, all
5152
buckets will be included in the backup.
5253

54+
--worm <days>::
55+
The repo WORM compliance period in days. Must be in the [3, 36525] range.
56+
Used to enable WORM for the repository. Newly created backups will be immutable
57+
for the provided period. The repo must be located in an object store to enable
58+
WORM.
59+
60+
--default-retention <days>::
61+
The default retention period in days. Scheduled PRUNE tasks will automatically
62+
delete backups with an expired retention period.
63+
5364
== CLOUD OPTIONS
5465

5566
The following options are used when creating a cloud backup repository that
@@ -88,6 +99,12 @@ stores data in object storage.
8899
instead of virtual-hosted-style URLs. Some S3-compatible stores require
89100
this option.
90101

102+
--cloud-retention-delete-versions::
103+
Pruning expired backups will also delete old object versions. If this is
104+
set, whenever a backup's retention period expires we will also deleted old
105+
versions of the cloud objects. This applies only to backups in a
106+
versioning-enabled object store. Versioning permissions are required.
107+
91108
include::{partialsdir}/cbcli/part-common-options.adoc[]
92109

93110
include::{partialsdir}/cbcli/part-host-formats.adoc[]

test/test_cli.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5303,6 +5303,59 @@ def test_add_repository_with_refresh_token(self):
53035303
body = json.loads(self.server.rest_params[0])
53045304
self.assertEqual('refresh-token-value', body['cloud_credentials_refresh_token'])
53055305

5306+
def test_add_repository_with_worm(self):
5307+
"""Test adding a repository with WORM compliance period"""
5308+
self.server_args['POST:/api/v1/cluster/self/repository/active/wormrepo'] = {}
5309+
5310+
self.no_error_run(self.command + [
5311+
'--id', 'wormrepo',
5312+
'--plan', 'daily',
5313+
'--location', '/backup/archive',
5314+
'--worm', '365'
5315+
], self.server_args)
5316+
self.assertIn('POST:/api/v1/cluster/self/repository/active/wormrepo', self.server.trace)
5317+
self.assertIn('Added repository', self.str_output)
5318+
# Verify JSON body contains expected parameters
5319+
self.assertEqual(1, len(self.server.rest_params))
5320+
body = json.loads(self.server.rest_params[0])
5321+
self.assertEqual(365, body['worm'])
5322+
5323+
def test_add_repository_with_default_retention(self):
5324+
"""Test adding a repository with default retention period"""
5325+
self.server_args['POST:/api/v1/cluster/self/repository/active/retentionrepo'] = {}
5326+
5327+
self.no_error_run(self.command + [
5328+
'--id', 'retentionrepo',
5329+
'--plan', 'daily',
5330+
'--location', '/backup/archive',
5331+
'--default-retention', '30'
5332+
], self.server_args)
5333+
self.assertIn('POST:/api/v1/cluster/self/repository/active/retentionrepo', self.server.trace)
5334+
self.assertIn('Added repository', self.str_output)
5335+
# Verify JSON body contains expected parameters
5336+
self.assertEqual(1, len(self.server.rest_params))
5337+
body = json.loads(self.server.rest_params[0])
5338+
self.assertEqual(30, body['default_retention'])
5339+
5340+
def test_add_repository_with_cloud_retention_delete_versions(self):
5341+
"""Test adding a cloud repository with retention delete versions enabled"""
5342+
self.server_args['POST:/api/v1/cluster/self/repository/active/deleteversionrepo'] = {}
5343+
5344+
self.no_error_run(self.command + [
5345+
'--id', 'deleteversionrepo',
5346+
'--plan', 'daily',
5347+
'--location', 's3://mybucket/backup',
5348+
'--cloud-credentials-name', 'my-aws-creds',
5349+
'--cloud-staging-dir', '/tmp/staging',
5350+
'--cloud-retention-delete-versions'
5351+
], self.server_args)
5352+
self.assertIn('POST:/api/v1/cluster/self/repository/active/deleteversionrepo', self.server.trace)
5353+
self.assertIn('Added repository', self.str_output)
5354+
# Verify JSON body contains expected parameters
5355+
self.assertEqual(1, len(self.server.rest_params))
5356+
body = json.loads(self.server.rest_params[0])
5357+
self.assertTrue(body['cloud_retention_delete_versions'])
5358+
53065359

53075360
class TestBackupServiceRepoArchive(CommandTest):
53085361
"""Test the backup-service repo-archive subcommand"""

0 commit comments

Comments
 (0)