diff --git a/CHANGES.rst b/CHANGES.rst index 1301a1c8..98f5d93b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -9,6 +9,9 @@ Unreleased - Added support for scheduling sql jobs with the ``scheduled-jobs`` commands. +- Added command ``croud cloud-configurations`` that allows superusers to manage + configuration settings of CrateDB Cloud. + 1.10.1 - 2024/01/11 =================== diff --git a/croud/__main__.py b/croud/__main__.py index 67056f11..12484a1e 100644 --- a/croud/__main__.py +++ b/croud/__main__.py @@ -31,6 +31,11 @@ api_keys_edit, api_keys_list, ) +from croud.cloud_configurations.commands import ( + cloud_configurations_get, + cloud_configurations_list, + cloud_configurations_set, +) from croud.clusters.commands import ( clusters_delete, clusters_deploy, @@ -1632,6 +1637,64 @@ }, }, }, + "cloud-configurations": { + "help": "Manage configurations of CrateDB Cloud.", + "commands": { + "set": { + "help": ( + "Set a configuration key/value. Command " + "is for superusers only." + ), + "extra_args": [ + Argument( + "--key", type=str, required=True, + help="The configuration key to set.", + ), + Argument( + "--value", type=str, required=True, + help="The configuration value to use.", + ), + Argument( + "--org-id", type=str, required=False, + help="Override the value for a single organization only.", + ), + ], + "resolver": cloud_configurations_set, + }, + "get": { + "help": ( + "Get the configuration value by its key. Command " + "is for superusers only." + ), + "extra_args": [ + Argument( + "--key", type=str, required=True, + help="The configuration key to get.", + ), + Argument( + "--org-id", type=str, required=False, + help="Optionally get the value for a certain organization. " + "Defaults to the global configuration value.", + ), + ], + "resolver": cloud_configurations_get, + }, + "list": { + "help": ( + "List all cloud configurations. Command " + "is for superusers only." + ), + "extra_args": [ + Argument( + "--org-id", type=str, required=False, + help="Optionally get the values for a certain organization. " + "Defaults to the global configuration values.", + ), + ], + "resolver": cloud_configurations_list, + } + }, + } } # fmt: on diff --git a/croud/cloud_configurations/__init__.py b/croud/cloud_configurations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/croud/cloud_configurations/commands.py b/croud/cloud_configurations/commands.py new file mode 100644 index 00000000..89cadec9 --- /dev/null +++ b/croud/cloud_configurations/commands.py @@ -0,0 +1,75 @@ +# Licensed to CRATE Technology GmbH ("Crate") under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. Crate licenses +# this file to you under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. You may +# obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# However, if you have executed another commercial license agreement +# with Crate these terms will supersede the license and you may use the +# software solely pursuant to the terms of the relevant commercial agreement. + +from argparse import Namespace + +from croud.api import Client +from croud.config import get_output_format +from croud.printer import print_response + + +def _org_id_transform(field): + return field or "" + + +def cloud_configurations_set(args: Namespace) -> None: + body = {"value": args.value} + if args.org_id: + body["organization_id"] = args.org_id + + client = Client.from_args(args) + data, errors = client.put(f"/api/v2/configurations/{args.key}/", body=body) + print_response( + data=data, + errors=errors, + keys=["key", "value", "organization_id"], + success_message="Configuration updated.", + output_fmt=get_output_format(args), + transforms={"organization_id": _org_id_transform}, + ) + + +def cloud_configurations_get(args: Namespace) -> None: + client = Client.from_args(args) + params = {} + if args.org_id: + params["organization_id"] = args.org_id + data, errors = client.get(f"/api/v2/configurations/{args.key}/", params=params) + print_response( + data=data, + errors=errors, + keys=["key", "value", "organization_id"], + output_fmt=get_output_format(args), + transforms={"organization_id": _org_id_transform}, + ) + + +def cloud_configurations_list(args: Namespace) -> None: + client = Client.from_args(args) + params = {} + if args.org_id: + params["organization_id"] = args.org_id + data, errors = client.get("/api/v2/configurations/", params=params) + print_response( + data=data, + errors=errors, + keys=["key", "value", "organization_id"], + output_fmt=get_output_format(args), + transforms={"organization_id": _org_id_transform}, + ) diff --git a/docs/commands/cloud-configurations.rst b/docs/commands/cloud-configurations.rst new file mode 100644 index 00000000..d1c52fec --- /dev/null +++ b/docs/commands/cloud-configurations.rst @@ -0,0 +1,104 @@ +======================== +``cloud-configurations`` +======================== + +The ``cloud-configurations`` command allows you to list, get and set configuration +keys of CrateDB Cloud. + +.. argparse:: + :module: croud.__main__ + :func: get_parser + :prog: croud + :path: cloud-configurations + :nosubcommands: + + +``cloud-configurations list`` +============================= + + Lists all configurations of CrateDB Cloud. Optionally it returns org specific values. + +.. argparse:: + :module: croud.__main__ + :func: get_parser + :prog: croud + :path: cloud-configurations list + +Example +------- + +.. code-block:: console + + sh$ croud cloud-configurations list \ + --org-id f6c39580-5719-431d-a508-0cee4f9e8209 --sudo + +-------------------------------------------------+-------------+--------------------------------------+ + | key | value | organization_id | + |-------------------------------------------------+-------------+--------------------------------------| + | CRATEDB_CLOUD_SETTING_ONE | 100 | | + | CRATEDB_CLOUD_SETTING_ORG_SPECIFIC | 1024 | f6c39580-5719-431d-a508-0cee4f9e8209 | + | CRATEDB_CLOUD_SETTING_THREE | 30 | | + +-------------------------------------------------+-------------+--------------------------------------+ + +.. note:: + + This command is only available for superusers. + + +``cloud-configurations get`` +============================ + + Get a single configuration value of CrateDB Cloud. Optionally it returns the org specific value. + +.. argparse:: + :module: croud.__main__ + :func: get_parser + :prog: croud + :path: cloud-configurations get + :nosubcommands: + +.. code-block:: console + + sh$ croud cloud-configurations get \ + --key CRATEDB_CLOUD_SETTING_ORG_SPECIFIC \ + --org-id f6c39580-5719-431d-a508-0cee4f9e8209 \ + --sudo + +-------------------------------------------------+-------------+--------------------------------------+ + | key | value | organization_id | + |-------------------------------------------------+-------------+--------------------------------------| + | CRATEDB_CLOUD_SETTING_ORG_SPECIFIC | 1024 | f6c39580-5719-431d-a508-0cee4f9e8209 | + +-------------------------------------------------+-------------+--------------------------------------+ + +.. note:: + + This command is only available for superusers. + + +``cloud-configurations set`` +============================ + + Set a configuration value of CrateDB Cloud either globally or for a single organization only. + +.. argparse:: + :module: croud.__main__ + :func: get_parser + :prog: croud + :path: cloud-configurations set + :nosubcommands: + +.. code-block:: console + + sh$ croud cloud-configurations set \ + --key CRATEDB_CLOUD_SETTING_ORG_SPECIFIC \ + --value 2048 \ + --org-id f6c39580-5719-431d-a508-0cee4f9e8209 \ + --sudo + +-------------------------------------------------+-------------+--------------------------------------+ + | key | value | organization_id | + |-------------------------------------------------+-------------+--------------------------------------| + | CRATEDB_CLOUD_SETTING_ORG_SPECIFIC | 2048 | f6c39580-5719-431d-a508-0cee4f9e8209 | + +-------------------------------------------------+-------------+--------------------------------------+ + ==> Success: Configuration updated. + +.. note:: + + This command is only available for superusers. diff --git a/docs/commands/index.rst b/docs/commands/index.rst index 587f23b4..78661ec3 100644 --- a/docs/commands/index.rst +++ b/docs/commands/index.rst @@ -47,6 +47,7 @@ To get help for a specific command, you can append ``--help``: api-keys regions scheduled-jobs + cloud-configurations .. note:: diff --git a/tests/commands/test_cloud_configurations.py b/tests/commands/test_cloud_configurations.py new file mode 100644 index 00000000..7142efb8 --- /dev/null +++ b/tests/commands/test_cloud_configurations.py @@ -0,0 +1,58 @@ +from unittest import mock + +from croud.api import Client, RequestMethod +from tests.util import assert_rest, call_command, gen_uuid + + +@mock.patch.object(Client, "request", return_value=({}, None)) +def test_cloud_configurations_get(mock_request): + org_id = gen_uuid() + call_command( + "croud", + "cloud-configurations", + "get", + "--key", + "my_config_key", + "--org-id", + org_id, + ) + assert_rest( + mock_request, + RequestMethod.GET, + "/api/v2/configurations/my_config_key/", + params={"organization_id": org_id}, + ) + + +@mock.patch.object(Client, "request", return_value=({}, None)) +def test_cloud_configurations_set(mock_request): + org_id = gen_uuid() + call_command( + "croud", + "cloud-configurations", + "set", + "--key", + "my_config_key", + "--value", + "new_config_value", + "--org-id", + org_id, + ) + assert_rest( + mock_request, + RequestMethod.PUT, + "/api/v2/configurations/my_config_key/", + body={"value": "new_config_value", "organization_id": org_id}, + ) + + +@mock.patch.object(Client, "request", return_value=({}, None)) +def test_cloud_configurations_list(mock_request): + org_id = gen_uuid() + call_command("croud", "cloud-configurations", "list", "--org-id", org_id) + assert_rest( + mock_request, + RequestMethod.GET, + "/api/v2/configurations/", + params={"organization_id": org_id}, + )