From bfbd700a5a6d8fac3aee96b4cd7f444575d912c3 Mon Sep 17 00:00:00 2001 From: Joris Baum Date: Tue, 17 Feb 2026 17:51:51 +0100 Subject: [PATCH 01/11] Support skipping CF API V2 tests TODO: I am unsure about this one. Needs more exploration # Conflicts: # README.md # integration-test/src/test/java/org/cloudfoundry/operations/StacksTest.java --- README.md | 1 + .../org/cloudfoundry/CloudFoundryCleaner.java | 98 ++++++++++++++----- .../IntegrationTestConfiguration.java | 8 ++ .../java/org/cloudfoundry/RequiresV2Api.java | 72 ++++++++++++++ .../client/v2/ApplicationsTest.java | 2 + .../client/v2/BlobstoresTest.java | 2 + .../client/v2/BuildpacksTest.java | 2 + .../cloudfoundry/client/v2/DomainsTest.java | 2 + .../cloudfoundry/client/v2/EventsTest.java | 2 + .../client/v2/FeatureFlagsTest.java | 2 + .../org/cloudfoundry/client/v2/InfoTest.java | 2 + .../org/cloudfoundry/client/v2/JobsTest.java | 2 + .../v2/OrganizationQuotaDefinitionsTest.java | 2 + .../client/v2/OrganizationsTest.java | 6 +- .../client/v2/PrivateDomainsTest.java | 2 + .../client/v2/RouteMappingsTest.java | 2 + .../cloudfoundry/client/v2/RoutesTest.java | 2 + .../client/v2/SecurityGroupsTest.java | 2 + .../client/v2/ServiceBindingsTest.java | 2 + .../client/v2/ServiceBrokersTest.java | 6 +- .../client/v2/ServiceInstancesTest.java | 6 +- .../client/v2/ServiceKeysTest.java | 6 +- .../v2/ServicePlanVisibilitiesTest.java | 2 + .../client/v2/ServicePlansTest.java | 6 +- .../client/v2/ServiceUsageEventsTest.java | 6 +- .../cloudfoundry/client/v2/ServicesTest.java | 6 +- .../client/v2/SharedDomainsTest.java | 2 + .../client/v2/SpaceQuotaDefinitionsTest.java | 2 + .../cloudfoundry/client/v2/SpacesTest.java | 6 +- .../cloudfoundry/client/v2/StacksTest.java | 2 + .../client/v2/UserProvidedServicesTest.java | 2 + .../org/cloudfoundry/client/v2/UsersTest.java | 2 + .../org/cloudfoundry/client/v3/AdminTest.java | 3 + .../client/v3/DeploymentsTest.java | 2 + .../client/v3/IsolationSegmentsTest.java | 2 + .../client/v3/OrganizationsTest.java | 2 + .../cloudfoundry/client/v3/ProcessesTest.java | 2 + .../client/v3/ServiceBindingsTest.java | 6 +- .../client/v3/ServiceBrokersTest.java | 6 +- .../client/v3/ServiceInstancesTest.java | 6 +- .../client/v3/ServiceOfferingsTest.java | 6 +- .../client/v3/ServicePlansTest.java | 6 +- .../org/cloudfoundry/client/v3/TasksTest.java | 2 + .../cloudfoundry/operations/AdvancedTest.java | 2 + .../operations/ApplicationsTest.java | 2 + .../operations/BuildpacksTest.java | 2 + .../cloudfoundry/operations/DomainsTest.java | 2 + .../operations/NetworkPoliciesTest.java | 2 + .../operations/OrganizationAdminTest.java | 2 + .../operations/OrganizationsTest.java | 2 + .../cloudfoundry/operations/RoutesTest.java | 2 + .../operations/ServiceAdminTest.java | 2 + .../cloudfoundry/operations/ServicesTest.java | 6 +- .../cloudfoundry/operations/SpacesTest.java | 2 + .../cloudfoundry/operations/StacksTest.java | 0 .../operations/UserAdminTest.java | 2 + 56 files changed, 297 insertions(+), 41 deletions(-) create mode 100644 integration-test/src/test/java/org/cloudfoundry/RequiresV2Api.java create mode 100644 integration-test/src/test/java/org/cloudfoundry/operations/StacksTest.java diff --git a/README.md b/README.md index 715033c14e6..5b4b1fad713 100644 --- a/README.md +++ b/README.md @@ -353,6 +353,7 @@ Name | Description `TEST_PROXY_PORT` | _(Optional)_ The port of a proxy to route all requests through. Defaults to `8080`. `TEST_PROXY_USERNAME` | _(Optional)_ The username for a proxy to route all requests through `TEST_SKIPSSLVALIDATION` | _(Optional)_ Whether to skip SSL validation when connecting to the Cloud Foundry instance. Defaults to `false`. +`SKIP_V2_TESTS` | _(Optional)_ Set to `true` to skip all V2 API integration tests. Useful when the Cloud Foundry V2 API is rate-limited or unavailable. When enabled, tests annotated with `@RequiresV2Api` will be skipped, including V3 tests that depend on V2 API calls (e.g., service broker creation). Defaults to `false`. If you do not have access to a CloudFoundry instance with admin access, you can run one locally using [bosh-deployment](https://github.com/cloudfoundry/bosh-deployment) & [cf-deployment](https://github.com/cloudfoundry/cf-deployment/) and Virtualbox. diff --git a/integration-test/src/test/java/org/cloudfoundry/CloudFoundryCleaner.java b/integration-test/src/test/java/org/cloudfoundry/CloudFoundryCleaner.java index d515a86b092..2985a04cde6 100644 --- a/integration-test/src/test/java/org/cloudfoundry/CloudFoundryCleaner.java +++ b/integration-test/src/test/java/org/cloudfoundry/CloudFoundryCleaner.java @@ -77,6 +77,7 @@ import org.cloudfoundry.client.v3.Metadata; import org.cloudfoundry.client.v3.Relationship; import org.cloudfoundry.client.v3.applications.Application; +import org.cloudfoundry.client.v3.applications.ApplicationResource; import org.cloudfoundry.client.v3.applications.DeleteApplicationRequest; import org.cloudfoundry.client.v3.applications.ListApplicationsRequest; import org.cloudfoundry.client.v3.serviceinstances.ListSharedSpacesRelationshipRequest; @@ -129,6 +130,12 @@ final class CloudFoundryCleaner implements InitializingBean, DisposableBean { private static final Logger LOGGER = LoggerFactory.getLogger("cloudfoundry-client.test"); + private static final boolean RUN_V2_CLEANUP = isRunV2Tests(); + + private static boolean isRunV2Tests() { + return !"true".equalsIgnoreCase(System.getenv("SKIP_V2_TESTS")); + } + private static final Map STANDARD_FEATURE_FLAGS = FluentMap.builder() .entry("app_bits_upload", true) @@ -186,6 +193,31 @@ public void destroy() { } void clean() { + if (!RUN_V2_CLEANUP) { + LOGGER.info("Skipping V2 API cleanup operations (SKIP_V2_TESTS=true)"); + // Only run V3 and UAA cleanup operations + Flux.empty() + .thenMany( + Mono.when( // No prerequisites - V3/UAA only + cleanClients(this.uaaClient, this.nameFactory), + cleanGroups(this.uaaClient, this.nameFactory), + cleanIdentityProviders(this.uaaClient, this.nameFactory), + cleanIdentityZones(this.uaaClient, this.nameFactory))) + .thenMany( + Mono.when( + cleanApplicationsV3( + this.cloudFoundryClient, + this.nameFactory, + false), // runV2Calls = false (V3-only path) + cleanUsers(this.uaaClient, this.nameFactory))) + .retryWhen(Retry.max(5).filter(SSLException.class::isInstance)) + .doOnSubscribe(s -> LOGGER.debug(">> CLEANUP (V3 only) <<")) + .doOnComplete(() -> LOGGER.debug("<< CLEANUP (V3 only) >>")) + .then() + .block(Duration.ofMinutes(30)); + return; + } + Flux.empty() .thenMany( Mono.when( // Before Routes @@ -218,7 +250,8 @@ void clean() { Mono.when( cleanApplicationsV3( this.cloudFoundryClient, - this.nameFactory), // After Routes, cannot run with + this.nameFactory, + true), // After Routes, cannot run with // other cleanApps cleanUsers(this.uaaClient, this.nameFactory) // After CF Users )) @@ -241,32 +274,43 @@ void clean() { } private static Flux cleanApplicationsV3( - CloudFoundryClient cloudFoundryClient, NameFactory nameFactory) { - return PaginationUtils.requestClientV3Resources( - page -> - cloudFoundryClient - .applicationsV3() - .list(ListApplicationsRequest.builder().page(page).build())) - .filter(application -> nameFactory.isApplicationName(application.getName())) - .delayUntil( - application -> - removeApplicationServiceBindings(cloudFoundryClient, application)) - .flatMap( - application -> - cloudFoundryClient - .applicationsV3() - .delete( - DeleteApplicationRequest.builder() - .applicationId(application.getId()) - .build()) - .then() - .doOnError( - t -> - LOGGER.error( - "Unable to delete V3 application" - + " {}", - application.getName(), - t))); + CloudFoundryClient cloudFoundryClient, NameFactory nameFactory, boolean runV2Calls) { + Flux apps = + PaginationUtils.requestClientV3Resources( + page -> + cloudFoundryClient + .applicationsV3() + .list( + ListApplicationsRequest.builder() + .page(page) + .build())) + .filter( + application -> + nameFactory.isApplicationName(application.getName())); + + if (runV2Calls) { + apps = + apps.delayUntil( + application -> + removeApplicationServiceBindings( + cloudFoundryClient, application)); + } + + return apps.flatMap( + application -> + cloudFoundryClient + .applicationsV3() + .delete( + DeleteApplicationRequest.builder() + .applicationId(application.getId()) + .build()) + .then() + .doOnError( + t -> + LOGGER.error( + "Unable to delete V3 application" + " {}", + application.getName(), + t))); } private static Flux cleanBuildpacks( diff --git a/integration-test/src/test/java/org/cloudfoundry/IntegrationTestConfiguration.java b/integration-test/src/test/java/org/cloudfoundry/IntegrationTestConfiguration.java index da390ac2040..8a6a1ad4b62 100644 --- a/integration-test/src/test/java/org/cloudfoundry/IntegrationTestConfiguration.java +++ b/integration-test/src/test/java/org/cloudfoundry/IntegrationTestConfiguration.java @@ -86,6 +86,7 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; @@ -346,6 +347,7 @@ RandomNameFactory nameFactory() { @Bean(initMethod = "block") @DependsOn("cloudFoundryCleaner") + @ConditionalOnProperty(name = "SKIP_V2_TESTS", havingValue = "false", matchIfMissing = true) Mono metricRegistrarServiceInstance( CloudFoundryClient cloudFoundryClient, Mono spaceId, NameFactory nameFactory) { return spaceId.flatMap( @@ -373,6 +375,7 @@ NetworkingClient networkingClient( @Bean(initMethod = "block") @DependsOn("cloudFoundryCleaner") + @ConditionalOnProperty(name = "SKIP_V2_TESTS", havingValue = "false", matchIfMissing = true) Mono organizationId( CloudFoundryClient cloudFoundryClient, String organizationName, @@ -512,6 +515,7 @@ String serviceName(NameFactory nameFactory) { @Bean(initMethod = "block") @DependsOn("cloudFoundryCleaner") + @ConditionalOnProperty(name = "SKIP_V2_TESTS", havingValue = "false", matchIfMissing = true) Mono spaceId( CloudFoundryClient cloudFoundryClient, Mono organizationId, String spaceName) { return organizationId @@ -538,6 +542,7 @@ String spaceName(NameFactory nameFactory) { @Bean(initMethod = "block") @DependsOn("cloudFoundryCleaner") + @ConditionalOnProperty(name = "SKIP_V2_TESTS", havingValue = "false", matchIfMissing = true) Mono stackId(CloudFoundryClient cloudFoundryClient, Mono stackName) { return stackName .flux() @@ -566,6 +571,7 @@ Mono stackId(CloudFoundryClient cloudFoundryClient, Mono stackNa */ @Bean(initMethod = "block") @DependsOn("cloudFoundryCleaner") + @ConditionalOnProperty(name = "SKIP_V2_TESTS", havingValue = "false", matchIfMissing = true) Mono stackName(CloudFoundryClient cloudFoundryClient) { return PaginationUtils.requestClientV2Resources( page -> @@ -583,6 +589,7 @@ Mono stackName(CloudFoundryClient cloudFoundryClient) { @Lazy @Bean(initMethod = "block") @DependsOn("cloudFoundryCleaner") + @ConditionalOnProperty(name = "SKIP_V2_TESTS", havingValue = "false", matchIfMissing = true) Mono testLogCacheApp( CloudFoundryClient cloudFoundryClient, Mono spaceId, @@ -619,6 +626,7 @@ String testLogCacheAppName(NameFactory nameFactory) { @Lazy @Bean + @ConditionalOnProperty(name = "SKIP_V2_TESTS", havingValue = "false", matchIfMissing = true) TestLogCacheEndpoints testLogCacheEndpoints( ConnectionContext connectionContext, TokenProvider tokenProvider, diff --git a/integration-test/src/test/java/org/cloudfoundry/RequiresV2Api.java b/integration-test/src/test/java/org/cloudfoundry/RequiresV2Api.java new file mode 100644 index 00000000000..acde38fb6bd --- /dev/null +++ b/integration-test/src/test/java/org/cloudfoundry/RequiresV2Api.java @@ -0,0 +1,72 @@ +/* + * Copyright 2026 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.cloudfoundry; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.junit.jupiter.api.extension.ConditionEvaluationResult; +import org.junit.jupiter.api.extension.ExecutionCondition; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.ExtensionContext; + +/** + * Annotation to mark tests that require the V2 API. Tests annotated with this + * will be skipped if the environment variable {@code SKIP_V2_TESTS} is set to "true". + * + *

Usage: + *

+ * @RequiresV2Api
+ * public class MyV2Test extends AbstractIntegrationTest {
+ *     // ...
+ * }
+ * 
+ * + *

To skip V2 tests, set the environment variable: + *

+ * export SKIP_V2_TESTS=true
+ * 
+ */ +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@ExtendWith(RequiresV2Api.V2ApiCondition.class) +public @interface RequiresV2Api { + + /** + * JUnit 5 ExecutionCondition that checks if V2 tests should be skipped. + */ + class V2ApiCondition implements ExecutionCondition { + + private static final String SKIP_V2_TESTS_ENV = "SKIP_V2_TESTS"; + + @Override + public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { + if ("true".equalsIgnoreCase(System.getenv(SKIP_V2_TESTS_ENV))) { + return ConditionEvaluationResult.disabled( + "V2 API tests are disabled via " + + SKIP_V2_TESTS_ENV + + " environment variable"); + } + return ConditionEvaluationResult.enabled("V2 API tests are enabled"); + } + } +} diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/ApplicationsTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/ApplicationsTest.java index 9774568bd02..df19fe4c8a4 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/ApplicationsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/ApplicationsTest.java @@ -39,6 +39,7 @@ import org.cloudfoundry.CleanupCloudFoundryAfterClass; import org.cloudfoundry.CloudFoundryVersion; import org.cloudfoundry.IfCloudFoundryVersion; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.applications.AbstractApplicationResource; import org.cloudfoundry.client.v2.applications.ApplicationEnvironmentRequest; @@ -98,6 +99,7 @@ import reactor.util.function.Tuple2; @CleanupCloudFoundryAfterClass +@RequiresV2Api public final class ApplicationsTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/BlobstoresTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/BlobstoresTest.java index f9368a07307..223f55eb4ed 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/BlobstoresTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/BlobstoresTest.java @@ -19,6 +19,7 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; import org.cloudfoundry.ApplicationUtils; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.blobstores.DeleteBlobstoreBuildpackCachesRequest; import org.cloudfoundry.util.JobUtils; @@ -27,6 +28,7 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +@RequiresV2Api public final class BlobstoresTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/BuildpacksTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/BuildpacksTest.java index 03b7d3f0e95..00afd83bcb9 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/BuildpacksTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/BuildpacksTest.java @@ -20,6 +20,7 @@ import java.nio.file.Path; import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.buildpacks.BuildpackEntity; import org.cloudfoundry.client.v2.buildpacks.BuildpackResource; @@ -40,6 +41,7 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +@RequiresV2Api public final class BuildpacksTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/DomainsTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/DomainsTest.java index 676d130484f..8d4841222d7 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/DomainsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/DomainsTest.java @@ -23,6 +23,7 @@ import java.time.Duration; import java.util.function.Consumer; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.applications.CreateApplicationRequest; import org.cloudfoundry.client.v2.applications.CreateApplicationResponse; @@ -59,6 +60,7 @@ import reactor.util.function.Tuple2; @SuppressWarnings("deprecation") +@RequiresV2Api public final class DomainsTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/EventsTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/EventsTest.java index 76dcea594d2..d52358d9dbf 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/EventsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/EventsTest.java @@ -18,6 +18,7 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.events.EventResource; import org.cloudfoundry.client.v2.events.GetEventRequest; @@ -29,6 +30,7 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +@RequiresV2Api public final class EventsTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/FeatureFlagsTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/FeatureFlagsTest.java index d47962b5aa9..217bdd155a0 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/FeatureFlagsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/FeatureFlagsTest.java @@ -26,6 +26,7 @@ import java.util.Set; import java.util.stream.Collectors; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.featureflags.FeatureFlagEntity; import org.cloudfoundry.client.v2.featureflags.GetFeatureFlagRequest; @@ -38,6 +39,7 @@ import reactor.test.StepVerifier; import reactor.util.function.Tuples; +@RequiresV2Api public final class FeatureFlagsTest extends AbstractIntegrationTest { private static final List coreFeatureFlagNameList = diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/InfoTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/InfoTest.java index 471cb284e8a..a4395079a54 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/InfoTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/InfoTest.java @@ -22,12 +22,14 @@ import com.github.zafarkhaja.semver.Version; import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.info.GetInfoRequest; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import reactor.test.StepVerifier; +@RequiresV2Api public final class InfoTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/JobsTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/JobsTest.java index 0727b062d2e..950ae4e35ad 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/JobsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/JobsTest.java @@ -20,6 +20,7 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.jobs.GetJobRequest; import org.cloudfoundry.client.v2.organizations.CreateOrganizationRequest; @@ -31,6 +32,7 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +@RequiresV2Api public final class JobsTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/OrganizationQuotaDefinitionsTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/OrganizationQuotaDefinitionsTest.java index 8a435cfa81b..b99f91e3076 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/OrganizationQuotaDefinitionsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/OrganizationQuotaDefinitionsTest.java @@ -20,6 +20,7 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.organizationquotadefinitions.CreateOrganizationQuotaDefinitionRequest; import org.cloudfoundry.client.v2.organizationquotadefinitions.CreateOrganizationQuotaDefinitionResponse; @@ -37,6 +38,7 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +@RequiresV2Api public final class OrganizationQuotaDefinitionsTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/OrganizationsTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/OrganizationsTest.java index e1d1762e649..1b31140d922 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/OrganizationsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/OrganizationsTest.java @@ -22,6 +22,7 @@ import java.time.Duration; import java.util.function.UnaryOperator; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.applications.CreateApplicationRequest; import org.cloudfoundry.client.v2.applications.CreateApplicationResponse; @@ -98,13 +99,16 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +@RequiresV2Api public final class OrganizationsTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; @Autowired private Mono organizationId; - @Autowired private Mono serviceBrokerId; + // Optional: bean requires V2 API; class is guarded by @RequiresV2Api + @Autowired(required = false) + private Mono serviceBrokerId; @Autowired private String serviceName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/PrivateDomainsTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/PrivateDomainsTest.java index 587cfa35aea..4dde9496a38 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/PrivateDomainsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/PrivateDomainsTest.java @@ -23,6 +23,7 @@ import java.time.Duration; import java.util.function.Consumer; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.organizations.AssociateOrganizationAuditorRequest; import org.cloudfoundry.client.v2.organizations.AssociateOrganizationAuditorResponse; @@ -57,6 +58,7 @@ import reactor.test.StepVerifier; import reactor.util.function.Tuple2; +@RequiresV2Api public final class PrivateDomainsTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/RouteMappingsTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/RouteMappingsTest.java index 1056e983040..9b31ddf78a8 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/RouteMappingsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/RouteMappingsTest.java @@ -22,6 +22,7 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.applications.CreateApplicationRequest; import org.cloudfoundry.client.v2.applications.CreateApplicationResponse; @@ -43,6 +44,7 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +@RequiresV2Api public final class RouteMappingsTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/RoutesTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/RoutesTest.java index 3ee56508931..cb974f35e6b 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/RoutesTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/RoutesTest.java @@ -23,6 +23,7 @@ import java.time.Duration; import java.util.function.Consumer; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.applications.CreateApplicationRequest; import org.cloudfoundry.client.v2.applications.CreateApplicationResponse; @@ -53,6 +54,7 @@ import reactor.test.StepVerifier; import reactor.util.function.Tuple3; +@RequiresV2Api public final class RoutesTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/SecurityGroupsTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/SecurityGroupsTest.java index 64ee5df01a8..ba249ceff2c 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/SecurityGroupsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/SecurityGroupsTest.java @@ -21,6 +21,7 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.securitygroups.AssociateSecurityGroupSpaceRequest; import org.cloudfoundry.client.v2.securitygroups.AssociateSecurityGroupSpaceResponse; @@ -55,6 +56,7 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +@RequiresV2Api public final class SecurityGroupsTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceBindingsTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceBindingsTest.java index 668976376d4..f596238704f 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceBindingsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceBindingsTest.java @@ -24,6 +24,7 @@ import java.util.Optional; import java.util.function.Consumer; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.applications.CreateApplicationRequest; import org.cloudfoundry.client.v2.applications.CreateApplicationResponse; @@ -49,6 +50,7 @@ import reactor.util.function.Tuple2; import reactor.util.function.Tuple3; +@RequiresV2Api public final class ServiceBindingsTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceBrokersTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceBrokersTest.java index 214577e4a90..50be1ea1b52 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceBrokersTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceBrokersTest.java @@ -26,6 +26,7 @@ import org.cloudfoundry.AbstractIntegrationTest; import org.cloudfoundry.ApplicationUtils; import org.cloudfoundry.CleanupCloudFoundryAfterClass; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.ServiceBrokerUtils; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.servicebrokers.CreateServiceBrokerRequest; @@ -45,13 +46,16 @@ import reactor.test.StepVerifier; @CleanupCloudFoundryAfterClass +@RequiresV2Api public final class ServiceBrokersTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; @Autowired private Mono organizationId; - @Autowired private Mono serviceBrokerId; + // Optional: bean requires V2 API; class is guarded by @RequiresV2Api + @Autowired(required = false) + private Mono serviceBrokerId; @Autowired private String serviceBrokerName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceInstancesTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceInstancesTest.java index ed152f87a39..cad61ddbd58 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceInstancesTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceInstancesTest.java @@ -24,6 +24,7 @@ import org.cloudfoundry.AbstractIntegrationTest; import org.cloudfoundry.CloudFoundryVersion; import org.cloudfoundry.IfCloudFoundryVersion; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.applications.CreateApplicationRequest; import org.cloudfoundry.client.v2.applications.CreateApplicationResponse; @@ -65,6 +66,7 @@ import reactor.test.StepVerifier; import reactor.util.function.Tuples; +@RequiresV2Api public final class ServiceInstancesTest extends AbstractIntegrationTest { private static final String DEFAULT_ROUTER_GROUP = "default-tcp"; @@ -75,7 +77,9 @@ public final class ServiceInstancesTest extends AbstractIntegrationTest { @Autowired private RoutingClient routingClient; - @Autowired private Mono serviceBrokerId; + // Optional: bean requires V2 API; class is guarded by @RequiresV2Api + @Autowired(required = false) + private Mono serviceBrokerId; @Autowired private String serviceName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceKeysTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceKeysTest.java index 58067e0d31f..485e9ba5719 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceKeysTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceKeysTest.java @@ -20,6 +20,7 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.serviceinstances.CreateServiceInstanceRequest; import org.cloudfoundry.client.v2.serviceinstances.CreateServiceInstanceResponse; @@ -42,11 +43,14 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +@RequiresV2Api public final class ServiceKeysTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; - @Autowired private Mono serviceBrokerId; + // Optional: bean requires V2 API; class is guarded by @RequiresV2Api + @Autowired(required = false) + private Mono serviceBrokerId; @Autowired private String serviceName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServicePlanVisibilitiesTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServicePlanVisibilitiesTest.java index 910294d42ac..e2a9ecbece2 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServicePlanVisibilitiesTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServicePlanVisibilitiesTest.java @@ -22,6 +22,7 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.ServiceBrokerUtils; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.organizations.CreateOrganizationRequest; @@ -47,6 +48,7 @@ import reactor.test.StepVerifier; import reactor.util.function.Tuples; +@RequiresV2Api public final class ServicePlanVisibilitiesTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServicePlansTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServicePlansTest.java index c8f4db7e148..e9fc66b8e8e 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServicePlansTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServicePlansTest.java @@ -22,6 +22,7 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.ServiceBrokerUtils; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.applications.CreateApplicationRequest; @@ -53,6 +54,7 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +@RequiresV2Api public final class ServicePlansTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; @@ -61,7 +63,9 @@ public final class ServicePlansTest extends AbstractIntegrationTest { @Autowired private String planName; - @Autowired private Mono serviceBrokerId; + // Optional: bean requires V2 API; class is guarded by @RequiresV2Api + @Autowired(required = false) + private Mono serviceBrokerId; @Autowired private String serviceName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceUsageEventsTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceUsageEventsTest.java index 987de74b28b..32703e319e4 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceUsageEventsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceUsageEventsTest.java @@ -21,6 +21,7 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; import org.cloudfoundry.NameFactory; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.serviceinstances.CreateServiceInstanceRequest; import org.cloudfoundry.client.v2.serviceinstances.CreateServiceInstanceResponse; @@ -40,11 +41,14 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +@RequiresV2Api public final class ServiceUsageEventsTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; - @Autowired private Mono serviceBrokerId; + // Optional: bean requires V2 API; class is guarded by @RequiresV2Api + @Autowired(required = false) + private Mono serviceBrokerId; @Autowired private String serviceName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServicesTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServicesTest.java index 9af396d3159..1469bfdd361 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServicesTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServicesTest.java @@ -22,6 +22,7 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.ServiceBrokerUtils; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.serviceinstances.CreateServiceInstanceRequest; @@ -46,6 +47,7 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +@RequiresV2Api public final class ServicesTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; @@ -54,7 +56,9 @@ public final class ServicesTest extends AbstractIntegrationTest { @Autowired private String planName; - @Autowired private Mono serviceBrokerId; + // Optional: bean requires V2 API; class is guarded by @RequiresV2Api + @Autowired(required = false) + private Mono serviceBrokerId; @Autowired private String serviceName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/SharedDomainsTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/SharedDomainsTest.java index 063992a6574..bf606542523 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/SharedDomainsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/SharedDomainsTest.java @@ -19,6 +19,7 @@ import java.time.Duration; import java.util.Optional; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.shareddomains.CreateSharedDomainRequest; import org.cloudfoundry.client.v2.shareddomains.CreateSharedDomainResponse; @@ -37,6 +38,7 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +@RequiresV2Api public final class SharedDomainsTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/SpaceQuotaDefinitionsTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/SpaceQuotaDefinitionsTest.java index 47c9ae0f5f3..ebe8ca1b618 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/SpaceQuotaDefinitionsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/SpaceQuotaDefinitionsTest.java @@ -20,6 +20,7 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.applications.CreateApplicationRequest; import org.cloudfoundry.client.v2.applications.CreateApplicationResponse; @@ -48,6 +49,7 @@ import reactor.test.StepVerifier; import reactor.util.function.Tuples; +@RequiresV2Api public final class SpaceQuotaDefinitionsTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/SpacesTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/SpacesTest.java index 4193ec53d6e..eae93b616bb 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/SpacesTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/SpacesTest.java @@ -27,6 +27,7 @@ import java.util.function.Function; import java.util.function.UnaryOperator; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.applications.ApplicationResource; import org.cloudfoundry.client.v2.applications.CreateApplicationRequest; @@ -116,13 +117,16 @@ import reactor.test.StepVerifier; import reactor.util.function.Tuple2; +@RequiresV2Api public final class SpacesTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; @Autowired private Mono organizationId; - @Autowired private Mono serviceBrokerId; + // Optional: bean requires V2 API; class is guarded by @RequiresV2Api + @Autowired(required = false) + private Mono serviceBrokerId; @Autowired private String serviceName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/StacksTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/StacksTest.java index cbd3ac2d296..3360a86a3f5 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/StacksTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/StacksTest.java @@ -20,6 +20,7 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.stacks.CreateStackRequest; import org.cloudfoundry.client.v2.stacks.CreateStackResponse; @@ -38,6 +39,7 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +@RequiresV2Api public final class StacksTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/UserProvidedServicesTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/UserProvidedServicesTest.java index 555741d6340..a850b861418 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/UserProvidedServicesTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/UserProvidedServicesTest.java @@ -24,6 +24,7 @@ import java.util.Collections; import java.util.function.Consumer; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.applications.CreateApplicationRequest; import org.cloudfoundry.client.v2.applications.CreateApplicationResponse; @@ -56,6 +57,7 @@ import reactor.util.function.Tuple3; import reactor.util.function.Tuples; +@RequiresV2Api public final class UserProvidedServicesTest extends AbstractIntegrationTest { private static final String DEFAULT_ROUTER_GROUP = "default-tcp"; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/UsersTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/UsersTest.java index 27f1232c3d0..08efb1965e8 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/UsersTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/UsersTest.java @@ -20,6 +20,7 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.applications.CreateApplicationRequest; import org.cloudfoundry.client.v2.applications.CreateApplicationResponse; @@ -80,6 +81,7 @@ import reactor.test.StepVerifier; import reactor.util.function.Tuples; +@RequiresV2Api public final class UsersTest extends AbstractIntegrationTest { private static final String STATUS_FILTER = "active"; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v3/AdminTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v3/AdminTest.java index d185f15deac..bdbc6778c87 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v3/AdminTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v3/AdminTest.java @@ -21,6 +21,7 @@ import org.cloudfoundry.ApplicationUtils; import org.cloudfoundry.CloudFoundryVersion; import org.cloudfoundry.IfCloudFoundryVersion; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v3.admin.ClearBuildpackCacheRequest; import org.cloudfoundry.util.JobUtils; @@ -29,6 +30,8 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +@RequiresV2Api +// TODO Does it really require V2? public final class AdminTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v3/DeploymentsTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v3/DeploymentsTest.java index d823ad7b1c1..bcec4978420 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v3/DeploymentsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v3/DeploymentsTest.java @@ -25,6 +25,7 @@ import org.cloudfoundry.CleanupCloudFoundryAfterClass; import org.cloudfoundry.CloudFoundryVersion; import org.cloudfoundry.IfCloudFoundryVersion; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v3.applications.GetApplicationCurrentDropletRequest; import org.cloudfoundry.client.v3.applications.GetApplicationCurrentDropletResponse; @@ -52,6 +53,7 @@ import reactor.test.StepVerifier; @IfCloudFoundryVersion(greaterThanOrEqualTo = CloudFoundryVersion.PCF_2_4) +@RequiresV2Api // Due to ApplicationUtils @CleanupCloudFoundryAfterClass public final class DeploymentsTest extends AbstractIntegrationTest { diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v3/IsolationSegmentsTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v3/IsolationSegmentsTest.java index 0f0a56fc1cd..580fb302146 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v3/IsolationSegmentsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v3/IsolationSegmentsTest.java @@ -22,6 +22,7 @@ import org.cloudfoundry.AbstractIntegrationTest; import org.cloudfoundry.CloudFoundryVersion; import org.cloudfoundry.IfCloudFoundryVersion; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.organizations.CreateOrganizationRequest; import org.cloudfoundry.client.v2.organizations.CreateOrganizationResponse; @@ -53,6 +54,7 @@ import reactor.test.StepVerifier; @IfCloudFoundryVersion(greaterThanOrEqualTo = CloudFoundryVersion.PCF_1_11) +@RequiresV2Api public final class IsolationSegmentsTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v3/OrganizationsTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v3/OrganizationsTest.java index a1fbd52f3df..e3da7d85e66 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v3/OrganizationsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v3/OrganizationsTest.java @@ -24,6 +24,7 @@ import org.cloudfoundry.ApplicationUtils; import org.cloudfoundry.CloudFoundryVersion; import org.cloudfoundry.IfCloudFoundryVersion; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v3.domains.CreateDomainRequest; import org.cloudfoundry.client.v3.domains.CreateDomainResponse; @@ -57,6 +58,7 @@ import reactor.test.StepVerifier; @IfCloudFoundryVersion(greaterThanOrEqualTo = CloudFoundryVersion.PCF_1_12) +@RequiresV2Api public final class OrganizationsTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v3/ProcessesTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v3/ProcessesTest.java index e4a4184e85a..8e3cbba3cba 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v3/ProcessesTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v3/ProcessesTest.java @@ -25,6 +25,7 @@ import org.cloudfoundry.CleanupCloudFoundryAfterClass; import org.cloudfoundry.CloudFoundryVersion; import org.cloudfoundry.IfCloudFoundryVersion; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v3.applications.GetApplicationProcessRequest; import org.cloudfoundry.client.v3.applications.GetApplicationProcessResponse; @@ -43,6 +44,7 @@ import reactor.test.StepVerifier; @IfCloudFoundryVersion(greaterThanOrEqualTo = CloudFoundryVersion.PCF_2_0) +@RequiresV2Api // Due to ApplicationUtils @CleanupCloudFoundryAfterClass public final class ProcessesTest extends AbstractIntegrationTest { diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceBindingsTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceBindingsTest.java index 81477aef522..acdb96f1e94 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceBindingsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceBindingsTest.java @@ -25,6 +25,7 @@ import org.cloudfoundry.AbstractIntegrationTest; import org.cloudfoundry.CloudFoundryVersion; import org.cloudfoundry.IfCloudFoundryVersion; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v3.servicebindings.CreateServiceBindingRequest; import org.cloudfoundry.client.v3.servicebindings.DeleteServiceBindingRequest; @@ -54,11 +55,14 @@ import reactor.test.StepVerifier; @IfCloudFoundryVersion(greaterThanOrEqualTo = CloudFoundryVersion.PCF_2_11) +@RequiresV2Api public class ServiceBindingsTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; - @Autowired private Mono serviceBrokerId; + // Optional: bean requires V2 API; class is guarded by @RequiresV2Api + @Autowired(required = false) + private Mono serviceBrokerId; @Autowired private String serviceName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceBrokersTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceBrokersTest.java index 656a0b0efe6..07e0b219cfc 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceBrokersTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceBrokersTest.java @@ -28,6 +28,7 @@ import org.cloudfoundry.CleanupCloudFoundryAfterClass; import org.cloudfoundry.CloudFoundryVersion; import org.cloudfoundry.IfCloudFoundryVersion; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.ServiceBrokerUtils; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v3.servicebrokers.BasicAuthentication; @@ -50,6 +51,7 @@ import reactor.test.StepVerifier; @IfCloudFoundryVersion(greaterThanOrEqualTo = CloudFoundryVersion.PCF_2_10) +@RequiresV2Api @CleanupCloudFoundryAfterClass public final class ServiceBrokersTest extends AbstractIntegrationTest { @@ -57,7 +59,9 @@ public final class ServiceBrokersTest extends AbstractIntegrationTest { @Autowired private Mono organizationId; - @Autowired private Mono serviceBrokerId; + // Optional: bean requires V2 API; class is guarded by @RequiresV2Api + @Autowired(required = false) + private Mono serviceBrokerId; @Autowired private String serviceBrokerName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceInstancesTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceInstancesTest.java index 507b288a653..941c0e56169 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceInstancesTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceInstancesTest.java @@ -25,6 +25,7 @@ import org.cloudfoundry.AbstractIntegrationTest; import org.cloudfoundry.CloudFoundryVersion; import org.cloudfoundry.IfCloudFoundryVersion; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v3.serviceinstances.CreateServiceInstanceRequest; import org.cloudfoundry.client.v3.serviceinstances.CreateServiceInstanceResponse; @@ -57,13 +58,16 @@ import reactor.test.StepVerifier; @IfCloudFoundryVersion(greaterThanOrEqualTo = CloudFoundryVersion.PCF_2_1) +@RequiresV2Api public final class ServiceInstancesTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; @Autowired private Mono organizationId; - @Autowired private Mono serviceBrokerId; + // Optional: bean requires V2 API; class is guarded by @RequiresV2Api + @Autowired(required = false) + private Mono serviceBrokerId; @Autowired private String serviceName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceOfferingsTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceOfferingsTest.java index f0b67a37b46..20334935909 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceOfferingsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceOfferingsTest.java @@ -24,6 +24,7 @@ import org.cloudfoundry.AbstractIntegrationTest; import org.cloudfoundry.CloudFoundryVersion; import org.cloudfoundry.IfCloudFoundryVersion; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.ServiceBrokerUtils; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v3.serviceofferings.DeleteServiceOfferingRequest; @@ -43,13 +44,16 @@ import reactor.test.StepVerifier; @IfCloudFoundryVersion(greaterThanOrEqualTo = CloudFoundryVersion.PCF_2_10) +@RequiresV2Api public final class ServiceOfferingsTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; @Autowired private Mono organizationId; - @Autowired private Mono serviceBrokerId; + // Optional: bean requires V2 API; class is guarded by @RequiresV2Api + @Autowired(required = false) + private Mono serviceBrokerId; @Autowired private String serviceName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v3/ServicePlansTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v3/ServicePlansTest.java index 5e37753b66b..7f5f0383945 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v3/ServicePlansTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v3/ServicePlansTest.java @@ -24,6 +24,7 @@ import org.cloudfoundry.AbstractIntegrationTest; import org.cloudfoundry.CloudFoundryVersion; import org.cloudfoundry.IfCloudFoundryVersion; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.ServiceBrokerUtils; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v3.serviceplans.DeleteServicePlanRequest; @@ -45,6 +46,7 @@ import reactor.test.StepVerifier; @IfCloudFoundryVersion(greaterThanOrEqualTo = CloudFoundryVersion.PCF_2_10) +@RequiresV2Api public final class ServicePlansTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; @@ -53,7 +55,9 @@ public final class ServicePlansTest extends AbstractIntegrationTest { @Autowired private String planName; - @Autowired private Mono serviceBrokerId; + // Optional: bean requires V2 API; class is guarded by @RequiresV2Api + @Autowired(required = false) + private Mono serviceBrokerId; @Test public void delete() { diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v3/TasksTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v3/TasksTest.java index 0e3fdada8ce..ec5970a08bb 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v3/TasksTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v3/TasksTest.java @@ -25,6 +25,7 @@ import org.cloudfoundry.CleanupCloudFoundryAfterClass; import org.cloudfoundry.CloudFoundryVersion; import org.cloudfoundry.IfCloudFoundryVersion; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v3.applications.ApplicationResource; import org.cloudfoundry.client.v3.applications.GetApplicationCurrentDropletRequest; @@ -52,6 +53,7 @@ @IfCloudFoundryVersion(greaterThanOrEqualTo = CloudFoundryVersion.PCF_1_12) @CleanupCloudFoundryAfterClass +@RequiresV2Api // Due to ApplicationUtils public final class TasksTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; diff --git a/integration-test/src/test/java/org/cloudfoundry/operations/AdvancedTest.java b/integration-test/src/test/java/org/cloudfoundry/operations/AdvancedTest.java index 733e95d6bc9..201b9a49883 100644 --- a/integration-test/src/test/java/org/cloudfoundry/operations/AdvancedTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/operations/AdvancedTest.java @@ -20,10 +20,12 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import reactor.test.StepVerifier; +@RequiresV2Api public final class AdvancedTest extends AbstractIntegrationTest { @Autowired private CloudFoundryOperations cloudFoundryOperations; diff --git a/integration-test/src/test/java/org/cloudfoundry/operations/ApplicationsTest.java b/integration-test/src/test/java/org/cloudfoundry/operations/ApplicationsTest.java index 37c701dbbe5..04a2e3c5674 100644 --- a/integration-test/src/test/java/org/cloudfoundry/operations/ApplicationsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/operations/ApplicationsTest.java @@ -29,6 +29,7 @@ import org.cloudfoundry.CleanupCloudFoundryAfterClass; import org.cloudfoundry.CloudFoundryVersion; import org.cloudfoundry.IfCloudFoundryVersion; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.operations.applications.ApplicationDetail; import org.cloudfoundry.operations.applications.ApplicationEnvironments; @@ -88,6 +89,7 @@ import reactor.test.StepVerifier; @CleanupCloudFoundryAfterClass +@RequiresV2Api public final class ApplicationsTest extends AbstractIntegrationTest { private static final String DEFAULT_ROUTER_GROUP = "default-tcp"; diff --git a/integration-test/src/test/java/org/cloudfoundry/operations/BuildpacksTest.java b/integration-test/src/test/java/org/cloudfoundry/operations/BuildpacksTest.java index 08b1dfcc243..fb9026d6fda 100644 --- a/integration-test/src/test/java/org/cloudfoundry/operations/BuildpacksTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/operations/BuildpacksTest.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.operations.buildpacks.Buildpack; import org.cloudfoundry.operations.buildpacks.CreateBuildpackRequest; import org.cloudfoundry.operations.buildpacks.DeleteBuildpackRequest; @@ -31,6 +32,7 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +@RequiresV2Api public final class BuildpacksTest extends AbstractIntegrationTest { @Autowired private CloudFoundryOperations cloudFoundryOperations; 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 f56d7c777b9..87fd783ebf5 100644 --- a/integration-test/src/test/java/org/cloudfoundry/operations/DomainsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/operations/DomainsTest.java @@ -22,6 +22,7 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.ClientV2Exception; import org.cloudfoundry.client.v3.domains.GetDomainRequest; @@ -38,6 +39,7 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +@RequiresV2Api public final class DomainsTest extends AbstractIntegrationTest { private static final String DEFAULT_ROUTER_GROUP = "default-tcp"; diff --git a/integration-test/src/test/java/org/cloudfoundry/operations/NetworkPoliciesTest.java b/integration-test/src/test/java/org/cloudfoundry/operations/NetworkPoliciesTest.java index 1643a3ef4f8..1d32a910a2d 100644 --- a/integration-test/src/test/java/org/cloudfoundry/operations/NetworkPoliciesTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/operations/NetworkPoliciesTest.java @@ -20,6 +20,7 @@ import org.cloudfoundry.AbstractIntegrationTest; import org.cloudfoundry.CloudFoundryVersion; import org.cloudfoundry.IfCloudFoundryVersion; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.applications.CreateApplicationRequest; import org.cloudfoundry.client.v2.applications.CreateApplicationResponse; @@ -34,6 +35,7 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +@RequiresV2Api public final class NetworkPoliciesTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; diff --git a/integration-test/src/test/java/org/cloudfoundry/operations/OrganizationAdminTest.java b/integration-test/src/test/java/org/cloudfoundry/operations/OrganizationAdminTest.java index 35186836804..4a4325d1914 100644 --- a/integration-test/src/test/java/org/cloudfoundry/operations/OrganizationAdminTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/operations/OrganizationAdminTest.java @@ -20,6 +20,7 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.operations.organizationadmin.CreateQuotaRequest; import org.cloudfoundry.operations.organizationadmin.DeleteQuotaRequest; import org.cloudfoundry.operations.organizationadmin.GetQuotaRequest; @@ -33,6 +34,7 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +@RequiresV2Api public final class OrganizationAdminTest extends AbstractIntegrationTest { @Autowired private CloudFoundryOperations cloudFoundryOperations; diff --git a/integration-test/src/test/java/org/cloudfoundry/operations/OrganizationsTest.java b/integration-test/src/test/java/org/cloudfoundry/operations/OrganizationsTest.java index 3e4e2b57a63..ebe3f90ebe9 100644 --- a/integration-test/src/test/java/org/cloudfoundry/operations/OrganizationsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/operations/OrganizationsTest.java @@ -18,12 +18,14 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.operations.organizations.CreateOrganizationRequest; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +@RequiresV2Api public final class OrganizationsTest extends AbstractIntegrationTest { @Autowired private CloudFoundryOperations cloudFoundryOperations; diff --git a/integration-test/src/test/java/org/cloudfoundry/operations/RoutesTest.java b/integration-test/src/test/java/org/cloudfoundry/operations/RoutesTest.java index 19db1a53b1a..47a37e3fb91 100644 --- a/integration-test/src/test/java/org/cloudfoundry/operations/RoutesTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/operations/RoutesTest.java @@ -28,6 +28,7 @@ import java.util.function.Predicate; import org.cloudfoundry.AbstractIntegrationTest; import org.cloudfoundry.CleanupCloudFoundryAfterClass; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.operations.applications.ApplicationHealthCheck; import org.cloudfoundry.operations.applications.PushApplicationRequest; import org.cloudfoundry.operations.domains.CreateDomainRequest; @@ -51,6 +52,7 @@ import reactor.test.StepVerifier; @CleanupCloudFoundryAfterClass +@RequiresV2Api public final class RoutesTest extends AbstractIntegrationTest { private static final String DEFAULT_ROUTER_GROUP = "default-tcp"; diff --git a/integration-test/src/test/java/org/cloudfoundry/operations/ServiceAdminTest.java b/integration-test/src/test/java/org/cloudfoundry/operations/ServiceAdminTest.java index 7a8f1ec3787..ebd89c92e3f 100644 --- a/integration-test/src/test/java/org/cloudfoundry/operations/ServiceAdminTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/operations/ServiceAdminTest.java @@ -22,6 +22,7 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; import org.cloudfoundry.CleanupCloudFoundryAfterClass; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.ServiceBrokerUtils; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.spaces.CreateSpaceRequest; @@ -40,6 +41,7 @@ import reactor.test.StepVerifier; @CleanupCloudFoundryAfterClass +@RequiresV2Api public final class ServiceAdminTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; diff --git a/integration-test/src/test/java/org/cloudfoundry/operations/ServicesTest.java b/integration-test/src/test/java/org/cloudfoundry/operations/ServicesTest.java index 520027128be..32b8cb4e687 100644 --- a/integration-test/src/test/java/org/cloudfoundry/operations/ServicesTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/operations/ServicesTest.java @@ -24,6 +24,7 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; import org.cloudfoundry.CleanupCloudFoundryAfterClass; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.servicebindings.ListServiceBindingsRequest; import org.cloudfoundry.client.v2.servicebindings.ServiceBindingResource; @@ -66,6 +67,7 @@ import reactor.test.StepVerifier; @CleanupCloudFoundryAfterClass +@RequiresV2Api public final class ServicesTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; @@ -76,7 +78,9 @@ public final class ServicesTest extends AbstractIntegrationTest { @Autowired private String planName; - @Autowired private Mono serviceBrokerId; + // Optional: bean requires V2 API; class is guarded by @RequiresV2Api + @Autowired(required = false) + private Mono serviceBrokerId; @Autowired private String serviceName; diff --git a/integration-test/src/test/java/org/cloudfoundry/operations/SpacesTest.java b/integration-test/src/test/java/org/cloudfoundry/operations/SpacesTest.java index fbb8dc765b3..7f862e04784 100644 --- a/integration-test/src/test/java/org/cloudfoundry/operations/SpacesTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/operations/SpacesTest.java @@ -20,6 +20,7 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.operations.spaces.CreateSpaceRequest; import org.cloudfoundry.operations.spaces.GetSpaceRequest; import org.cloudfoundry.operations.spaces.SpaceDetail; @@ -27,6 +28,7 @@ import org.springframework.beans.factory.annotation.Autowired; import reactor.test.StepVerifier; +@RequiresV2Api public final class SpacesTest extends AbstractIntegrationTest { @Autowired private CloudFoundryOperations cloudFoundryOperations; diff --git a/integration-test/src/test/java/org/cloudfoundry/operations/StacksTest.java b/integration-test/src/test/java/org/cloudfoundry/operations/StacksTest.java new file mode 100644 index 00000000000..e69de29bb2d diff --git a/integration-test/src/test/java/org/cloudfoundry/operations/UserAdminTest.java b/integration-test/src/test/java/org/cloudfoundry/operations/UserAdminTest.java index b0c12b8ea3f..af534acda39 100644 --- a/integration-test/src/test/java/org/cloudfoundry/operations/UserAdminTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/operations/UserAdminTest.java @@ -20,6 +20,7 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.client.v2.organizations.ListOrganizationAuditorsRequest; import org.cloudfoundry.client.v2.organizations.ListOrganizationsRequest; @@ -47,6 +48,7 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +@RequiresV2Api public final class UserAdminTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; From b56ad0cf00119cf7f8f03265156df5f313d05173 Mon Sep 17 00:00:00 2001 From: Joris Baum Date: Fri, 20 Feb 2026 16:58:02 +0100 Subject: [PATCH 02/11] Add ability to skip tests that require TCP routing --- README.md | 1 + .../org/cloudfoundry/RequiresTcpRouting.java | 77 +++++++++++++++++++ .../operations/ApplicationsTest.java | 5 ++ .../routing/v1/RouterGroupsTest.java | 2 + .../routing/v1/TcpRoutesTest.java | 2 + 5 files changed, 87 insertions(+) create mode 100644 integration-test/src/test/java/org/cloudfoundry/RequiresTcpRouting.java diff --git a/README.md b/README.md index 5b4b1fad713..3b1ebbfd1dc 100644 --- a/README.md +++ b/README.md @@ -353,6 +353,7 @@ Name | Description `TEST_PROXY_PORT` | _(Optional)_ The port of a proxy to route all requests through. Defaults to `8080`. `TEST_PROXY_USERNAME` | _(Optional)_ The username for a proxy to route all requests through `TEST_SKIPSSLVALIDATION` | _(Optional)_ Whether to skip SSL validation when connecting to the Cloud Foundry instance. Defaults to `false`. +`SKIP_TCP_ROUTING_TESTS` | _(Optional)_ Set to `true` to skip TCP routing integration tests (TcpRoutesTest, RouterGroupsTest). Useful when the Cloud Foundry instance does not have TCP routing configured (i.e., no `routing_endpoint` in the info payload). Defaults to `false`. `SKIP_V2_TESTS` | _(Optional)_ Set to `true` to skip all V2 API integration tests. Useful when the Cloud Foundry V2 API is rate-limited or unavailable. When enabled, tests annotated with `@RequiresV2Api` will be skipped, including V3 tests that depend on V2 API calls (e.g., service broker creation). Defaults to `false`. If you do not have access to a CloudFoundry instance with admin access, you can run one locally using [bosh-deployment](https://github.com/cloudfoundry/bosh-deployment) & [cf-deployment](https://github.com/cloudfoundry/cf-deployment/) and Virtualbox. diff --git a/integration-test/src/test/java/org/cloudfoundry/RequiresTcpRouting.java b/integration-test/src/test/java/org/cloudfoundry/RequiresTcpRouting.java new file mode 100644 index 00000000000..0ee45aee62c --- /dev/null +++ b/integration-test/src/test/java/org/cloudfoundry/RequiresTcpRouting.java @@ -0,0 +1,77 @@ +/* + * Copyright 2026 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.cloudfoundry; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.junit.jupiter.api.extension.ConditionEvaluationResult; +import org.junit.jupiter.api.extension.ExecutionCondition; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.ExtensionContext; + +/** + * Annotation to mark tests that require TCP routing to be configured. + * + *

Tests annotated with this (or test classes containing this annotation) + * will be skipped if the {@code SKIP_TCP_ROUTING_TESTS} environment variable + * is set to "true". + * + *

Use this when your Cloud Foundry instance does not have TCP routing + * configured (i.e., when the info payload does not contain a 'routing_endpoint' key). + * + *

Example usage: + *

+ * @RequiresTcpRouting
+ * public class TcpRoutesTest extends AbstractIntegrationTest {
+ *     // tests that require TCP routing
+ * }
+ * 
+ */ +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@ExtendWith(RequiresTcpRouting.SkipTcpRoutingCondition.class) +public @interface RequiresTcpRouting { + + /** + * JUnit 5 ExecutionCondition that checks if tcp routing tests should be skipped. + */ + class SkipTcpRoutingCondition implements ExecutionCondition { + + private static final String ENV_VAR = "SKIP_TCP_ROUTING_TESTS"; + + @Override + public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { + String envValue = System.getenv(ENV_VAR); + + if ("true".equalsIgnoreCase(envValue)) { + return ConditionEvaluationResult.disabled( + "TCP routing tests are disabled via " + + ENV_VAR + + " environment variable" + + ". TCP routing may not be configured on the target CF instance."); + } + + return ConditionEvaluationResult.enabled("TCP routing tests are enabled"); + } + } +} diff --git a/integration-test/src/test/java/org/cloudfoundry/operations/ApplicationsTest.java b/integration-test/src/test/java/org/cloudfoundry/operations/ApplicationsTest.java index 04a2e3c5674..43f65276114 100644 --- a/integration-test/src/test/java/org/cloudfoundry/operations/ApplicationsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/operations/ApplicationsTest.java @@ -29,6 +29,7 @@ import org.cloudfoundry.CleanupCloudFoundryAfterClass; import org.cloudfoundry.CloudFoundryVersion; import org.cloudfoundry.IfCloudFoundryVersion; +import org.cloudfoundry.RequiresTcpRouting; import org.cloudfoundry.RequiresV2Api; import org.cloudfoundry.client.CloudFoundryClient; import org.cloudfoundry.operations.applications.ApplicationDetail; @@ -352,6 +353,7 @@ public void getManifest() throws IOException { } @Test + @RequiresTcpRouting public void getManifestForTcpRoute() throws IOException { String applicationName = this.nameFactory.getApplicationName(); @@ -438,6 +440,7 @@ public void getStopped() throws IOException { } @Test + @RequiresTcpRouting public void getTcp() throws IOException { String applicationName = this.nameFactory.getApplicationName(); String domainName = this.nameFactory.getDomainName(); @@ -1142,6 +1145,7 @@ public void pushRoutePath() throws IOException { } @Test + @RequiresTcpRouting public void pushTcpRoute() throws IOException { String applicationName = this.nameFactory.getApplicationName(); String domainName = this.nameFactory.getDomainName(); @@ -1265,6 +1269,7 @@ public void pushUpdateRoute() throws IOException { } @Test + @RequiresTcpRouting public void pushUpdateTcpRoute() throws IOException { String applicationName = this.nameFactory.getApplicationName(); String domainName = this.nameFactory.getDomainName(); diff --git a/integration-test/src/test/java/org/cloudfoundry/routing/v1/RouterGroupsTest.java b/integration-test/src/test/java/org/cloudfoundry/routing/v1/RouterGroupsTest.java index 8253f29ad5a..7a812c7e262 100644 --- a/integration-test/src/test/java/org/cloudfoundry/routing/v1/RouterGroupsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/routing/v1/RouterGroupsTest.java @@ -18,6 +18,7 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresTcpRouting; import org.cloudfoundry.routing.RoutingClient; import org.cloudfoundry.routing.v1.routergroups.ListRouterGroupsRequest; import org.cloudfoundry.routing.v1.routergroups.ListRouterGroupsResponse; @@ -29,6 +30,7 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +@RequiresTcpRouting public final class RouterGroupsTest extends AbstractIntegrationTest { private static final String DEFAULT_ROUTER_GROUP = "default-tcp"; diff --git a/integration-test/src/test/java/org/cloudfoundry/routing/v1/TcpRoutesTest.java b/integration-test/src/test/java/org/cloudfoundry/routing/v1/TcpRoutesTest.java index a562fa42232..6fb7af061b0 100644 --- a/integration-test/src/test/java/org/cloudfoundry/routing/v1/TcpRoutesTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/routing/v1/TcpRoutesTest.java @@ -19,6 +19,7 @@ import java.time.Duration; import org.cloudfoundry.AbstractIntegrationTest; import org.cloudfoundry.NameFactory; +import org.cloudfoundry.RequiresTcpRouting; import org.cloudfoundry.routing.RoutingClient; import org.cloudfoundry.routing.v1.routergroups.ListRouterGroupsRequest; import org.cloudfoundry.routing.v1.routergroups.ListRouterGroupsResponse; @@ -39,6 +40,7 @@ import reactor.test.StepVerifier; import reactor.util.retry.Retry; +@RequiresTcpRouting public final class TcpRoutesTest extends AbstractIntegrationTest { private static final String DEFAULT_ROUTER_GROUP = "default-tcp"; From 8cf89171544be9bce92a6e26fe999ea94fd378af Mon Sep 17 00:00:00 2001 From: Joris Baum Date: Mon, 23 Feb 2026 17:27:54 +0100 Subject: [PATCH 03/11] Allow skipping tests tha require browser auth Some UAA do not return a Location header. --- README.md | 1 + .../org/cloudfoundry/RequiresBrowserAuth.java | 74 +++++++++++++++++++ .../cloudfoundry/uaa/AuthorizationsTest.java | 7 ++ 3 files changed, 82 insertions(+) create mode 100644 integration-test/src/test/java/org/cloudfoundry/RequiresBrowserAuth.java diff --git a/README.md b/README.md index 3b1ebbfd1dc..e9bbbe5f1b9 100644 --- a/README.md +++ b/README.md @@ -353,6 +353,7 @@ Name | Description `TEST_PROXY_PORT` | _(Optional)_ The port of a proxy to route all requests through. Defaults to `8080`. `TEST_PROXY_USERNAME` | _(Optional)_ The username for a proxy to route all requests through `TEST_SKIPSSLVALIDATION` | _(Optional)_ Whether to skip SSL validation when connecting to the Cloud Foundry instance. Defaults to `false`. +`SKIP_BROWSER_AUTH_TESTS` | _(Optional)_ Set to `true` to skip integration tests that require browser-based authentication (e.g., SSO tests). Useful when the Cloud Foundry instance does not support browser-based authentication or when running tests in a non-interactive environment. Defaults to `false`. `SKIP_TCP_ROUTING_TESTS` | _(Optional)_ Set to `true` to skip TCP routing integration tests (TcpRoutesTest, RouterGroupsTest). Useful when the Cloud Foundry instance does not have TCP routing configured (i.e., no `routing_endpoint` in the info payload). Defaults to `false`. `SKIP_V2_TESTS` | _(Optional)_ Set to `true` to skip all V2 API integration tests. Useful when the Cloud Foundry V2 API is rate-limited or unavailable. When enabled, tests annotated with `@RequiresV2Api` will be skipped, including V3 tests that depend on V2 API calls (e.g., service broker creation). Defaults to `false`. diff --git a/integration-test/src/test/java/org/cloudfoundry/RequiresBrowserAuth.java b/integration-test/src/test/java/org/cloudfoundry/RequiresBrowserAuth.java new file mode 100644 index 00000000000..d675dd63242 --- /dev/null +++ b/integration-test/src/test/java/org/cloudfoundry/RequiresBrowserAuth.java @@ -0,0 +1,74 @@ +/* + * Copyright 2026 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.cloudfoundry; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.junit.jupiter.api.extension.ConditionEvaluationResult; +import org.junit.jupiter.api.extension.ExecutionCondition; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.ExtensionContext; + +/** + * Annotation to mark tests that require browser-based authentication (e.g., OAuth + * authorization code grants, implicit grants). Tests annotated with this will be skipped + * if the environment variable {@code SKIP_BROWSER_AUTH_TESTS} is set to "true". + * + *

Usage: + *

+ * @RequiresBrowserAuth
+ * public class MyAuthTest extends AbstractIntegrationTest {
+ *     // ...
+ * }
+ * 
+ * + *

To skip browser auth tests, set the environment variable: + *

+ * export SKIP_BROWSER_AUTH_TESTS=true
+ * 
+ */ +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@ExtendWith(RequiresBrowserAuth.BrowserAuthCondition.class) +public @interface RequiresBrowserAuth { + + /** + * JUnit 5 ExecutionCondition that checks if Browser Auth tests should be skipped. + */ + class BrowserAuthCondition implements ExecutionCondition { + + private static final String SKIP_BROWSER_AUTH_ENV = "SKIP_BROWSER_AUTH_TESTS"; + + @Override + public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { + if ("true".equalsIgnoreCase(System.getenv(SKIP_BROWSER_AUTH_ENV))) { + return ConditionEvaluationResult.disabled( + "Tests requiring Browser Authentication are disabled via " + + SKIP_BROWSER_AUTH_ENV + + " environment variable"); + } + + return ConditionEvaluationResult.enabled("Browser authentication tests are enabled"); + } + } +} diff --git a/integration-test/src/test/java/org/cloudfoundry/uaa/AuthorizationsTest.java b/integration-test/src/test/java/org/cloudfoundry/uaa/AuthorizationsTest.java index 6480aef0b9c..e0eac2d2149 100644 --- a/integration-test/src/test/java/org/cloudfoundry/uaa/AuthorizationsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/uaa/AuthorizationsTest.java @@ -21,6 +21,7 @@ import java.time.Duration; import java.util.function.Consumer; import org.cloudfoundry.AbstractIntegrationTest; +import org.cloudfoundry.RequiresBrowserAuth; import org.cloudfoundry.uaa.authorizations.AuthorizeByAuthorizationCodeGrantApiRequest; import org.cloudfoundry.uaa.authorizations.AuthorizeByAuthorizationCodeGrantBrowserRequest; import org.cloudfoundry.uaa.authorizations.AuthorizeByAuthorizationCodeGrantHybridRequest; @@ -55,6 +56,7 @@ public void authorizeByAuthorizationCodeGrantApi() { } @Test + @RequiresBrowserAuth public void authorizeByAuthorizationCodeGrantBrowser() { this.uaaClient .authorizations() @@ -70,6 +72,7 @@ public void authorizeByAuthorizationCodeGrantBrowser() { } @Test + @RequiresBrowserAuth public void authorizeByAuthorizationCodeGrantHybrid() { this.uaaClient .authorizations() @@ -85,6 +88,7 @@ public void authorizeByAuthorizationCodeGrantHybrid() { } @Test + @RequiresBrowserAuth public void authorizeByImplicitGrantBrowser() { this.uaaClient .authorizations() @@ -100,6 +104,7 @@ public void authorizeByImplicitGrantBrowser() { } @Test + @RequiresBrowserAuth public void authorizeByOpenIdWithAuthorizationCodeGrant() { this.uaaClient .authorizations() @@ -116,6 +121,7 @@ public void authorizeByOpenIdWithAuthorizationCodeGrant() { } @Test + @RequiresBrowserAuth public void authorizeByOpenIdWithIdToken() { this.uaaClient .authorizations() @@ -132,6 +138,7 @@ public void authorizeByOpenIdWithIdToken() { } @Test + @RequiresBrowserAuth public void authorizeByOpenIdWithImplicitGrant() { this.uaaClient .authorizations() From c431ba6ae624eaf989b0dc97cfd4f4357815aa91 Mon Sep 17 00:00:00 2001 From: Joris Baum Date: Mon, 23 Feb 2026 17:37:47 +0100 Subject: [PATCH 04/11] Only run very basic LogCacheTest when V2 is missing --- .../org/cloudfoundry/logcache/v1/LogCacheTest.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/integration-test/src/test/java/org/cloudfoundry/logcache/v1/LogCacheTest.java b/integration-test/src/test/java/org/cloudfoundry/logcache/v1/LogCacheTest.java index 414af210bde..56190b818e4 100644 --- a/integration-test/src/test/java/org/cloudfoundry/logcache/v1/LogCacheTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/logcache/v1/LogCacheTest.java @@ -29,6 +29,7 @@ import org.cloudfoundry.ApplicationUtils; import org.cloudfoundry.CloudFoundryVersion; import org.cloudfoundry.IfCloudFoundryVersion; +import org.cloudfoundry.RequiresV2Api; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -43,13 +44,15 @@ public class LogCacheTest extends AbstractIntegrationTest { private ApplicationUtils.ApplicationMetadata testLogCacheAppMetadata; - @Autowired private TestLogCacheEndpoints testLogCacheEndpoints; + @Autowired(required = false) private TestLogCacheEndpoints testLogCacheEndpoints; private final Random random = new SecureRandom(); @BeforeEach - void setUp(@Autowired Mono testLogCacheApp) { - this.testLogCacheAppMetadata = testLogCacheApp.block(); + void setUp(@Autowired(required = false) Mono testLogCacheApp) { + if (testLogCacheApp != null) { + this.testLogCacheAppMetadata = testLogCacheApp.block(); + } } @Test @@ -68,6 +71,7 @@ public void info() { } @Test + @RequiresV2Api public void meta() { this.logCacheClient .meta(MetaRequest.builder().build()) @@ -83,6 +87,7 @@ public void meta() { } @Test + @RequiresV2Api public void readCounter() { final String name = this.nameFactory.getName("counter-"); final int delta = this.random.nextInt(1000); @@ -102,6 +107,7 @@ public void readCounter() { } @Test + @RequiresV2Api public void readEvent() { final String title = this.nameFactory.getName("event-"); final String body = "This is the body. " + new BigInteger(1024, this.random).toString(32); @@ -117,6 +123,7 @@ public void readEvent() { @Test @Disabled("fails often for no reasons") + @RequiresV2Api public void readGauge() { final String gaugeName = this.nameFactory.getName("gauge-"); final Double value = this.random.nextDouble() % 100; @@ -138,6 +145,7 @@ public void readGauge() { } @Test + @RequiresV2Api public void readLogs() { final String logMessage = this.nameFactory.getName("log-"); From 2957b014fef3f8c01318f8de89269cb3a0e3b347 Mon Sep 17 00:00:00 2001 From: Joris Baum Date: Thu, 26 Feb 2026 09:13:28 +0100 Subject: [PATCH 05/11] Support skipping tests requiring metric registrar --- README.md | 1 + .../cloudfoundry/RequiresMetricRegistrar.java | 74 +++++++++++++++++++ .../logcache/v1/LogCacheTest.java | 18 ++++- 3 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 integration-test/src/test/java/org/cloudfoundry/RequiresMetricRegistrar.java diff --git a/README.md b/README.md index e9bbbe5f1b9..7e516ec5416 100644 --- a/README.md +++ b/README.md @@ -354,6 +354,7 @@ Name | Description `TEST_PROXY_USERNAME` | _(Optional)_ The username for a proxy to route all requests through `TEST_SKIPSSLVALIDATION` | _(Optional)_ Whether to skip SSL validation when connecting to the Cloud Foundry instance. Defaults to `false`. `SKIP_BROWSER_AUTH_TESTS` | _(Optional)_ Set to `true` to skip integration tests that require browser-based authentication (e.g., SSO tests). Useful when the Cloud Foundry instance does not support browser-based authentication or when running tests in a non-interactive environment. Defaults to `false`. +`SKIP_METRIC_REGISTRAR_TESTS` | _(Optional)_ Set to `true` to skip integration tests that require the Metric Registrar service (e.g., MetricRegistrarTest). Useful when the Cloud Foundry instance does not have the Metric Registrar service available. Defaults to `false`. `SKIP_TCP_ROUTING_TESTS` | _(Optional)_ Set to `true` to skip TCP routing integration tests (TcpRoutesTest, RouterGroupsTest). Useful when the Cloud Foundry instance does not have TCP routing configured (i.e., no `routing_endpoint` in the info payload). Defaults to `false`. `SKIP_V2_TESTS` | _(Optional)_ Set to `true` to skip all V2 API integration tests. Useful when the Cloud Foundry V2 API is rate-limited or unavailable. When enabled, tests annotated with `@RequiresV2Api` will be skipped, including V3 tests that depend on V2 API calls (e.g., service broker creation). Defaults to `false`. diff --git a/integration-test/src/test/java/org/cloudfoundry/RequiresMetricRegistrar.java b/integration-test/src/test/java/org/cloudfoundry/RequiresMetricRegistrar.java new file mode 100644 index 00000000000..c70d21dfe25 --- /dev/null +++ b/integration-test/src/test/java/org/cloudfoundry/RequiresMetricRegistrar.java @@ -0,0 +1,74 @@ +/* + * Copyright 2026 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.cloudfoundry; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.junit.jupiter.api.extension.ConditionEvaluationResult; +import org.junit.jupiter.api.extension.ExecutionCondition; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.ExtensionContext; + +/** + * Annotation to mark tests that require the Metric Registrar service to be available. + * Tests annotated with this will be skipped if the environment variable + * {@code SKIP_METRIC_REGISTRAR_TESTS} is set to "true". + * + *

Usage: + *

+ * @RequiresMetricRegistrar
+ * public class MetricTest extends AbstractIntegrationTest {
+ *     // ...
+ * }
+ * 
+ * + *

To skip metric registrar tests, set the environment variable: + *

+ * export SKIP_METRIC_REGISTRAR_TESTS=true
+ * 
+ */ +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +@ExtendWith(RequiresMetricRegistrar.RegistrarCondition.class) +public @interface RequiresMetricRegistrar { + + /** + * JUnit 5 ExecutionCondition that checks if Metric Registrar tests should be skipped. + */ + class RegistrarCondition implements ExecutionCondition { + + private static final String SKIP_REGISTRAR_ENV = "SKIP_METRIC_REGISTRAR_TESTS"; + + @Override + public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { + if ("true".equalsIgnoreCase(System.getenv(SKIP_REGISTRAR_ENV))) { + return ConditionEvaluationResult.disabled( + "Tests requiring Metric Registrar Service are disabled via " + + SKIP_REGISTRAR_ENV + + " environment variable."); + } + + return ConditionEvaluationResult.enabled("Metric Registrar tests are enabled"); + } + } +} diff --git a/integration-test/src/test/java/org/cloudfoundry/logcache/v1/LogCacheTest.java b/integration-test/src/test/java/org/cloudfoundry/logcache/v1/LogCacheTest.java index 56190b818e4..eb53f391235 100644 --- a/integration-test/src/test/java/org/cloudfoundry/logcache/v1/LogCacheTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/logcache/v1/LogCacheTest.java @@ -29,6 +29,7 @@ import org.cloudfoundry.ApplicationUtils; import org.cloudfoundry.CloudFoundryVersion; import org.cloudfoundry.IfCloudFoundryVersion; +import org.cloudfoundry.RequiresMetricRegistrar; import org.cloudfoundry.RequiresV2Api; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; @@ -44,12 +45,23 @@ public class LogCacheTest extends AbstractIntegrationTest { private ApplicationUtils.ApplicationMetadata testLogCacheAppMetadata; - @Autowired(required = false) private TestLogCacheEndpoints testLogCacheEndpoints; + // Optional: only available when V2 API is enabled (requires deployed test app) + @Autowired(required = false) + private TestLogCacheEndpoints testLogCacheEndpoints; private final Random random = new SecureRandom(); + /** + * Sets up the test log cache app metadata. The testLogCacheApp bean is optional + * ({@code required = false}) because it depends on V2 API calls for app deployment. + * When SKIP_V2_TESTS=true, this bean won't be available and setUp becomes a no-op. + * Tests that need testLogCacheAppMetadata are annotated with {@code @RequiresV2Api} + * and will be skipped in that case. + */ @BeforeEach - void setUp(@Autowired(required = false) Mono testLogCacheApp) { + void setUp( + @Autowired(required = false) + Mono testLogCacheApp) { if (testLogCacheApp != null) { this.testLogCacheAppMetadata = testLogCacheApp.block(); } @@ -88,6 +100,7 @@ public void meta() { @Test @RequiresV2Api + @RequiresMetricRegistrar public void readCounter() { final String name = this.nameFactory.getName("counter-"); final int delta = this.random.nextInt(1000); @@ -108,6 +121,7 @@ public void readCounter() { @Test @RequiresV2Api + @RequiresMetricRegistrar public void readEvent() { final String title = this.nameFactory.getName("event-"); final String body = "This is the body. " + new BigInteger(1024, this.random).toString(32); From 5918572d1346ea5c2e07497dc03fc766833035a7 Mon Sep 17 00:00:00 2001 From: Joris Baum Date: Fri, 17 Apr 2026 16:05:30 +0200 Subject: [PATCH 06/11] Guard serviceBrokerId with @ConditionalOnProperty Prevent the serviceBrokerId bean from being created when SKIP_V2_TESTS=true, rather than relying on @Autowired(required=false) in each test class. This avoids the bean's initMethod="block" eagerly calling the V2 API at context startup even when all V2 tests are disabled. --- .../java/org/cloudfoundry/IntegrationTestConfiguration.java | 1 + .../java/org/cloudfoundry/client/v2/OrganizationsTest.java | 4 +--- .../java/org/cloudfoundry/client/v2/ServiceBrokersTest.java | 4 +--- .../java/org/cloudfoundry/client/v2/ServiceInstancesTest.java | 4 +--- .../test/java/org/cloudfoundry/client/v2/ServiceKeysTest.java | 4 +--- .../java/org/cloudfoundry/client/v2/ServicePlansTest.java | 4 +--- .../org/cloudfoundry/client/v2/ServiceUsageEventsTest.java | 4 +--- .../test/java/org/cloudfoundry/client/v2/ServicesTest.java | 4 +--- .../src/test/java/org/cloudfoundry/client/v2/SpacesTest.java | 4 +--- .../java/org/cloudfoundry/client/v3/ServiceBindingsTest.java | 4 +--- .../java/org/cloudfoundry/client/v3/ServiceBrokersTest.java | 4 +--- .../java/org/cloudfoundry/client/v3/ServiceInstancesTest.java | 4 +--- .../java/org/cloudfoundry/client/v3/ServiceOfferingsTest.java | 4 +--- .../java/org/cloudfoundry/client/v3/ServicePlansTest.java | 4 +--- .../test/java/org/cloudfoundry/operations/ServicesTest.java | 4 +--- 15 files changed, 15 insertions(+), 42 deletions(-) diff --git a/integration-test/src/test/java/org/cloudfoundry/IntegrationTestConfiguration.java b/integration-test/src/test/java/org/cloudfoundry/IntegrationTestConfiguration.java index 8a6a1ad4b62..aec0afc99cd 100644 --- a/integration-test/src/test/java/org/cloudfoundry/IntegrationTestConfiguration.java +++ b/integration-test/src/test/java/org/cloudfoundry/IntegrationTestConfiguration.java @@ -473,6 +473,7 @@ Version serverVersion(@Qualifier("admin") CloudFoundryClient cloudFoundryClient) @Lazy @Bean(initMethod = "block") @DependsOn("cloudFoundryCleaner") + @ConditionalOnProperty(name = "SKIP_V2_TESTS", havingValue = "false", matchIfMissing = true) Mono serviceBrokerId( CloudFoundryClient cloudFoundryClient, NameFactory nameFactory, diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/OrganizationsTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/OrganizationsTest.java index 1b31140d922..3c8740d0fb2 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/OrganizationsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/OrganizationsTest.java @@ -106,9 +106,7 @@ public final class OrganizationsTest extends AbstractIntegrationTest { @Autowired private Mono organizationId; - // Optional: bean requires V2 API; class is guarded by @RequiresV2Api - @Autowired(required = false) - private Mono serviceBrokerId; + @Autowired private Mono serviceBrokerId; @Autowired private String serviceName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceBrokersTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceBrokersTest.java index 50be1ea1b52..61320ccd50d 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceBrokersTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceBrokersTest.java @@ -53,9 +53,7 @@ public final class ServiceBrokersTest extends AbstractIntegrationTest { @Autowired private Mono organizationId; - // Optional: bean requires V2 API; class is guarded by @RequiresV2Api - @Autowired(required = false) - private Mono serviceBrokerId; + @Autowired private Mono serviceBrokerId; @Autowired private String serviceBrokerName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceInstancesTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceInstancesTest.java index cad61ddbd58..c3620f4957e 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceInstancesTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceInstancesTest.java @@ -77,9 +77,7 @@ public final class ServiceInstancesTest extends AbstractIntegrationTest { @Autowired private RoutingClient routingClient; - // Optional: bean requires V2 API; class is guarded by @RequiresV2Api - @Autowired(required = false) - private Mono serviceBrokerId; + @Autowired private Mono serviceBrokerId; @Autowired private String serviceName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceKeysTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceKeysTest.java index 485e9ba5719..3ec01e0d95c 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceKeysTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceKeysTest.java @@ -48,9 +48,7 @@ public final class ServiceKeysTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; - // Optional: bean requires V2 API; class is guarded by @RequiresV2Api - @Autowired(required = false) - private Mono serviceBrokerId; + @Autowired private Mono serviceBrokerId; @Autowired private String serviceName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServicePlansTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServicePlansTest.java index e9fc66b8e8e..d0cc34c36b9 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServicePlansTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServicePlansTest.java @@ -63,9 +63,7 @@ public final class ServicePlansTest extends AbstractIntegrationTest { @Autowired private String planName; - // Optional: bean requires V2 API; class is guarded by @RequiresV2Api - @Autowired(required = false) - private Mono serviceBrokerId; + @Autowired private Mono serviceBrokerId; @Autowired private String serviceName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceUsageEventsTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceUsageEventsTest.java index 32703e319e4..56ddd5bbfc0 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceUsageEventsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServiceUsageEventsTest.java @@ -46,9 +46,7 @@ public final class ServiceUsageEventsTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; - // Optional: bean requires V2 API; class is guarded by @RequiresV2Api - @Autowired(required = false) - private Mono serviceBrokerId; + @Autowired private Mono serviceBrokerId; @Autowired private String serviceName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServicesTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServicesTest.java index 1469bfdd361..5410c1a951f 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/ServicesTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/ServicesTest.java @@ -56,9 +56,7 @@ public final class ServicesTest extends AbstractIntegrationTest { @Autowired private String planName; - // Optional: bean requires V2 API; class is guarded by @RequiresV2Api - @Autowired(required = false) - private Mono serviceBrokerId; + @Autowired private Mono serviceBrokerId; @Autowired private String serviceName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v2/SpacesTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v2/SpacesTest.java index eae93b616bb..54fc74e861c 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v2/SpacesTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v2/SpacesTest.java @@ -124,9 +124,7 @@ public final class SpacesTest extends AbstractIntegrationTest { @Autowired private Mono organizationId; - // Optional: bean requires V2 API; class is guarded by @RequiresV2Api - @Autowired(required = false) - private Mono serviceBrokerId; + @Autowired private Mono serviceBrokerId; @Autowired private String serviceName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceBindingsTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceBindingsTest.java index acdb96f1e94..3c0695a2da8 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceBindingsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceBindingsTest.java @@ -60,9 +60,7 @@ public class ServiceBindingsTest extends AbstractIntegrationTest { @Autowired private CloudFoundryClient cloudFoundryClient; - // Optional: bean requires V2 API; class is guarded by @RequiresV2Api - @Autowired(required = false) - private Mono serviceBrokerId; + @Autowired private Mono serviceBrokerId; @Autowired private String serviceName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceBrokersTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceBrokersTest.java index 07e0b219cfc..4a13ea744cf 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceBrokersTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceBrokersTest.java @@ -59,9 +59,7 @@ public final class ServiceBrokersTest extends AbstractIntegrationTest { @Autowired private Mono organizationId; - // Optional: bean requires V2 API; class is guarded by @RequiresV2Api - @Autowired(required = false) - private Mono serviceBrokerId; + @Autowired private Mono serviceBrokerId; @Autowired private String serviceBrokerName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceInstancesTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceInstancesTest.java index 941c0e56169..1af91bbdf82 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceInstancesTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceInstancesTest.java @@ -65,9 +65,7 @@ public final class ServiceInstancesTest extends AbstractIntegrationTest { @Autowired private Mono organizationId; - // Optional: bean requires V2 API; class is guarded by @RequiresV2Api - @Autowired(required = false) - private Mono serviceBrokerId; + @Autowired private Mono serviceBrokerId; @Autowired private String serviceName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceOfferingsTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceOfferingsTest.java index 20334935909..fec36409fe8 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceOfferingsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v3/ServiceOfferingsTest.java @@ -51,9 +51,7 @@ public final class ServiceOfferingsTest extends AbstractIntegrationTest { @Autowired private Mono organizationId; - // Optional: bean requires V2 API; class is guarded by @RequiresV2Api - @Autowired(required = false) - private Mono serviceBrokerId; + @Autowired private Mono serviceBrokerId; @Autowired private String serviceName; diff --git a/integration-test/src/test/java/org/cloudfoundry/client/v3/ServicePlansTest.java b/integration-test/src/test/java/org/cloudfoundry/client/v3/ServicePlansTest.java index 7f5f0383945..c749b3e23de 100644 --- a/integration-test/src/test/java/org/cloudfoundry/client/v3/ServicePlansTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/client/v3/ServicePlansTest.java @@ -55,9 +55,7 @@ public final class ServicePlansTest extends AbstractIntegrationTest { @Autowired private String planName; - // Optional: bean requires V2 API; class is guarded by @RequiresV2Api - @Autowired(required = false) - private Mono serviceBrokerId; + @Autowired private Mono serviceBrokerId; @Test public void delete() { diff --git a/integration-test/src/test/java/org/cloudfoundry/operations/ServicesTest.java b/integration-test/src/test/java/org/cloudfoundry/operations/ServicesTest.java index 32b8cb4e687..f81ddb1a674 100644 --- a/integration-test/src/test/java/org/cloudfoundry/operations/ServicesTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/operations/ServicesTest.java @@ -78,9 +78,7 @@ public final class ServicesTest extends AbstractIntegrationTest { @Autowired private String planName; - // Optional: bean requires V2 API; class is guarded by @RequiresV2Api - @Autowired(required = false) - private Mono serviceBrokerId; + @Autowired private Mono serviceBrokerId; @Autowired private String serviceName; From 2c8da39c95b53c38807f5863b476f5185db96743 Mon Sep 17 00:00:00 2001 From: Joris Baum Date: Fri, 17 Apr 2026 16:22:02 +0200 Subject: [PATCH 07/11] Centralize SKIP_V2_TESTS property name Extract the "SKIP_V2_TESTS" string literal into a public constant RequiresV2Api.SKIP_V2_TESTS_ENV and reference it from IntegrationTestConfiguration and CloudFoundryCleaner. --- .../org/cloudfoundry/CloudFoundryCleaner.java | 2 +- .../IntegrationTestConfiguration.java | 16 ++++++++-------- .../java/org/cloudfoundry/RequiresV2Api.java | 5 +++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/integration-test/src/test/java/org/cloudfoundry/CloudFoundryCleaner.java b/integration-test/src/test/java/org/cloudfoundry/CloudFoundryCleaner.java index 2985a04cde6..ef1dda0f795 100644 --- a/integration-test/src/test/java/org/cloudfoundry/CloudFoundryCleaner.java +++ b/integration-test/src/test/java/org/cloudfoundry/CloudFoundryCleaner.java @@ -133,7 +133,7 @@ final class CloudFoundryCleaner implements InitializingBean, DisposableBean { private static final boolean RUN_V2_CLEANUP = isRunV2Tests(); private static boolean isRunV2Tests() { - return !"true".equalsIgnoreCase(System.getenv("SKIP_V2_TESTS")); + return !"true".equalsIgnoreCase(System.getenv(RequiresV2Api.SKIP_V2_TESTS_ENV)); } private static final Map STANDARD_FEATURE_FLAGS = diff --git a/integration-test/src/test/java/org/cloudfoundry/IntegrationTestConfiguration.java b/integration-test/src/test/java/org/cloudfoundry/IntegrationTestConfiguration.java index aec0afc99cd..94df918ecaa 100644 --- a/integration-test/src/test/java/org/cloudfoundry/IntegrationTestConfiguration.java +++ b/integration-test/src/test/java/org/cloudfoundry/IntegrationTestConfiguration.java @@ -347,7 +347,7 @@ RandomNameFactory nameFactory() { @Bean(initMethod = "block") @DependsOn("cloudFoundryCleaner") - @ConditionalOnProperty(name = "SKIP_V2_TESTS", havingValue = "false", matchIfMissing = true) + @ConditionalOnProperty(name = RequiresV2Api.SKIP_V2_TESTS_ENV, havingValue = "false", matchIfMissing = true) Mono metricRegistrarServiceInstance( CloudFoundryClient cloudFoundryClient, Mono spaceId, NameFactory nameFactory) { return spaceId.flatMap( @@ -375,7 +375,7 @@ NetworkingClient networkingClient( @Bean(initMethod = "block") @DependsOn("cloudFoundryCleaner") - @ConditionalOnProperty(name = "SKIP_V2_TESTS", havingValue = "false", matchIfMissing = true) + @ConditionalOnProperty(name = RequiresV2Api.SKIP_V2_TESTS_ENV, havingValue = "false", matchIfMissing = true) Mono organizationId( CloudFoundryClient cloudFoundryClient, String organizationName, @@ -473,7 +473,7 @@ Version serverVersion(@Qualifier("admin") CloudFoundryClient cloudFoundryClient) @Lazy @Bean(initMethod = "block") @DependsOn("cloudFoundryCleaner") - @ConditionalOnProperty(name = "SKIP_V2_TESTS", havingValue = "false", matchIfMissing = true) + @ConditionalOnProperty(name = RequiresV2Api.SKIP_V2_TESTS_ENV, havingValue = "false", matchIfMissing = true) Mono serviceBrokerId( CloudFoundryClient cloudFoundryClient, NameFactory nameFactory, @@ -516,7 +516,7 @@ String serviceName(NameFactory nameFactory) { @Bean(initMethod = "block") @DependsOn("cloudFoundryCleaner") - @ConditionalOnProperty(name = "SKIP_V2_TESTS", havingValue = "false", matchIfMissing = true) + @ConditionalOnProperty(name = RequiresV2Api.SKIP_V2_TESTS_ENV, havingValue = "false", matchIfMissing = true) Mono spaceId( CloudFoundryClient cloudFoundryClient, Mono organizationId, String spaceName) { return organizationId @@ -543,7 +543,7 @@ String spaceName(NameFactory nameFactory) { @Bean(initMethod = "block") @DependsOn("cloudFoundryCleaner") - @ConditionalOnProperty(name = "SKIP_V2_TESTS", havingValue = "false", matchIfMissing = true) + @ConditionalOnProperty(name = RequiresV2Api.SKIP_V2_TESTS_ENV, havingValue = "false", matchIfMissing = true) Mono stackId(CloudFoundryClient cloudFoundryClient, Mono stackName) { return stackName .flux() @@ -572,7 +572,7 @@ Mono stackId(CloudFoundryClient cloudFoundryClient, Mono stackNa */ @Bean(initMethod = "block") @DependsOn("cloudFoundryCleaner") - @ConditionalOnProperty(name = "SKIP_V2_TESTS", havingValue = "false", matchIfMissing = true) + @ConditionalOnProperty(name = RequiresV2Api.SKIP_V2_TESTS_ENV, havingValue = "false", matchIfMissing = true) Mono stackName(CloudFoundryClient cloudFoundryClient) { return PaginationUtils.requestClientV2Resources( page -> @@ -590,7 +590,7 @@ Mono stackName(CloudFoundryClient cloudFoundryClient) { @Lazy @Bean(initMethod = "block") @DependsOn("cloudFoundryCleaner") - @ConditionalOnProperty(name = "SKIP_V2_TESTS", havingValue = "false", matchIfMissing = true) + @ConditionalOnProperty(name = RequiresV2Api.SKIP_V2_TESTS_ENV, havingValue = "false", matchIfMissing = true) Mono testLogCacheApp( CloudFoundryClient cloudFoundryClient, Mono spaceId, @@ -627,7 +627,7 @@ String testLogCacheAppName(NameFactory nameFactory) { @Lazy @Bean - @ConditionalOnProperty(name = "SKIP_V2_TESTS", havingValue = "false", matchIfMissing = true) + @ConditionalOnProperty(name = RequiresV2Api.SKIP_V2_TESTS_ENV, havingValue = "false", matchIfMissing = true) TestLogCacheEndpoints testLogCacheEndpoints( ConnectionContext connectionContext, TokenProvider tokenProvider, diff --git a/integration-test/src/test/java/org/cloudfoundry/RequiresV2Api.java b/integration-test/src/test/java/org/cloudfoundry/RequiresV2Api.java index acde38fb6bd..82bedb514e1 100644 --- a/integration-test/src/test/java/org/cloudfoundry/RequiresV2Api.java +++ b/integration-test/src/test/java/org/cloudfoundry/RequiresV2Api.java @@ -51,13 +51,14 @@ @ExtendWith(RequiresV2Api.V2ApiCondition.class) public @interface RequiresV2Api { + /** Environment variable name used to skip V2 API tests. */ + String SKIP_V2_TESTS_ENV = "SKIP_V2_TESTS"; + /** * JUnit 5 ExecutionCondition that checks if V2 tests should be skipped. */ class V2ApiCondition implements ExecutionCondition { - private static final String SKIP_V2_TESTS_ENV = "SKIP_V2_TESTS"; - @Override public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { if ("true".equalsIgnoreCase(System.getenv(SKIP_V2_TESTS_ENV))) { From 3f0db750166f510f0d681c1d5ee9680ed6efcd29 Mon Sep 17 00:00:00 2001 From: Joris Baum Date: Fri, 17 Apr 2026 16:24:32 +0200 Subject: [PATCH 08/11] Annotate LogCacheTest class with @RequiresV2Api The info() test alone doesn't bring enough value to justify keeping the class partially enabled without V2. --- .../logcache/v1/LogCacheTest.java | 25 +++---------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/integration-test/src/test/java/org/cloudfoundry/logcache/v1/LogCacheTest.java b/integration-test/src/test/java/org/cloudfoundry/logcache/v1/LogCacheTest.java index eb53f391235..26e5143229c 100644 --- a/integration-test/src/test/java/org/cloudfoundry/logcache/v1/LogCacheTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/logcache/v1/LogCacheTest.java @@ -39,32 +39,20 @@ import reactor.test.StepVerifier; @IfCloudFoundryVersion(greaterThanOrEqualTo = CloudFoundryVersion.PCF_2_9) +@RequiresV2Api public class LogCacheTest extends AbstractIntegrationTest { @Autowired LogCacheClient logCacheClient; private ApplicationUtils.ApplicationMetadata testLogCacheAppMetadata; - // Optional: only available when V2 API is enabled (requires deployed test app) - @Autowired(required = false) - private TestLogCacheEndpoints testLogCacheEndpoints; + @Autowired private TestLogCacheEndpoints testLogCacheEndpoints; private final Random random = new SecureRandom(); - /** - * Sets up the test log cache app metadata. The testLogCacheApp bean is optional - * ({@code required = false}) because it depends on V2 API calls for app deployment. - * When SKIP_V2_TESTS=true, this bean won't be available and setUp becomes a no-op. - * Tests that need testLogCacheAppMetadata are annotated with {@code @RequiresV2Api} - * and will be skipped in that case. - */ @BeforeEach - void setUp( - @Autowired(required = false) - Mono testLogCacheApp) { - if (testLogCacheApp != null) { - this.testLogCacheAppMetadata = testLogCacheApp.block(); - } + void setUp(@Autowired Mono testLogCacheApp) { + this.testLogCacheAppMetadata = testLogCacheApp.block(); } @Test @@ -83,7 +71,6 @@ public void info() { } @Test - @RequiresV2Api public void meta() { this.logCacheClient .meta(MetaRequest.builder().build()) @@ -99,7 +86,6 @@ public void meta() { } @Test - @RequiresV2Api @RequiresMetricRegistrar public void readCounter() { final String name = this.nameFactory.getName("counter-"); @@ -120,7 +106,6 @@ public void readCounter() { } @Test - @RequiresV2Api @RequiresMetricRegistrar public void readEvent() { final String title = this.nameFactory.getName("event-"); @@ -137,7 +122,6 @@ public void readEvent() { @Test @Disabled("fails often for no reasons") - @RequiresV2Api public void readGauge() { final String gaugeName = this.nameFactory.getName("gauge-"); final Double value = this.random.nextDouble() % 100; @@ -159,7 +143,6 @@ public void readGauge() { } @Test - @RequiresV2Api public void readLogs() { final String logMessage = this.nameFactory.getName("log-"); From 7fa9681b4b9132022664f16c1ff2cf1b7c5dd31c Mon Sep 17 00:00:00 2001 From: Joris Baum Date: Fri, 17 Apr 2026 16:39:21 +0200 Subject: [PATCH 09/11] Port cleanApplicationsV3 binding removal from to V3 Replace V2 applicationsV2().listServiceBindings / removeServiceBinding calls with V3 serviceBindingsV3().list / delete in the cleaner's application cleanup path, eliminating the runV2Calls boolean parameter. --- .../org/cloudfoundry/CloudFoundryCleaner.java | 51 +++++++++---------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/integration-test/src/test/java/org/cloudfoundry/CloudFoundryCleaner.java b/integration-test/src/test/java/org/cloudfoundry/CloudFoundryCleaner.java index ef1dda0f795..d491e880907 100644 --- a/integration-test/src/test/java/org/cloudfoundry/CloudFoundryCleaner.java +++ b/integration-test/src/test/java/org/cloudfoundry/CloudFoundryCleaner.java @@ -28,7 +28,6 @@ import java.util.function.Supplier; import javax.net.ssl.SSLException; import org.cloudfoundry.client.CloudFoundryClient; -import org.cloudfoundry.client.v2.applications.ListApplicationServiceBindingsRequest; import org.cloudfoundry.client.v2.applications.RemoveApplicationServiceBindingRequest; import org.cloudfoundry.client.v2.buildpacks.DeleteBuildpackRequest; import org.cloudfoundry.client.v2.buildpacks.ListBuildpacksRequest; @@ -80,6 +79,8 @@ import org.cloudfoundry.client.v3.applications.ApplicationResource; import org.cloudfoundry.client.v3.applications.DeleteApplicationRequest; import org.cloudfoundry.client.v3.applications.ListApplicationsRequest; +import org.cloudfoundry.client.v3.servicebindings.DeleteServiceBindingRequest; +import org.cloudfoundry.client.v3.servicebindings.ListServiceBindingsRequest; import org.cloudfoundry.client.v3.serviceinstances.ListSharedSpacesRelationshipRequest; import org.cloudfoundry.client.v3.serviceinstances.ListSharedSpacesRelationshipResponse; import org.cloudfoundry.client.v3.serviceinstances.UnshareServiceInstanceRequest; @@ -207,8 +208,7 @@ void clean() { Mono.when( cleanApplicationsV3( this.cloudFoundryClient, - this.nameFactory, - false), // runV2Calls = false (V3-only path) + this.nameFactory), cleanUsers(this.uaaClient, this.nameFactory))) .retryWhen(Retry.max(5).filter(SSLException.class::isInstance)) .doOnSubscribe(s -> LOGGER.debug(">> CLEANUP (V3 only) <<")) @@ -250,9 +250,7 @@ void clean() { Mono.when( cleanApplicationsV3( this.cloudFoundryClient, - this.nameFactory, - true), // After Routes, cannot run with - // other cleanApps + this.nameFactory), cleanUsers(this.uaaClient, this.nameFactory) // After CF Users )) .thenMany( @@ -274,9 +272,8 @@ void clean() { } private static Flux cleanApplicationsV3( - CloudFoundryClient cloudFoundryClient, NameFactory nameFactory, boolean runV2Calls) { - Flux apps = - PaginationUtils.requestClientV3Resources( + CloudFoundryClient cloudFoundryClient, NameFactory nameFactory) { + return PaginationUtils.requestClientV3Resources( page -> cloudFoundryClient .applicationsV3() @@ -286,17 +283,12 @@ private static Flux cleanApplicationsV3( .build())) .filter( application -> - nameFactory.isApplicationName(application.getName())); - - if (runV2Calls) { - apps = - apps.delayUntil( - application -> - removeApplicationServiceBindings( - cloudFoundryClient, application)); - } - - return apps.flatMap( + nameFactory.isApplicationName(application.getName())) + .delayUntil( + application -> + removeApplicationServiceBindings( + cloudFoundryClient, application)) + .flatMap( application -> cloudFoundryClient .applicationsV3() @@ -1204,21 +1196,24 @@ private static boolean isCleanable(NameFactory nameFactory, UserResource resourc private static Flux removeApplicationServiceBindings( CloudFoundryClient cloudFoundryClient, Application application) { - return PaginationUtils.requestClientV2Resources( + return PaginationUtils.requestClientV3Resources( page -> cloudFoundryClient - .applicationsV2() - .listServiceBindings( - ListApplicationServiceBindingsRequest.builder() + .serviceBindingsV3() + .list( + ListServiceBindingsRequest.builder() .page(page) .applicationId(application.getId()) .build())) .flatMap( serviceBinding -> - requestRemoveServiceBinding( - cloudFoundryClient, - application.getId(), - ResourceUtils.getId(serviceBinding)) + cloudFoundryClient + .serviceBindingsV3() + .delete( + DeleteServiceBindingRequest.builder() + .serviceBindingId(serviceBinding.getId()) + .build()) + .then() .doOnError( t -> LOGGER.error( From e98ece3471ccaa605b5a6d33bff14a00e481f977 Mon Sep 17 00:00:00 2001 From: Joris Baum Date: Fri, 17 Apr 2026 16:45:46 +0200 Subject: [PATCH 10/11] Clarify SKIP_BROWSER_AUTH_TESTS description in README Reword to explain the env var is for when UAA doesn't have browser-based auth configured, rather than referencing "non-interactive environments". --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7e516ec5416..06464884264 100644 --- a/README.md +++ b/README.md @@ -353,7 +353,7 @@ Name | Description `TEST_PROXY_PORT` | _(Optional)_ The port of a proxy to route all requests through. Defaults to `8080`. `TEST_PROXY_USERNAME` | _(Optional)_ The username for a proxy to route all requests through `TEST_SKIPSSLVALIDATION` | _(Optional)_ Whether to skip SSL validation when connecting to the Cloud Foundry instance. Defaults to `false`. -`SKIP_BROWSER_AUTH_TESTS` | _(Optional)_ Set to `true` to skip integration tests that require browser-based authentication (e.g., SSO tests). Useful when the Cloud Foundry instance does not support browser-based authentication or when running tests in a non-interactive environment. Defaults to `false`. +`SKIP_BROWSER_AUTH_TESTS` | _(Optional)_ Set to `true` to skip integration tests that require browser-based authentication (e.g., SSO tests). Useful when the Cloud Foundry instance's UAA does not have browser-based authentication configured. Defaults to `false`. `SKIP_METRIC_REGISTRAR_TESTS` | _(Optional)_ Set to `true` to skip integration tests that require the Metric Registrar service (e.g., MetricRegistrarTest). Useful when the Cloud Foundry instance does not have the Metric Registrar service available. Defaults to `false`. `SKIP_TCP_ROUTING_TESTS` | _(Optional)_ Set to `true` to skip TCP routing integration tests (TcpRoutesTest, RouterGroupsTest). Useful when the Cloud Foundry instance does not have TCP routing configured (i.e., no `routing_endpoint` in the info payload). Defaults to `false`. `SKIP_V2_TESTS` | _(Optional)_ Set to `true` to skip all V2 API integration tests. Useful when the Cloud Foundry V2 API is rate-limited or unavailable. When enabled, tests annotated with `@RequiresV2Api` will be skipped, including V3 tests that depend on V2 API calls (e.g., service broker creation). Defaults to `false`. From 25cb827d848bc79d8d01d6e07d78609f51bb59be Mon Sep 17 00:00:00 2001 From: Joris Baum Date: Fri, 17 Apr 2026 16:48:11 +0200 Subject: [PATCH 11/11] Share V2 skip condition via RequiresV2Api Move the SKIP_V2_TESTS check into a reusable static method in V2ApiCondition. --- .../test/java/org/cloudfoundry/CloudFoundryCleaner.java | 6 +----- .../src/test/java/org/cloudfoundry/RequiresV2Api.java | 7 ++++++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/integration-test/src/test/java/org/cloudfoundry/CloudFoundryCleaner.java b/integration-test/src/test/java/org/cloudfoundry/CloudFoundryCleaner.java index d491e880907..feaed95df6a 100644 --- a/integration-test/src/test/java/org/cloudfoundry/CloudFoundryCleaner.java +++ b/integration-test/src/test/java/org/cloudfoundry/CloudFoundryCleaner.java @@ -131,11 +131,7 @@ final class CloudFoundryCleaner implements InitializingBean, DisposableBean { private static final Logger LOGGER = LoggerFactory.getLogger("cloudfoundry-client.test"); - private static final boolean RUN_V2_CLEANUP = isRunV2Tests(); - - private static boolean isRunV2Tests() { - return !"true".equalsIgnoreCase(System.getenv(RequiresV2Api.SKIP_V2_TESTS_ENV)); - } + private static final boolean RUN_V2_CLEANUP = RequiresV2Api.V2ApiCondition.isEnabled(); private static final Map STANDARD_FEATURE_FLAGS = FluentMap.builder() diff --git a/integration-test/src/test/java/org/cloudfoundry/RequiresV2Api.java b/integration-test/src/test/java/org/cloudfoundry/RequiresV2Api.java index 82bedb514e1..b11fe8ca06b 100644 --- a/integration-test/src/test/java/org/cloudfoundry/RequiresV2Api.java +++ b/integration-test/src/test/java/org/cloudfoundry/RequiresV2Api.java @@ -59,9 +59,14 @@ */ class V2ApiCondition implements ExecutionCondition { + /** Returns {@code true} if V2 API tests should run (i.e., not skipped). */ + public static boolean isEnabled() { + return !"true".equalsIgnoreCase(System.getenv(SKIP_V2_TESTS_ENV)); + } + @Override public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { - if ("true".equalsIgnoreCase(System.getenv(SKIP_V2_TESTS_ENV))) { + if (!isEnabled()) { return ConditionEvaluationResult.disabled( "V2 API tests are disabled via " + SKIP_V2_TESTS_ENV