Skip to content

Commit c4c6820

Browse files
authored
Connectors: add option to turn off the built-in post-processors (#1680)
* Add property to disable built-in post-processors, including sample code for binding third-party brokers * Update links to supported service brokers * Review feedback: adapt documentation * Bugfix: preserve custom query string parameters in local RabbitMQ URI; relax other parsers to allow unknown parameters to support third-party brokers * Refactor to allow multiple CloudFoundryServiceBindingConfigurationSources in configuration, each scoped to a subset of post-processors * Fix broken build * Review feedback: filter already registered post-processors
1 parent e061cc0 commit c4c6820

52 files changed

Lines changed: 904 additions & 238 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/Bootstrap/test/AutoConfiguration.Test/HostBuilderExtensionsTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ private static void AssertConnectorsAreAutowired(HostWrapper hostWrapper)
308308
var configuration = hostWrapper.Services.GetRequiredService<IConfiguration>();
309309

310310
configuration.EnumerateProviders<KubernetesServiceBindingConfigurationProvider>().Should().NotBeEmpty();
311-
configuration.EnumerateProviders<CloudFoundryServiceBindingConfigurationProvider>().Should().ContainSingle();
311+
configuration.EnumerateProviders<CloudFoundryServiceBindingConfigurationProvider>().Should().NotBeEmpty();
312312

313313
hostWrapper.Services.GetService<ConnectorFactory<CosmosDbOptions, CosmosClient>>().Should().NotBeNull();
314314
hostWrapper.Services.GetService<ConnectorFactory<MongoDbOptions, IMongoClient>>().Should().NotBeNull();
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,14 @@
11
#nullable enable
2+
static Steeltoe.Configuration.CloudFoundry.ServiceBindings.ConfigurationBuilderExtensions.AddCloudFoundryServiceBindings(this Microsoft.Extensions.Configuration.IConfigurationBuilder! builder, Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes brokerTypes) -> Microsoft.Extensions.Configuration.IConfigurationBuilder!
3+
static Steeltoe.Configuration.CloudFoundry.ServiceBindings.ConfigurationBuilderExtensions.AddCloudFoundryServiceBindings(this Microsoft.Extensions.Configuration.IConfigurationBuilder! builder, System.Predicate<string!>! ignoreKeyPredicate, Steeltoe.Configuration.CloudFoundry.ServiceBindings.IServiceBindingsReader? serviceBindingsReader, Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes brokerTypes, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> Microsoft.Extensions.Configuration.IConfigurationBuilder!
4+
Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes
5+
Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.All = Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.Eureka | Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.Identity | Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.MongoDb | Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.MySql | Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.PostgreSql | Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.RabbitMQ | Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.Redis | Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.SqlServer -> Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes
6+
Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.Eureka = 1 -> Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes
7+
Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.Identity = 2 -> Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes
8+
Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.MongoDb = 4 -> Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes
9+
Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.MySql = 8 -> Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes
10+
Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.None = 0 -> Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes
11+
Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.PostgreSql = 16 -> Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes
12+
Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.RabbitMQ = 32 -> Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes
13+
Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.Redis = 64 -> Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes
14+
Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.SqlServer = 128 -> Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes

src/Configuration/src/CloudFoundry/ServiceBindings/CloudFoundryServiceBindingConfigurationSource.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,24 @@
22
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
33
// See the LICENSE file in the project root for more information.
44

5+
using System.Diagnostics;
56
using Microsoft.Extensions.Configuration;
67

78
namespace Steeltoe.Configuration.CloudFoundry.ServiceBindings;
89

10+
[DebuggerDisplay("{DebuggerToString(),nq}")]
911
internal sealed class CloudFoundryServiceBindingConfigurationSource : PostProcessorConfigurationSource, IConfigurationSource
1012
{
1113
private readonly IServiceBindingsReader _serviceBindingsReader;
1214

13-
public CloudFoundryServiceBindingConfigurationSource(IServiceBindingsReader serviceBindingsReader)
15+
public CloudFoundryServiceBrokerTypes BrokerTypes { get; }
16+
17+
public CloudFoundryServiceBindingConfigurationSource(IServiceBindingsReader serviceBindingsReader, CloudFoundryServiceBrokerTypes brokerTypes)
1418
{
1519
ArgumentNullException.ThrowIfNull(serviceBindingsReader);
1620

1721
_serviceBindingsReader = serviceBindingsReader;
22+
BrokerTypes = brokerTypes;
1823
}
1924

2025
public IConfigurationProvider Build(IConfigurationBuilder builder)
@@ -24,4 +29,9 @@ public IConfigurationProvider Build(IConfigurationBuilder builder)
2429
CaptureConfigurationBuilder(builder);
2530
return new CloudFoundryServiceBindingConfigurationProvider(this, _serviceBindingsReader);
2631
}
32+
33+
private string DebuggerToString()
34+
{
35+
return $"{GetType().FullName} ({BrokerTypes})";
36+
}
2737
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information.
4+
5+
namespace Steeltoe.Configuration.CloudFoundry.ServiceBindings;
6+
7+
/// <summary>
8+
/// Lists the built-in Cloud Foundry service brokers.
9+
/// </summary>
10+
[Flags]
11+
public enum CloudFoundryServiceBrokerTypes
12+
{
13+
/// <summary>
14+
/// Don't use any of the built-in brokers.
15+
/// </summary>
16+
None = 0x0,
17+
18+
/// <summary>
19+
/// Use the built-in brokers for Netflix Eureka.
20+
/// </summary>
21+
Eureka = 0x1,
22+
23+
/// <summary>
24+
/// Use the built-in brokers for JWT and OpenID Connect.
25+
/// </summary>
26+
Identity = 0x2,
27+
28+
/// <summary>
29+
/// Use the built-in brokers for MongoDB.
30+
/// </summary>
31+
MongoDb = 0x4,
32+
33+
/// <summary>
34+
/// Use the built-in brokers for MySQL.
35+
/// </summary>
36+
MySql = 0x8,
37+
38+
/// <summary>
39+
/// Use the built-in brokers for PostgreSQL.
40+
/// </summary>
41+
PostgreSql = 0x10,
42+
43+
/// <summary>
44+
/// Use the built-in brokers for RabbitMQ.
45+
/// </summary>
46+
RabbitMQ = 0x20,
47+
48+
/// <summary>
49+
/// Use the built-in brokers for Redis/Valkey.
50+
/// </summary>
51+
Redis = 0x40,
52+
53+
/// <summary>
54+
/// Use the built-in brokers for Microsoft SQL Server.
55+
/// </summary>
56+
SqlServer = 0x80,
57+
58+
/// <summary>
59+
/// Use all built-in brokers.
60+
/// </summary>
61+
All = Eureka | Identity | MongoDb | MySql | PostgreSql | RabbitMQ | Redis | SqlServer
62+
}

src/Configuration/src/CloudFoundry/ServiceBindings/ConfigurationBuilderExtensions.cs

Lines changed: 111 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,24 @@ public static class ConfigurationBuilderExtensions
2929
/// </returns>
3030
public static IConfigurationBuilder AddCloudFoundryServiceBindings(this IConfigurationBuilder builder)
3131
{
32-
return builder.AddCloudFoundryServiceBindings(DefaultIgnoreKeyPredicate, DefaultReader, NullLoggerFactory.Instance);
32+
return builder.AddCloudFoundryServiceBindings(DefaultIgnoreKeyPredicate, null, CloudFoundryServiceBrokerTypes.All, NullLoggerFactory.Instance);
33+
}
34+
35+
/// <summary>
36+
/// Adds CloudFoundry service bindings from the JSON provided by the specified reader.
37+
/// </summary>
38+
/// <param name="builder">
39+
/// The <see cref="IConfigurationBuilder" /> to add configuration to.
40+
/// </param>
41+
/// <param name="brokerTypes">
42+
/// The set of broker types to read service bindings for.
43+
/// </param>
44+
/// <returns>
45+
/// The incoming <paramref name="builder" /> so that additional calls can be chained.
46+
/// </returns>
47+
public static IConfigurationBuilder AddCloudFoundryServiceBindings(this IConfigurationBuilder builder, CloudFoundryServiceBrokerTypes brokerTypes)
48+
{
49+
return builder.AddCloudFoundryServiceBindings(DefaultIgnoreKeyPredicate, null, brokerTypes, NullLoggerFactory.Instance);
3350
}
3451

3552
/// <summary>
@@ -46,7 +63,8 @@ public static IConfigurationBuilder AddCloudFoundryServiceBindings(this IConfigu
4663
/// </returns>
4764
public static IConfigurationBuilder AddCloudFoundryServiceBindings(this IConfigurationBuilder builder, IServiceBindingsReader serviceBindingsReader)
4865
{
49-
return builder.AddCloudFoundryServiceBindings(DefaultIgnoreKeyPredicate, serviceBindingsReader, NullLoggerFactory.Instance);
66+
return builder.AddCloudFoundryServiceBindings(DefaultIgnoreKeyPredicate, serviceBindingsReader, CloudFoundryServiceBrokerTypes.All,
67+
NullLoggerFactory.Instance);
5068
}
5169

5270
/// <summary>
@@ -56,7 +74,7 @@ public static IConfigurationBuilder AddCloudFoundryServiceBindings(this IConfigu
5674
/// The <see cref="IConfigurationBuilder" /> to add configuration to.
5775
/// </param>
5876
/// <param name="ignoreKeyPredicate">
59-
/// A predicate which is called before adding a key to the configuration. If it returns false, the key will be ignored.
77+
/// A predicate that is called before adding a key to the configuration. If it returns false, the key will be ignored.
6078
/// </param>
6179
/// <param name="serviceBindingsReader">
6280
/// The source to read JSON service bindings from.
@@ -69,15 +87,43 @@ public static IConfigurationBuilder AddCloudFoundryServiceBindings(this IConfigu
6987
/// </returns>
7088
public static IConfigurationBuilder AddCloudFoundryServiceBindings(this IConfigurationBuilder builder, Predicate<string> ignoreKeyPredicate,
7189
IServiceBindingsReader serviceBindingsReader, ILoggerFactory loggerFactory)
90+
{
91+
return AddCloudFoundryServiceBindings(builder, ignoreKeyPredicate, serviceBindingsReader, CloudFoundryServiceBrokerTypes.All, loggerFactory);
92+
}
93+
94+
/// <summary>
95+
/// Adds CloudFoundry service bindings from the JSON provided by the specified reader.
96+
/// </summary>
97+
/// <param name="builder">
98+
/// The <see cref="IConfigurationBuilder" /> to add configuration to.
99+
/// </param>
100+
/// <param name="ignoreKeyPredicate">
101+
/// A predicate that is called before adding a key to the configuration. If it returns false, the key will be ignored.
102+
/// </param>
103+
/// <param name="serviceBindingsReader">
104+
/// The source to read JSON service bindings from.
105+
/// </param>
106+
/// <param name="brokerTypes">
107+
/// The set of broker types to read service bindings for.
108+
/// </param>
109+
/// <param name="loggerFactory">
110+
/// Used for internal logging. Pass <see cref="NullLoggerFactory.Instance" /> to disable logging.
111+
/// </param>
112+
/// <returns>
113+
/// The incoming <paramref name="builder" /> so that additional calls can be chained.
114+
/// </returns>
115+
public static IConfigurationBuilder AddCloudFoundryServiceBindings(this IConfigurationBuilder builder, Predicate<string> ignoreKeyPredicate,
116+
IServiceBindingsReader? serviceBindingsReader, CloudFoundryServiceBrokerTypes brokerTypes, ILoggerFactory loggerFactory)
72117
{
73118
ArgumentNullException.ThrowIfNull(builder);
74119
ArgumentNullException.ThrowIfNull(ignoreKeyPredicate);
75-
ArgumentNullException.ThrowIfNull(serviceBindingsReader);
76120
ArgumentNullException.ThrowIfNull(loggerFactory);
77121

78-
if (!builder.EnumerateSources<CloudFoundryServiceBindingConfigurationSource>().Any())
122+
CloudFoundryServiceBrokerTypes missingBrokerTypes = GetMissingBrokerTypes(builder, brokerTypes);
123+
124+
if (missingBrokerTypes != CloudFoundryServiceBrokerTypes.None)
79125
{
80-
var source = new CloudFoundryServiceBindingConfigurationSource(serviceBindingsReader)
126+
var source = new CloudFoundryServiceBindingConfigurationSource(serviceBindingsReader ?? DefaultReader, missingBrokerTypes)
81127
{
82128
IgnoreKeyPredicate = ignoreKeyPredicate
83129
};
@@ -86,25 +132,71 @@ public static IConfigurationBuilder AddCloudFoundryServiceBindings(this IConfigu
86132
// WebApplicationBuilder immediately builds the configuration provider and loads it, which executes the post-processors.
87133
// Therefore, adding post-processors afterward is a no-op.
88134

89-
RegisterPostProcessors(source, loggerFactory);
135+
RegisterPostProcessors(source, missingBrokerTypes, loggerFactory);
90136
builder.Add(source);
91137
}
92138

93139
return builder;
94140
}
95141

96-
private static void RegisterPostProcessors(CloudFoundryServiceBindingConfigurationSource source, ILoggerFactory loggerFactory)
142+
private static CloudFoundryServiceBrokerTypes GetMissingBrokerTypes(IConfigurationBuilder builder, CloudFoundryServiceBrokerTypes brokerTypesRequested)
97143
{
98-
ILogger<EurekaCloudFoundryPostProcessor> eurekaLogger = loggerFactory.CreateLogger<EurekaCloudFoundryPostProcessor>();
99-
ILogger<IdentityCloudFoundryPostProcessor> identityLogger = loggerFactory.CreateLogger<IdentityCloudFoundryPostProcessor>();
100-
101-
source.RegisterPostProcessor(new EurekaCloudFoundryPostProcessor(eurekaLogger));
102-
source.RegisterPostProcessor(new IdentityCloudFoundryPostProcessor(identityLogger));
103-
source.RegisterPostProcessor(new MongoDbCloudFoundryPostProcessor());
104-
source.RegisterPostProcessor(new MySqlCloudFoundryPostProcessor());
105-
source.RegisterPostProcessor(new PostgreSqlCloudFoundryPostProcessor());
106-
source.RegisterPostProcessor(new RabbitMQCloudFoundryPostProcessor());
107-
source.RegisterPostProcessor(new RedisCloudFoundryPostProcessor());
108-
source.RegisterPostProcessor(new SqlServerCloudFoundryPostProcessor());
144+
CloudFoundryServiceBrokerTypes missingBrokerTypes = brokerTypesRequested;
145+
146+
if (brokerTypesRequested != CloudFoundryServiceBrokerTypes.None)
147+
{
148+
foreach (CloudFoundryServiceBindingConfigurationSource existingSource in builder.EnumerateSources<CloudFoundryServiceBindingConfigurationSource>())
149+
{
150+
missingBrokerTypes &= ~existingSource.BrokerTypes;
151+
}
152+
}
153+
154+
return missingBrokerTypes;
155+
}
156+
157+
private static void RegisterPostProcessors(CloudFoundryServiceBindingConfigurationSource source, CloudFoundryServiceBrokerTypes brokerTypes,
158+
ILoggerFactory loggerFactory)
159+
{
160+
if (brokerTypes.HasFlag(CloudFoundryServiceBrokerTypes.Eureka))
161+
{
162+
ILogger<EurekaCloudFoundryPostProcessor> eurekaLogger = loggerFactory.CreateLogger<EurekaCloudFoundryPostProcessor>();
163+
source.RegisterPostProcessor(new EurekaCloudFoundryPostProcessor(eurekaLogger));
164+
}
165+
166+
if (brokerTypes.HasFlag(CloudFoundryServiceBrokerTypes.Identity))
167+
{
168+
ILogger<IdentityCloudFoundryPostProcessor> identityLogger = loggerFactory.CreateLogger<IdentityCloudFoundryPostProcessor>();
169+
source.RegisterPostProcessor(new IdentityCloudFoundryPostProcessor(identityLogger));
170+
}
171+
172+
if (brokerTypes.HasFlag(CloudFoundryServiceBrokerTypes.MongoDb))
173+
{
174+
source.RegisterPostProcessor(new MongoDbCloudFoundryPostProcessor());
175+
}
176+
177+
if (brokerTypes.HasFlag(CloudFoundryServiceBrokerTypes.MySql))
178+
{
179+
source.RegisterPostProcessor(new MySqlCloudFoundryPostProcessor());
180+
}
181+
182+
if (brokerTypes.HasFlag(CloudFoundryServiceBrokerTypes.PostgreSql))
183+
{
184+
source.RegisterPostProcessor(new PostgreSqlCloudFoundryPostProcessor());
185+
}
186+
187+
if (brokerTypes.HasFlag(CloudFoundryServiceBrokerTypes.RabbitMQ))
188+
{
189+
source.RegisterPostProcessor(new RabbitMQCloudFoundryPostProcessor());
190+
}
191+
192+
if (brokerTypes.HasFlag(CloudFoundryServiceBrokerTypes.Redis))
193+
{
194+
source.RegisterPostProcessor(new RedisCloudFoundryPostProcessor());
195+
}
196+
197+
if (brokerTypes.HasFlag(CloudFoundryServiceBrokerTypes.SqlServer))
198+
{
199+
source.RegisterPostProcessor(new SqlServerCloudFoundryPostProcessor());
200+
}
109201
}
110202
}

src/Configuration/src/CloudFoundry/ServiceBindings/PostProcessors/MongoDbCloudFoundryPostProcessor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public override void PostProcessConfiguration(PostProcessorConfigurationProvider
1616

1717
// Mapping from CloudFoundry service binding credentials to driver-specific connection string parameters.
1818
// The available credentials are documented at:
19-
// - Azure Service Broker: https://techdocs.broadcom.com/us/en/vmware-tanzu/platform-services/tanzu-cloud-service-broker-for-microsoft-azure/1-13/csb-azure/reference-azure-cosmosdb-mongo.html#binding-creds
19+
// - Azure Service Broker: https://techdocs.broadcom.com/us/en/vmware-tanzu/platform/cloud-service-broker-azure/1-13/csb-azure/reference-azure-cosmosdb-mongo.html#binding-creds
2020

2121
mapper.MapFromTo("credentials:uri", "url");
2222

src/Configuration/src/CloudFoundry/ServiceBindings/PostProcessors/MySqlCloudFoundryPostProcessor.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ public override void PostProcessConfiguration(PostProcessorConfigurationProvider
1616

1717
// Mapping from CloudFoundry service binding credentials to driver-specific connection string parameters.
1818
// The available credentials are documented at:
19-
// - Tanzu Broker: https://techdocs.broadcom.com/us/en/vmware-tanzu/data-solutions/tanzu-for-mysql-on-cloud-foundry/10-0/mysql-for-tpcf/use.html#vcap
20-
// - GCP Service Broker: https://techdocs.broadcom.com/us/en/vmware-tanzu/platform-services/tanzu-cloud-service-broker-for-gcp/1-9/csb-gcp/reference-gcp-mysql.html#binding-creds
21-
// - AWS Service Broker: https://techdocs.broadcom.com/us/en/vmware-tanzu/platform-services/tanzu-cloud-service-broker-for-aws/1-14/csb-aws/reference-aws-mysql.html#binding-creds
19+
// - Tanzu Broker: https://techdocs.broadcom.com/us/en/vmware-tanzu/platform/tanzu-mysql-tanzu-platform/10-1/mysql-tp/use.html#vcap
20+
// - GCP Service Broker: https://techdocs.broadcom.com/us/en/vmware-tanzu/platform/cloud-service-broker-gcp/1-8/csb-gcp/reference-gcp-mysql.html#binding-creds
21+
// - AWS Service Broker: https://techdocs.broadcom.com/us/en/vmware-tanzu/platform/cloud-service-broker-aws/1-15/csb-aws/reference-aws-mysql.html#binding-creds
2222

2323
mapper.MapFromTo("credentials:hostname", "host");
2424
mapper.MapFromTo("credentials:port", "port");

0 commit comments

Comments
 (0)