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 @@ -308,7 +308,7 @@ private static void AssertConnectorsAreAutowired(HostWrapper hostWrapper)
var configuration = hostWrapper.Services.GetRequiredService<IConfiguration>();

configuration.EnumerateProviders<KubernetesServiceBindingConfigurationProvider>().Should().NotBeEmpty();
configuration.EnumerateProviders<CloudFoundryServiceBindingConfigurationProvider>().Should().ContainSingle();
configuration.EnumerateProviders<CloudFoundryServiceBindingConfigurationProvider>().Should().NotBeEmpty();

hostWrapper.Services.GetService<ConnectorFactory<CosmosDbOptions, CosmosClient>>().Should().NotBeNull();
hostWrapper.Services.GetService<ConnectorFactory<MongoDbOptions, IMongoClient>>().Should().NotBeNull();
Expand Down
13 changes: 13 additions & 0 deletions src/Configuration/src/CloudFoundry/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1 +1,14 @@
#nullable enable
static Steeltoe.Configuration.CloudFoundry.ServiceBindings.ConfigurationBuilderExtensions.AddCloudFoundryServiceBindings(this Microsoft.Extensions.Configuration.IConfigurationBuilder! builder, Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes brokerTypes) -> Microsoft.Extensions.Configuration.IConfigurationBuilder!
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!
Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes
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
Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.Eureka = 1 -> Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes
Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.Identity = 2 -> Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes
Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.MongoDb = 4 -> Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes
Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.MySql = 8 -> Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes
Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.None = 0 -> Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes
Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.PostgreSql = 16 -> Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes
Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.RabbitMQ = 32 -> Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes
Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.Redis = 64 -> Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes
Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes.SqlServer = 128 -> Steeltoe.Configuration.CloudFoundry.ServiceBindings.CloudFoundryServiceBrokerTypes
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,24 @@
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.

using System.Diagnostics;
using Microsoft.Extensions.Configuration;

namespace Steeltoe.Configuration.CloudFoundry.ServiceBindings;

[DebuggerDisplay("{DebuggerToString(),nq}")]
internal sealed class CloudFoundryServiceBindingConfigurationSource : PostProcessorConfigurationSource, IConfigurationSource
{
private readonly IServiceBindingsReader _serviceBindingsReader;

public CloudFoundryServiceBindingConfigurationSource(IServiceBindingsReader serviceBindingsReader)
public CloudFoundryServiceBrokerTypes BrokerTypes { get; }

public CloudFoundryServiceBindingConfigurationSource(IServiceBindingsReader serviceBindingsReader, CloudFoundryServiceBrokerTypes brokerTypes)
{
ArgumentNullException.ThrowIfNull(serviceBindingsReader);

_serviceBindingsReader = serviceBindingsReader;
BrokerTypes = brokerTypes;
}

public IConfigurationProvider Build(IConfigurationBuilder builder)
Expand All @@ -24,4 +29,9 @@ public IConfigurationProvider Build(IConfigurationBuilder builder)
CaptureConfigurationBuilder(builder);
return new CloudFoundryServiceBindingConfigurationProvider(this, _serviceBindingsReader);
}

private string DebuggerToString()
{
return $"{GetType().FullName} ({BrokerTypes})";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.

namespace Steeltoe.Configuration.CloudFoundry.ServiceBindings;

/// <summary>
/// Lists the built-in Cloud Foundry service brokers.
/// </summary>
[Flags]
public enum CloudFoundryServiceBrokerTypes
{
/// <summary>
/// Don't use any of the built-in brokers.
/// </summary>
None = 0x0,

/// <summary>
/// Use the built-in brokers for Netflix Eureka.
/// </summary>
Eureka = 0x1,

/// <summary>
/// Use the built-in brokers for JWT and OpenID Connect.
/// </summary>
Identity = 0x2,

/// <summary>
/// Use the built-in brokers for MongoDB.
/// </summary>
MongoDb = 0x4,

/// <summary>
/// Use the built-in brokers for MySQL.
/// </summary>
MySql = 0x8,

/// <summary>
/// Use the built-in brokers for PostgreSQL.
/// </summary>
PostgreSql = 0x10,

/// <summary>
/// Use the built-in brokers for RabbitMQ.
/// </summary>
RabbitMQ = 0x20,

/// <summary>
/// Use the built-in brokers for Redis/Valkey.
/// </summary>
Redis = 0x40,

/// <summary>
/// Use the built-in brokers for Microsoft SQL Server.
/// </summary>
SqlServer = 0x80,

/// <summary>
/// Use all built-in brokers.
/// </summary>
All = Eureka | Identity | MongoDb | MySql | PostgreSql | RabbitMQ | Redis | SqlServer
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,24 @@ public static class ConfigurationBuilderExtensions
/// </returns>
public static IConfigurationBuilder AddCloudFoundryServiceBindings(this IConfigurationBuilder builder)
{
return builder.AddCloudFoundryServiceBindings(DefaultIgnoreKeyPredicate, DefaultReader, NullLoggerFactory.Instance);
return builder.AddCloudFoundryServiceBindings(DefaultIgnoreKeyPredicate, null, CloudFoundryServiceBrokerTypes.All, NullLoggerFactory.Instance);
}

/// <summary>
/// Adds CloudFoundry service bindings from the JSON provided by the specified reader.
/// </summary>
/// <param name="builder">
/// The <see cref="IConfigurationBuilder" /> to add configuration to.
/// </param>
/// <param name="brokerTypes">
/// The set of broker types to read service bindings for.
/// </param>
/// <returns>
/// The incoming <paramref name="builder" /> so that additional calls can be chained.
/// </returns>
public static IConfigurationBuilder AddCloudFoundryServiceBindings(this IConfigurationBuilder builder, CloudFoundryServiceBrokerTypes brokerTypes)
{
return builder.AddCloudFoundryServiceBindings(DefaultIgnoreKeyPredicate, null, brokerTypes, NullLoggerFactory.Instance);
}

/// <summary>
Expand All @@ -46,7 +63,8 @@ public static IConfigurationBuilder AddCloudFoundryServiceBindings(this IConfigu
/// </returns>
public static IConfigurationBuilder AddCloudFoundryServiceBindings(this IConfigurationBuilder builder, IServiceBindingsReader serviceBindingsReader)
{
return builder.AddCloudFoundryServiceBindings(DefaultIgnoreKeyPredicate, serviceBindingsReader, NullLoggerFactory.Instance);
return builder.AddCloudFoundryServiceBindings(DefaultIgnoreKeyPredicate, serviceBindingsReader, CloudFoundryServiceBrokerTypes.All,
NullLoggerFactory.Instance);
}

/// <summary>
Expand All @@ -56,7 +74,7 @@ public static IConfigurationBuilder AddCloudFoundryServiceBindings(this IConfigu
/// The <see cref="IConfigurationBuilder" /> to add configuration to.
/// </param>
/// <param name="ignoreKeyPredicate">
/// A predicate which is called before adding a key to the configuration. If it returns false, the key will be ignored.
/// A predicate that is called before adding a key to the configuration. If it returns false, the key will be ignored.
/// </param>
/// <param name="serviceBindingsReader">
/// The source to read JSON service bindings from.
Expand All @@ -69,15 +87,43 @@ public static IConfigurationBuilder AddCloudFoundryServiceBindings(this IConfigu
/// </returns>
public static IConfigurationBuilder AddCloudFoundryServiceBindings(this IConfigurationBuilder builder, Predicate<string> ignoreKeyPredicate,
IServiceBindingsReader serviceBindingsReader, ILoggerFactory loggerFactory)
{
return AddCloudFoundryServiceBindings(builder, ignoreKeyPredicate, serviceBindingsReader, CloudFoundryServiceBrokerTypes.All, loggerFactory);
}

/// <summary>
/// Adds CloudFoundry service bindings from the JSON provided by the specified reader.
/// </summary>
/// <param name="builder">
/// The <see cref="IConfigurationBuilder" /> to add configuration to.
/// </param>
/// <param name="ignoreKeyPredicate">
/// A predicate that is called before adding a key to the configuration. If it returns false, the key will be ignored.
/// </param>
/// <param name="serviceBindingsReader">
/// The source to read JSON service bindings from.
/// </param>
/// <param name="brokerTypes">
/// The set of broker types to read service bindings for.
/// </param>
/// <param name="loggerFactory">
/// Used for internal logging. Pass <see cref="NullLoggerFactory.Instance" /> to disable logging.
/// </param>
/// <returns>
/// The incoming <paramref name="builder" /> so that additional calls can be chained.
/// </returns>
public static IConfigurationBuilder AddCloudFoundryServiceBindings(this IConfigurationBuilder builder, Predicate<string> ignoreKeyPredicate,
IServiceBindingsReader? serviceBindingsReader, CloudFoundryServiceBrokerTypes brokerTypes, ILoggerFactory loggerFactory)
{
ArgumentNullException.ThrowIfNull(builder);
ArgumentNullException.ThrowIfNull(ignoreKeyPredicate);
ArgumentNullException.ThrowIfNull(serviceBindingsReader);
ArgumentNullException.ThrowIfNull(loggerFactory);

if (!builder.EnumerateSources<CloudFoundryServiceBindingConfigurationSource>().Any())
CloudFoundryServiceBrokerTypes missingBrokerTypes = GetMissingBrokerTypes(builder, brokerTypes);

if (missingBrokerTypes != CloudFoundryServiceBrokerTypes.None)
{
var source = new CloudFoundryServiceBindingConfigurationSource(serviceBindingsReader)
var source = new CloudFoundryServiceBindingConfigurationSource(serviceBindingsReader ?? DefaultReader, missingBrokerTypes)
{
IgnoreKeyPredicate = ignoreKeyPredicate
};
Expand All @@ -86,25 +132,71 @@ public static IConfigurationBuilder AddCloudFoundryServiceBindings(this IConfigu
// WebApplicationBuilder immediately builds the configuration provider and loads it, which executes the post-processors.
// Therefore, adding post-processors afterward is a no-op.

RegisterPostProcessors(source, loggerFactory);
RegisterPostProcessors(source, missingBrokerTypes, loggerFactory);
builder.Add(source);
}

return builder;
}

private static void RegisterPostProcessors(CloudFoundryServiceBindingConfigurationSource source, ILoggerFactory loggerFactory)
private static CloudFoundryServiceBrokerTypes GetMissingBrokerTypes(IConfigurationBuilder builder, CloudFoundryServiceBrokerTypes brokerTypesRequested)
{
ILogger<EurekaCloudFoundryPostProcessor> eurekaLogger = loggerFactory.CreateLogger<EurekaCloudFoundryPostProcessor>();
ILogger<IdentityCloudFoundryPostProcessor> identityLogger = loggerFactory.CreateLogger<IdentityCloudFoundryPostProcessor>();

source.RegisterPostProcessor(new EurekaCloudFoundryPostProcessor(eurekaLogger));
source.RegisterPostProcessor(new IdentityCloudFoundryPostProcessor(identityLogger));
source.RegisterPostProcessor(new MongoDbCloudFoundryPostProcessor());
source.RegisterPostProcessor(new MySqlCloudFoundryPostProcessor());
source.RegisterPostProcessor(new PostgreSqlCloudFoundryPostProcessor());
source.RegisterPostProcessor(new RabbitMQCloudFoundryPostProcessor());
source.RegisterPostProcessor(new RedisCloudFoundryPostProcessor());
source.RegisterPostProcessor(new SqlServerCloudFoundryPostProcessor());
CloudFoundryServiceBrokerTypes missingBrokerTypes = brokerTypesRequested;

if (brokerTypesRequested != CloudFoundryServiceBrokerTypes.None)
{
foreach (CloudFoundryServiceBindingConfigurationSource existingSource in builder.EnumerateSources<CloudFoundryServiceBindingConfigurationSource>())
{
missingBrokerTypes &= ~existingSource.BrokerTypes;
}
}

return missingBrokerTypes;
}

private static void RegisterPostProcessors(CloudFoundryServiceBindingConfigurationSource source, CloudFoundryServiceBrokerTypes brokerTypes,
ILoggerFactory loggerFactory)
{
if (brokerTypes.HasFlag(CloudFoundryServiceBrokerTypes.Eureka))
{
ILogger<EurekaCloudFoundryPostProcessor> eurekaLogger = loggerFactory.CreateLogger<EurekaCloudFoundryPostProcessor>();
source.RegisterPostProcessor(new EurekaCloudFoundryPostProcessor(eurekaLogger));
}

if (brokerTypes.HasFlag(CloudFoundryServiceBrokerTypes.Identity))
{
ILogger<IdentityCloudFoundryPostProcessor> identityLogger = loggerFactory.CreateLogger<IdentityCloudFoundryPostProcessor>();
source.RegisterPostProcessor(new IdentityCloudFoundryPostProcessor(identityLogger));
}

if (brokerTypes.HasFlag(CloudFoundryServiceBrokerTypes.MongoDb))
{
source.RegisterPostProcessor(new MongoDbCloudFoundryPostProcessor());
}

if (brokerTypes.HasFlag(CloudFoundryServiceBrokerTypes.MySql))
{
source.RegisterPostProcessor(new MySqlCloudFoundryPostProcessor());
}

if (brokerTypes.HasFlag(CloudFoundryServiceBrokerTypes.PostgreSql))
{
source.RegisterPostProcessor(new PostgreSqlCloudFoundryPostProcessor());
}

if (brokerTypes.HasFlag(CloudFoundryServiceBrokerTypes.RabbitMQ))
{
source.RegisterPostProcessor(new RabbitMQCloudFoundryPostProcessor());
}

if (brokerTypes.HasFlag(CloudFoundryServiceBrokerTypes.Redis))
{
source.RegisterPostProcessor(new RedisCloudFoundryPostProcessor());
}

if (brokerTypes.HasFlag(CloudFoundryServiceBrokerTypes.SqlServer))
{
source.RegisterPostProcessor(new SqlServerCloudFoundryPostProcessor());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public override void PostProcessConfiguration(PostProcessorConfigurationProvider

// Mapping from CloudFoundry service binding credentials to driver-specific connection string parameters.
// The available credentials are documented at:
// - 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
// - 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

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ public override void PostProcessConfiguration(PostProcessorConfigurationProvider

// Mapping from CloudFoundry service binding credentials to driver-specific connection string parameters.
// The available credentials are documented at:
// - 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
// - 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
// - 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
// - Tanzu Broker: https://techdocs.broadcom.com/us/en/vmware-tanzu/platform/tanzu-mysql-tanzu-platform/10-1/mysql-tp/use.html#vcap
// - 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
// - 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

mapper.MapFromTo("credentials:hostname", "host");
mapper.MapFromTo("credentials:port", "port");
Expand Down
Loading