Skip to content

Commit 6d26b78

Browse files
committed
Dynamic password example
This example shows how to use Npgsql dynamic passwords by supplying a custom DbProviderFactory.
1 parent 658a4a9 commit 6d26b78

File tree

4 files changed

+166
-0
lines changed

4 files changed

+166
-0
lines changed

FluentMigrator.sln

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{850DAD53-4
108108
EndProject
109109
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentMigrator.Example.MSBuild", "samples\FluentMigrator.Example.MSBuild\FluentMigrator.Example.MSBuild.csproj", "{2755D82C-E45D-479B-B502-FAAF3322DD9B}"
110110
EndProject
111+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FluentMigrator.Example.AwsAuroraMigrator", "samples\FluentMigrator.Example.AwsAuroraMigrator\FluentMigrator.Example.AwsAuroraMigrator.csproj", "{38C9DE57-5A02-46FD-B113-2A7568149022}"
112+
EndProject
111113
Global
112114
GlobalSection(SolutionConfigurationPlatforms) = preSolution
113115
Debug|Any CPU = Debug|Any CPU
@@ -454,6 +456,18 @@ Global
454456
{2755D82C-E45D-479B-B502-FAAF3322DD9B}.Release|x64.Build.0 = Release|Any CPU
455457
{2755D82C-E45D-479B-B502-FAAF3322DD9B}.Release|x86.ActiveCfg = Release|Any CPU
456458
{2755D82C-E45D-479B-B502-FAAF3322DD9B}.Release|x86.Build.0 = Release|Any CPU
459+
{38C9DE57-5A02-46FD-B113-2A7568149022}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
460+
{38C9DE57-5A02-46FD-B113-2A7568149022}.Debug|Any CPU.Build.0 = Debug|Any CPU
461+
{38C9DE57-5A02-46FD-B113-2A7568149022}.Debug|x64.ActiveCfg = Debug|Any CPU
462+
{38C9DE57-5A02-46FD-B113-2A7568149022}.Debug|x64.Build.0 = Debug|Any CPU
463+
{38C9DE57-5A02-46FD-B113-2A7568149022}.Debug|x86.ActiveCfg = Debug|Any CPU
464+
{38C9DE57-5A02-46FD-B113-2A7568149022}.Debug|x86.Build.0 = Debug|Any CPU
465+
{38C9DE57-5A02-46FD-B113-2A7568149022}.Release|Any CPU.ActiveCfg = Release|Any CPU
466+
{38C9DE57-5A02-46FD-B113-2A7568149022}.Release|Any CPU.Build.0 = Release|Any CPU
467+
{38C9DE57-5A02-46FD-B113-2A7568149022}.Release|x64.ActiveCfg = Release|Any CPU
468+
{38C9DE57-5A02-46FD-B113-2A7568149022}.Release|x64.Build.0 = Release|Any CPU
469+
{38C9DE57-5A02-46FD-B113-2A7568149022}.Release|x86.ActiveCfg = Release|Any CPU
470+
{38C9DE57-5A02-46FD-B113-2A7568149022}.Release|x86.Build.0 = Release|Any CPU
457471
EndGlobalSection
458472
GlobalSection(SolutionProperties) = preSolution
459473
HideSolutionNode = FALSE
@@ -491,6 +505,7 @@ Global
491505
{DB61C1AF-8934-4F5F-BB8A-451C817536F1} = {16DED0B3-1401-43AD-9402-3DC90918FFD7}
492506
{CD51E6A3-B43A-493B-B9FD-1C7A6E68F389} = {DE3C74CA-1396-44E6-B46B-5536BC9771DB}
493507
{2755D82C-E45D-479B-B502-FAAF3322DD9B} = {DE3C74CA-1396-44E6-B46B-5536BC9771DB}
508+
{38C9DE57-5A02-46FD-B113-2A7568149022} = {DE3C74CA-1396-44E6-B46B-5536BC9771DB}
494509
EndGlobalSection
495510
GlobalSection(ExtensibilityGlobals) = postSolution
496511
SolutionGuid = {722C9D0D-FAB6-4CCE-9A4A-56E24235A9E0}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#region License
2+
// Copyright (c) 2019, Fluent Migrator Project
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
#endregion
16+
17+
using System.Data.Common;
18+
19+
namespace FluentMigrator.Example.AwsAuroraMigrator
20+
{
21+
class DelegatingDbProviderFactory : DbProviderFactory
22+
{
23+
private readonly DbDataSource _dbDataSource;
24+
25+
private readonly DbProviderFactory _dbProviderFactory;
26+
27+
public DelegatingDbProviderFactory(DbDataSource dbDataSource, DbProviderFactory dbProviderFactory)
28+
{
29+
_dbDataSource = dbDataSource ?? throw new ArgumentNullException(nameof(dbDataSource));
30+
_dbProviderFactory = dbProviderFactory ?? throw new ArgumentNullException(nameof(dbProviderFactory));
31+
}
32+
33+
public override bool CanCreateDataSourceEnumerator => _dbProviderFactory.CanCreateDataSourceEnumerator;
34+
public override DbCommand CreateCommand() => _dbProviderFactory.CreateCommand();
35+
public override DbCommandBuilder CreateCommandBuilder() => _dbProviderFactory.CreateCommandBuilder();
36+
37+
/// <summary>
38+
/// Delegates connection creation to the underlying <see cref="DbDataSource"/>, which encapsulates all the information needed to connect to a specific database.
39+
/// </summary>
40+
/// <returns></returns>
41+
public override DbConnection CreateConnection() => _dbDataSource.CreateConnection();
42+
43+
public override DbConnectionStringBuilder CreateConnectionStringBuilder() => _dbProviderFactory.CreateConnectionStringBuilder();
44+
45+
public override DbDataAdapter CreateDataAdapter() => _dbProviderFactory.CreateDataAdapter();
46+
47+
public override DbDataSourceEnumerator CreateDataSourceEnumerator() => _dbProviderFactory.CreateDataSourceEnumerator();
48+
49+
public override DbParameter CreateParameter() => _dbProviderFactory.CreateParameter();
50+
}
51+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net8.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<PackageReference Include="AWSSDK.RDS" Version="3.7.410.46" />
12+
<PackageReference Include="Npgsql" Version="8.0.7" />
13+
</ItemGroup>
14+
15+
<ItemGroup>
16+
<ProjectReference Include="../../src/FluentMigrator.Runner.Postgres/FluentMigrator.Runner.Postgres.csproj" />
17+
<ProjectReference Include="../../src/FluentMigrator.Runner/FluentMigrator.Runner.csproj" />
18+
<ProjectReference Include="../FluentMigrator.Example.Migrations/FluentMigrator.Example.Migrations.csproj" />
19+
</ItemGroup>
20+
21+
</Project>
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+

2+
using Microsoft.Extensions.DependencyInjection;
3+
4+
using Amazon.RDS.Util;
5+
6+
using Npgsql;
7+
using FluentMigrator.Example.AwsAuroraMigrator;
8+
using System.Data.Common;
9+
using FluentMigrator.Runner;
10+
using FluentMigrator.Example.Migrations;
11+
12+
namespace DbMigrationRunner
13+
{
14+
class Program
15+
{
16+
static void Main(string[] args)
17+
{
18+
var hostname = Environment.GetEnvironmentVariable("DB_HOSTNAME");
19+
var username = Environment.GetEnvironmentVariable("DB_USERNAME");
20+
var port = int.Parse(Environment.GetEnvironmentVariable("DB_PORT"));
21+
var database = Environment.GetEnvironmentVariable("DB_DATABASE");
22+
23+
var csb = new NpgsqlConnectionStringBuilder();
24+
csb.Host = hostname;
25+
csb.Username = username;
26+
csb.Port = port;
27+
csb.Database = database;
28+
csb.SslMode = SslMode.Require;
29+
30+
using (var dbDataSource = CreateDbDataSource(csb))
31+
using (var serviceProvider = CreateServices(dbDataSource))
32+
using (var scope = serviceProvider.CreateScope())
33+
{
34+
// Put the database update into a scope to ensure
35+
// that all resources will be disposed.
36+
UpdateDatabase(scope.ServiceProvider);
37+
}
38+
}
39+
40+
/// <summary>
41+
/// Configure the dependency injection services
42+
/// </summary>
43+
private static ServiceProvider CreateServices(DbDataSource dbDataSource)
44+
{
45+
var dbProviderFactory = new DelegatingDbProviderFactory(dbDataSource, NpgsqlFactory.Instance);
46+
return new ServiceCollection()
47+
// Add common FluentMigrator services
48+
.AddFluentMigratorCore()
49+
.ConfigureRunner(rb => rb
50+
// Add SQLite support to FluentMigrator
51+
.AddPostgres(dbProviderFactory)
52+
// Define the assembly containing the migrations
53+
.ScanIn(typeof(AddGTDTables).Assembly).For.Migrations())
54+
// Enable logging to console in the FluentMigrator way
55+
.AddLogging(lb => lb.AddFluentMigratorConsole())
56+
// Build the service provider
57+
.BuildServiceProvider(false);
58+
}
59+
60+
/// <summary>
61+
/// Update the database
62+
/// </summary>
63+
private static void UpdateDatabase(IServiceProvider serviceProvider)
64+
{
65+
// Instantiate the runner
66+
var runner = serviceProvider.GetRequiredService<IMigrationRunner>();
67+
68+
// Execute the migrations
69+
runner.MigrateUp();
70+
}
71+
72+
private static DbDataSource CreateDbDataSource(NpgsqlConnectionStringBuilder connectionStringBuilder)
73+
{
74+
return new NpgsqlDataSourceBuilder(connectionStringBuilder.ToString())
75+
.UsePeriodicPasswordProvider((settings, cancellationToken) => ValueTask.FromResult(RDSAuthTokenGenerator.GenerateAuthToken(connectionStringBuilder.Host, connectionStringBuilder.Port, connectionStringBuilder.Username)), TimeSpan.FromMinutes(10), TimeSpan.FromSeconds(5))
76+
.Build();
77+
}
78+
}
79+
}

0 commit comments

Comments
 (0)