Skip to content
This repository has been archived by the owner on Jan 19, 2022. It is now read-only.

Commit

Permalink
Extend PCF module to read tags to support user-provided services (#2238)
Browse files Browse the repository at this point in the history
Extend the PCF module to read tags of apps to support user-provided services.
  • Loading branch information
dzou committed Mar 5, 2020
1 parent 923b65b commit 05334fd
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 4 deletions.
32 changes: 32 additions & 0 deletions docs/src/main/asciidoc/cloudfoundry.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,35 @@ This includes both MySQL and PostgreSQL bindings to the same app.
WARNING: In order for the Cloud SQL integration to work in Cloud Foundry, auto-reconfiguration must be disabled.
You can do so using the `cf set-env <APP> JBP_CONFIG_SPRING_AUTO_RECONFIGURATION '{enabled: false}'` command.
Otherwise, Cloud Foundry will produce a `DataSource` with an invalid JDBC URL (i.e., `jdbc:mysql://null/null`).

=== User-Provided Services

https://docs.cloudfoundry.org/devguide/services/user-provided.html[User-provided services] enable developers to use services that are not available in the marketplace with their apps running on Cloud Foundry.
For example, you may want to use a user-provided service that points to a shared Google Service (like Cloud Spanner) used across your organization.

In order for Spring Cloud GCP to detect your user-provided service as a Google Cloud Service, you must add an https://docs.cloudfoundry.org/devguide/services/managing-services.html#instance-tags-create[instance tag] indicating the Google Cloud Service it uses.
The tag should simply be the Cloud Foundry name for the Google Service.

For example, if you create a user-provided service using Cloud Spanner, you might run:
[source, shell]
----
$ cf create-user-provided-service user-spanner-service -t "google-spanner" ...
----

This allows Spring Cloud GCP to retrieve the correct service properties from Cloud Foundry and use them in the auto configuration for your application.

A mapping of Google service names to Cloud Foundry names are provided below:

|===
| Google Cloud Service | Cloud Foundry Name (add this as a tag)
| https://cloud.google.com/pubsub[Google Cloud Pub/Sub] | `google-pubsub`
| https://cloud.google.com/storage[Google Cloud Storage] | `google-storage`
| https://cloud.google.com/spanner[Google Cloud Spanner] | `google-spanner`
| https://cloud.google.com/datastore[Datastore] | `google-datastore`
| https://cloud.google.com/firestore[Firestore] | `google-firestore`
| https://cloud.google.com/bigquery[BigQuery] | `google-bigquery`
| https://cloud.google.com/products/operations[Stackdriver Trace] | `google-stackdriver-trace`
| https://cloud.google.com/sql[Cloud Sql (MySQL)] | `google-cloudsql-mysql`
| https://cloud.google.com/sql[Cloud Sql (PostgreSQL)] | `google-cloudsql-postgres`
|===

Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,16 @@ private static Properties retrieveCfProperties(CfEnv cfEnv,
try {
List<CfService> serviceBindings = cfEnv.findServicesByLabel(cfServiceName);

if (serviceBindings == null) {
return properties;
// If finding by label fails, attempt to find the service by tag.
if (serviceBindings.isEmpty()) {
serviceBindings = cfEnv.findServicesByTag(cfServiceName);
}

if (serviceBindings.size() != 1) {
LOGGER.warn("The service " + cfServiceName + " has to be bound to a "
+ "Cloud Foundry application once and only once.");
if (serviceBindings.size() > 1) {
LOGGER.warn("The service " + cfServiceName + " has to be bound to a "
+ "Cloud Foundry application once and only once.");
}
return properties;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,20 @@ public void test2Sqls() throws IOException {
.isEqualTo("test-key");
}

@Test
public void testUserProvidedServices() throws IOException {
String vcapFileContents = new String(Files.readAllBytes(
new ClassPathResource("VCAP_SERVICES_USER_PROVIDED").getFile().toPath()));
mockVcapServices(vcapFileContents);

this.initializer.postProcessEnvironment(this.context.getEnvironment(), null);

assertThat(getProperty("spring.cloud.gcp.spanner.project-id"))
.isEqualTo("spanner-project-id");
assertThat(getProperty("spring.cloud.gcp.spanner.instance-id"))
.isEqualTo("spanner-instance");
}

private String getPrivateKeyDataFromJson(String json, String serviceName) {
JsonParser parser = JsonParserFactory.getJsonParser();
Map<String, Object> vcapMap = parser.parseMap(json);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"user-provided": [
{
"label": "user-provided",
"name": "supply-spanner-service",
"tags": ["google-spanner"],
"instance_name": "supply-spanner-service",
"binding_name": null,
"credentials": {
"Email": "hello-world@gmail.com",
"Name": "hello-world",
"PrivateKeyData": "xxxxxxxxx",
"ProjectId": "spanner-project-id",
"instance_id": "spanner-instance",
"UniqueId": "xxxxxxxxxx"
},
"syslog_drain_url": "",
"volume_mounts": []
}
]
}

0 comments on commit 05334fd

Please sign in to comment.