diff --git a/.secrets.baseline b/.secrets.baseline index e4f13c8..79c986c 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2025-09-25T03:10:12Z", + "generated_at": "2025-10-28T12:41:17Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -104,7 +104,7 @@ "hashed_secret": "d4c3d66fd0c38547a3c7a4c6bdc29c36911bc030", "is_secret": false, "is_verified": false, - "line_number": 1373, + "line_number": 1377, "type": "Secret Keyword", "verified_result": null }, @@ -112,7 +112,7 @@ "hashed_secret": "3235b7f8d626cde63611d2e9ec43473f4e844c67", "is_secret": false, "is_verified": false, - "line_number": 2519, + "line_number": 2523, "type": "Base64 High Entropy String", "verified_result": null } @@ -122,7 +122,7 @@ "hashed_secret": "d4c3d66fd0c38547a3c7a4c6bdc29c36911bc030", "is_secret": false, "is_verified": false, - "line_number": 623, + "line_number": 627, "type": "Secret Keyword", "verified_result": null }, @@ -130,7 +130,7 @@ "hashed_secret": "0cc20f91828bed53ddb6294968b7f9abd631a3ba", "is_secret": false, "is_verified": false, - "line_number": 1739, + "line_number": 1743, "type": "Secret Keyword", "verified_result": null }, @@ -138,7 +138,7 @@ "hashed_secret": "3235b7f8d626cde63611d2e9ec43473f4e844c67", "is_secret": false, "is_verified": false, - "line_number": 3706, + "line_number": 3710, "type": "Base64 High Entropy String", "verified_result": null } @@ -148,7 +148,7 @@ "hashed_secret": "7eeef8638d6f283c8d76d7811ec6e5f198e16021", "is_secret": false, "is_verified": false, - "line_number": 7630, + "line_number": 7675, "type": "Base64 High Entropy String", "verified_result": null }, @@ -156,13 +156,13 @@ "hashed_secret": "b8473b86d4c2072ca9b08bd28e373e8253e865c4", "is_secret": false, "is_verified": false, - "line_number": 10637, + "line_number": 10682, "type": "Secret Keyword", "verified_result": null } ] }, - "version": "0.13.1+ibm.62.dss", + "version": "0.13.1+ibm.64.dss", "word_list": { "file": null, "hash": null diff --git a/README.md b/README.md index 7dec94d..7157989 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,7 @@ SDK Methods to consume - [SMTP Configurations](#SMTPConfigurations) - [Create SMTP Configuration](#create-smtp-configuration) - [Create SMTP User](#create-smtp-user) + - [Clone SMTP User](#clone-smtp-user) - [Get SMTP Configuration](#get-smtp-configuration) - [Get SMTP User](#get-smtp-user) - [Get SMTP Allowed Ips](#get-smtp-allowed-ips) @@ -1037,6 +1038,20 @@ create_user_response = create_smtp_user_response.get_result() ``` +### Clone SMTP User + +```py + +clone_smtp_user_response = self.event_notifications_service.create_smtp_user( + instance_id=, + id=, + username_to_clone=, +) + +clone_user_response = create_smtp_user_response.get_result() + +``` + ### Get SMTP Configuration ```py @@ -1391,6 +1406,7 @@ Find `event_notifications_v1.env.hide` in the repo and rename it to `event_notif - `EVENT_NOTIFICATIONS_CODE_ENGINE_JOB_TEMPLATE_BODY` - base 64 encoded json body for Code Engine Job - `EVENT_NOTIFICATIONS_APP_CONFIG_CRN` - CRN of App Configuration instance - `EVENT_NOTIFICATIONS_APP_CONFIG_TEMPLATE_BODY` - base 64 encoded json body for App Configuration +- `EVENT_NOTIFICATIONS_SMTP_USER_TO_CLONE` - SMTP username to be cloned ## Questions diff --git a/examples/test_event_notifications_v1_examples.py b/examples/test_event_notifications_v1_examples.py index eae4878..2696860 100644 --- a/examples/test_event_notifications_v1_examples.py +++ b/examples/test_event_notifications_v1_examples.py @@ -108,6 +108,7 @@ cos_integration_id = "" code_engine_project_CRN = "" smtp_user_id = "" +smtp_user_id2 = "" smtp_config_id = "" notificationID = "" slack_dm_token = "" @@ -128,6 +129,7 @@ app_config_crn = "" app_config_template_body = "" app_config_template_id = "" +smtp_user_to_clone = "" ############################################################################## @@ -141,7 +143,7 @@ class TestEventNotificationsV1Examples: @classmethod def setup_class(cls): - global instance_id, fcmServerKey, fcmSenderId, safariCertificatePath, fcm_project_id, fcm_private_key, fcm_client_email, code_engine_URL, huawei_client_id, huawei_client_secret, cos_instance_id, cos_end_point, cos_bucket_name, cos_instance_crn, template_body, code_engine_project_CRN, slack_template_body, slack_dm_token, slack_channel_id, webhook_template_body, code_engine_URL, event_streams_template_body, code_engine_app_template_body, code_engine_job_template_body, app_config_template_body, app_config_crn + global instance_id, fcmServerKey, fcmSenderId, safariCertificatePath, fcm_project_id, fcm_private_key, fcm_client_email, code_engine_URL, huawei_client_id, huawei_client_secret, cos_instance_id, cos_end_point, cos_bucket_name, cos_instance_crn, template_body, code_engine_project_CRN, slack_template_body, slack_dm_token, slack_channel_id, webhook_template_body, code_engine_URL, event_streams_template_body, code_engine_app_template_body, code_engine_job_template_body, app_config_template_body, app_config_crn, smtp_user_to_clone global event_notifications_service if os.path.exists(config_file): os.environ["IBM_CREDENTIALS_FILE"] = config_file @@ -189,6 +191,7 @@ def setup_class(cls): event_streams_topic = cls.config["EVENT_STREAMS_TOPIC"] code_engine_job_template_body = cls.config["CODE_ENGINE_JOB_TEMPLATE_BODY"] code_engine_app_template_body = cls.config["CODE_ENGINE_APP_TEMPLATE_BODY"] + smtp_user_to_clone = cls.config["SMTP_USER_TO_CLONE"] assert event_streams_crn is not None assert event_streams_endpoint is not None assert event_streams_topic is not None @@ -212,6 +215,7 @@ def setup_class(cls): assert pagerduty_template_body is not None assert code_engine_job_template_body is not None assert code_engine_app_template_body is not None + assert smtp_user_to_clone is not None print("Setup complete.") @@ -2632,7 +2636,7 @@ def test_create_smtp_user_example(self): try: print("\n test_create_smtp_user_example() result:") # begin-create_smtp_user - global smtp_user_id + global smtp_user_id, smtp_user_id2 description = 'SMTP user description' create_smtp_user_response = self.event_notifications_service.create_smtp_user( instance_id, id=smtp_config_id, description=description @@ -2644,6 +2648,15 @@ def test_create_smtp_user_example(self): smtp_user_id = smtp_user.id # end-create_smtp_user + clone_smtp_user_response = self.event_notifications_service.create_smtp_user( + instance_id, id=smtp_config_id, username_to_clone=smtp_user_to_clone + ) + + clone_user_response = clone_smtp_user_response.get_result() + print(json.dumps(clone_user_response, indent=2)) + smtp_user = SMTPUserResponse.from_dict(clone_user_response) + smtp_user_id2 = smtp_user.id + except ApiException as e: pytest.fail(str(e)) @@ -2832,6 +2845,12 @@ def test_delete_smtp_user_example(self): print(json.dumps(delete_smtp_user_response, indent=2)) # end-delete_smtp_user + delete_clone_smtp_user_response = self.event_notifications_service.delete_smtp_user( + instance_id, id=smtp_config_id, user_id=smtp_user_id2 + ) + + print(json.dumps(delete_clone_smtp_user_response, indent=2)) + except ApiException as e: pytest.fail(str(e)) diff --git a/ibm_eventnotifications/event_notifications_v1.py b/ibm_eventnotifications/event_notifications_v1.py index e860f4f..5d1dd8c 100644 --- a/ibm_eventnotifications/event_notifications_v1.py +++ b/ibm_eventnotifications/event_notifications_v1.py @@ -2696,6 +2696,7 @@ def create_smtp_user( id: str, *, description: str = None, + username_to_clone: str = None, **kwargs, ) -> DetailedResponse: """ @@ -2707,6 +2708,7 @@ def create_smtp_user( instance. :param str id: Unique identifier for SMTP. :param str description: (optional) The description of SMTP configuration. + :param str username_to_clone: (optional) provide name of the user to clone. :param dict headers: A `dict` containing the request headers :return: A `DetailedResponse` containing the result, headers and HTTP status code. :rtype: DetailedResponse with `dict` result representing a `SMTPUserResponse` object @@ -2724,6 +2726,10 @@ def create_smtp_user( ) headers.update(sdk_headers) + params = { + 'username_to_clone': username_to_clone, + } + data = { 'description': description, } @@ -2744,6 +2750,7 @@ def create_smtp_user( method='POST', url=url, headers=headers, + params=params, data=data, ) @@ -7785,7 +7792,8 @@ class SMTPUserResponse: :attr str domain: (optional) Domain Name. :attr str smtp_config_id: SMTP confg Id. :attr str username: SMTP user name. - :attr str password: password. + :attr str password: (optional) Password for SMTP user; Cloned SMTP user response + do not include a password. :attr datetime created_at: Created time. """ @@ -7794,11 +7802,11 @@ def __init__( id: str, smtp_config_id: str, username: str, - password: str, created_at: datetime, *, description: str = None, domain: str = None, + password: str = None, ) -> None: """ Initialize a SMTPUserResponse object. @@ -7806,10 +7814,11 @@ def __init__( :param str id: SMTP Id. :param str smtp_config_id: SMTP confg Id. :param str username: SMTP user name. - :param str password: password. :param datetime created_at: Created time. :param str description: (optional) SMTP User description. :param str domain: (optional) Domain Name. + :param str password: (optional) Password for SMTP user; Cloned SMTP user + response do not include a password. """ self.id = id self.description = description @@ -7841,8 +7850,6 @@ def from_dict(cls, _dict: Dict) -> 'SMTPUserResponse': raise ValueError('Required property \'username\' not present in SMTPUserResponse JSON') if 'password' in _dict: args['password'] = _dict.get('password') - else: - raise ValueError('Required property \'password\' not present in SMTPUserResponse JSON') if 'created_at' in _dict: args['created_at'] = string_to_datetime(_dict.get('created_at')) else: diff --git a/test/integration/test_event_notifications_v1.py b/test/integration/test_event_notifications_v1.py index 9d32f48..2904a4c 100644 --- a/test/integration/test_event_notifications_v1.py +++ b/test/integration/test_event_notifications_v1.py @@ -106,7 +106,9 @@ cos_instance_crn = "" cos_integration_id = "" smtp_config_id = "" +smtp_user_to_clone = "" smtp_user_id = "" +smtp_user_id2 = "" slack_dm_token = "" slack_channel_id = "" webhook_template_id = "" @@ -135,7 +137,7 @@ class TestEventNotificationsV1: @classmethod def setup_class(cls): - global instance_id, fcmServerKey, fcmSenderId, safariCertificatePath, fcm_project_id, fcm_private_key, fcm_client_email, huawei_client_id, huawei_client_secret, cos_instance_id, cos_end_point, cos_bucket_name, slack_url, teams_url, pager_duty_api_key, pager_duty_routing_key, template_body, cos_instance_crn, code_engine_project_CRN, slack_template_body, slack_dm_token, slack_channel_id, webhook_template_body, code_engine_URL, snow_client_id, snow_client_secret, snow_user_name, snow_password, snow_instance_name, scheduler_source_id, pagerduty_template_body, event_streams_template_body, event_streams_crn, event_streams_topic, event_streams_endpoint, code_engine_job_template_body, code_engine_app_template_body, app_config_template_body, app_config_crn + global instance_id, fcmServerKey, fcmSenderId, safariCertificatePath, fcm_project_id, fcm_private_key, fcm_client_email, huawei_client_id, huawei_client_secret, cos_instance_id, cos_end_point, cos_bucket_name, slack_url, teams_url, pager_duty_api_key, pager_duty_routing_key, template_body, cos_instance_crn, code_engine_project_CRN, slack_template_body, slack_dm_token, slack_channel_id, webhook_template_body, code_engine_URL, snow_client_id, snow_client_secret, snow_user_name, snow_password, snow_instance_name, scheduler_source_id, pagerduty_template_body, event_streams_template_body, event_streams_crn, event_streams_topic, event_streams_endpoint, code_engine_job_template_body, code_engine_app_template_body, app_config_template_body, app_config_crn, smtp_user_to_clone if os.path.exists(config_file): os.environ["IBM_CREDENTIALS_FILE"] = config_file @@ -186,6 +188,7 @@ def setup_class(cls): code_engine_app_template_body = cls.config["CODE_ENGINE_APP_TEMPLATE_BODY"] app_config_crn = cls.config["APP_CONFIG_CRN"] app_config_template_body = cls.config["APP_CONFIG_TEMPLATE_BODY"] + smtp_user_to_clone = cls.config["SMTP_USER_TO_CLONE"] assert instance_id is not None assert fcmServerKey is not None @@ -220,6 +223,7 @@ def setup_class(cls): assert code_engine_app_template_body is not None assert app_config_crn is not None assert app_config_template_body is not None + assert smtp_user_to_clone is not None print("Setup complete.") @@ -3821,7 +3825,7 @@ def test_create_smtp_configuration(self): global smtp_config_id name = "SMTP configuration" - domain = "test.event-notifications.test.cloud.ibm.com" + domain = "mailx.event-notifications.test.cloud.ibm.com" description = "SMTP description" create_smtp_config_response = self.event_notifications_service.create_smtp_configuration( @@ -3889,6 +3893,24 @@ def test_create_smtp_user(self): assert smtp_user.description == description smtp_user_id = smtp_user.id + @needscredentials + def test_clone_smtp_user(self): + + global smtp_user_id, smtp_user_id2 + description = 'SMTP user description' + create_smtp_user_response = self.event_notifications_service.create_smtp_user( + instance_id, id=smtp_config_id, username_to_clone=smtp_user_to_clone, description=description + ) + + assert create_smtp_user_response.get_status_code() == 201 + create_user_response = create_smtp_user_response.get_result() + assert create_user_response is not None + + smtp_user = SMTPUserResponse.from_dict(create_user_response) + assert smtp_user.username is not None + assert smtp_user.description == description + smtp_user_id2 = smtp_user.id + @needscredentials def test_list_smtp_configurations(self): @@ -4048,6 +4070,7 @@ def test_get_predefined_template(self): def test_delete_smtp_user(self): for id in [ smtp_user_id, + smtp_user_id2, ]: delete_smtp_user_response = self.event_notifications_service.delete_smtp_user( instance_id, id=smtp_config_id, user_id=id diff --git a/test/unit/test_event_notifications_v1.py b/test/unit/test_event_notifications_v1.py index fde20c2..7e4bbbd 100644 --- a/test/unit/test_event_notifications_v1.py +++ b/test/unit/test_event_notifications_v1.py @@ -5825,18 +5825,24 @@ def test_create_smtp_user_all_params(self): instance_id = 'testString' id = 'testString' description = 'testString' + username_to_clone = 'testString' # Invoke method response = _service.create_smtp_user( instance_id, id, description=description, + username_to_clone=username_to_clone, headers={}, ) # Check for correct operation assert len(responses.calls) == 1 assert response.status_code == 201 + # Validate query params + query_string = responses.calls[0].request.url.split('?', 1)[1] + query_string = urllib.parse.unquote_plus(query_string) + assert 'username_to_clone={}'.format(username_to_clone) in query_string # Validate body params req_body = json.loads(str(responses.calls[0].request.body, 'utf-8')) assert req_body['description'] == 'testString' @@ -5850,6 +5856,46 @@ def test_create_smtp_user_all_params_with_retries(self): _service.disable_retries() self.test_create_smtp_user_all_params() + @responses.activate + def test_create_smtp_user_required_params(self): + """ + test_create_smtp_user_required_params() + """ + # Set up mock + url = preprocess_url('/v1/instances/testString/smtp/config/testString/users') + mock_response = '{"id": "id", "description": "description", "domain": "domain", "smtp_config_id": "smtp_config_id", "username": "username", "password": "password", "created_at": "2019-01-01T12:00:00.000Z"}' + responses.add( + responses.POST, + url, + body=mock_response, + content_type='application/json', + status=201, + ) + + # Set up parameter values + instance_id = 'testString' + id = 'testString' + + # Invoke method + response = _service.create_smtp_user( + instance_id, + id, + headers={}, + ) + + # Check for correct operation + assert len(responses.calls) == 1 + assert response.status_code == 201 + + def test_create_smtp_user_required_params_with_retries(self): + # Enable retries and run test_create_smtp_user_required_params. + _service.enable_retries() + self.test_create_smtp_user_required_params() + + # Disable retries and run test_create_smtp_user_required_params. + _service.disable_retries() + self.test_create_smtp_user_required_params() + @responses.activate def test_create_smtp_user_value_error(self): """ @@ -5869,7 +5915,6 @@ def test_create_smtp_user_value_error(self): # Set up parameter values instance_id = 'testString' id = 'testString' - description = 'testString' # Pass in all but one required param and check for a ValueError req_param_dict = {