Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@
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.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;
Expand Down Expand Up @@ -172,8 +174,14 @@ private static ManifestV3Application.Builder toApplicationManifest(
variables,
raw -> getSidecar((Map<String, Object>) 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<String, Object>) raw, variables),
builder::metadata);

asBoolean(application, "default-route", variables, builder::defaultRoute);

return builder;
Expand Down Expand Up @@ -253,6 +261,31 @@ private static ManifestV3Service getService(Object raw, Map<String, String> vari
return builder.build();
}

private static Metadata getMetadata(Map<String, Object> raw, Map<String, String> variables) {

if (raw == null) return null;

Map<String, String> labels = new HashMap<>();
Map<String, String> 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<String, Object> toYaml(ManifestV3 manifest) {
Map<String, Object> yaml = new TreeMap<>();
yaml.put("version", manifest.getVersion());
Expand Down Expand Up @@ -282,8 +315,8 @@ private static Map<String, Object> 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;
}

Expand Down Expand Up @@ -337,4 +370,12 @@ private static Map<String, Object> toProcessYaml(ManifestV3Process process) {
putIfPresent(yaml, "timeout", process.getTimeout());
return yaml;
}

private static Map<String, Object> toMetadataYaml(Metadata metadata) {
if (metadata == null) return null;
Map<String, Object> map = new HashMap<>();
putIfPresent(map, "labels", metadata.getLabels());
putIfPresent(map, "annotations", metadata.getAnnotations());
return map.isEmpty() ? null : map;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -31,25 +30,17 @@
@Value.Immutable
abstract class _ManifestV3Application extends _ApplicationManifestCommon {

/**
* The annotations configured for this application
*/
@AllowNulls
@Nullable
abstract Map<String, String> getAnnotations();

/**
* Generate a default route based on the application name
*/
@Nullable
abstract Boolean getDefaultRoute();

/**
* The labels configured for this application
* The metadata for this application
*/
@AllowNulls
@Nullable
abstract Map<String, String> getLabels();
abstract Metadata getMetadata();

/**
* The collection of processes configured for this application
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import org.cloudfoundry.client.v3.Metadata;
import org.cloudfoundry.client.v3.processes.ReadinessHealthCheckType;
import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -60,6 +61,62 @@ 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -789,6 +791,62 @@ 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();
Map<String, String> labels = Collections.singletonMap("test-label", "test-label-value");
Map<String, String> 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(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));
}

@Test
@IfCloudFoundryVersion(
greaterThanOrEqualTo =
Expand Down