diff --git a/cloudplatform/connectivity-destination-service/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationService.java b/cloudplatform/connectivity-destination-service/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationService.java index 5c73050fe..aa2277636 100644 --- a/cloudplatform/connectivity-destination-service/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationService.java +++ b/cloudplatform/connectivity-destination-service/src/main/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationService.java @@ -174,7 +174,7 @@ public Try> tryGetAllDestinations() } /** - * Fetches all destination properties from the BTP Destination Service. + * Fetches all destination properties from the BTP Destination Service on behalf of the current tenant. *

* Caution: This will not perform any authorization flows for the destinations. Destinations * obtained this way should only be used for accessing the properties of the destination configuration. For @@ -184,21 +184,43 @@ public Try> tryGetAllDestinations() * destination at service instance level takes precedence. * * @return A list of destination properties. + * @see DestinationService#getAllDestinationProperties(DestinationServiceRetrievalStrategy) * @since 5.1.0 */ @Nonnull public Collection getAllDestinationProperties() { + return getAllDestinationProperties(DestinationServiceRetrievalStrategy.CURRENT_TENANT); + } + + /** + * Fetches all destination properties from the BTP Destination Service. + *

+ * Caution: This will not perform any authorization flows for the destinations. Destinations + * obtained this way should only be used for accessing the properties of the destination configuration. For + * obtaining full destination objects, use {@link #tryGetDestination(String, DestinationOptions)} instead. + *

+ * In case there exists a destination with the same name on service instance and on sub-account level, the + * destination at service instance level takes precedence. + * + * @return A list of destination properties. + * @param retrievalStrategy + * Strategy for loading destinations in a multi-tenant application. + * @since 5.12.0 + */ + @Nonnull + public Collection getAllDestinationProperties( + @Nonnull final DestinationServiceRetrievalStrategy retrievalStrategy ) + { + final var augmenter = DestinationServiceOptionsAugmenter.augmenter().retrievalStrategy(retrievalStrategy); + final var options = DestinationOptions.builder().augmentBuilder(augmenter).build(); return new ArrayList<>( - Cache - .getOrComputeAllDestinations( - DestinationOptions.builder().build(), - this::getAllDestinationsByRetrievalStrategy) - .get()); + Cache.getOrComputeAllDestinations(options, this::getAllDestinationsByRetrievalStrategy).get()); } /** - * Fetches the properties of a specific destination from the BTP Destination Service. + * Fetches the properties of a specific destination from the BTP Destination Service on behalf of the current + * tenant. *

* Caution: This will not perform any authorization flows for the destination. Destinations * obtained this way should only be used for accessing the properties of the destination configuration. For @@ -235,7 +257,8 @@ public DestinationProperties getDestinationProperties( @Nonnull final String des * @param options * Destination configuration object. * @return A Try iterable of CF destinations. - * @deprecated since 5.1.0. Use {@link #getAllDestinationProperties()} instead. + * @deprecated since 5.1.0. Use {@link #getAllDestinationProperties()} and + * {@link #getAllDestinationProperties(DestinationServiceRetrievalStrategy)} instead. */ @Nonnull @Deprecated diff --git a/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationServiceTest.java b/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationServiceTest.java index ffc559a23..985d431b2 100644 --- a/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationServiceTest.java +++ b/cloudplatform/connectivity-destination-service/src/test/java/com/sap/cloud/sdk/cloudplatform/connectivity/DestinationServiceTest.java @@ -467,6 +467,38 @@ void testGettingDestinationProperties() .getConfigurationAsJson("/subaccountDestinations", withoutToken(TECHNICAL_USER_CURRENT_TENANT)); } + @Test + void testGettingDestinationPropertiesProvider() + { + doReturn(responseServiceInstanceDestination) + .when(destinationServiceAdapter) + .getConfigurationAsJson("/instanceDestinations", withoutToken(TECHNICAL_USER_PROVIDER)); + doReturn(responseSubaccountDestination) + .when(destinationServiceAdapter) + .getConfigurationAsJson("/subaccountDestinations", withoutToken(TECHNICAL_USER_PROVIDER)); + + final Collection destinationList = loader.getAllDestinationProperties(ALWAYS_PROVIDER); + assertThat(destinationList) + .extracting(d -> d.get(DestinationProperty.NAME).get()) + .containsExactly("CC8-HTTP-BASIC", "CC8-HTTP-CERT1", "CC8-HTTP-CERT"); + } + + @Test + void testGettingDestinationPropertiesSubscriber() + { + doReturn(responseServiceInstanceDestination) + .when(destinationServiceAdapter) + .getConfigurationAsJson("/instanceDestinations", withoutToken(TECHNICAL_USER_CURRENT_TENANT)); + doReturn(responseSubaccountDestination) + .when(destinationServiceAdapter) + .getConfigurationAsJson("/subaccountDestinations", withoutToken(TECHNICAL_USER_CURRENT_TENANT)); + + final Collection destinationList = loader.getAllDestinationProperties(ONLY_SUBSCRIBER); + assertThat(destinationList) + .extracting(d -> d.get(DestinationProperty.NAME).get()) + .containsExactly("CC8-HTTP-BASIC", "CC8-HTTP-CERT1", "CC8-HTTP-CERT"); + } + @Test // slow test, run manually if needed void destinationServiceTimeOutWhileGettingDestination() @@ -540,8 +572,8 @@ void testDestinationServiceTimeoutDisabled() @SuppressWarnings( "deprecation" ) @Test - @DisplayName( "Test getting Destination Properties for the provider" ) - void testDestinationPropertiesForProvider() + @DisplayName( "Test getting Destinations for the provider" ) + void testGetAllDestinationsForProvider() { doReturn(responseServiceInstanceDestination) .when(destinationServiceAdapter) @@ -567,7 +599,7 @@ void testDestinationPropertiesForProvider() @SuppressWarnings( "deprecation" ) @Test - @DisplayName( "Test getting Destination Properties can enforce a subscriber tenant" ) + @DisplayName( "Test getting Destinations can enforce a subscriber tenant" ) void testGetAllDestinationsOnlySubscriberStrategyReadsSubscriberDestinations() { final DestinationOptions options = @@ -584,6 +616,17 @@ void testGetAllDestinationsOnlySubscriberStrategyReadsSubscriberDestinations() "The current tenant is the provider tenant, which should not be the case with the option OnlySubscriber. Cannot retrieve destination."); } + @Test + @DisplayName( "Test getting Destination Properties can enforce a subscriber tenant" ) + void testGetAllDestinationPropertiesOnlySubscriberStrategyReadsSubscriberDestinations() + { + context.setTenant(providerTenant); + assertThatThrownBy(() -> loader.getAllDestinationProperties(ONLY_SUBSCRIBER)) + .isInstanceOf(DestinationAccessException.class) + .hasMessageContaining( + "The current tenant is the provider tenant, which should not be the case with the option OnlySubscriber. Cannot retrieve destination."); + } + @Test void testDestinationRetrievalProviderOnly() { diff --git a/release_notes.md b/release_notes.md index afb694f87..948a8d2b2 100644 --- a/release_notes.md +++ b/release_notes.md @@ -15,6 +15,10 @@ - Timeouts for OAuth2 token retrievals can now be customized. As part of `ServiceBindingDestinationOptions` the new option `OAuth2Options.TokenRetrievalTimeout` can now be passed to set a custom timeout. Refer to [this documentation](https://sap.github.io/cloud-sdk/docs/java/features/connectivity/service-bindings#about-the-options) for more details. +- In `DestinationService` class allow for optional argument `DestinationServiceRetrievalStrategy` in method `getAllDestinationProperties`. + This additional API allows for ensuring tenant-specific destination lookups. + Available values are: `CURRENT_TENANT` (default), `ALWAYS_PROVIDER` and `ONLY_SUBSCRIBER`. + ### 📈 Improvements