From 033ecebbc09b71e9911f3e182c5d0590e2502b94 Mon Sep 17 00:00:00 2001 From: Xiaocong Li Date: Sun, 5 Oct 2025 23:09:32 +0800 Subject: [PATCH 1/6] move label and annotations under metadata node --- .../ApplicationManifestUtilsV3.java | 64 +++++++++++++++++-- .../applications/_ManifestV3Application.java | 15 +---- .../ApplicationManifestUtilsV3Test.java | 48 ++++++++++++++ .../operations/ApplicationsTest.java | 60 +++++++++++++++++ 4 files changed, 171 insertions(+), 16 deletions(-) diff --git a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/applications/ApplicationManifestUtilsV3.java b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/applications/ApplicationManifestUtilsV3.java index 942e1e9d74..de279f7334 100644 --- a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/applications/ApplicationManifestUtilsV3.java +++ b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/applications/ApplicationManifestUtilsV3.java @@ -30,8 +30,11 @@ import java.util.Map; import java.util.Optional; import java.util.TreeMap; +import java.util.HashMap; import java.util.regex.Pattern; import java.util.stream.Stream; + +import org.cloudfoundry.client.v3.Metadata; import org.cloudfoundry.client.v3.processes.HealthCheckType; import org.cloudfoundry.client.v3.processes.ReadinessHealthCheckType; import org.yaml.snakeyaml.DumperOptions; @@ -172,8 +175,13 @@ private static ManifestV3Application.Builder toApplicationManifest( variables, raw -> getSidecar((Map) raw, variables), builder::sidecar); - as(application, "labels", variables, Map.class::cast, builder::labels); - as(application, "annotations", variables, Map.class::cast, builder::annotations); + + as(application, + "metadata", + variables, + raw -> getMetadata((Map) raw, variables), + builder::metadata); + asBoolean(application, "default-route", variables, builder::defaultRoute); return builder; @@ -253,6 +261,46 @@ private static ManifestV3Service getService(Object raw, Map vari return builder.build(); } + private static Metadata getMetadata( + Map raw, + Map variables) { + + if (raw == null) return null; + + Map labels = new HashMap<>(); + Map annotations = new HashMap<>(); + + asMap( + raw, + "labels", + variables, + String.class::cast, + labels::put + ); + + asMap( + raw, + "annotations", + variables, + String.class::cast, + annotations::put + ); + + if (labels.isEmpty() && annotations.isEmpty()) { + return null; + } + + Metadata.Builder builder = Metadata.builder(); + if (!labels.isEmpty()) { + builder.labels(labels); + } + if (!annotations.isEmpty()) { + builder.annotations(annotations); + } + return builder.build(); + } + + private static Map toYaml(ManifestV3 manifest) { Map yaml = new TreeMap<>(); yaml.put("version", manifest.getVersion()); @@ -282,8 +330,8 @@ private static Map toApplicationYaml(ManifestV3Application appli "sidecars", convertCollection( application.getSidecars(), ApplicationManifestUtilsV3::toSidecarsYaml)); - putIfPresent(yaml, "labels", application.getLabels()); - putIfPresent(yaml, "annotations", application.getAnnotations()); + + putIfPresent(yaml, "metadata", toMetadataYaml(application.getMetadata())); return yaml; } @@ -337,4 +385,12 @@ private static Map toProcessYaml(ManifestV3Process process) { putIfPresent(yaml, "timeout", process.getTimeout()); return yaml; } + + private static Map toMetadataYaml(Metadata metadata) { + if (metadata == null) return null; + Map map = new HashMap<>(); + putIfPresent(map, "labels", metadata.getLabels()); + putIfPresent(map, "annotations", metadata.getAnnotations()); + return map.isEmpty() ? null : map; + } } diff --git a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/applications/_ManifestV3Application.java b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/applications/_ManifestV3Application.java index 1da9f0fc43..800eb2272c 100644 --- a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/applications/_ManifestV3Application.java +++ b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/applications/_ManifestV3Application.java @@ -16,10 +16,9 @@ package org.cloudfoundry.operations.applications; - -import org.cloudfoundry.AllowNulls; import org.cloudfoundry.Nullable; import org.immutables.value.Value; +import org.cloudfoundry.client.v3.Metadata; import java.util.List; import java.util.Map; @@ -31,13 +30,6 @@ @Value.Immutable abstract class _ManifestV3Application extends _ApplicationManifestCommon { - /** - * The annotations configured for this application - */ - @AllowNulls - @Nullable - abstract Map getAnnotations(); - /** * Generate a default route based on the application name */ @@ -45,11 +37,10 @@ abstract class _ManifestV3Application extends _ApplicationManifestCommon { abstract Boolean getDefaultRoute(); /** - * The labels configured for this application + * The metadta for this application */ - @AllowNulls @Nullable - abstract Map getLabels(); + abstract Metadata getMetadata(); /** * The collection of processes configured for this application diff --git a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/applications/ApplicationManifestUtilsV3Test.java b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/applications/ApplicationManifestUtilsV3Test.java index fd7826d444..8728947f3b 100644 --- a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/applications/ApplicationManifestUtilsV3Test.java +++ b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/applications/ApplicationManifestUtilsV3Test.java @@ -5,7 +5,9 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; + import org.cloudfoundry.client.v3.processes.ReadinessHealthCheckType; +import org.cloudfoundry.client.v3.Metadata; import org.junit.jupiter.api.Test; class ApplicationManifestUtilsV3Test { @@ -60,6 +62,52 @@ void testWithDockerApp() throws IOException { assertSerializeDeserialize(manifest); } + @Test + void testWithMetadata() throws IOException { + ManifestV3 manifest = + ManifestV3.builder() + .application( + ManifestV3Application.builder() + .name("test-app") + .metadata( + Metadata.builder() + .label("test-label", "test-label-value") + .annotation("test-annotation", "test-annotation-value") + .build()) + .build()) + .build(); + + assertSerializeDeserialize(manifest); + } + + @Test + void testWithMetadataOnlyLabel() throws IOException { + ManifestV3 manifest = + ManifestV3.builder() + .application( + ManifestV3Application.builder() + .name("test-app") + .metadata(Metadata.builder().label("test-label", "test-label-value").build()) + .build()) + .build(); + + assertSerializeDeserialize(manifest); + } + + @Test + void testWithMetadataOnlyAnnotation() throws IOException { + ManifestV3 manifest = + ManifestV3.builder() + .application( + ManifestV3Application.builder() + .name("test-app") + .metadata(Metadata.builder().annotation("test-annotation", "test-annotation-value").build()) + .build()) + .build(); + + assertSerializeDeserialize(manifest); + } + private void assertSerializeDeserialize(ManifestV3 manifest) throws IOException { Path file = Files.createTempFile("test-manifest-", ".yml"); ApplicationManifestUtilsV3.write(file, manifest); 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 2ffd49b285..c3492404a1 100644 --- a/integration-test/src/test/java/org/cloudfoundry/operations/ApplicationsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/operations/ApplicationsTest.java @@ -100,6 +100,7 @@ public final class ApplicationsTest extends AbstractIntegrationTest { private static final String DEFAULT_ROUTER_GROUP = "default-tcp"; @Autowired private CloudFoundryOperations cloudFoundryOperations; + @Autowired private org.cloudfoundry.client.CloudFoundryClient cloudFoundryClient; @Autowired private String organizationName; @@ -789,6 +790,65 @@ public void pushManifestV3() throws IOException { .verify(Duration.ofMinutes(5)); } + @Test + @IfCloudFoundryVersion(greaterThanOrEqualTo = CloudFoundryVersion.PCF_4_v2) + public void pushManifestV3WithMetadata() throws IOException { + String applicationName = this.nameFactory.getApplicationName(); + + ManifestV3 manifest = + ManifestV3.builder() + .application( + ManifestV3Application.builder() + .buildpack("staticfile_buildpack") + .disk(512) + .healthCheckType(ApplicationHealthCheck.PORT) + .memory(64) + .name(applicationName) + .metadata( + org.cloudfoundry.client.v3.Metadata.builder() + .label("test-label", "test-label-value") + .annotation("test-annotation", "test-annotation-value") + .build() + ) + .path( + new ClassPathResource("test-application.zip") + .getFile() + .toPath()) + .build()) + .build(); + + this.cloudFoundryOperations + .applications() + .pushManifestV3(PushManifestV3Request.builder().manifest(manifest).build()) + .then( + // fetch application id via operations API + this.cloudFoundryOperations + .applications() + .get( + org.cloudfoundry.operations.applications.GetApplicationRequest + .builder() + .name(applicationName) + .build()) + .map(org.cloudfoundry.operations.applications.ApplicationDetail::getId)) + .flatMap( + appId -> + this.cloudFoundryClient + .applicationsV3() + .get( + org.cloudfoundry.client.v3.applications + .GetApplicationRequest + .builder() + .applicationId(appId) + .build())) + .map( + response -> + response.getMetadata().getLabels().get("test-label")) + .as(StepVerifier::create) + .expectNext("test-value") + .expectComplete() + .verify(Duration.ofMinutes(5)); + } + @Test @IfCloudFoundryVersion( greaterThanOrEqualTo = From 4c85487a16fbd0f354ed1822f53ee44d76dc6032 Mon Sep 17 00:00:00 2001 From: Xiaocong Li Date: Mon, 6 Oct 2025 21:53:29 +0800 Subject: [PATCH 2/6] code cleanup --- .../operations/ApplicationsTest.java | 73 +++++++------------ 1 file changed, 26 insertions(+), 47 deletions(-) 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 c3492404a1..9152aae252 100644 --- a/integration-test/src/test/java/org/cloudfoundry/operations/ApplicationsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/operations/ApplicationsTest.java @@ -100,7 +100,6 @@ public final class ApplicationsTest extends AbstractIntegrationTest { private static final String DEFAULT_ROUTER_GROUP = "default-tcp"; @Autowired private CloudFoundryOperations cloudFoundryOperations; - @Autowired private org.cloudfoundry.client.CloudFoundryClient cloudFoundryClient; @Autowired private String organizationName; @@ -794,57 +793,37 @@ public void pushManifestV3() throws IOException { @IfCloudFoundryVersion(greaterThanOrEqualTo = CloudFoundryVersion.PCF_4_v2) public void pushManifestV3WithMetadata() throws IOException { String applicationName = this.nameFactory.getApplicationName(); - - ManifestV3 manifest = - ManifestV3.builder() - .application( - ManifestV3Application.builder() - .buildpack("staticfile_buildpack") - .disk(512) - .healthCheckType(ApplicationHealthCheck.PORT) - .memory(64) - .name(applicationName) - .metadata( - org.cloudfoundry.client.v3.Metadata.builder() - .label("test-label", "test-label-value") - .annotation("test-annotation", "test-annotation-value") - .build() - ) - .path( - new ClassPathResource("test-application.zip") - .getFile() - .toPath()) - .build()) - .build(); + Map labels = Collections.singletonMap("test-label", "test-label-value"); + Map annotations = Collections.singletonMap("test-annotation", "test-annotation-value"); this.cloudFoundryOperations .applications() - .pushManifestV3(PushManifestV3Request.builder().manifest(manifest).build()) - .then( - // fetch application id via operations API - this.cloudFoundryOperations - .applications() - .get( - org.cloudfoundry.operations.applications.GetApplicationRequest - .builder() - .name(applicationName) + .pushManifestV3( + PushManifestV3Request.builder() + .manifest( + ManifestV3.builder() + .application( + ManifestV3Application.builder() + .buildpack("staticfile_buildpack") + .disk(512) + .healthCheckType(ApplicationHealthCheck.PORT) + .memory(64) + .name(applicationName) + .metadata( + org.cloudfoundry.client.v3.Metadata.builder() + .labels(labels) + .annotations(annotations) + .build()) + .path(new ClassPathResource("test-application.zip").getFile().toPath()) + .build()) .build()) - .map(org.cloudfoundry.operations.applications.ApplicationDetail::getId)) - .flatMap( - appId -> - this.cloudFoundryClient - .applicationsV3() - .get( - org.cloudfoundry.client.v3.applications - .GetApplicationRequest - .builder() - .applicationId(appId) - .build())) - .map( - response -> - response.getMetadata().getLabels().get("test-label")) + .build()) + .map(manifestm -> manifest.getMetadata()) .as(StepVerifier::create) - .expectNext("test-value") + .consumeNextWith(metadata -> { + assertThat(metadata.getLabels()).containsAllEntriesOf(labels); + assertThat(metadata.getAnnotations()).containsAllEntriesOf(annotations); + }) .expectComplete() .verify(Duration.ofMinutes(5)); } From 795966162b54420f4b84248deab5b088b4684f9c Mon Sep 17 00:00:00 2001 From: Xiaocong Li Date: Tue, 7 Oct 2025 23:51:18 +0800 Subject: [PATCH 3/6] fix typo in integrationtest --- .../test/java/org/cloudfoundry/operations/ApplicationsTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 9152aae252..a9e56cf799 100644 --- a/integration-test/src/test/java/org/cloudfoundry/operations/ApplicationsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/operations/ApplicationsTest.java @@ -818,7 +818,7 @@ public void pushManifestV3WithMetadata() throws IOException { .build()) .build()) .build()) - .map(manifestm -> manifest.getMetadata()) + .map(manifest -> manifest.getMetadata()) .as(StepVerifier::create) .consumeNextWith(metadata -> { assertThat(metadata.getLabels()).containsAllEntriesOf(labels); From 74ca1d6043af25b10c424f70d7f145cc6c74808a Mon Sep 17 00:00:00 2001 From: Xiaocong Li Date: Wed, 8 Oct 2025 22:51:18 +0800 Subject: [PATCH 4/6] fix spotless check --- .../ApplicationManifestUtilsV3.java | 27 +++++-------------- .../ApplicationManifestUtilsV3Test.java | 19 +++++++++---- .../operations/ApplicationsTest.java | 27 ++++++++++++------- 3 files changed, 38 insertions(+), 35 deletions(-) diff --git a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/applications/ApplicationManifestUtilsV3.java b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/applications/ApplicationManifestUtilsV3.java index de279f7334..da335ae704 100644 --- a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/applications/ApplicationManifestUtilsV3.java +++ b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/applications/ApplicationManifestUtilsV3.java @@ -26,14 +26,13 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.TreeMap; -import java.util.HashMap; import java.util.regex.Pattern; import java.util.stream.Stream; - import org.cloudfoundry.client.v3.Metadata; import org.cloudfoundry.client.v3.processes.HealthCheckType; import org.cloudfoundry.client.v3.processes.ReadinessHealthCheckType; @@ -176,7 +175,8 @@ private static ManifestV3Application.Builder toApplicationManifest( raw -> getSidecar((Map) raw, variables), builder::sidecar); - as(application, + as( + application, "metadata", variables, raw -> getMetadata((Map) raw, variables), @@ -261,30 +261,16 @@ private static ManifestV3Service getService(Object raw, Map vari return builder.build(); } - private static Metadata getMetadata( - Map raw, - Map variables) { + private static Metadata getMetadata(Map raw, Map variables) { if (raw == null) return null; Map labels = new HashMap<>(); Map annotations = new HashMap<>(); - asMap( - raw, - "labels", - variables, - String.class::cast, - labels::put - ); + asMap(raw, "labels", variables, String.class::cast, labels::put); - asMap( - raw, - "annotations", - variables, - String.class::cast, - annotations::put - ); + asMap(raw, "annotations", variables, String.class::cast, annotations::put); if (labels.isEmpty() && annotations.isEmpty()) { return null; @@ -300,7 +286,6 @@ private static Metadata getMetadata( return builder.build(); } - private static Map toYaml(ManifestV3 manifest) { Map yaml = new TreeMap<>(); yaml.put("version", manifest.getVersion()); diff --git a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/applications/ApplicationManifestUtilsV3Test.java b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/applications/ApplicationManifestUtilsV3Test.java index 8728947f3b..cf54b8120b 100644 --- a/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/applications/ApplicationManifestUtilsV3Test.java +++ b/cloudfoundry-operations/src/test/java/org/cloudfoundry/operations/applications/ApplicationManifestUtilsV3Test.java @@ -5,9 +5,8 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; - -import org.cloudfoundry.client.v3.processes.ReadinessHealthCheckType; import org.cloudfoundry.client.v3.Metadata; +import org.cloudfoundry.client.v3.processes.ReadinessHealthCheckType; import org.junit.jupiter.api.Test; class ApplicationManifestUtilsV3Test { @@ -72,7 +71,9 @@ void testWithMetadata() throws IOException { .metadata( Metadata.builder() .label("test-label", "test-label-value") - .annotation("test-annotation", "test-annotation-value") + .annotation( + "test-annotation", + "test-annotation-value") .build()) .build()) .build(); @@ -87,7 +88,10 @@ void testWithMetadataOnlyLabel() throws IOException { .application( ManifestV3Application.builder() .name("test-app") - .metadata(Metadata.builder().label("test-label", "test-label-value").build()) + .metadata( + Metadata.builder() + .label("test-label", "test-label-value") + .build()) .build()) .build(); @@ -101,7 +105,12 @@ void testWithMetadataOnlyAnnotation() throws IOException { .application( ManifestV3Application.builder() .name("test-app") - .metadata(Metadata.builder().annotation("test-annotation", "test-annotation-value").build()) + .metadata( + Metadata.builder() + .annotation( + "test-annotation", + "test-annotation-value") + .build()) .build()) .build(); 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 a9e56cf799..28a8f87a15 100644 --- a/integration-test/src/test/java/org/cloudfoundry/operations/ApplicationsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/operations/ApplicationsTest.java @@ -794,7 +794,8 @@ public void pushManifestV3() throws IOException { public void pushManifestV3WithMetadata() throws IOException { String applicationName = this.nameFactory.getApplicationName(); Map labels = Collections.singletonMap("test-label", "test-label-value"); - Map annotations = Collections.singletonMap("test-annotation", "test-annotation-value"); + Map annotations = + Collections.singletonMap("test-annotation", "test-annotation-value"); this.cloudFoundryOperations .applications() @@ -806,24 +807,32 @@ public void pushManifestV3WithMetadata() throws IOException { ManifestV3Application.builder() .buildpack("staticfile_buildpack") .disk(512) - .healthCheckType(ApplicationHealthCheck.PORT) + .healthCheckType( + ApplicationHealthCheck.PORT) .memory(64) .name(applicationName) .metadata( - org.cloudfoundry.client.v3.Metadata.builder() + org.cloudfoundry.client.v3 + .Metadata.builder() .labels(labels) - .annotations(annotations) + .annotations( + annotations) .build()) - .path(new ClassPathResource("test-application.zip").getFile().toPath()) + .path( + new ClassPathResource( + "test-application.zip") + .getFile() + .toPath()) .build()) .build()) .build()) .map(manifest -> manifest.getMetadata()) .as(StepVerifier::create) - .consumeNextWith(metadata -> { - assertThat(metadata.getLabels()).containsAllEntriesOf(labels); - assertThat(metadata.getAnnotations()).containsAllEntriesOf(annotations); - }) + .consumeNextWith( + metadata -> { + assertThat(metadata.getLabels()).containsAllEntriesOf(labels); + assertThat(metadata.getAnnotations()).containsAllEntriesOf(annotations); + }) .expectComplete() .verify(Duration.ofMinutes(5)); } From bb9b25219ca5bc73786951f321f4af1507d18ea0 Mon Sep 17 00:00:00 2001 From: Xiaocong Li Date: Thu, 9 Oct 2025 11:55:43 +0800 Subject: [PATCH 5/6] fix integration test build issue and fix a typo --- .../applications/_ManifestV3Application.java | 2 +- .../operations/ApplicationsTest.java | 55 ++++++++----------- 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/applications/_ManifestV3Application.java b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/applications/_ManifestV3Application.java index 800eb2272c..b235a1eb5d 100644 --- a/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/applications/_ManifestV3Application.java +++ b/cloudfoundry-operations/src/main/java/org/cloudfoundry/operations/applications/_ManifestV3Application.java @@ -37,7 +37,7 @@ abstract class _ManifestV3Application extends _ApplicationManifestCommon { abstract Boolean getDefaultRoute(); /** - * The metadta for this application + * The metadata for this application */ @Nullable abstract Metadata getMetadata(); 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 28a8f87a15..2e98b004d2 100644 --- a/integration-test/src/test/java/org/cloudfoundry/operations/ApplicationsTest.java +++ b/integration-test/src/test/java/org/cloudfoundry/operations/ApplicationsTest.java @@ -797,42 +797,31 @@ public void pushManifestV3WithMetadata() throws IOException { Map annotations = Collections.singletonMap("test-annotation", "test-annotation-value"); + ManifestV3 manifest = + ManifestV3.builder() + .application( + ManifestV3Application.builder() + .buildpack("staticfile_buildpack") + .disk(512) + .healthCheckType(ApplicationHealthCheck.PORT) + .memory(64) + .name(applicationName) + .path( + new ClassPathResource("test-application.zip") + .getFile() + .toPath()) + .metadata( + org.cloudfoundry.client.v3.Metadata.builder() + .labels(labels) + .annotations(annotations) + .build()) + .build()) + .build(); + this.cloudFoundryOperations .applications() - .pushManifestV3( - PushManifestV3Request.builder() - .manifest( - ManifestV3.builder() - .application( - ManifestV3Application.builder() - .buildpack("staticfile_buildpack") - .disk(512) - .healthCheckType( - ApplicationHealthCheck.PORT) - .memory(64) - .name(applicationName) - .metadata( - org.cloudfoundry.client.v3 - .Metadata.builder() - .labels(labels) - .annotations( - annotations) - .build()) - .path( - new ClassPathResource( - "test-application.zip") - .getFile() - .toPath()) - .build()) - .build()) - .build()) - .map(manifest -> manifest.getMetadata()) + .pushManifestV3(PushManifestV3Request.builder().manifest(manifest).build()) .as(StepVerifier::create) - .consumeNextWith( - metadata -> { - assertThat(metadata.getLabels()).containsAllEntriesOf(labels); - assertThat(metadata.getAnnotations()).containsAllEntriesOf(annotations); - }) .expectComplete() .verify(Duration.ofMinutes(5)); } From a892ebc6a9cb6a08bad26acbbdc908d1d6689bf0 Mon Sep 17 00:00:00 2001 From: Xiaocong Li Date: Mon, 13 Oct 2025 17:43:21 +0800 Subject: [PATCH 6/6] involve cloudFoundryClient in operations ApplicationsTest to verify manefest metadata after pushing --- .../operations/ApplicationsTest.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) 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 2e98b004d2..36e1bd9456 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.client.CloudFoundryClient; import org.cloudfoundry.logcache.v1.Envelope; import org.cloudfoundry.logcache.v1.EnvelopeBatch; import org.cloudfoundry.logcache.v1.EnvelopeType; @@ -108,6 +109,7 @@ public final class ApplicationsTest extends AbstractIntegrationTest { @Autowired private String serviceName; @Autowired private LogCacheClient logCacheClient; + @Autowired private CloudFoundryClient cloudFoundryClient; // To create a service in #pushBindService, the Service Broker must be installed first. // We ensure it is by loading the serviceBrokerId @Lazy bean. @@ -821,7 +823,26 @@ public void pushManifestV3WithMetadata() throws IOException { this.cloudFoundryOperations .applications() .pushManifestV3(PushManifestV3Request.builder().manifest(manifest).build()) + .then( + this.cloudFoundryOperations + .applications() + .get(GetApplicationRequest.builder().name(applicationName).build())) + .map(ApplicationDetail::getId) + .flatMap( + id -> + this.cloudFoundryClient + .applicationsV3() + .get( + org.cloudfoundry.client.v3.applications + .GetApplicationRequest.builder() + .applicationId(id) + .build())) .as(StepVerifier::create) + .expectNextMatches( + createdApp -> + labels.equals(createdApp.getMetadata().getLabels()) + && annotations.equals( + createdApp.getMetadata().getAnnotations())) .expectComplete() .verify(Duration.ofMinutes(5)); }