Skip to content

Commit a3882c0

Browse files
committed
MB-70103 Add backup-service repo-remove command
Also, marks the backup-service repository command as deprecated. Duplicates the functionality of backup-service repository --remove which will be deprecated. Change-Id: I258142b244ce61f91f419674a6a6cdc9ed5e0a7d Reviewed-on: https://review.couchbase.org/c/couchbase-cli/+/238413 Reviewed-by: Safian Ali <safian.ali@couchbase.com> Tested-by: Build Bot <build@couchbase.com>
1 parent ef38e70 commit a3882c0

9 files changed

Lines changed: 218 additions & 9 deletions

cbmgr.py

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7000,12 +7000,13 @@ def __init__(self):
70007000
self.repo_get_cmd = BackupServiceRepoGet(self.subparser)
70017001
self.repo_add_cmd = BackupServiceRepoAdd(self.subparser)
70027002
self.repo_archive_cmd = BackupServiceRepoArchive(self.subparser)
7003+
self.repo_remove_cmd = BackupServiceRepoRemove(self.subparser)
70037004
self.plan_cmd = BackupServicePlan(self.subparser)
70047005
self.nodeThreads_cmd = BackupServiceNodeThreadsMap(self.subparser)
70057006

70067007
def execute(self, opts):
7007-
subcommands = ['settings', 'repository', 'repo-list', 'repo-get', 'repo-add', 'repo-archive', 'plan',
7008-
'node-threads']
7008+
subcommands = ['settings', 'repository', 'repo-list', 'repo-get', 'repo-add', 'repo-archive', 'repo-remove',
7009+
'plan', 'node-threads']
70097010

70107011
if opts.sub_cmd is None or opts.sub_cmd not in subcommands:
70117012
_exit_if_errors([f'<subcommand> must be one of {subcommands}'])
@@ -7022,6 +7023,8 @@ def execute(self, opts):
70227023
self.repo_add_cmd.execute(opts)
70237024
elif opts.sub_cmd == 'repo-archive':
70247025
self.repo_archive_cmd.execute(opts)
7026+
elif opts.sub_cmd == 'repo-remove':
7027+
self.repo_remove_cmd.execute(opts)
70257028
elif opts.sub_cmd == 'plan':
70267029
self.plan_cmd.execute(opts)
70277030
elif opts.sub_cmd == 'node-threads':
@@ -7435,8 +7438,44 @@ def get_description():
74357438
return 'Archive a repository'
74367439

74377440

7441+
class BackupServiceRepoRemove:
7442+
"""Removes a backup repository
7443+
"""
7444+
7445+
def __init__(self, subparser):
7446+
"""setup the parser"""
7447+
self.rest = None
7448+
repository_parser = subparser.add_parser('repo-remove', help='Remove a backup repository', add_help=False,
7449+
allow_abbrev=False)
7450+
7451+
group = repository_parser.add_argument_group('Backup service repository configuration')
7452+
group.add_argument('--id', metavar='<id>', help='The repository id', required=True)
7453+
group.add_argument('--state', metavar='<state>', choices=['archived', 'imported'],
7454+
help='The repository state.', required=True)
7455+
group.add_argument('--delete-data', action='store_true',
7456+
help='Used to delete the repository data of an archived repository')
7457+
7458+
@rest_initialiser(version_check=True, enterprise_check=True, cluster_init_check=True)
7459+
def execute(self, opts):
7460+
"""Run the backup-service repo-remove subcommand"""
7461+
if opts.delete_data and opts.state == 'imported':
7462+
_exit_if_errors(['cannot delete the data of an imported repository'])
7463+
7464+
_, errors = self.rest.delete_backup_repository(opts.id, opts.state, opts.delete_data)
7465+
_exit_if_errors(errors)
7466+
_success('Repository was removed')
7467+
7468+
@staticmethod
7469+
def get_man_page_name():
7470+
return get_doc_page_name("couchbase-cli-backup-service-repo-remove")
7471+
7472+
@staticmethod
7473+
def get_description():
7474+
return 'Remove a repository'
7475+
7476+
74387477
class BackupServiceRepository:
7439-
"""This command manages backup services repositories.
7478+
"""(Deprecated) This command manages backup services repositories.
74407479
74417480
Things this command can do is:
74427481
- List repositories
@@ -7496,6 +7535,9 @@ def __init__(self, subparser):
74967535
@rest_initialiser(version_check=True, enterprise_check=True, cluster_init_check=True)
74977536
def execute(self, opts):
74987537
"""Run the backup-service repository subcommand"""
7538+
_deprecated("The 'backup-service repository' subcommand is deprecated. Please use the 'repo-add', "
7539+
"'repo-list', 'repo-get', 'repo-remove' and 'repo-archive' subcommands instead")
7540+
74997541
if opts.list:
75007542
self.list_repositories(opts.state, opts.output == 'json')
75017543
elif opts.get:

docs/modules/cli/pages/_partials/cbcli/nav.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
** xref:cli:cbcli/couchbase-cli-backup-service-repo-archive.adoc[backup-service repo-archive]
99
** xref:cli:cbcli/couchbase-cli-backup-service-repo-get.adoc[backup-service repo-get]
1010
** xref:cli:cbcli/couchbase-cli-backup-service-repo-list.adoc[backup-service repo-list]
11+
** xref:cli:cbcli/couchbase-cli-backup-service-repo-remove.adoc[backup-service repo-remove]
1112
** xref:cli:cbcli/couchbase-cli-backup-service-repository.adoc[backup-service repository]
1213
** xref:cli:cbcli/couchbase-cli-backup-service-settings.adoc[backup-service settings]
1314
** xref:cli:cbcli/couchbase-cli-bucket-compact.adoc[bucket-compact]

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ man:couchbase-cli-backup-service[1],
185185
man:couchbase-cli-backup-service-repo-get[1],
186186
man:couchbase-cli-backup-service-repo-list[1],
187187
man:couchbase-cli-backup-service-repo-archive[1],
188+
man:couchbase-cli-backup-service-repo-remove[1],
188189
man:couchbase-cli-backup-service-plan[1]
189190

190191

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ include::{partialsdir}/cbcli/part-common-env.adoc[]
7979
man:couchbase-cli-backup-service[1],
8080
man:couchbase-cli-backup-service-repo-add[1],
8181
man:couchbase-cli-backup-service-repo-get[1],
82-
man:couchbase-cli-backup-service-repo-list[1]
82+
man:couchbase-cli-backup-service-repo-list[1],
83+
man:couchbase-cli-backup-service-repo-remove[1]
8384

8485
include::{partialsdir}/cbcli/part-footer.adoc[]
8586

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ include::{partialsdir}/cbcli/part-common-env.adoc[]
114114
man:couchbase-cli-backup-service[1],
115115
man:couchbase-cli-backup-service-repo-get[1],
116116
man:couchbase-cli-backup-service-repo-add[1],
117-
man:couchbase-cli-backup-service-repo-archive[1]
117+
man:couchbase-cli-backup-service-repo-archive[1],
118+
man:couchbase-cli-backup-service-repo-remove[1]
118119

119120
include::{partialsdir}/cbcli/part-footer.adoc[]
120121

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
= couchbase-cli-backup-service-repo-remove(1)
2+
:description: Remove a backup service repository
3+
ifndef::doctype-manpage[:doctitle: backup-service repo-remove]
4+
5+
ifdef::doctype-manpage[]
6+
== NAME
7+
8+
couchbase-cli-backup-service-repo-remove -
9+
endif::[]
10+
Remove a backup service repository
11+
12+
== SYNOPSIS
13+
14+
[verse]
15+
_couchbase-cli backup-service_ [--cluster <url>] [--username <user>]
16+
[--password <password>] [--client-cert <path>]
17+
[--client-cert-password <password>] [--client-key <path>]
18+
[--client-key-password <password>] _repo-remove_ [--id <id>]
19+
[--state <state>] [--delete-data]
20+
21+
== DESCRIPTION
22+
23+
Removes an archived or imported backup repository from the backup service.
24+
Optionally, the underlying backup data can also be deleted using the
25+
`--delete-data` flag (only valid for archived repositories).
26+
27+
Note that active repositories cannot be removed directly. To remove an active
28+
repository, it must first be archived. This can be done using the `repo-archive` command.
29+
30+
== OPTIONS
31+
32+
--id <id>::
33+
The ID of the repository to remove. This argument is required.
34+
35+
--state <state>::
36+
The state of the repository to remove. Valid states are 'archived' or
37+
'imported'. This argument is required. Note that active repositories
38+
cannot be removed directly.
39+
40+
--delete-data::
41+
If specified, the underlying backup data will also be deleted. This flag
42+
is only valid for archived repositories. Imported repositories cannot have
43+
their data deleted.
44+
45+
include::{partialsdir}/cbcli/part-common-options.adoc[]
46+
47+
include::{partialsdir}/cbcli/part-host-formats.adoc[]
48+
49+
include::{partialsdir}/cbcli/part-certificate-authentication.adoc[]
50+
51+
== EXAMPLES
52+
53+
To remove an archived repository with ID 'old-backup' without deleting the
54+
underlying backup data, run the following command.
55+
56+
----
57+
$ couchbase-cli backup-service -c 127.0.0.1:8091 -u Administrator -p password \
58+
repo-remove --id old-backup --state archived
59+
----
60+
61+
To remove an archived repository and also delete the underlying backup data,
62+
use the `--delete-data` flag.
63+
64+
----
65+
$ couchbase-cli backup-service -c 127.0.0.1:8091 -u Administrator -p password \
66+
repo-remove --id old-backup --state archived --delete-data
67+
----
68+
69+
To remove an imported repository, specify `--state imported`. Note that
70+
the `--delete-data` flag cannot be used with imported repositories.
71+
72+
----
73+
$ couchbase-cli backup-service -c 127.0.0.1:8091 -u Administrator -p password \
74+
repo-remove --id imported-repo --state imported
75+
----
76+
77+
== ENVIRONMENT AND CONFIGURATION VARIABLES
78+
79+
include::{partialsdir}/cbcli/part-common-env.adoc[]
80+
81+
== SEE ALSO
82+
83+
man:couchbase-cli-backup-service[1],
84+
man:couchbase-cli-backup-service-repo-add[1],
85+
man:couchbase-cli-backup-service-repo-get[1],
86+
man:couchbase-cli-backup-service-repo-list[1],
87+
man:couchbase-cli-backup-service-repo-archive[1]
88+
89+
include::{partialsdir}/cbcli/part-footer.adoc[]
90+

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ usage: couchbase-cli backup-service repository (--list | --get | --archive | --a
2323

2424
== DESCRIPTION
2525

26+
DEPRECATED: This subcommand is deprecated and will be removed in future
27+
releases. Please use the man:couchbase-cli-backup-service-repo-add[1], man:couchbase-cli-backup-service-repo-get[1],
28+
man:couchbase-cli-backup-service-repo-list[1], man:couchbase-cli-backup-service-repo-remove[1] and
29+
man:couchbase-cli-backup-service-repo-archive[1] subcommands instead.
30+
2631
Manage backup service repositories
2732

2833
== ACTION OPTIONS
@@ -235,6 +240,11 @@ include::{partialsdir}/cbcli/part-common-env.adoc[]
235240

236241
== SEE ALSO
237242

238-
man:couchbase-cli-backup-service[1]
243+
man:couchbase-cli-backup-service[1],
244+
man:couchbase-cli-backup-service-repo-add[1],
245+
man:couchbase-cli-backup-service-repo-get[1],
246+
man:couchbase-cli-backup-service-repo-remove[1],
247+
man:couchbase-cli-backup-service-repo-archive[1],
248+
man:couchbase-cli-backup-service-repo-list[1]
239249

240250
include::{partialsdir}/cbcli/part-footer.adoc[]

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ include::{partialsdir}/cbcli/part-common-options.adoc[]
2828
man:couchbase-cli-backup-service-settings[1]::
2929
Manage backup service configuration.
3030

31-
man:couchbase-cli-backup-service-repository[1]::
32-
Manage backup repositories.
33-
3431
man:couchbase-cli-backup-service-plan[1]::
3532
Manage backup plans.
3633

@@ -49,6 +46,9 @@ man:couchbase-cli-backup-service-repo-add[1]::
4946
man:couchbase-cli-backup-service-repo-archive[1]::
5047
Archive a backup service repository.
5148

49+
man:couchbase-cli-backup-service-repo-remove[1]::
50+
Remove a backup service repository.
51+
5252
include::{partialsdir}/cbcli/part-host-formats.adoc[]
5353

5454
include::{partialsdir}/cbcli/part-certificate-authentication.adoc[]

test/test_cli.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5347,6 +5347,69 @@ def test_archive_repository_request_body(self):
53475347
self.assertEqual('weeklybackup_archived', body['id'])
53485348

53495349

5350+
class TestBackupServiceRepoRemove(CommandTest):
5351+
"""Test the backup-service repo-remove subcommand"""
5352+
5353+
def setUp(self):
5354+
self.server_args = {'enterprise': True, 'init': True, 'is_admin': True,
5355+
'/pools/default/nodeServices': {'nodesExt': [{
5356+
'hostname': host,
5357+
'services': {
5358+
'backupAPI': port,
5359+
},
5360+
}]}}
5361+
self.command = ['couchbase-cli', 'backup-service'] + cluster_connect_args + ['repo-remove']
5362+
super(TestBackupServiceRepoRemove, self).setUp()
5363+
5364+
def test_missing_id(self):
5365+
"""Test that the command fails if --id is not provided"""
5366+
self.system_exit_run(self.command + ['--state', 'archived'], self.server_args)
5367+
self.assertIn('--id', self.str_error)
5368+
self.assertIn('required', self.str_error)
5369+
5370+
def test_missing_state(self):
5371+
"""Test that the command fails if --state is not provided"""
5372+
self.system_exit_run(self.command + ['--id', 'repo1'], self.server_args)
5373+
self.assertIn('--state', self.str_error)
5374+
self.assertIn('required', self.str_error)
5375+
5376+
def test_invalid_state(self):
5377+
"""Test that only 'archived' or 'imported' are valid state values"""
5378+
self.system_exit_run(self.command + ['--id', 'repo1', '--state', 'active'], self.server_args)
5379+
self.assertIn('invalid choice', self.str_error)
5380+
5381+
def test_remove_archived_repository_success(self):
5382+
"""Test that the command successfully removes an archived repository"""
5383+
self.no_error_run(self.command + ['--id', 'archivedrepo', '--state', 'archived'], self.server_args)
5384+
self.assertIn('DELETE:/api/v1/cluster/self/repository/archived/archivedrepo', self.server.trace)
5385+
self.assertIn('Repository was removed', self.str_output)
5386+
5387+
def test_remove_imported_repository_success(self):
5388+
"""Test that the command successfully removes an imported repository"""
5389+
self.no_error_run(self.command + ['--id', 'importedrepo', '--state', 'imported'], self.server_args)
5390+
self.assertIn('DELETE:/api/v1/cluster/self/repository/imported/importedrepo', self.server.trace)
5391+
self.assertIn('Repository was removed', self.str_output)
5392+
5393+
def test_remove_archived_with_delete_data(self):
5394+
"""Test that --delete-data flag is passed correctly for archived repositories"""
5395+
self.no_error_run(self.command + ['--id', 'archivedrepo', '--state', 'archived', '--delete-data'],
5396+
self.server_args)
5397+
self.assertIn('DELETE:/api/v1/cluster/self/repository/archived/archivedrepo', self.server.trace)
5398+
self.assertIn('remove_repository=True', self.server.queries)
5399+
self.assertIn('Repository was removed', self.str_output)
5400+
5401+
def test_cannot_delete_data_for_imported(self):
5402+
"""Test that --delete-data fails for imported repositories"""
5403+
self.system_exit_run(self.command + ['--id', 'importedrepo', '--state', 'imported', '--delete-data'],
5404+
self.server_args)
5405+
self.assertIn('cannot delete the data of an imported repository', self.str_output)
5406+
5407+
def test_remove_repository_without_delete_data(self):
5408+
"""Test that remove_repository=False is passed when --delete-data is not specified"""
5409+
self.no_error_run(self.command + ['--id', 'repo1', '--state', 'archived'], self.server_args)
5410+
self.assertIn('remove_repository=False', self.server.queries)
5411+
5412+
53505413
class TestBackupServiceSettings(CommandTest):
53515414
"""Test the backup-service settings subcommand"""
53525415

0 commit comments

Comments
 (0)