diff --git a/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/domains/_CreateDomainRequest.java b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/domains/_CreateDomainRequest.java index fe42ce4bc3..d452ebdc2f 100644 --- a/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/domains/_CreateDomainRequest.java +++ b/cloudfoundry-client/src/main/java/org/cloudfoundry/client/v3/domains/_CreateDomainRequest.java @@ -56,4 +56,11 @@ abstract class _CreateDomainRequest { @Nullable abstract DomainRelationships getRelationships(); + /** + * The router group + */ + @JsonProperty("router_group") + @Nullable + abstract RouterGroup getRouterGroup(); + } diff --git a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/_DefaultCloudFoundryOperations.java b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/_DefaultCloudFoundryOperations.java index 299b4bf5e4..f1a8d9f97d 100644 --- a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/_DefaultCloudFoundryOperations.java +++ b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/_DefaultCloudFoundryOperations.java @@ -91,7 +91,15 @@ public Buildpacks buildpacks() { @Override @Value.Derived public Domains domains() { - return new DefaultDomains(getCloudFoundryClientPublisher(), getRoutingClientPublisher()); + CloudFoundryClient cloudFoundryClient = getCloudFoundryClient(); + if (cloudFoundryClient == null) { + throw new IllegalStateException("CloudFoundryClient must be set"); + } + RoutingClient routingClient = getRoutingClient(); + if (routingClient == null) { + throw new IllegalStateException("RoutingClient must be set"); + } + return new DefaultDomains(cloudFoundryClient, routingClient); } @Override diff --git a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/domains/DefaultDomains.java b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/domains/DefaultDomains.java index aa30f42811..3df9c0d4a0 100644 --- a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/domains/DefaultDomains.java +++ b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/domains/DefaultDomains.java @@ -18,22 +18,26 @@ import static org.cloudfoundry.util.tuple.TupleUtils.function; +import java.util.List; +import java.util.Map; import java.util.NoSuchElementException; +import java.util.Optional; +import java.util.stream.Collectors; import org.cloudfoundry.client.CloudFoundryClient; -import org.cloudfoundry.client.v2.organizations.AssociateOrganizationPrivateDomainRequest; -import org.cloudfoundry.client.v2.organizations.AssociateOrganizationPrivateDomainResponse; -import org.cloudfoundry.client.v2.organizations.ListOrganizationsRequest; -import org.cloudfoundry.client.v2.organizations.OrganizationResource; -import org.cloudfoundry.client.v2.organizations.RemoveOrganizationPrivateDomainRequest; -import org.cloudfoundry.client.v2.privatedomains.CreatePrivateDomainRequest; -import org.cloudfoundry.client.v2.privatedomains.CreatePrivateDomainResponse; import org.cloudfoundry.client.v2.privatedomains.ListPrivateDomainsRequest; -import org.cloudfoundry.client.v2.privatedomains.PrivateDomainEntity; import org.cloudfoundry.client.v2.privatedomains.PrivateDomainResource; import org.cloudfoundry.client.v2.shareddomains.CreateSharedDomainResponse; import org.cloudfoundry.client.v2.shareddomains.ListSharedDomainsRequest; -import org.cloudfoundry.client.v2.shareddomains.SharedDomainEntity; import org.cloudfoundry.client.v2.shareddomains.SharedDomainResource; +import org.cloudfoundry.client.v3.Relationship; +import org.cloudfoundry.client.v3.ToOneRelationship; +import org.cloudfoundry.client.v3.domains.CreateDomainResponse; +import org.cloudfoundry.client.v3.domains.DomainRelationships; +import org.cloudfoundry.client.v3.domains.DomainResource; +import org.cloudfoundry.client.v3.domains.ListDomainsRequest; +import org.cloudfoundry.client.v3.domains.ShareDomainResponse; +import org.cloudfoundry.client.v3.organizations.ListOrganizationsRequest; +import org.cloudfoundry.client.v3.organizations.OrganizationResource; import org.cloudfoundry.operations.util.OperationsLogging; import org.cloudfoundry.routing.RoutingClient; import org.cloudfoundry.routing.v1.routergroups.ListRouterGroupsResponse; @@ -45,89 +49,82 @@ public final class DefaultDomains implements Domains { - private final Mono cloudFoundryClient; + private final CloudFoundryClient cloudFoundryClient; - private final Mono routingClient; + private final RoutingClient routingClient; - public DefaultDomains( - Mono cloudFoundryClient, Mono routingClient) { + public DefaultDomains(CloudFoundryClient cloudFoundryClient, RoutingClient routingClient) { this.cloudFoundryClient = cloudFoundryClient; this.routingClient = routingClient; } + /** + * @deprecated use {@link DefaultDomains(CloudFoundryClient, RoutingClient)} instead. + */ + @Deprecated + public DefaultDomains( + Mono cloudFoundryClient, Mono routingClient) { + this.cloudFoundryClient = cloudFoundryClient.block(); + this.routingClient = routingClient.block(); + } + @Override public Mono create(CreateDomainRequest request) { - return this.cloudFoundryClient - .flatMap( - cloudFoundryClient -> - Mono.zip( - Mono.just(cloudFoundryClient), - getOrganizationId( - cloudFoundryClient, request.getOrganization()))) + Mono> organizationId = + Mono.justOrEmpty(request.getOrganization()) + .flatMap(this::getOrganization) + .map(OrganizationResource::getId) + .map(Optional::of) + .defaultIfEmpty(Optional.empty()); + + Mono> groupId = + Mono.justOrEmpty(request.getRouterGroup()) + .flatMap(this::getRouterGroupId) + .map(Optional::of) + .defaultIfEmpty(Optional.empty()); + + return Mono.zip(organizationId, groupId) .flatMap( function( - (cloudFoundryClient, organizationId) -> + (oId, gId) -> requestCreateDomain( - cloudFoundryClient, request.getDomain(), - organizationId))) + oId.orElse(null), + gId.orElse(null)))) .then() .transform(OperationsLogging.log("Create Domain")) .checkpoint(); } @Override + @Deprecated public Mono createShared(CreateSharedDomainRequest request) { - if (request.getRouterGroup() == null) { - return this.cloudFoundryClient - .flatMap( - cloudFoundryClient -> - requestCreateSharedDomain( - cloudFoundryClient, request.getDomain(), null)) - .then() - .transform(OperationsLogging.log("Create Shared Domain")) - .checkpoint(); - } else { - return Mono.zip(this.cloudFoundryClient, this.routingClient) - .flatMap( - function( - (cloudFoundryClient, routingClient) -> - Mono.zip( - Mono.just(cloudFoundryClient), - getRouterGroupId( - routingClient, - request.getRouterGroup())))) - .flatMap( - function( - (cloudFoundryClient, routerGroupId) -> - requestCreateSharedDomain( - cloudFoundryClient, - request.getDomain(), - routerGroupId))) - .then() - .transform(OperationsLogging.log("Create Shared Domain")) - .checkpoint(); - } + return create( + CreateDomainRequest.builder() + .domain(request.getDomain()) + .routerGroup(request.getRouterGroup()) + .build()); } @Override public Flux list() { - return this.cloudFoundryClient + return requestListRouterGroups() + .map(ListRouterGroupsResponse::getRouterGroups) + .map(DefaultDomains::indexRouterGroupsById) .flatMapMany( - cloudFoundryClient -> - requestListPrivateDomains(cloudFoundryClient) - .map(DefaultDomains::toDomain) - .mergeWith( - requestListSharedDomains(cloudFoundryClient) - .map(DefaultDomains::toDomain))) + routerGroupsIndexedById -> + requestListDomains() + .map( + domain -> + DefaultDomains.toDomain( + domain, routerGroupsIndexedById))) .transform(OperationsLogging.log("List Domains")) .checkpoint(); } @Override public Flux listRouterGroups() { - return this.routingClient - .flatMapMany(DefaultDomains::requestListRouterGroups) + return requestListRouterGroups() .flatMapIterable(ListRouterGroupsResponse::getRouterGroups) .map(DefaultDomains::toRouterGroup) .transform(OperationsLogging.log("List Router Groups")) @@ -136,15 +133,10 @@ public Flux listRouterGroups() { @Override public Mono share(ShareDomainRequest request) { - return this.cloudFoundryClient - .flatMap( - cloudFoundryClient -> - Mono.zip( - Mono.just(cloudFoundryClient), - getPrivateDomainId(cloudFoundryClient, request.getDomain()), - getOrganizationId( - cloudFoundryClient, request.getOrganization()))) - .flatMap(function(DefaultDomains::requestAssociateOrganizationPrivateDomainRequest)) + return Mono.zip( + getDomainId(request.getDomain()), + getOrganizationId(request.getOrganization())) + .flatMap(function(this::requestShareDomain)) .then() .transform(OperationsLogging.log("Share Domain")) .checkpoint(); @@ -152,22 +144,16 @@ public Mono share(ShareDomainRequest request) { @Override public Mono unshare(UnshareDomainRequest request) { - return this.cloudFoundryClient - .flatMap( - cloudFoundryClient -> - Mono.zip( - Mono.just(cloudFoundryClient), - getPrivateDomainId(cloudFoundryClient, request.getDomain()), - getOrganizationId( - cloudFoundryClient, request.getOrganization()))) - .flatMap(function(DefaultDomains::requestRemoveOrganizationPrivateDomainRequest)) + return Mono.zip( + getDomainId(request.getDomain()), + getOrganizationId(request.getOrganization())) + .flatMap(function(this::requestUnshareDomain)) .transform(OperationsLogging.log("Unshare Domain")) .checkpoint(); } - private static Mono getOrganization( - CloudFoundryClient cloudFoundryClient, String organization) { - return requestOrganizations(cloudFoundryClient, organization) + private Mono getOrganization(String organization) { + return requestOrganizations(organization) .single() .onErrorResume( NoSuchElementException.class, @@ -176,14 +162,14 @@ private static Mono getOrganization( "Organization %s does not exist", organization)); } - private static Mono getOrganizationId( - CloudFoundryClient cloudFoundryClient, String organization) { - return getOrganization(cloudFoundryClient, organization).map(ResourceUtils::getId); + private Mono getOrganizationId(String organization) { + return getOrganization(organization).map(OrganizationResource::getId); } - private static Mono getPrivateDomain( - CloudFoundryClient cloudFoundryClient, String domain) { - return requestListPrivateDomains(cloudFoundryClient, domain) + private Mono getDomainId(String domain) { + return this.requestListDomains() + .filter(d -> d.getName().equals(domain)) + .map(DomainResource::getId) .single() .onErrorResume( NoSuchElementException.class, @@ -192,45 +178,63 @@ private static Mono getPrivateDomain( "Private domain %s does not exist", domain)); } - private static Mono getPrivateDomainId( - CloudFoundryClient cloudFoundryClient, String domain) { - return getPrivateDomain(cloudFoundryClient, domain).map(ResourceUtils::getId); + private Mono getPrivateDomain(String domain) { + return requestListPrivateDomains(domain) + .single() + .onErrorResume( + NoSuchElementException.class, + t -> + ExceptionUtils.illegalArgument( + "Private domain %s does not exist", domain)); } - private static Mono getRouterGroupId(RoutingClient routingClient, String routerGroup) { - return requestListRouterGroups(routingClient) + private Mono getPrivateDomainId(String domain) { + return getPrivateDomain(domain).map(ResourceUtils::getId); + } + + private Mono getRouterGroupId(String routerGroup) { + return requestListRouterGroups() .flatMapIterable(ListRouterGroupsResponse::getRouterGroups) .filter(group -> routerGroup.equals(group.getName())) .single() .map(org.cloudfoundry.routing.v1.routergroups.RouterGroup::getRouterGroupId); } - private static Mono - requestAssociateOrganizationPrivateDomainRequest( - CloudFoundryClient cloudFoundryClient, String domainId, String organizationId) { - return cloudFoundryClient - .organizations() - .associatePrivateDomain( - AssociateOrganizationPrivateDomainRequest.builder() - .organizationId(organizationId) - .privateDomainId(domainId) + private Mono requestShareDomain(String domainId, String organizationId) { + return this.cloudFoundryClient + .domainsV3() + .share( + org.cloudfoundry.client.v3.domains.ShareDomainRequest.builder() + .domainId(domainId) + .data(Relationship.builder().id(organizationId).build()) .build()); } - private static Mono requestCreateDomain( - CloudFoundryClient cloudFoundryClient, String domain, String organizationId) { - return cloudFoundryClient - .privateDomains() - .create( - CreatePrivateDomainRequest.builder() - .name(domain) - .owningOrganizationId(organizationId) - .build()); + private Mono requestCreateDomain( + String domain, String organizationId, String routerGroupId) { + org.cloudfoundry.client.v3.domains.CreateDomainRequest.Builder createDomainRequest = + org.cloudfoundry.client.v3.domains.CreateDomainRequest.builder().name(domain); + if (organizationId != null) { + createDomainRequest.relationships( + DomainRelationships.builder() + .organization( + ToOneRelationship.builder() + .data(Relationship.builder().id(organizationId).build()) + .build()) + .build()); + } + if (routerGroupId != null) { + createDomainRequest.routerGroup( + org.cloudfoundry.client.v3.domains.RouterGroup.builder() + .id(routerGroupId) + .build()); + } + return this.cloudFoundryClient.domainsV3().create(createDomainRequest.build()); } - private static Mono requestCreateSharedDomain( - CloudFoundryClient cloudFoundryClient, String domain, String routerGroupId) { - return cloudFoundryClient + private Mono requestCreateSharedDomain( + String domain, String routerGroupId) { + return this.cloudFoundryClient .sharedDomains() .create( org.cloudfoundry.client.v2.shareddomains.CreateSharedDomainRequest.builder() @@ -239,11 +243,10 @@ private static Mono requestCreateSharedDomain( .build()); } - private static Flux requestListPrivateDomains( - CloudFoundryClient cloudFoundryClient, String domain) { + private Flux requestListPrivateDomains(String domain) { return PaginationUtils.requestClientV2Resources( page -> - cloudFoundryClient + this.cloudFoundryClient .privateDomains() .list( ListPrivateDomainsRequest.builder() @@ -252,39 +255,35 @@ private static Flux requestListPrivateDomains( .build())); } - private static Flux requestListPrivateDomains( - CloudFoundryClient cloudFoundryClient) { - return PaginationUtils.requestClientV2Resources( + private Flux requestListDomains() { + return PaginationUtils.requestClientV3Resources( page -> - cloudFoundryClient - .privateDomains() - .list(ListPrivateDomainsRequest.builder().page(page).build())); + this.cloudFoundryClient + .domainsV3() + .list(ListDomainsRequest.builder().page(page).build())); } - private static Mono requestListRouterGroups( - RoutingClient routingClient) { - return routingClient + private Mono requestListRouterGroups() { + return this.routingClient .routerGroups() .list( org.cloudfoundry.routing.v1.routergroups.ListRouterGroupsRequest.builder() .build()); } - private static Flux requestListSharedDomains( - CloudFoundryClient cloudFoundryClient) { + private Flux requestListSharedDomains() { return PaginationUtils.requestClientV2Resources( page -> - cloudFoundryClient + this.cloudFoundryClient .sharedDomains() .list(ListSharedDomainsRequest.builder().page(page).build())); } - private static Flux requestOrganizations( - CloudFoundryClient cloudFoundryClient, String organization) { - return PaginationUtils.requestClientV2Resources( + private Flux requestOrganizations(String organization) { + return PaginationUtils.requestClientV3Resources( page -> - cloudFoundryClient - .organizations() + this.cloudFoundryClient + .organizationsV3() .list( ListOrganizationsRequest.builder() .name(organization) @@ -292,36 +291,39 @@ private static Flux requestOrganizations( .build())); } - private static Mono requestRemoveOrganizationPrivateDomainRequest( - CloudFoundryClient cloudFoundryClient, String domainId, String organizationId) { - return cloudFoundryClient - .organizations() - .removePrivateDomain( - RemoveOrganizationPrivateDomainRequest.builder() + private Mono requestUnshareDomain(String domainId, String organizationId) { + return this.cloudFoundryClient + .domainsV3() + .unshare( + org.cloudfoundry.client.v3.domains.UnshareDomainRequest.builder() .organizationId(organizationId) - .privateDomainId(domainId) + .domainId(domainId) .build()); } - private static Domain toDomain(PrivateDomainResource resource) { - PrivateDomainEntity entity = ResourceUtils.getEntity(resource); - + private static Domain toDomain(DomainResource entity, Map type) { return Domain.builder() - .id(ResourceUtils.getId(resource)) + .id(entity.getId()) .name(entity.getName()) - .status(Status.OWNED) + .status( + entity.getRelationships().getOrganization().getData() != null + ? Status.OWNED + : Status.SHARED) + .type( + entity.getRouterGroup() != null + ? type.get(entity.getRouterGroup().getId()) + : null) .build(); } - private static Domain toDomain(SharedDomainResource resource) { - SharedDomainEntity entity = ResourceUtils.getEntity(resource); - - return Domain.builder() - .id(ResourceUtils.getId(resource)) - .name(entity.getName()) - .status(Status.SHARED) - .type(entity.getRouterGroupType()) - .build(); + private static Map indexRouterGroupsById( + List routeGroups) { + return routeGroups.stream() + .collect( + Collectors.toMap( + org.cloudfoundry.routing.v1.routergroups.RouterGroup + ::getRouterGroupId, + org.cloudfoundry.routing.v1.routergroups.RouterGroup::getType)); } private static RouterGroup toRouterGroup( diff --git a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/domains/Domains.java b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/domains/Domains.java index 74ffa068b8..e32fc01ead 100644 --- a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/domains/Domains.java +++ b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/domains/Domains.java @@ -37,7 +37,9 @@ public interface Domains { * * @param request the Create Shared Domain request * @return a completion indicator + * @deprecated use {@link #create} instead */ + @Deprecated Mono createShared(CreateSharedDomainRequest request); /** diff --git a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/domains/_CreateDomainRequest.java b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/domains/_CreateDomainRequest.java index 924e47e2a8..04d4d2bcfc 100644 --- a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/domains/_CreateDomainRequest.java +++ b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/domains/_CreateDomainRequest.java @@ -16,6 +16,7 @@ package org.cloudfoundry.operations.domains; +import org.cloudfoundry.Nullable; import org.immutables.value.Value; /** @@ -32,6 +33,13 @@ abstract class _CreateDomainRequest { /** * The organization name of the domain */ + @Nullable abstract String getOrganization(); + /** + * The router group of the domain + */ + @Nullable + abstract String getRouterGroup(); + } diff --git a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/DefaultCloudFoundryOperationsTest.java b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/DefaultCloudFoundryOperationsTest.java index fd1027e7f0..02e671a3e6 100644 --- a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/DefaultCloudFoundryOperationsTest.java +++ b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/DefaultCloudFoundryOperationsTest.java @@ -26,6 +26,7 @@ final class DefaultCloudFoundryOperationsTest extends AbstractOperationsTest { DefaultCloudFoundryOperations.builder() .cloudFoundryClient(this.cloudFoundryClient) .dopplerClient(this.dopplerClient) + .routingClient(this.routingClient) .organization(TEST_ORGANIZATION_NAME) .space(TEST_SPACE_NAME) .uaaClient(this.uaaClient) diff --git a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/domains/CreateDomainRequestTest.java b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/domains/CreateDomainRequestTest.java index bb41e2a15d..d974026dda 100644 --- a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/domains/CreateDomainRequestTest.java +++ b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/domains/CreateDomainRequestTest.java @@ -31,15 +31,6 @@ void noDomain() { }); } - @Test - void noOrganization() { - assertThrows( - IllegalStateException.class, - () -> { - CreateDomainRequest.builder().domain("test-domain").build(); - }); - } - @Test void valid() { CreateDomainRequest.builder() diff --git a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/domains/DefaultDomainsTest.java b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/domains/DefaultDomainsTest.java index 15d97267ad..6fdae8380f 100644 --- a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/domains/DefaultDomainsTest.java +++ b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/domains/DefaultDomainsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 the original author or authors. + * Copyright 2013-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,29 +18,27 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.cloudfoundry.operations.TestObjects.fill; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import java.time.Duration; import org.cloudfoundry.client.CloudFoundryClient; -import org.cloudfoundry.client.v2.Metadata; -import org.cloudfoundry.client.v2.organizations.AssociateOrganizationPrivateDomainRequest; -import org.cloudfoundry.client.v2.organizations.ListOrganizationsRequest; -import org.cloudfoundry.client.v2.organizations.ListOrganizationsResponse; -import org.cloudfoundry.client.v2.organizations.OrganizationResource; -import org.cloudfoundry.client.v2.organizations.RemoveOrganizationPrivateDomainRequest; -import org.cloudfoundry.client.v2.privatedomains.CreatePrivateDomainRequest; -import org.cloudfoundry.client.v2.privatedomains.CreatePrivateDomainResponse; -import org.cloudfoundry.client.v2.privatedomains.ListPrivateDomainsRequest; -import org.cloudfoundry.client.v2.privatedomains.ListPrivateDomainsResponse; -import org.cloudfoundry.client.v2.privatedomains.PrivateDomainResource; -import org.cloudfoundry.client.v2.shareddomains.CreateSharedDomainResponse; -import org.cloudfoundry.client.v2.shareddomains.ListSharedDomainsRequest; -import org.cloudfoundry.client.v2.shareddomains.ListSharedDomainsResponse; -import org.cloudfoundry.client.v2.shareddomains.SharedDomainEntity; -import org.cloudfoundry.client.v2.shareddomains.SharedDomainResource; +import org.cloudfoundry.client.v3.Pagination; +import org.cloudfoundry.client.v3.Relationship; +import org.cloudfoundry.client.v3.ToOneRelationship; +import org.cloudfoundry.client.v3.domains.CreateDomainResponse; +import org.cloudfoundry.client.v3.domains.DomainRelationships; +import org.cloudfoundry.client.v3.domains.DomainResource; +import org.cloudfoundry.client.v3.domains.ListDomainsRequest; +import org.cloudfoundry.client.v3.domains.ListDomainsResponse; +import org.cloudfoundry.client.v3.organizations.ListOrganizationsRequest; +import org.cloudfoundry.client.v3.organizations.ListOrganizationsResponse; +import org.cloudfoundry.client.v3.organizations.OrganizationResource; import org.cloudfoundry.operations.AbstractOperationsTest; import org.cloudfoundry.routing.RoutingClient; -import org.cloudfoundry.routing.v1.routergroups.ListRouterGroupsRequest; import org.cloudfoundry.routing.v1.routergroups.ListRouterGroupsResponse; import org.junit.jupiter.api.Test; import reactor.core.publisher.Mono; @@ -49,12 +47,12 @@ final class DefaultDomainsTest extends AbstractOperationsTest { private final DefaultDomains domains = - new DefaultDomains(Mono.just(this.cloudFoundryClient), Mono.just(this.routingClient)); + new DefaultDomains(this.cloudFoundryClient, this.routingClient); @Test void createDomain() { requestOrganizations(this.cloudFoundryClient, "test-organization"); - requestCreatePrivateDomain(this.cloudFoundryClient, "test-domain", "test-organization-id"); + requestCreateDomain(this.cloudFoundryClient, "test-domain", "test-organization-id"); this.domains .create( @@ -63,56 +61,89 @@ void createDomain() { .organization("test-organization") .build()) .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .verifyComplete(); + + verify(this.cloudFoundryClient.domainsV3()) + .create( + argThat( + a -> + a.getName().equals("test-domain") + && a.getRelationships() + .getOrganization() + .getData() + .getId() + .equals("test-organization-id"))); + verifyNoInteractions(this.routingClient.routerGroups().list(any())); } @Test void createSharedDomain() { - requestCreateSharedDomain(this.cloudFoundryClient, "test-domain"); + requestCreateDomain(this.cloudFoundryClient, "test-domain"); this.domains .createShared(CreateSharedDomainRequest.builder().domain("test-domain").build()) .as(StepVerifier::create) - .expectComplete() - .verify(Duration.ofSeconds(5)); + .verifyComplete(); + + verify(this.cloudFoundryClient.domainsV3()) + .create(argThat(a -> a.getName().equals("test-domain"))); + verifyNoInteractions(this.cloudFoundryClient.organizationsV3().list(any())); + verifyNoInteractions(this.routingClient.routerGroups().list(any())); } @Test - void listDomains() { - requestPrivateDomains(this.cloudFoundryClient); - requestSharedDomains(this.cloudFoundryClient); + void createDomainRouterGroup() { + requestCreateDomain(this.cloudFoundryClient, "test-domain"); + requestListRouterGroups(this.routingClient, "test-router-group"); this.domains - .list() - .as(StepVerifier::create) - .expectNext( - Domain.builder() - .id("test-private-domain-id") - .name("test-private-domain-name") - .status(Status.OWNED) - .build(), - Domain.builder() - .id("test-shared-domain-id") - .name("test-shared-domain-name") - .status(Status.SHARED) + .create( + CreateDomainRequest.builder() + .domain("test-domain") + .routerGroup("test-router-group") .build()) + .as(StepVerifier::create) .expectComplete() .verify(Duration.ofSeconds(5)); + + verifyNoInteractions(this.cloudFoundryClient.organizationsV3().list(any())); + verify(this.routingClient.routerGroups()).list(any()); + verify(this.cloudFoundryClient.domainsV3()) + .create(argThat(a -> a.getRouterGroup().getId().equals("test-routerGroupId"))); } @Test - void listDomainsOnlyPrivate() { - requestPrivateDomains(this.cloudFoundryClient); - requestSharedDomainsEmpty(this.cloudFoundryClient); + void createSharedDomainRouterGroup() { + requestCreateDomain(this.cloudFoundryClient, "test-domain"); + requestListRouterGroups(this.routingClient, "test-router-group"); + + this.domains + .createShared( + CreateSharedDomainRequest.builder() + .domain("test-domain") + .routerGroup("test-router-group") + .build()) + .as(StepVerifier::create) + .verifyComplete(); + + verifyNoInteractions(this.cloudFoundryClient.organizationsV3().list(any())); + verify(this.routingClient.routerGroups()).list(any()); + verify(this.cloudFoundryClient.domainsV3()) + .create(argThat(a -> a.getRouterGroup().getId().equals("test-routerGroupId"))); + } + + @Test + void listDomains() { + requestListRouterGroups(this.routingClient, "test-router-group"); + requestListDomains(this.cloudFoundryClient, "test-organization-id", null); this.domains .list() .as(StepVerifier::create) .expectNext( Domain.builder() - .id("test-private-domain-id") - .name("test-private-domain-name") + .id("test-domain-id") + .name("test-domain-name") .status(Status.OWNED) .build()) .expectComplete() @@ -120,17 +151,17 @@ void listDomainsOnlyPrivate() { } @Test - void listDomainsOnlyShared() { - requestSharedDomains(this.cloudFoundryClient); - requestPrivateDomainsEmpty(this.cloudFoundryClient); + void listDomainsShared() { + requestListRouterGroups(this.routingClient, "test-router-group"); + requestListDomains(this.cloudFoundryClient, null, null); this.domains .list() .as(StepVerifier::create) .expectNext( Domain.builder() - .id("test-shared-domain-id") - .name("test-shared-domain-name") + .id("test-domain-id") + .name("test-domain-name") .status(Status.SHARED) .build()) .expectComplete() @@ -139,23 +170,18 @@ void listDomainsOnlyShared() { @Test void listDomainsTcp() { - requestPrivateDomains(this.cloudFoundryClient); - requestSharedDomainsTcp(this.cloudFoundryClient); + requestListDomains(this.cloudFoundryClient, null, "test-routerGroupId"); + requestListRouterGroups(this.routingClient, "test-tcp-group"); this.domains .list() .as(StepVerifier::create) .expectNext( Domain.builder() - .id("test-private-domain-id") - .name("test-private-domain-name") - .status(Status.OWNED) - .build(), - Domain.builder() - .id("test-shared-domain-id") - .name("test-shared-domain-name") + .id("test-domain-id") + .name("test-domain-name") .status(Status.SHARED) - .type("test-shared-domain-type") + .type("tcp") .build()) .expectComplete() .verify(Duration.ofSeconds(5)); @@ -163,7 +189,7 @@ void listDomainsTcp() { @Test void listRouterGroups() { - requestListRouterGroups(this.routingClient); + requestListRouterGroups(this.routingClient, "test-router-group"); this.domains .listRouterGroups() @@ -171,8 +197,8 @@ void listRouterGroups() { .expectNext( RouterGroup.builder() .id("test-routerGroupId") - .name("test-name") - .type("test-type") + .name("test-router-group") + .type("tcp") .build()) .expectComplete() .verify(Duration.ofSeconds(5)); @@ -180,15 +206,14 @@ void listRouterGroups() { @Test void shareDomain() { - requestListPrivateDomains(this.cloudFoundryClient, "test-domain", "test-domain-id"); requestOrganizations(this.cloudFoundryClient, "test-organization"); - requestAssociateOrganizationPrivateDomain( - this.cloudFoundryClient, "test-domain-id", "test-organization-id"); + requestListDomains(this.cloudFoundryClient, "test-organization-id", null); + requestShareDomain(this.cloudFoundryClient, "test-domain-id", "test-organization-id"); this.domains .share( ShareDomainRequest.builder() - .domain("test-domain") + .domain("test-domain-name") .organization("test-organization") .build()) .as(StepVerifier::create) @@ -197,14 +222,15 @@ void shareDomain() { } @Test - void shareDomainSharedDomain() { - requestListPrivateDomainsEmpty(this.cloudFoundryClient, "test-domain"); + void shareDomainDoesNotExist() { requestOrganizations(this.cloudFoundryClient, "test-organization"); + requestListDomains(this.cloudFoundryClient, "test-organization-id", null); + requestShareDomain(this.cloudFoundryClient, "test-domain-id", "test-organization-id"); this.domains .share( ShareDomainRequest.builder() - .domain("test-domain") + .domain("invalid-domain-name") .organization("test-organization") .build()) .as(StepVerifier::create) @@ -212,21 +238,22 @@ void shareDomainSharedDomain() { t -> assertThat(t) .isInstanceOf(IllegalArgumentException.class) - .hasMessage("Private domain test-domain does not exist")) + .hasMessage( + "Private domain invalid-domain-name does not" + + " exist")) .verify(Duration.ofSeconds(5)); } @Test void unshareDomain() { - requestListPrivateDomains(this.cloudFoundryClient, "test-domain", "test-domain-id"); + requestListDomains(this.cloudFoundryClient, "test-organization-id", null); requestOrganizations(this.cloudFoundryClient, "test-organization"); - requestRemoveOrganizationPrivateDomain( - this.cloudFoundryClient, "test-domain-id", "test-organization-id"); + requestUnshareDomain(this.cloudFoundryClient, "test-domain-id", "test-organization-id"); this.domains .unshare( UnshareDomainRequest.builder() - .domain("test-domain") + .domain("test-domain-name") .organization("test-organization") .build()) .as(StepVerifier::create) @@ -234,85 +261,110 @@ void unshareDomain() { .verify(Duration.ofSeconds(5)); } - private static void requestAssociateOrganizationPrivateDomain( + private static void requestShareDomain( CloudFoundryClient cloudFoundryClient, String domainId, String organizationId) { when(cloudFoundryClient - .organizations() - .associatePrivateDomain( - AssociateOrganizationPrivateDomainRequest.builder() - .privateDomainId(domainId) - .organizationId(organizationId) + .domainsV3() + .share( + org.cloudfoundry.client.v3.domains.ShareDomainRequest.builder() + .domainId(domainId) + .data(Relationship.builder().id(organizationId).build()) .build())) .thenReturn(Mono.empty()); } - private static void requestCreatePrivateDomain( - CloudFoundryClient cloudFoundryClient, String domain, String organizationId) { + private static void requestUnshareDomain( + CloudFoundryClient cloudFoundryClient, String domainId, String organizationId) { when(cloudFoundryClient - .privateDomains() - .create( - CreatePrivateDomainRequest.builder() - .name(domain) - .owningOrganizationId(organizationId) + .domainsV3() + .unshare( + org.cloudfoundry.client.v3.domains.UnshareDomainRequest.builder() + .domainId(domainId) + .organizationId(organizationId) .build())) + .thenReturn(Mono.empty()); + } + + private static void requestCreateDomain(CloudFoundryClient cloudFoundryClient, String domain) { + when(cloudFoundryClient.domainsV3().create(any())) .thenReturn( Mono.just( - fill(CreatePrivateDomainResponse.builder(), "private-domain-") + fill(CreateDomainResponse.builder(), "domain-") + .isInternal(false) .build())); } - private static void requestCreateSharedDomain( - CloudFoundryClient cloudFoundryClient, String domain) { + private static void requestCreateDomain( + CloudFoundryClient cloudFoundryClient, String domain, String organizationId) { when(cloudFoundryClient - .sharedDomains() + .domainsV3() .create( - org.cloudfoundry.client.v2.shareddomains.CreateSharedDomainRequest - .builder() + org.cloudfoundry.client.v3.domains.CreateDomainRequest.builder() .name(domain) + .relationships( + DomainRelationships.builder() + .organization( + ToOneRelationship.builder() + .data( + Relationship + .builder() + .id( + organizationId) + .build()) + .build()) + .build()) .build())) .thenReturn( Mono.just( - fill(CreateSharedDomainResponse.builder(), "shared-domain-") + fill(CreateDomainResponse.builder(), "domain-") + .isInternal(false) .build())); } - private static void requestListPrivateDomains( - CloudFoundryClient cloudFoundryClient, String domain, String domainId) { - when(cloudFoundryClient - .privateDomains() - .list(ListPrivateDomainsRequest.builder().name(domain).page(1).build())) + private static void requestListDomains( + CloudFoundryClient cloudFoundryClient, String organizationId, String routerGroupId) { + ToOneRelationship organizationRelationShip = + organizationId != null + ? ToOneRelationship.builder() + .data(Relationship.builder().id(organizationId).build()) + .build() + : ToOneRelationship.builder().build(); + org.cloudfoundry.client.v3.domains.RouterGroup routerGroup = + routerGroupId != null + ? org.cloudfoundry.client.v3.domains.RouterGroup.builder() + .id(routerGroupId) + .build() + : null; + + when(cloudFoundryClient.domainsV3().list(ListDomainsRequest.builder().page(1).build())) .thenReturn( Mono.just( - fill(ListPrivateDomainsResponse.builder()) + fill(ListDomainsResponse.builder()) .resource( - fill(PrivateDomainResource.builder()) - .metadata( - fill( - Metadata.builder(), - "private-domain-") - .id(domainId) + fill(DomainResource.builder(), "domain-") + .isInternal(false) + .relationships( + DomainRelationships.builder() + .organization( + organizationRelationShip) .build()) + .routerGroup(routerGroup) .build()) - .totalPages(1) + .pagination(Pagination.builder().totalPages(1).build()) .build())); } - private static void requestListPrivateDomainsEmpty( - CloudFoundryClient cloudFoundryClient, String domain) { - when(cloudFoundryClient - .privateDomains() - .list(ListPrivateDomainsRequest.builder().name(domain).page(1).build())) - .thenReturn(Mono.just(fill(ListPrivateDomainsResponse.builder()).build())); - } - - private static void requestListRouterGroups(RoutingClient routingClient) { - when(routingClient.routerGroups().list(ListRouterGroupsRequest.builder().build())) + private static void requestListRouterGroups( + RoutingClient routingClient, String routerGroupName) { + when(routingClient.routerGroups().list(any())) .thenReturn( Mono.just( ListRouterGroupsResponse.builder() .routerGroup( fill(org.cloudfoundry.routing.v1.routergroups .RouterGroup.builder()) + .name(routerGroupName) + .type("tcp") .build()) .build())); } @@ -320,7 +372,7 @@ private static void requestListRouterGroups(RoutingClient routingClient) { private static void requestOrganizations( CloudFoundryClient cloudFoundryClient, String organization) { when(cloudFoundryClient - .organizations() + .organizationsV3() .list( ListOrganizationsRequest.builder() .name(organization) @@ -336,90 +388,4 @@ private static void requestOrganizations( .build()) .build())); } - - private static void requestPrivateDomains(CloudFoundryClient cloudFoundryClient) { - when(cloudFoundryClient - .privateDomains() - .list(ListPrivateDomainsRequest.builder().page(1).build())) - .thenReturn( - Mono.just( - fill(ListPrivateDomainsResponse.builder()) - .resource( - fill( - PrivateDomainResource.builder(), - "private-domain-") - .build()) - .build())); - } - - private static void requestPrivateDomainsEmpty(CloudFoundryClient cloudFoundryClient) { - when(cloudFoundryClient - .privateDomains() - .list(ListPrivateDomainsRequest.builder().page(1).build())) - .thenReturn(Mono.just(fill(ListPrivateDomainsResponse.builder()).build())); - } - - private static void requestRemoveOrganizationPrivateDomain( - CloudFoundryClient cloudFoundryClient, String domainId, String organizationId) { - when(cloudFoundryClient - .organizations() - .removePrivateDomain( - RemoveOrganizationPrivateDomainRequest.builder() - .privateDomainId(domainId) - .organizationId(organizationId) - .build())) - .thenReturn(Mono.empty()); - } - - private static void requestSharedDomains(CloudFoundryClient cloudFoundryClient) { - when(cloudFoundryClient - .sharedDomains() - .list(ListSharedDomainsRequest.builder().page(1).build())) - .thenReturn( - Mono.just( - fill(ListSharedDomainsResponse.builder()) - .resource( - fill( - SharedDomainResource.builder(), - "shared-domain-") - .entity( - fill( - SharedDomainEntity - .builder(), - "shared-domain-") - .routerGroupType(null) - .build()) - .build()) - .build())); - } - - private static void requestSharedDomainsEmpty(CloudFoundryClient cloudFoundryClient) { - when(cloudFoundryClient - .sharedDomains() - .list(ListSharedDomainsRequest.builder().page(1).build())) - .thenReturn(Mono.just(fill(ListSharedDomainsResponse.builder()).build())); - } - - private static void requestSharedDomainsTcp(CloudFoundryClient cloudFoundryClient) { - when(cloudFoundryClient - .sharedDomains() - .list(ListSharedDomainsRequest.builder().page(1).build())) - .thenReturn( - Mono.just( - fill(ListSharedDomainsResponse.builder()) - .resource( - fill( - SharedDomainResource.builder(), - "shared-domain-") - .entity( - fill( - SharedDomainEntity - .builder(), - "shared-domain-") - .routerGroupType( - "test-shared-domain-type") - .build()) - .build()) - .build())); - } } diff --git a/integration-test/src/test/java/org/cloudfoundry/operations/DomainsTest.java b/integration-test/src/test/java/org/cloudfoundry/operations/DomainsTest.java index f56d7c777b..b75ca3f3a4 100644 --- a/integration-test/src/test/java/org/cloudfoundry/operations/DomainsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/operations/DomainsTest.java @@ -17,13 +17,15 @@ package org.cloudfoundry.operations; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.InstanceOfAssertFactories.type; import static org.cloudfoundry.operations.domains.Status.OWNED; import static org.cloudfoundry.operations.domains.Status.SHARED; import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; import org.cloudfoundry.client.CloudFoundryClient; -import org.cloudfoundry.client.v2.ClientV2Exception; +import org.cloudfoundry.client.v3.ClientV3Exception; +import org.cloudfoundry.client.v3.Error; import org.cloudfoundry.client.v3.domains.GetDomainRequest; import org.cloudfoundry.operations.domains.CreateDomainRequest; import org.cloudfoundry.operations.domains.CreateSharedDomainRequest; @@ -60,10 +62,20 @@ public void createInvalidDomain() { .consumeErrorWith( t -> assertThat(t) - .isInstanceOf(ClientV2Exception.class) - .hasMessageMatching( - "CF-DomainInvalid\\([0-9]+\\): The domain is" - + " invalid.*")) + .asInstanceOf(type(ClientV3Exception.class)) + .extracting(ClientV3Exception::getErrors) + .asList() + .hasSize(1) + .first() + .isEqualTo( + Error.builder() + .title("CF-UnprocessableEntity") + .code(10008) + .detail( + "Name does not comply with RFC 1035" + + " standards, Name must" + + " contain at least one \".\"") + .build())) .verify(Duration.ofMinutes(5)); }