Skip to content

Commit 9593657

Browse files
committed
MB-55692 Add support for editing collections history field
Change-Id: I601f493f46b858f7f316ed8d9353682205667a1f Reviewed-on: https://review.couchbase.org/c/couchbase-cli/+/187445 Well-Formed: Restriction Checker Tested-by: Build Bot <build@couchbase.com> Reviewed-by: James Lee <james.lee@couchbase.com>
1 parent 5f3f7ad commit 9593657

5 files changed

Lines changed: 103 additions & 11 deletions

File tree

cbmgr.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4721,6 +4721,8 @@ def __init__(self):
47214721
help="List all of the scopes in the bucket")
47224722
group.add_argument("--create-collection", dest="create_collection", metavar="<collection>", default=None,
47234723
help="The path to the collection to make")
4724+
group.add_argument("--edit-collection", dest="edit_collection", metavar="<collection>", default=None,
4725+
help="The path to the collection to edit")
47244726
group.add_argument("--drop-collection", dest="drop_collection", metavar="<collection>", default=None,
47254727
help="The path to the collection to remove")
47264728
group.add_argument("--list-collections", dest="list_collections", metavar="<scope_list>", default=None,
@@ -4733,12 +4735,12 @@ def __init__(self):
47334735

47344736
@rest_initialiser(cluster_init_check=True, version_check=True)
47354737
def execute(self, opts):
4736-
cmds = [opts.create_scope, opts.drop_scope, opts.list_scopes, opts.create_collection, opts.drop_collection,
4737-
opts.list_collections]
4738+
cmds = [opts.create_scope, opts.drop_scope, opts.list_scopes, opts.create_collection, opts.edit_collection,
4739+
opts.drop_collection, opts.list_collections]
47384740
cmd_total = sum(cmd is not None for cmd in cmds)
47394741

4740-
args = "--create-scope, --drop-scope, --list-scopes, --create-collection, --drop-collection, or " \
4741-
"--list-collections"
4742+
args = "--create-scope, --drop-scope, --list-scopes, --create-collection, --edit-collection, " \
4743+
"--drop-collection, or --list-collections"
47424744
if cmd_total == 0:
47434745
_exit_if_errors([f'Must specify one of the following: {args}'])
47444746
elif cmd_total != 1:
@@ -4747,8 +4749,14 @@ def execute(self, opts):
47474749
if opts.max_ttl is not None and opts.create_collection is None:
47484750
_exit_if_errors(["--max-ttl can only be set with --create-collection"])
47494751

4750-
if opts.enable_history is not None and opts.create_collection is None:
4751-
_exit_if_errors(["--enable-history-retention can only be set with --create-collection"])
4752+
if opts.enable_history is not None and opts.create_collection is None and opts.edit_collection is None:
4753+
_exit_if_errors(["--enable-history-retention can only be set with --create-collection or "
4754+
"--edit-collection"])
4755+
4756+
if opts.edit_collection is not None and opts.enable_history is None:
4757+
_exit_if_errors(["--enable-history-retention should be set with --edit-collection"])
4758+
if opts.edit_collection is not None and opts.max_ttl is not None:
4759+
_exit_if_errors(["--max-ttl cannot be set with --edit-collection"])
47524760

47534761
if opts.create_scope:
47544762
self._create_scope(opts)
@@ -4758,6 +4766,8 @@ def execute(self, opts):
47584766
self._list_scopes(opts)
47594767
if opts.create_collection:
47604768
self._create_collection(opts)
4769+
if opts.edit_collection:
4770+
self._edit_collection(opts)
47614771
if opts.drop_collection:
47624772
self._drop_collection(opts)
47634773
if opts.list_collections is not None:
@@ -4785,6 +4795,12 @@ def _create_collection(self, opts):
47854795
_exit_if_errors(errors)
47864796
_success("Collection created")
47874797

4798+
def _edit_collection(self, opts):
4799+
scope, collection = self._get_scope_collection(opts.edit_collection)
4800+
_, errors = self.rest.edit_collection(opts.bucket, scope, collection, opts.enable_history)
4801+
_exit_if_errors(errors)
4802+
_success("Collection edited")
4803+
47884804
def _drop_collection(self, opts):
47894805
scope, collection = self._get_scope_collection(opts.drop_collection)
47904806
_, errors = self.rest.drop_collection(opts.bucket, scope, collection)

cluster_manager.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2233,8 +2233,17 @@ def create_collection(self, bucket, scope, collection, max_ttl, enable_history):
22332233

22342234
return self._post_form_encoded(url, params)
22352235

2236+
def edit_collection(self, bucket, scope, collection, enable_history):
2237+
url = f'{self.hostname}/pools/default/buckets/{urllib.parse.quote_plus(bucket)}/scopes/' \
2238+
f'{urllib.parse.quote_plus(scope)}/collections/{urllib.parse.quote_plus(collection)}'
2239+
params = {}
2240+
if enable_history:
2241+
params["history"] = one_zero_boolean_to_string(enable_history)
2242+
2243+
return self._patch_form_encoded(url, params)
2244+
22362245
def drop_collection(self, bucket, scope, collection):
2237-
url = f'{self.hostname}/pools/default/buckets/{urllib.parse.quote_plus(bucket)}/scopes/'\
2246+
url = f'{self.hostname}/pools/default/buckets/{urllib.parse.quote_plus(bucket)}/scopes/' \
22382247
f'{urllib.parse.quote_plus(scope)}/collections/{urllib.parse.quote_plus(collection)}'
22392248
return self._delete(url, None)
22402249

@@ -2406,6 +2415,21 @@ def _post_json(self, url, params):
24062415
return self._handle_response(self.session.post(url, auth=(self.username, self.password), json=params,
24072416
verify=self.ca_cert, timeout=self.timeout, headers=self.headers))
24082417

2418+
@request
2419+
def _patch_form_encoded(self, url, params):
2420+
if self.debug:
2421+
print(f'PATCH {url} {self._url_encode_params(params)}')
2422+
2423+
return self._handle_response(
2424+
self.session.patch(
2425+
url, auth=(
2426+
self.username,
2427+
self.password),
2428+
data=params,
2429+
verify=self.ca_cert,
2430+
timeout=self.timeout,
2431+
headers=self.headers))
2432+
24092433
@request
24102434
def _patch_json(self, url, params):
24112435
if self.debug:

docs/modules/cli/pages/cbcli/couchbase-cli-collection-manage.adoc

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ _couchbase-cli collection-manage_ [--cluster <url>] [--username <user>]
1616
[--password <password>] [--client-cert <path>] [--client-cert-password <password>]
1717
[--client-key <path>] [--client-key-password <password>] [--bucket <bucket>]
1818
[--create-scope <scope>] [--drop-scope <scope>] [--list-scopes]
19-
[--create-collection <collection>] [--drop-collection <collection>]
20-
[--list-collections [<scope_list>]] [--max-ttl <seconds>]
21-
[--enable-history-retention <0|1>]
19+
[--create-collection <collection>] [--edit-collection <collection>]
20+
[--drop-collection <collection>] [--list-collections [<scope_list>]]
21+
[--max-ttl <seconds>] [--enable-history-retention <0|1>]
2222

2323
== DESCRIPTION
2424

@@ -58,6 +58,11 @@ include::{partialsdir}/cbcli/part-common-options.adoc[]
5858
format (scope.collection), specifying the scope in which the
5959
collection and the name to be created.
6060

61+
--edit-collection <collection>::
62+
Edits the collection in the scope. The option takes a path in dot
63+
format (scope.collection), specifying the collection in a scope which is
64+
to be edited.
65+
6166
--drop-collection <collection>::
6267
Removes the collection from the scope. The option takes a path in
6368
dot format (scope.collection), specifying the scope from which
@@ -73,12 +78,14 @@ include::{partialsdir}/cbcli/part-common-options.adoc[]
7378
collection, in seconds. If enabled and a document is mutated with
7479
no TTL or a TTL greater than than the maximum, its TTL will be set
7580
to the maximum TTL. Setting this option to 0 disables the use of
76-
max-TTL, and the largest TTL that is allowed is 2147483647.
81+
max-TTL, and the largest TTL that is allowed is 2147483647. This setting
82+
cannot be edited after a collection has been created.
7783

7884
--enable-history-retention <0|1>::
7985
Specifies whether or not the document history retention should be enabled for
8086
the collection. To enable the document history retention, set this option to
8187
"1". To disable the document history retention, set this option to "0".
88+
This setting can be edited after a collection has been created.
8289

8390

8491
include::{partialsdir}/cbcli/part-host-formats.adoc[]
@@ -98,6 +105,13 @@ furniture bucket.
98105
$ couchbase-cli collection-manage -c 192.168.1.5 -u Administrator \
99106
-p password --bucket furniture --create-collection chairs.couches
100107

108+
To edit the collection called "couches" in the chairs scope in the furniture
109+
bucket.
110+
111+
$ couchbase-cli collection-manage -c 192.168.1.5 -u Administrator \
112+
-p password --bucket furniture --edit-collection chairs.couches
113+
--enable-history-retention 1
114+
101115
To list all of the collections in the chairs and tables scopes in the furniture
102116
bucket.
103117

test/mock_server.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,7 @@ def export_eventing_functions(rest_params=None, server_args=None, path="", endpo
518518
(r'/pools/default/buckets/\w+/scopes/\w+$', {'DELETE': do_nothing}),
519519
(r'/pools/default/buckets/\w+/scopes/\w+/collections$', {'POST': do_nothing}),
520520
(r'/pools/default/buckets/\w+/scopes/\w+/collections/\w+$', {'DELETE': do_nothing}),
521+
(r'/pools/default/buckets/\w+/scopes/\w+/collections/\w+$', {'PATCH': do_nothing}),
521522
(r'/pools/default/trustedCAs/\d+$', {'DELETE': get_by_path}),
522523
(r'/pools/nodes', {'GET': get_by_path}),
523524
(r'/settings/analytics', {'POST': do_nothing, 'GET': get_by_path}),

test/test_cli.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2718,6 +2718,36 @@ def setUp(self):
27182718
self.server_args = {'enterprise': True, 'init': True, 'is_admin': True}
27192719
super(TestCollectionManage, self).setUp()
27202720

2721+
def test_missing_cmd(self):
2722+
self.system_exit_run(self.command + ['--max-ttl', '100'], self.server_args)
2723+
self.assertIn("Must specify one of the following: --create-scope, --drop-scope, --list-scopes, "
2724+
"--create-collection, --edit-collection, --drop-collection, or --list-collections",
2725+
self.str_output)
2726+
2727+
def test_more_than_one_cmd(self):
2728+
self.system_exit_run(self.command + ['--create-scope', 'scope_1', '--list-collections'], self.server_args)
2729+
self.assertIn("Only one of the following may be specified: --create-scope, --drop-scope, --list-scopes, "
2730+
"--create-collection, --edit-collection, --drop-collection, or --list-collections",
2731+
self.str_output)
2732+
2733+
def test_max_ttl_set_with_not_create_collection(self):
2734+
self.system_exit_run(self.command + ['--list-collections', '--max-ttl', '100'], self.server_args)
2735+
self.assertIn("--max-ttl can only be set with --create-collection", self.str_output)
2736+
2737+
def test_enable_history_set_with_not_create_collection_or_edit_collection(self):
2738+
self.system_exit_run(self.command + ['--list-collections', '--enable-history-retention', '1'], self.server_args)
2739+
self.assertIn("--enable-history-retention can only be set with --create-collection or --edit-collection",
2740+
self.str_output)
2741+
2742+
def test_enable_history_should_be_set_with_edit_collection(self):
2743+
self.system_exit_run(self.command + ['--edit-collection', 'scope_1.collection_1'], self.server_args)
2744+
self.assertIn("--enable-history-retention should be set with --edit-collection", self.str_output)
2745+
2746+
def test_max_ttl_cannot_be_set_with_edit_collection(self):
2747+
self.system_exit_run(self.command + ['--edit-collection', 'scope_1.collection_1', "--max-ttl", "100"],
2748+
self.server_args)
2749+
self.assertIn("--max-ttl can only be set with --create-collection", self.str_output)
2750+
27212751
def test_create_scope(self):
27222752
self.no_error_run(self.command + ['--create-scope', 'scope_1'], self.server_args)
27232753
self.assertIn('POST:/pools/default/buckets/name/scopes', self.server.trace)
@@ -2743,6 +2773,13 @@ def test_create_collection(self):
27432773
expected_params = ['name=collection_1', 'maxTTL=100', 'history=true']
27442774
self.rest_parameter_match(expected_params)
27452775

2776+
def test_edit_collection(self):
2777+
self.no_error_run(self.command + ['--edit-collection', 'scope_1.collection_1', '--enable-history-retention',
2778+
'1'], self.server_args)
2779+
self.assertIn('PATCH:/pools/default/buckets/name/scopes/scope_1/collections/collection_1', self.server.trace)
2780+
expected_params = ['history=true']
2781+
self.rest_parameter_match(expected_params)
2782+
27462783
def test_delete_collection(self):
27472784
self.no_error_run(self.command + ['--drop-collection', 'scope_1.collection_1'], self.server_args)
27482785
self.assertIn('DELETE:/pools/default/buckets/name/scopes/scope_1/collections/collection_1', self.server.trace)

0 commit comments

Comments
 (0)