Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add database migration with yuniql #224

Merged
merged 5 commits into from
Oct 18, 2024
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
8 changes: 6 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
FROM mcr.microsoft.com/dotnet/sdk:8.0.403-alpine3.20 AS build
WORKDIR Altinn.Profile/
WORKDIR /app

COPY src/Altinn.Profile/*.csproj ./src/Altinn.Profile/
COPY src/Altinn.Profile.Core/*.csproj ./src/Altinn.Profile.Core/
COPY src/Altinn.Profile.Integrations/*.csproj ./src/Altinn.Profile.Integrations/
RUN dotnet restore ./src/Altinn.Profile/Altinn.Profile.csproj

RUN dotnet restore ./src/Altinn.Profile/Altinn.Profile.csproj

COPY src ./src
RUN dotnet publish -c Release -o /app_output ./src/Altinn.Profile/Altinn.Profile.csproj

FROM mcr.microsoft.com/dotnet/aspnet:8.0.10-alpine3.20 AS final
EXPOSE 5030
WORKDIR /app

COPY --from=build /app_output .
COPY --from=build /app/src/Altinn.Profile.Integrations/Migration ./Migration

# setup the user and group
# the user will have no password, using shell /bin/false and using the group dotnet
RUN addgroup -g 3000 dotnet && adduser -u 1000 -G dotnet -D -s /bin/false dotnet

# update permissions of files if neccessary before becoming dotnet user
USER dotnet
RUN mkdir /tmp/logtelemetry
Expand Down
5 changes: 3 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ services:
networks:
- altinnplatform_network
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_ENVIRONMENT=Docker
- ASPNETCORE_URLS=http://+:5030
- GeneralSettings:BridgeApiEndpoint=https://at22.altinn.cloud/sblbridge/profile/api
- PostgreSqlSettings__AdminConnectionString=Host=host.docker.internal;Port=5432;Username=platform_profile_admin;Password={0};Database=profiledb
- PostgreSqlSettings__ConnectionString=Host=host.docker.internal;Port=5432;Username=platform_profile;Password={0};Database=profiledb
ports:
- "5030:5030"
build:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@
<PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.8" />
<PackageReference Include="Yuniql.AspNetCore" Version="1.2.25" />
<PackageReference Include="Yuniql.PostgreSql" Version="1.3.15" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Altinn.Profile.Core\Altinn.Profile.Core.csproj" />
<InternalsVisibleTo Include="Altinn.Profile.Tests" />
<InternalsVisibleTo Include="Altinn.Profile.Tests" />
</ItemGroup>

<ItemGroup Condition="'$(Configuration)'=='Debug'">
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556">
<PrivateAssets>all</PrivateAssets>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,43 +1,44 @@
using Microsoft.Extensions.Configuration;
using System.Diagnostics.CodeAnalysis;

using Microsoft.Extensions.Configuration;

namespace Altinn.Profile.Integrations.Extensions;

/// <summary>
/// Extension class for <see cref="IConfiguration"/> to add more members.
/// </summary>
[ExcludeFromCodeCoverage]
public static class ConfigurationExtensions
{
private const string ProfileDbAdminUserNameKey = "PostgreSqlSettings:ProfileDbAdminUserName";
private const string ProfileDbAdminPasswordKey = "PostgreSqlSettings:ProfileDbAdminPassword";
private const string ProfileDbConnectionStringKey = "PostgreSqlSettings:ProfileDbConnectionString";
private const string ConnectionStringKey = "PostgreSqlSettings:ConnectionString";
private const string ProfileDbPasswordKey = "PostgreSqlSettings:ProfileDbPwd";

Check warning on line 14 in src/Altinn.Profile.Integrations/Extensions/ConfigurationExtensions.cs

View workflow job for this annotation

GitHub Actions / Build, test & analyze

"password" detected here, make sure this is not a hard-coded credential. (https://rules.sonarsource.com/csharp/RSPEC-2068)

/// <summary>
/// Retrieves the database connection string from the configuration.
/// </summary>
/// <param name="config">The configuration instance containing the connection settings.</param>
/// <returns>The formatted database connection string if all required settings are present; otherwise, an empty string.</returns>
/// <remarks>
/// This method expects the configuration to contain the following keys:
/// This method expects IConfiguration to contain the following keys:
/// <list type="bullet">
/// <item><description><c>PostgreSqlSettings--ProfileDbAdminUserName</c></description></item>
/// <item><description><c>PostgreSqlSettings--ProfileDbAdminPassword</c></description></item>
/// <item><description><c>PostgreSqlSettings--ProfileDbConnectionString</c></description></item>
/// <item><description><c>PostgreSqlSettings:ConnectionString</c></description></item>
/// <item><description><c>PostgreSqlSettings:ProfileDbPwd</c></description></item>
/// </list>
/// The connection string is formatted using the administrator user name and password.
/// The connection string is expected to contain a placeholder for the password. The password is added to the connection string
/// through string formatting. The connection string value should be provieded as a value in the helm chart for profile. The password
/// is retrieved from the platform KeyVault. The names can therefore not be changed, but must follow the above naming conventions.
/// </remarks>
public static string GetDatabaseConnectionString(this IConfiguration config)
{
var adminUserName = config[ProfileDbAdminUserNameKey];
var adminPassword = config[ProfileDbAdminPasswordKey];
var connectionString = config[ProfileDbConnectionStringKey];
var connectionString = config[ConnectionStringKey];
var userPassword = config[ProfileDbPasswordKey];

if (string.IsNullOrWhiteSpace(adminUserName) ||
string.IsNullOrWhiteSpace(adminPassword) ||
if (string.IsNullOrWhiteSpace(userPassword) ||
string.IsNullOrWhiteSpace(connectionString))
{
return string.Empty;
}

return string.Format(connectionString, adminUserName, adminPassword);
return string.Format(connectionString, userPassword);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System.Diagnostics.CodeAnalysis;

using Altinn.Profile.Integrations.Persistence;

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;

using Yuniql.AspNetCore;
using Yuniql.PostgreSql;

namespace Altinn.Profile.Integrations.Extensions;

/// <summary>
/// Extension class for web application
/// </summary>
[ExcludeFromCodeCoverage]
public static class WebApplicationExtensions
{
/// <summary>
/// Configure and set up db
/// </summary>
/// <param name="app">app</param>
/// <param name="isDevelopment">is environment dev</param>
/// <param name="config">the configuration collection</param>
public static void SetUpPostgreSql(this IApplicationBuilder app, bool isDevelopment, IConfiguration config)
{
PostgreSqlSettings? settings = config.GetSection("PostgreSQLSettings")
.Get<PostgreSqlSettings>()
?? throw new ArgumentNullException(nameof(config), "Required PostgreSQLSettings is missing from application configuration");

if (settings.EnableDBConnection)
{
ConsoleTraceService traceService = new() { IsDebugEnabled = true };
SandGrainOne marked this conversation as resolved.
Show resolved Hide resolved

string connectionString = string.Format(settings.AdminConnectionString, settings.ProfileDbAdminPwd);

string fullWorkspacePath = isDevelopment ?
Path.Combine(Directory.GetParent(Environment.CurrentDirectory)!.FullName, settings.MigrationScriptPath) :
Path.Combine(Environment.CurrentDirectory, settings.MigrationScriptPath);

app.UseYuniql(
new PostgreSqlDataService(traceService),
new PostgreSqlBulkImportService(traceService),
traceService,
new Configuration
{
Workspace = fullWorkspacePath,
ConnectionString = connectionString,
IsAutoCreateDatabase = false,
IsDebug = settings.EnableDebug
});
}
}
}
2 changes: 2 additions & 0 deletions src/Altinn.Profile.Integrations/Migration/_draft/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# The `_draft` directory
Scripts in progress. Scripts that you are currently working and have not moved to specific version directory yet. Executed every time after the latest version.
2 changes: 2 additions & 0 deletions src/Altinn.Profile.Integrations/Migration/_erase/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# The `_erase` directory
Database cleanup scripts. Executed once only when you do `yuniql erase`.
2 changes: 2 additions & 0 deletions src/Altinn.Profile.Integrations/Migration/_init/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# The `_init` directory
Initialization scripts. Executed once. This is called the first time you do `yuniql run`.
2 changes: 2 additions & 0 deletions src/Altinn.Profile.Integrations/Migration/_post/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# The `_post` directory
Post migration scripts. Executed every time and always the last batch to run.
2 changes: 2 additions & 0 deletions src/Altinn.Profile.Integrations/Migration/_pre/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# The `_pre` directory
Pre migration scripts. Executed every time before any version.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- Create schema if it doesn't exist
CREATE SCHEMA IF NOT EXISTS contact_and_reservation;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-- Grant access to the schema
GRANT ALL ON SCHEMA contact_and_reservation TO platform_profile_admin;
GRANT USAGE ON SCHEMA contact_and_reservation TO platform_profile;
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
-- Create schema if it doesn't exist
CREATE SCHEMA IF NOT EXISTS contact_and_reservation;

-- Grant access to the schema
GRANT ALL ON SCHEMA contact_and_reservation TO platform_profile_admin;
GRANT USAGE ON SCHEMA contact_and_reservation TO platform_profile;

-- Create table MailboxSupplier
CREATE TABLE IF NOT EXISTS contact_and_reservation.mailbox_supplier (
mailbox_supplier_id INT GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1) PRIMARY KEY,
Expand Down
77 changes: 77 additions & 0 deletions src/Altinn.Profile.Integrations/Persistence/ConsoleTraceService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using System.Diagnostics.CodeAnalysis;

using Yuniql.Extensibility;

namespace Altinn.Profile.Integrations.Persistence;

/// <summary>
/// Copied from sample project.
/// </summary>
[ExcludeFromCodeCoverage]
public class ConsoleTraceService : ITraceService
{
/// <summary>
/// Debug enabled
/// </summary>
public bool IsDebugEnabled { get; set; } = false;

/// <inheritdoc/>>
public bool IsTraceSensitiveData { get; set; } = false;

/// <inheritdoc/>>
public bool IsTraceToFile { get; set; } = false;

/// <inheritdoc/>>
public bool IsTraceToDirectory { get; set; } = false;

/// <inheritdoc/>>
public string? TraceDirectory { get; set; }

/// <summary>
/// Info
/// </summary>
public void Info(string message, object? payload = null)
{
var traceMessage = $"INF {DateTime.UtcNow:o} {message}{Environment.NewLine}";
Console.Write(traceMessage);
}

/// <summary>
/// Error
/// </summary>
public void Error(string message, object? payload = null)
{
var traceMessage = $"ERR {DateTime.UtcNow:o} {message}{Environment.NewLine}";
Console.Write(traceMessage);
}

/// <summary>
/// Debug
/// </summary>
public void Debug(string message, object? payload = null)
{
if (IsDebugEnabled)
{
var traceMessage = $"DBG {DateTime.UtcNow:o} {message}{Environment.NewLine}";
Console.Write(traceMessage);
}
}

/// <summary>
/// Success
/// </summary>
public void Success(string message, object? payload = null)
{
var traceMessage = $"INF {DateTime.UtcNow:u} {message}{Environment.NewLine}";
Console.Write(traceMessage);
}

/// <summary>
/// Warn
/// </summary>
public void Warn(string message, object? payload = null)
{
var traceMessage = $"WRN {DateTime.UtcNow:o} {message}{Environment.NewLine}";
Console.Write(traceMessage);
}
}
47 changes: 47 additions & 0 deletions src/Altinn.Profile.Integrations/Persistence/PostgreSQLSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
namespace Altinn.Profile.Integrations.Persistence;

/// <summary>
/// Settings for Postgre database
/// </summary>
public class PostgreSqlSettings
{
/// <summary>
/// Boolean indicating if database should be connected
/// </summary>
public bool EnableDBConnection { get; set; } = true;

/// <summary>
/// Path to migration scripts
/// </summary>
public string MigrationScriptPath { get; set; } = string.Empty;

/// <summary>
/// Connection string for the admin user of postgre db
/// </summary>
public string AdminConnectionString { get; set; } = string.Empty;

/// <summary>
/// Password for admin user for the postgre db
/// </summary>
public string ProfileDbAdminPwd { get; set; } = string.Empty;

/// <summary>
/// Connection string for app user the postgre db
/// </summary>
public string ConnectionString { get; set; } = string.Empty;

/// <summary>
/// Password for app user for the postgre db
/// </summary>
public string ProfileDbPwd { get; set; } = string.Empty;

/// <summary>
/// Gets or sets a value indicating whether to include parameter values in logging/tracing
/// </summary>
public bool LogParameters { get; set; } = false;

/// <summary>
/// Boolean indicating if connection to db should be in debug mode
/// </summary>
public bool EnableDebug { get; set; } = false;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using Altinn.Profile.Core.Integrations;
using System.Diagnostics.CodeAnalysis;

using Altinn.Profile.Core.Integrations;
using Altinn.Profile.Integrations.Extensions;
using Altinn.Profile.Integrations.Mappings;
using Altinn.Profile.Integrations.Persistence;
using Altinn.Profile.Integrations.Repositories;
using Altinn.Profile.Integrations.SblBridge;
Expand All @@ -16,6 +19,7 @@ namespace Altinn.Profile.Integrations;
/// <summary>
/// Extension class for <see cref="IServiceCollection"/>
/// </summary>
[ExcludeFromCodeCoverage]
public static class ServiceCollectionExtensions
{
/// <summary>
Expand Down Expand Up @@ -56,7 +60,7 @@ public static void AddRegisterService(this IServiceCollection services, IConfigu

services.AddDbContext<ProfileDbContext>(options => options.UseNpgsql(connectionString));

services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
services.AddAutoMapper(typeof(PersonContactDetailsProfile));

services.AddScoped<IPersonService, PersonService>();
services.AddScoped<IPersonRepository, PersonRepository>();
Expand Down
Loading
Loading