diff --git a/examples/test_iam_identity_v1_examples.py b/examples/test_iam_identity_v1_examples.py index 27246df..86a4b2c 100644 --- a/examples/test_iam_identity_v1_examples.py +++ b/examples/test_iam_identity_v1_examples.py @@ -897,6 +897,39 @@ def test_delete_link_example(self): except ApiException as e: pytest.fail(str(e)) + @needscredentials + def test_delete_link_by_parameters_example(self): + """ + delete_link_by_parameters request example + """ + CreateProfileLinkRequestLink = {} + CreateProfileLinkRequestLink['crn'] = ( + 'crn:v1:staging:public:iam-identity::a/' + account_id + '::computeresource:Fake-Compute-Resource' + ) + CreateProfileLinkRequestLink['component_name'] = 'test_component_name' + CreateProfileLinkRequestLink['component_type'] = 'test_component_type' + link = iam_identity_service.create_link( + profile_id=profile_id, name='Great link', cr_type='CE', link=CreateProfileLinkRequestLink + ).get_result() + print(json.dumps(link, indent=2)) + + try: + # begin-delete_link_by_parameters + + response = iam_identity_service.delete_link_by_parameters( + profile_id=profile_id, + type='CE', + crn=CreateProfileLinkRequestLink['crn'], + component_name='test_component_name', + component_type='test_component_type', + ) + + # end-delete_link_by_parameters + print('\ndelete_link_by_parameters() response status code: ', response.get_status_code()) + + except ApiException as e: + pytest.fail(str(e)) + @needscredentials def test_get_profile_identities(self): """ diff --git a/ibm_platform_services/iam_identity_v1.py b/ibm_platform_services/iam_identity_v1.py index dd01836..b92ed2d 100644 --- a/ibm_platform_services/iam_identity_v1.py +++ b/ibm_platform_services/iam_identity_v1.py @@ -2196,6 +2196,78 @@ def list_links( response = self.send(request, **kwargs) return response + def delete_link_by_parameters( + self, + profile_id: str, + type: str, + *, + crn: Optional[str] = None, + namespace: Optional[str] = None, + name: Optional[str] = None, + component_type: Optional[str] = None, + component_name: Optional[str] = None, + **kwargs, + ) -> DetailedResponse: + """ + Delete compute resource link to profile by given parameters. + + Deletes compute resource link of a Trusted Profile matching the given parameters. + + :param str profile_id: The unique ID of the Trusted Profile. + :param str type: The compute resource type. Valid values are VSI, BMS, + IKS_SA, ROKS_SA, CE. + :param str crn: (optional) CRN of the compute resource (IKS/ROKS/VSI/BMS). + :param str namespace: (optional) Namespace of the compute resource + (IKS/ROKS). + :param str name: (optional) Name of the compute resource (IKS/ROKS). + :param str component_type: (optional) Component type of the compute + resource, only required if type is CE. + :param str component_name: (optional) Component name of the compute + resource, only required if type is CE. + :param dict headers: A `dict` containing the request headers + :return: A `DetailedResponse` containing the result, headers and HTTP status code. + :rtype: DetailedResponse + """ + + if not profile_id: + raise ValueError('profile_id must be provided') + if not type: + raise ValueError('type must be provided') + headers = {} + sdk_headers = get_sdk_headers( + service_name=self.DEFAULT_SERVICE_NAME, + service_version='V1', + operation_id='delete_link_by_parameters', + ) + headers.update(sdk_headers) + + params = { + 'type': type, + 'crn': crn, + 'namespace': namespace, + 'name': name, + 'component_type': component_type, + 'component_name': component_name, + } + + if 'headers' in kwargs: + headers.update(kwargs.get('headers')) + del kwargs['headers'] + + path_param_keys = ['profile-id'] + path_param_values = self.encode_path_vars(profile_id) + path_param_dict = dict(zip(path_param_keys, path_param_values)) + url = '/v1/profiles/{profile-id}/links'.format(**path_param_dict) + request = self.prepare_request( + method='DELETE', + url=url, + headers=headers, + params=params, + ) + + response = self.send(request, **kwargs) + return response + def get_link( self, profile_id: str, @@ -8665,31 +8737,43 @@ class CreateProfileLinkRequestLink: Link details. :param str crn: The CRN of the compute resource. - :param str namespace: The compute resource namespace, only required if cr_type - is IKS_SA or ROKS_SA. + :param str namespace: (optional) The compute resource namespace, only required + if cr_type is IKS_SA or ROKS_SA. :param str name: (optional) Name of the compute resource, only required if cr_type is IKS_SA or ROKS_SA. + :param str component_type: (optional) Component type of the compute resource, + only required if cr_type is CE. + :param str component_name: (optional) Component name of the compute resource, + only required if cr_type is CE. """ def __init__( self, crn: str, - namespace: str, *, + namespace: Optional[str] = None, name: Optional[str] = None, + component_type: Optional[str] = None, + component_name: Optional[str] = None, ) -> None: """ Initialize a CreateProfileLinkRequestLink object. :param str crn: The CRN of the compute resource. - :param str namespace: The compute resource namespace, only required if - cr_type is IKS_SA or ROKS_SA. + :param str namespace: (optional) The compute resource namespace, only + required if cr_type is IKS_SA or ROKS_SA. :param str name: (optional) Name of the compute resource, only required if cr_type is IKS_SA or ROKS_SA. + :param str component_type: (optional) Component type of the compute + resource, only required if cr_type is CE. + :param str component_name: (optional) Component name of the compute + resource, only required if cr_type is CE. """ self.crn = crn self.namespace = namespace self.name = name + self.component_type = component_type + self.component_name = component_name @classmethod def from_dict(cls, _dict: Dict) -> 'CreateProfileLinkRequestLink': @@ -8701,10 +8785,12 @@ def from_dict(cls, _dict: Dict) -> 'CreateProfileLinkRequestLink': raise ValueError('Required property \'crn\' not present in CreateProfileLinkRequestLink JSON') if (namespace := _dict.get('namespace')) is not None: args['namespace'] = namespace - else: - raise ValueError('Required property \'namespace\' not present in CreateProfileLinkRequestLink JSON') if (name := _dict.get('name')) is not None: args['name'] = name + if (component_type := _dict.get('component_type')) is not None: + args['component_type'] = component_type + if (component_name := _dict.get('component_name')) is not None: + args['component_name'] = component_name return cls(**args) @classmethod @@ -8721,6 +8807,10 @@ def to_dict(self) -> Dict: _dict['namespace'] = self.namespace if hasattr(self, 'name') and self.name is not None: _dict['name'] = self.name + if hasattr(self, 'component_type') and self.component_type is not None: + _dict['component_type'] = self.component_type + if hasattr(self, 'component_name') and self.component_name is not None: + _dict['component_name'] = self.component_name return _dict def _to_dict(self): @@ -10645,8 +10735,8 @@ class ProfileLink: :param datetime modified_at: If set contains a date time string of the last modification date in ISO format. :param str name: (optional) Optional name of the Link. - :param str cr_type: The compute resource type. Valid values are VSI, IKS_SA, - ROKS_SA. + :param str cr_type: The compute resource type. Valid values are VSI, BMS, + IKS_SA, ROKS_SA, CE. :param ProfileLinkLink link: """ @@ -10670,8 +10760,8 @@ def __init__( creation date in ISO format. :param datetime modified_at: If set contains a date time string of the last modification date in ISO format. - :param str cr_type: The compute resource type. Valid values are VSI, - IKS_SA, ROKS_SA. + :param str cr_type: The compute resource type. Valid values are VSI, BMS, + IKS_SA, ROKS_SA, CE. :param ProfileLinkLink link: :param str name: (optional) Optional name of the Link. """ @@ -10770,6 +10860,10 @@ class ProfileLinkLink: if cr_type is IKS_SA or ROKS_SA. :param str name: (optional) Name of the compute resource, only required if cr_type is IKS_SA or ROKS_SA. + :param str component_type: (optional) Component type of the compute resource, + only required if cr_type is CE. + :param str component_name: (optional) Component name of the compute resource, + only required if cr_type is CE. """ def __init__( @@ -10778,6 +10872,8 @@ def __init__( crn: Optional[str] = None, namespace: Optional[str] = None, name: Optional[str] = None, + component_type: Optional[str] = None, + component_name: Optional[str] = None, ) -> None: """ Initialize a ProfileLinkLink object. @@ -10787,10 +10883,16 @@ def __init__( required if cr_type is IKS_SA or ROKS_SA. :param str name: (optional) Name of the compute resource, only required if cr_type is IKS_SA or ROKS_SA. + :param str component_type: (optional) Component type of the compute + resource, only required if cr_type is CE. + :param str component_name: (optional) Component name of the compute + resource, only required if cr_type is CE. """ self.crn = crn self.namespace = namespace self.name = name + self.component_type = component_type + self.component_name = component_name @classmethod def from_dict(cls, _dict: Dict) -> 'ProfileLinkLink': @@ -10802,6 +10904,10 @@ def from_dict(cls, _dict: Dict) -> 'ProfileLinkLink': args['namespace'] = namespace if (name := _dict.get('name')) is not None: args['name'] = name + if (component_type := _dict.get('component_type')) is not None: + args['component_type'] = component_type + if (component_name := _dict.get('component_name')) is not None: + args['component_name'] = component_name return cls(**args) @classmethod @@ -10818,6 +10924,10 @@ def to_dict(self) -> Dict: _dict['namespace'] = self.namespace if hasattr(self, 'name') and self.name is not None: _dict['name'] = self.name + if hasattr(self, 'component_type') and self.component_type is not None: + _dict['component_type'] = self.component_type + if hasattr(self, 'component_name') and self.component_name is not None: + _dict['component_name'] = self.component_name return _dict def _to_dict(self): diff --git a/test/integration/test_iam_identity_v1.py b/test/integration/test_iam_identity_v1.py index b82c1c6..d57ec39 100644 --- a/test/integration/test_iam_identity_v1.py +++ b/test/integration/test_iam_identity_v1.py @@ -1084,6 +1084,37 @@ def test_delete_link(self): link = self.get_link(self.iam_identity_service, profile_id2, link_id) assert link is None + @needscredentials + def test_delete_link_with_parameters(self): + CreateProfileLinkRequestLink = {} + CreateProfileLinkRequestLink['crn'] = ( + 'crn:v1:staging:public:iam-identity::a/' + self.account_id + '::computeresource:Fake-Compute-Resource' + ) + CreateProfileLinkRequestLink['component_name'] = 'test_component_name' + CreateProfileLinkRequestLink['component_type'] = 'test_component_type' + + create_link_response = self.iam_identity_service.create_link( + profile_id=profile_id2, name='Great link', cr_type='CE', link=CreateProfileLinkRequestLink + ) + + assert create_link_response.get_status_code() == 201 + link = create_link_response.get_result() + assert link is not None + print('\ncreate_link() response: ', json.dumps(link, indent=2)) + + global link_id + link_id = link['id'] + assert link_id is not None + + delete_link_response = self.iam_identity_service.delete_link_by_parameters( + profile_id=profile_id2, + type='CE', + crn=CreateProfileLinkRequestLink['crn'], + component_name='test_component_name', + component_type='test_component_type', + ) + assert delete_link_response.get_status_code() == 204 + @needscredentials def test_set_identities(self): identifiers = [] @@ -2006,7 +2037,7 @@ def test_update_preference_on_scope_account(self): value_string=self.value_string, ).get_result() print('\nupdate_preference_on_scope_account() response: ', json.dumps(preference, indent=2)) - preference is not None + assert preference is not None @needscredentials def test_get_preferences_on_scope_account(self): @@ -2019,7 +2050,7 @@ def test_get_preferences_on_scope_account(self): preference_id=self.preference_id1, ).get_result() print('\nget_preference_on_scope_account() response: ', json.dumps(preference, indent=2)) - preference is not None + assert preference is not None @needscredentials def test_get_all_preferences_on_scope_account(self): @@ -2029,7 +2060,7 @@ def test_get_all_preferences_on_scope_account(self): account_id=self.account_id, iam_id=self.iam_id_for_preferences ).get_result() print('\nget_all_preference_on_scope_account() response: ', json.dumps(preference, indent=2)) - preference is not None + assert preference is not None @needscredentials def test_delete_preferences_on_scope_account(self): diff --git a/test/unit/test_iam_identity_v1.py b/test/unit/test_iam_identity_v1.py index 820e4fd..dfba890 100644 --- a/test/unit/test_iam_identity_v1.py +++ b/test/unit/test_iam_identity_v1.py @@ -3532,7 +3532,7 @@ def test_create_link_all_params(self): """ # Set up mock url = preprocess_url('/v1/profiles/testString/links') - mock_response = '{"id": "id", "entity_tag": "entity_tag", "created_at": "2019-01-01T12:00:00.000Z", "modified_at": "2019-01-01T12:00:00.000Z", "name": "name", "cr_type": "cr_type", "link": {"crn": "crn", "namespace": "namespace", "name": "name"}}' + mock_response = '{"id": "id", "entity_tag": "entity_tag", "created_at": "2019-01-01T12:00:00.000Z", "modified_at": "2019-01-01T12:00:00.000Z", "name": "name", "cr_type": "cr_type", "link": {"crn": "crn", "namespace": "namespace", "name": "name", "component_type": "component_type", "component_name": "component_name"}}' responses.add( responses.POST, url, @@ -3546,6 +3546,8 @@ def test_create_link_all_params(self): create_profile_link_request_link_model['crn'] = 'testString' create_profile_link_request_link_model['namespace'] = 'testString' create_profile_link_request_link_model['name'] = 'testString' + create_profile_link_request_link_model['component_type'] = 'testString' + create_profile_link_request_link_model['component_name'] = 'testString' # Set up parameter values profile_id = 'testString' @@ -3587,7 +3589,7 @@ def test_create_link_value_error(self): """ # Set up mock url = preprocess_url('/v1/profiles/testString/links') - mock_response = '{"id": "id", "entity_tag": "entity_tag", "created_at": "2019-01-01T12:00:00.000Z", "modified_at": "2019-01-01T12:00:00.000Z", "name": "name", "cr_type": "cr_type", "link": {"crn": "crn", "namespace": "namespace", "name": "name"}}' + mock_response = '{"id": "id", "entity_tag": "entity_tag", "created_at": "2019-01-01T12:00:00.000Z", "modified_at": "2019-01-01T12:00:00.000Z", "name": "name", "cr_type": "cr_type", "link": {"crn": "crn", "namespace": "namespace", "name": "name", "component_type": "component_type", "component_name": "component_name"}}' responses.add( responses.POST, url, @@ -3601,6 +3603,8 @@ def test_create_link_value_error(self): create_profile_link_request_link_model['crn'] = 'testString' create_profile_link_request_link_model['namespace'] = 'testString' create_profile_link_request_link_model['name'] = 'testString' + create_profile_link_request_link_model['component_type'] = 'testString' + create_profile_link_request_link_model['component_name'] = 'testString' # Set up parameter values profile_id = 'testString' @@ -3641,7 +3645,7 @@ def test_list_links_all_params(self): """ # Set up mock url = preprocess_url('/v1/profiles/testString/links') - mock_response = '{"links": [{"id": "id", "entity_tag": "entity_tag", "created_at": "2019-01-01T12:00:00.000Z", "modified_at": "2019-01-01T12:00:00.000Z", "name": "name", "cr_type": "cr_type", "link": {"crn": "crn", "namespace": "namespace", "name": "name"}}]}' + mock_response = '{"links": [{"id": "id", "entity_tag": "entity_tag", "created_at": "2019-01-01T12:00:00.000Z", "modified_at": "2019-01-01T12:00:00.000Z", "name": "name", "cr_type": "cr_type", "link": {"crn": "crn", "namespace": "namespace", "name": "name", "component_type": "component_type", "component_name": "component_name"}}]}' responses.add( responses.GET, url, @@ -3679,7 +3683,7 @@ def test_list_links_value_error(self): """ # Set up mock url = preprocess_url('/v1/profiles/testString/links') - mock_response = '{"links": [{"id": "id", "entity_tag": "entity_tag", "created_at": "2019-01-01T12:00:00.000Z", "modified_at": "2019-01-01T12:00:00.000Z", "name": "name", "cr_type": "cr_type", "link": {"crn": "crn", "namespace": "namespace", "name": "name"}}]}' + mock_response = '{"links": [{"id": "id", "entity_tag": "entity_tag", "created_at": "2019-01-01T12:00:00.000Z", "modified_at": "2019-01-01T12:00:00.000Z", "name": "name", "cr_type": "cr_type", "link": {"crn": "crn", "namespace": "namespace", "name": "name", "component_type": "component_type", "component_name": "component_name"}}]}' responses.add( responses.GET, url, @@ -3710,6 +3714,145 @@ def test_list_links_value_error_with_retries(self): self.test_list_links_value_error() +class TestDeleteLinkByParameters: + """ + Test Class for delete_link_by_parameters + """ + + @responses.activate + def test_delete_link_by_parameters_all_params(self): + """ + delete_link_by_parameters() + """ + # Set up mock + url = preprocess_url('/v1/profiles/testString/links') + responses.add( + responses.DELETE, + url, + status=204, + ) + + # Set up parameter values + profile_id = 'testString' + type = 'testString' + crn = 'testString' + namespace = 'testString' + name = 'testString' + component_type = 'testString' + component_name = 'testString' + + # Invoke method + response = _service.delete_link_by_parameters( + profile_id, + type, + crn=crn, + namespace=namespace, + name=name, + component_type=component_type, + component_name=component_name, + headers={}, + ) + + # Check for correct operation + assert len(responses.calls) == 1 + assert response.status_code == 204 + # Validate query params + query_string = responses.calls[0].request.url.split('?', 1)[1] + query_string = urllib.parse.unquote_plus(query_string) + assert 'type={}'.format(type) in query_string + assert 'crn={}'.format(crn) in query_string + assert 'namespace={}'.format(namespace) in query_string + assert 'name={}'.format(name) in query_string + assert 'component_type={}'.format(component_type) in query_string + assert 'component_name={}'.format(component_name) in query_string + + def test_delete_link_by_parameters_all_params_with_retries(self): + # Enable retries and run test_delete_link_by_parameters_all_params. + _service.enable_retries() + self.test_delete_link_by_parameters_all_params() + + # Disable retries and run test_delete_link_by_parameters_all_params. + _service.disable_retries() + self.test_delete_link_by_parameters_all_params() + + @responses.activate + def test_delete_link_by_parameters_required_params(self): + """ + test_delete_link_by_parameters_required_params() + """ + # Set up mock + url = preprocess_url('/v1/profiles/testString/links') + responses.add( + responses.DELETE, + url, + status=204, + ) + + # Set up parameter values + profile_id = 'testString' + type = 'testString' + + # Invoke method + response = _service.delete_link_by_parameters( + profile_id, + type, + headers={}, + ) + + # Check for correct operation + assert len(responses.calls) == 1 + assert response.status_code == 204 + # Validate query params + query_string = responses.calls[0].request.url.split('?', 1)[1] + query_string = urllib.parse.unquote_plus(query_string) + assert 'type={}'.format(type) in query_string + + def test_delete_link_by_parameters_required_params_with_retries(self): + # Enable retries and run test_delete_link_by_parameters_required_params. + _service.enable_retries() + self.test_delete_link_by_parameters_required_params() + + # Disable retries and run test_delete_link_by_parameters_required_params. + _service.disable_retries() + self.test_delete_link_by_parameters_required_params() + + @responses.activate + def test_delete_link_by_parameters_value_error(self): + """ + test_delete_link_by_parameters_value_error() + """ + # Set up mock + url = preprocess_url('/v1/profiles/testString/links') + responses.add( + responses.DELETE, + url, + status=204, + ) + + # Set up parameter values + profile_id = 'testString' + type = 'testString' + + # Pass in all but one required param and check for a ValueError + req_param_dict = { + "profile_id": profile_id, + "type": type, + } + for param in req_param_dict.keys(): + req_copy = {key: val if key is not param else None for (key, val) in req_param_dict.items()} + with pytest.raises(ValueError): + _service.delete_link_by_parameters(**req_copy) + + def test_delete_link_by_parameters_value_error_with_retries(self): + # Enable retries and run test_delete_link_by_parameters_value_error. + _service.enable_retries() + self.test_delete_link_by_parameters_value_error() + + # Disable retries and run test_delete_link_by_parameters_value_error. + _service.disable_retries() + self.test_delete_link_by_parameters_value_error() + + class TestGetLink: """ Test Class for get_link @@ -3722,7 +3865,7 @@ def test_get_link_all_params(self): """ # Set up mock url = preprocess_url('/v1/profiles/testString/links/testString') - mock_response = '{"id": "id", "entity_tag": "entity_tag", "created_at": "2019-01-01T12:00:00.000Z", "modified_at": "2019-01-01T12:00:00.000Z", "name": "name", "cr_type": "cr_type", "link": {"crn": "crn", "namespace": "namespace", "name": "name"}}' + mock_response = '{"id": "id", "entity_tag": "entity_tag", "created_at": "2019-01-01T12:00:00.000Z", "modified_at": "2019-01-01T12:00:00.000Z", "name": "name", "cr_type": "cr_type", "link": {"crn": "crn", "namespace": "namespace", "name": "name", "component_type": "component_type", "component_name": "component_name"}}' responses.add( responses.GET, url, @@ -3762,7 +3905,7 @@ def test_get_link_value_error(self): """ # Set up mock url = preprocess_url('/v1/profiles/testString/links/testString') - mock_response = '{"id": "id", "entity_tag": "entity_tag", "created_at": "2019-01-01T12:00:00.000Z", "modified_at": "2019-01-01T12:00:00.000Z", "name": "name", "cr_type": "cr_type", "link": {"crn": "crn", "namespace": "namespace", "name": "name"}}' + mock_response = '{"id": "id", "entity_tag": "entity_tag", "created_at": "2019-01-01T12:00:00.000Z", "modified_at": "2019-01-01T12:00:00.000Z", "name": "name", "cr_type": "cr_type", "link": {"crn": "crn", "namespace": "namespace", "name": "name", "component_type": "component_type", "component_name": "component_name"}}' responses.add( responses.GET, url, @@ -10343,6 +10486,8 @@ def test_create_profile_link_request_link_serialization(self): create_profile_link_request_link_model_json['crn'] = 'testString' create_profile_link_request_link_model_json['namespace'] = 'testString' create_profile_link_request_link_model_json['name'] = 'testString' + create_profile_link_request_link_model_json['component_type'] = 'testString' + create_profile_link_request_link_model_json['component_name'] = 'testString' # Construct a model instance of CreateProfileLinkRequestLink by calling from_dict on the json representation create_profile_link_request_link_model = CreateProfileLinkRequestLink.from_dict( @@ -11183,6 +11328,8 @@ def test_profile_link_serialization(self): profile_link_link_model['crn'] = 'testString' profile_link_link_model['namespace'] = 'testString' profile_link_link_model['name'] = 'testString' + profile_link_link_model['component_type'] = 'testString' + profile_link_link_model['component_name'] = 'testString' # Construct a json representation of a ProfileLink model profile_link_model_json = {} @@ -11225,6 +11372,8 @@ def test_profile_link_link_serialization(self): profile_link_link_model_json['crn'] = 'testString' profile_link_link_model_json['namespace'] = 'testString' profile_link_link_model_json['name'] = 'testString' + profile_link_link_model_json['component_type'] = 'testString' + profile_link_link_model_json['component_name'] = 'testString' # Construct a model instance of ProfileLinkLink by calling from_dict on the json representation profile_link_link_model = ProfileLinkLink.from_dict(profile_link_link_model_json) @@ -11258,6 +11407,8 @@ def test_profile_link_list_serialization(self): profile_link_link_model['crn'] = 'testString' profile_link_link_model['namespace'] = 'testString' profile_link_link_model['name'] = 'testString' + profile_link_link_model['component_type'] = 'testString' + profile_link_link_model['component_name'] = 'testString' profile_link_model = {} # ProfileLink profile_link_model['id'] = 'testString'