From 1ffd24af521c17271be77287de47c1f15242b401 Mon Sep 17 00:00:00 2001 From: Rohac Date: Thu, 14 May 2026 13:53:25 +0200 Subject: [PATCH 1/2] Add --auth-values option to ddl apistate set command Enable setting Authorization Default Value in API release state management for CDS views. --- doc/commands/ddl.md | 3 ++- sap/adt/apirelease.py | 1 + sap/cli/apirelease.py | 12 ++++++++-- test/unit/test_sap_adt_apirelease.py | 2 ++ test/unit/test_sap_cli_apirelease.py | 33 +++++++++++++++++++++++----- 5 files changed, 43 insertions(+), 8 deletions(-) diff --git a/doc/commands/ddl.md b/doc/commands/ddl.md index 5249d5c2..f93e7332 100644 --- a/doc/commands/ddl.md +++ b/doc/commands/ddl.md @@ -70,7 +70,7 @@ change with the server before applying it. If validation returns warnings, the user is prompted for confirmation unless `--force` is specified. ```bash -sapcli ddl apistate set CONTRACT NAME [--state STATE] [--comment COMMENT] [--cloud-dev YES|NO] [--key-user-apps YES|NO] [--corrnr TRANSPORT] [--force] +sapcli ddl apistate set CONTRACT NAME [--state STATE] [--comment COMMENT] [--cloud-dev YES|NO] [--key-user-apps YES|NO] [--auth-values YES|NO] [--corrnr TRANSPORT] [--force] ``` - **CONTRACT** - contract level: c0, c1, c2, c3, c4 @@ -79,5 +79,6 @@ sapcli ddl apistate set CONTRACT NAME [--state STATE] [--comment COMMENT] [--clo - **--comment** - free-text comment - **--cloud-dev** - use in Cloud Development: Yes or No - **--key-user-apps** - use in Key User Apps: Yes or No +- **--auth-values** - authorization Default Value: Yes or No - **--corrnr** - transport request number - **--force** - skip confirmation on validation warnings diff --git a/sap/adt/apirelease.py b/sap/adt/apirelease.py index f61fcde1..199a2189 100644 --- a/sap/adt/apirelease.py +++ b/sap/adt/apirelease.py @@ -202,6 +202,7 @@ def copy_contract(self, contract_key: ContractKey) -> Contract: target.use_in_key_user_apps = existing.use_in_key_user_apps target.use_in_sap_cloud_platform = existing.use_in_sap_cloud_platform target.comment = existing.comment + target.create_auth_values = existing.create_auth_values if existing.status is not None: target.status = ContractStatus() target.status.state = existing.status.state diff --git a/sap/cli/apirelease.py b/sap/cli/apirelease.py index 22211be9..1d522fb8 100644 --- a/sap/cli/apirelease.py +++ b/sap/cli/apirelease.py @@ -115,9 +115,9 @@ def _validate_set_args(args) -> ContractKey: contract_key = _parse_contract_key(args.contract) - if not any([args.state, args.comment is not None, args.cloud_dev, args.key_user_apps]): + if not any([args.state, args.comment is not None, args.cloud_dev, args.key_user_apps, args.auth_values]): raise InvalidCommandLineError( - 'at least one of --state, --comment, --cloud-dev, --key-user-apps is required' + 'at least one of --state, --comment, --cloud-dev, --key-user-apps, --auth-values is required' ) return contract_key @@ -141,6 +141,9 @@ def _check_behaviour(api_release, contract_key, args): if args.cloud_dev and contract_behaviour.use_in_sap_cloud_platform_read_only == 'true': raise SAPCliError('Use in Cloud Development is read-only for this contract') + if args.auth_values and contract_behaviour.auth_values_enabled != 'true': + raise SAPCliError('Authorization Default Value is not enabled for this contract') + def _apply_args_to_contract(target, args): """Apply user-provided options to the target contract""" @@ -160,6 +163,9 @@ def _apply_args_to_contract(target, args): if args.key_user_apps: target.use_in_key_user_apps = _normalize_yes_no(args.key_user_apps, '--key-user-apps') + if args.auth_values: + target.create_auth_values = _normalize_yes_no(args.auth_values, '--auth-values') + def _build_payload(api_release, contract_key, args): """Build the ApiRelease payload for validate/update""" @@ -278,6 +284,8 @@ def enhanced_install_parser(arg_parser): help='Use in Cloud Development: Yes or No') set_parser.add_argument('--key-user-apps', default=None, dest='key_user_apps', help='Use in Key User Apps: Yes or No') + set_parser.add_argument('--auth-values', default=None, dest='auth_values', + help='Authorization Default Value: Yes or No') set_parser.add_argument('--corrnr', default=None, help='Transport request number') set_parser.add_argument('--force', action='store_true', default=False, help='Skip confirmation on validation warnings') diff --git a/test/unit/test_sap_adt_apirelease.py b/test/unit/test_sap_adt_apirelease.py index c838c4b3..cb852f95 100644 --- a/test/unit/test_sap_adt_apirelease.py +++ b/test/unit/test_sap_adt_apirelease.py @@ -342,6 +342,7 @@ def test_set_api_release_response_deserialization(self): self.assertEqual(result.behaviour.create, 'true') self.assertEqual(result.c1_release.use_in_key_user_apps, 'true') self.assertEqual(result.c1_release.use_in_sap_cloud_platform, 'true') + self.assertEqual(result.c1_release.create_auth_values, 'true') self.assertEqual(result.c1_release.use_concept_as_successor, 'false') self.assertEqual(result.api_catalog_data.is_any_contract_released, 'true') @@ -381,6 +382,7 @@ def test_copy_contract_existing(self): self.assertEqual(copy.use_in_key_user_apps, 'true') self.assertEqual(copy.use_in_sap_cloud_platform, 'false') self.assertEqual(copy.comment, '') + self.assertEqual(copy.create_auth_values, 'false') self.assertEqual(copy.status.state, 'RELEASED') self.assertEqual(copy.status.state_description, 'Released') diff --git a/test/unit/test_sap_cli_apirelease.py b/test/unit/test_sap_cli_apirelease.py index 2a4049d4..83c59025 100644 --- a/test/unit/test_sap_cli_apirelease.py +++ b/test/unit/test_sap_cli_apirelease.py @@ -296,7 +296,7 @@ def test_set_no_flags_error(self): with self.assertRaises(sap.cli.core.InvalidCommandLineError) as cm: args.execute(Mock(), args) - self.assertIn('at least one of --state, --comment, --cloud-dev, --key-user-apps is required', + self.assertIn('at least one of --state, --comment, --cloud-dev, --key-user-apps, --auth-values is required', str(cm.exception)) def test_set_contract_not_supported(self): @@ -341,7 +341,8 @@ def test_set_new_contract(self): group = _make_group() console = BufferConsole() args = _parse(group, 'apistate', 'set', 'c1', 'I_STATISTICALKEYFIGURECAT', - '--state', 'Released', '--cloud-dev', 'No', '--key-user-apps', 'Yes') + '--state', 'Released', '--cloud-dev', 'No', '--key-user-apps', 'Yes', + '--auth-values', 'No') args.console_factory = Mock(return_value=console) result = args.execute(conn, args) @@ -407,6 +408,18 @@ def test_set_no_behaviour(self): args.execute(conn, args) self.assertIn('does not support API release management', str(cm.exception)) + def test_set_auth_values_disabled(self): + """Test error when auth_values is not enabled for the contract""" + conn = Connection([_resp(API_RELEASE_READONLY_XML)]) + group = _make_group() + args = _parse(group, 'apistate', 'set', 'c0', 'I_STATISTICALKEYFIGURECAT', + '--auth-values', 'Yes') + args.console_factory = Mock(return_value=BufferConsole()) + + with self.assertRaises(sap.errors.SAPCliError) as cm: + args.execute(conn, args) + self.assertIn('Authorization Default Value is not enabled', str(cm.exception)) + class TestEnhanceCommandGroup(unittest.TestCase): @@ -518,10 +531,18 @@ def test_apply_args_state_with_no_existing_status(self): target = sap.adt.apirelease.Contract() target.contract = 'C1' # status is None - no existing status - args = Mock(state='Released', comment=None, cloud_dev=None, key_user_apps=None) + args = Mock(state='Released', comment=None, cloud_dev=None, key_user_apps=None, auth_values=None) sap.cli.apirelease._apply_args_to_contract(target, args) self.assertEqual(target.status.state, 'RELEASED') + # def test_apply_args_auth_values(self): + # """Test applying auth_values argument""" + # target = sap.adt.apirelease.Contract() + # target.contract = 'C1' + # args = Mock(state=None, comment=None, cloud_dev=None, key_user_apps=None, auth_values='Yes') + # sap.cli.apirelease._apply_args_to_contract(target, args) + # self.assertEqual(target.create_auth_values, 'true') + def test_handle_validation_no_messages(self): """Cover line 176: no validation messages""" console = BufferConsole() @@ -544,6 +565,8 @@ def test_normalize_yes_no_valid(self): self.assertEqual(sap.cli.apirelease._normalize_yes_no('Yes', '--cloud-dev'), 'true') self.assertEqual(sap.cli.apirelease._normalize_yes_no('no', '--cloud-dev'), 'false') self.assertEqual(sap.cli.apirelease._normalize_yes_no('YES', '--key-user-apps'), 'true') + self.assertEqual(sap.cli.apirelease._normalize_yes_no('No', '--auth-values'), 'false') + self.assertEqual(sap.cli.apirelease._normalize_yes_no('yes', '--auth-values'), 'true') def test_normalize_yes_no_invalid(self): from sap.errors import SAPCliError @@ -555,7 +578,7 @@ def test_apply_args_invalid_cloud_dev(self): from sap.errors import SAPCliError target = sap.adt.apirelease.Contract() target.contract = 'C1' - args = Mock(state=None, comment=None, cloud_dev='invalid', key_user_apps=None) + args = Mock(state=None, comment=None, cloud_dev='invalid', key_user_apps=None, auth_values=None) with self.assertRaises(SAPCliError): sap.cli.apirelease._apply_args_to_contract(target, args) @@ -566,7 +589,7 @@ def test_build_payload_existing_contract_no_status(self): # Force status to None on the existing contract api_release.c1_release.status = None - args = Mock(state='Released', comment=None, cloud_dev=None, key_user_apps=None) + args = Mock(state='Released', comment=None, cloud_dev=None, key_user_apps=None, auth_values=None) payload = sap.cli.apirelease._build_payload(api_release, ContractKey.C1, args) contract = payload.get_contract(ContractKey.C1) From cc3f90f2bdec0971281b8a50d0d4e14b2f6f4daa Mon Sep 17 00:00:00 2001 From: Rohac Date: Thu, 14 May 2026 14:05:06 +0200 Subject: [PATCH 2/2] Remove commented test code --- test/unit/test_sap_cli_apirelease.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/unit/test_sap_cli_apirelease.py b/test/unit/test_sap_cli_apirelease.py index 83c59025..d809db5e 100644 --- a/test/unit/test_sap_cli_apirelease.py +++ b/test/unit/test_sap_cli_apirelease.py @@ -535,14 +535,6 @@ def test_apply_args_state_with_no_existing_status(self): sap.cli.apirelease._apply_args_to_contract(target, args) self.assertEqual(target.status.state, 'RELEASED') - # def test_apply_args_auth_values(self): - # """Test applying auth_values argument""" - # target = sap.adt.apirelease.Contract() - # target.contract = 'C1' - # args = Mock(state=None, comment=None, cloud_dev=None, key_user_apps=None, auth_values='Yes') - # sap.cli.apirelease._apply_args_to_contract(target, args) - # self.assertEqual(target.create_auth_values, 'true') - def test_handle_validation_no_messages(self): """Cover line 176: no validation messages""" console = BufferConsole()