cloudfoundry / cf-java-client

Java Client Library for Cloud Foundry
Apache License 2.0
328 stars 318 forks source link

Unable to delete a security group with given name #1123

Closed damzog closed 3 years ago

damzog commented 3 years ago

Hi folks,

I am trying to delete a security group from which I have the name (which is unique). Unfortunately I could not find a way to get the guid. I tried to use cloudFoundryClient.securityGroups().list() searching by name but I did not find a way to get the guid out of the result list (containing one SecurityGroupEntity instance). Looking at the code the entity class does not contain the guid:

...
  private final @Nullable String name;
  private final @Nullable List<RuleEntity> rules;
  private final @Nullable Boolean runningDefault;
  private final @Nullable String spacesUrl;
  private final @Nullable Boolean stagingDefault;
  private final @Nullable String stagingSpacesUrl;
...

Am I missing something?

Your help is much appreciated.

Joda

dmikusa commented 3 years ago

The guid is part of the metadata.

When you fetch a security group it returns an object that extends from AbstractSecurityGroupResource. That in turn extends from a generic Resource<SecurityGroupEntity>. The generic Resource type provides access to the metadata which in turn provides access to the guid.

The same should be true if you list security groups, or any other call that returns a security group.

Please give that a try and let me know how things go.

damzog commented 3 years ago

Thanks @dmikusa-pivotal !

I can't confirm that SecurityGroupEntity inherits from Resource . It does extend from rg.cloudfoundry.client.v2.securitygroups._SecurityGroupEntity with no further parents. Also looking at the instance at runtime did not reveal any metadata.

However I found a workaround while checking: The spaces url can be used to extract the guid of the securitygroups instance. Not nice but works for me:

    public static final Pattern REGEXP_GUID = Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}");

    private void deleteByGuidFromSpacesUrl(SecurityGroupEntity entity) {
        Matcher m = REGEXP_GUID.matcher(entity.getSpacesUrl());

        if(m.find()) {
            String guid = m.group();

            cloudFoundryClient.securityGroups().delete(DeleteSecurityGroupRequest.builder()
                    .securityGroupId(guid)
                    .build())
                    .doOnError(error -> log.error("Error: ", error))
                    .subscribe(result -> log.info(result.getEntity().toString()));
        } else {
            log.error("Error: Could not extract security groups guid from space url: " + entity.getSpacesUrl());
        }
    }
dmikusa commented 3 years ago

It should just be response.getMetadata().getId() or you can use the ResourceUtil which has a helper for getting the id. Where response is the response object you get from get or create. You need to get the guid from the response though. The entity does not have a guid attribute on it. The response does because it extends AbstractSecurityGroupResource which in turn extends Resource<org.cloudfoundry.client.v2.securitygroups.SecurityGroupEntity> and the generic Resource object has the metadata which has the guid.

Using your example function, you need to change the header to take the response object, not the entity. Or you need to add a second parameter for the guid and pass that separate from the entity object.

damzog commented 3 years ago

But that is exactly the issue: I have only the groups name in hand (which is unique) and I try to delete that security group. So I have to use the securityGroups().list() method to find the security group. But that method only returns entities with which I do not get the guid. What's the point of a finder method if it does not give you the ids of the objects found?

dmikusa commented 3 years ago

But that is exactly the issue: I have only the groups name in hand (which is unique) and I try to delete that security group. So I have to use the securityGroups().list() method to find the security group.

Correct. That is how you would effectively search for a security group based on the name.

But that method only returns entities with which I do not get the guid. What's the point of a finder method if it does not give you the ids of the objects found?

Incorrect. That method returns a Mono object which will give you a List<SecurityGroupResource>. This is a different object from the entity and it can give you both the metadata, which has the guid, and the entity which has the name for each returned security group.

See this example of iterating & returning security group guid & name. You can adapt that to do something with the guid other than just printing it.

damzog commented 3 years ago

Seems I did oversee the getResources() method of ListSecurityGroupsResponse.

I apologize. It is working now for me. Thank you so much!!

dmikusa commented 3 years ago

No worries, glad it's working for you. Happy to help.