diff --git a/.ci/dbm/buildContainerImage.js b/.ci/dbm/buildContainerImage.js
new file mode 100755
index 0000000000..f962b2ba8f
--- /dev/null
+++ b/.ci/dbm/buildContainerImage.js
@@ -0,0 +1,11 @@
+#!/usr/bin/env node
+
+import { $ } from "zx";
+import { getRequiredEnvVar } from "../lib.js";
+
+const tag = getRequiredEnvVar("TAG");
+
+const platforms = process.env.PLATFORMS ?? "linux/amd64,linux/arm64";
+const push = process.env.PUSH === "1" ? ["--push", "--provenance=true", "--sbom=true"] : "";
+
+await $`docker buildx build --file ./DatabaseMigrator/Dockerfile --tag ghcr.io/nmshd/backbone-database-migrator:${tag} --platform ${platforms} ${push} .`;
diff --git a/.ci/docker-compose.test.postgres.yml b/.ci/docker-compose.test.postgres.yml
index 67ce0ffaf7..96da41adae 100644
--- a/.ci/docker-compose.test.postgres.yml
+++ b/.ci/docker-compose.test.postgres.yml
@@ -21,20 +21,20 @@ services:
seed-database:
image: postgres
- volumes:
- - ../setup-db:/app/setup-db
environment:
- PGPASSWORD=Passw0rd
command: psql -h postgres -U postgres -d enmeshed -f /app/setup-db/setup-postgres.sql
- depends_on:
- database:
- condition: service_healthy
seed-client:
environment:
Database__Provider: Postgres
Database__ConnectionString: "Server=postgres;Database=enmeshed;User Id=devices;Password=Passw0rd;Port=5432"
+ database-migrator:
+ environment:
+ Infrastructure__SqlDatabase__Provider: Postgres
+ Infrastructure__SqlDatabase__ConnectionString: "Server=postgres;Database=enmeshed;User Id=postgres;Password=Passw0rd;Port=5432"
+
configs:
Config:
file: appsettings.override.postgres.json
diff --git a/.ci/docker-compose.test.sqlserver.yml b/.ci/docker-compose.test.sqlserver.yml
index b2d032b350..2e71f260b9 100644
--- a/.ci/docker-compose.test.sqlserver.yml
+++ b/.ci/docker-compose.test.sqlserver.yml
@@ -10,6 +10,11 @@ services:
- MSSQL_SA_PASSWORD=Passw0rd
- ACCEPT_EULA=Y
- MSSQL_PID=Express
+ healthcheck:
+ test: ["CMD", "echo"]
+ interval: 1s
+ timeout: 1s
+ retries: 1
ports:
- 1433:1433
@@ -17,17 +22,18 @@ services:
seed-database:
image: mcr.microsoft.com/mssql-tools
- volumes:
- - ../setup-db:/app/setup-db
command: bash -c " sleep 20 && /opt/mssql-tools/bin/sqlcmd -S sqlserver -U SA -P Passw0rd -i /app/setup-db/setup-sqlserver.sql "
- depends_on:
- - database
seed-client:
environment:
Database__Provider: SqlServer
Database__ConnectionString: "Server=sqlserver;Database=enmeshed;User Id=devices;Password=Passw0rd;TrustServerCertificate=True"
+ database-migrator:
+ environment:
+ Infrastructure__SqlDatabase__Provider: SqlServer
+ Infrastructure__SqlDatabase__ConnectionString: "Server=sqlserver;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True"
+
configs:
Config:
file: appsettings.override.sqlserver.json
diff --git a/.ci/docker-compose.test.yml b/.ci/docker-compose.test.yml
index ae822013af..84a994b46c 100644
--- a/.ci/docker-compose.test.yml
+++ b/.ci/docker-compose.test.yml
@@ -11,12 +11,10 @@ services:
ports:
- "5000:8080"
depends_on:
- database:
- condition: service_started
+ database-migrator:
+ condition: service_completed_successfully
rabbitmq:
condition: service_started
- seed-database:
- condition: service_completed_successfully
azure-storage-emulator:
condition: service_started
configs:
@@ -34,12 +32,10 @@ services:
ports:
- "5173:8080"
depends_on:
- database:
- condition: service_started
+ database-migrator:
+ condition: service_completed_successfully
rabbitmq:
condition: service_started
- consumer-api:
- condition: service_healthy
configs:
- source: Config
target: app/appsettings.override.json
@@ -52,14 +48,28 @@ services:
environment:
- ASPNETCORE_ENVIRONMENT=Development
depends_on:
- database:
- condition: service_started
+ database-migrator:
+ condition: service_completed_successfully
rabbitmq:
condition: service_started
configs:
- source: Config
target: app/appsettings.override.json
+ database-migrator:
+ container_name: database-migrator-test
+ build:
+ context: ..
+ dockerfile: DatabaseMigrator/Dockerfile
+ depends_on:
+ seed-database:
+ condition: service_completed_successfully
+ environment:
+ - ASPNETCORE_ENVIRONMENT=Development
+ configs:
+ - source: Config
+ target: app/appsettings.override.json
+
### infrastructure ###
azure-storage-emulator:
@@ -79,6 +89,13 @@ services:
### seeds ###
+ seed-database:
+ volumes:
+ - ../setup-db:/app/setup-db
+ depends_on:
+ database:
+ condition: service_healthy
+
seed-client:
container_name: seed-client-test
build:
diff --git a/.ci/helm/buildChart.js b/.ci/helm/buildChart.js
index 2a93da2ca8..dbe390960a 100755
--- a/.ci/helm/buildChart.js
+++ b/.ci/helm/buildChart.js
@@ -7,4 +7,4 @@ const version = getRequiredEnvVar("VERSION");
await $`helm dependency update helm`;
-await $`helm package --version ${version} --app-version ${version} helm`;
+await $`helm package --version ${version} --app-version ${version} helm`;
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index eef6319349..adcca3bc9e 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -161,6 +161,45 @@ jobs:
TAG: ${{ steps.extract-version-from-git-tag.outputs.VERSION }}
PUSH: 1
+ publish-database-migrator:
+ name: Publish Database Migrator Container Image
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Install script dependencies
+ run: npm install --prefix ./.ci
+ - name: Docker Login
+ uses: docker/login-action@v3.0.0
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+ - name: Extract version from git tag
+ id: extract-version-from-git-tag
+ run: echo "VERSION=$(./.ci/extractVersionFromGitTag.js)" >> $GITHUB_OUTPUT
+ env:
+ GIT_TAG: ${{ github.ref_name }}
+ - name: Log in to Docker Hub for accessing the cloud builder
+ uses: docker/login-action@v3
+ with:
+ username: ${{ secrets.CLOUD_BUILDER_USERNAME }}
+ password: ${{ secrets.CLOUD_BUILDER_TOKEN }}
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+ with:
+ version: "lab:latest"
+ driver: cloud
+ endpoint: "jssoft/js-soft"
+ - name: Build and Push Container Image
+ run: ./.ci/dbm/buildContainerImage.js
+ env:
+ TAG: ${{ steps.extract-version-from-git-tag.outputs.VERSION }}
+ PUSH: 1
+
publish-helm-chart:
name: Publish Helm Chart
runs-on: ubuntu-latest
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index fe5a80906c..f6526c8821 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -221,6 +221,22 @@ jobs:
TAG: test
PLATFORMS: linux/amd64
+ build-dbm-container-image:
+ name: Build Database Migrator Container Image
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Install script dependencies
+ run: npm install --prefix ./.ci
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+ - name: Build image
+ run: ./.ci/dbm/buildContainerImage.js
+ env:
+ TAG: test
+ PLATFORMS: linux/amd64
+
build-aui-container-image:
name: Build Admin UI Container Image
runs-on: ubuntu-latest
diff --git a/.run/Backbone.run.xml b/.run/Backbone.run.xml
new file mode 100644
index 0000000000..9d3047566d
--- /dev/null
+++ b/.run/Backbone.run.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AdminApi/src/AdminApi/Program.cs b/AdminApi/src/AdminApi/Program.cs
index b7582799cc..b77bb14770 100644
--- a/AdminApi/src/AdminApi/Program.cs
+++ b/AdminApi/src/AdminApi/Program.cs
@@ -15,6 +15,7 @@
using Backbone.Tooling.Extensions;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.Extensions.Options;
+using Microsoft.IdentityModel.Logging;
using Serilog;
using Serilog.Exceptions;
using Serilog.Exceptions.Core;
@@ -79,7 +80,8 @@ static WebApplication CreateApp(string[] args)
var app = builder.Build();
Configure(app);
- app.MigrateDbContext();
+ if ((app.Environment.IsLocal() || app.Environment.IsDevelopment()) && app.Configuration.GetValue("RunMigrations"))
+ app.MigrateDbContext();
return app;
}
@@ -175,7 +177,7 @@ static void Configure(WebApplication app)
app.UseSwagger().UseSwaggerUI();
if (app.Environment.IsDevelopment())
- Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
+ IdentityModelEventSource.ShowPII = true;
app.UseCors();
diff --git a/AdminApi/src/AdminApi/appsettings.override.json b/AdminApi/src/AdminApi/appsettings.override.json
index 655cbc153c..fac7faae2a 100644
--- a/AdminApi/src/AdminApi/appsettings.override.json
+++ b/AdminApi/src/AdminApi/appsettings.override.json
@@ -1,4 +1,5 @@
{
+ "RunMigrations": true,
"Authentication": {
"ApiKey": "test"
},
@@ -24,8 +25,8 @@
},
"SqlDatabase": {
"Provider": "Postgres",
- "ConnectionString": "User ID=adminUi;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres
- //"ConnectionString": "Server=ms-sql-server;Database=enmeshed;User Id=adminUi;Password=Passw0rd;TrustServerCertificate=True"
+ "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres
+// "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True"
}
},
"Modules": {
@@ -40,8 +41,8 @@
"Infrastructure": {
"SqlDatabase": {
"Provider": "Postgres",
- "ConnectionString": "User ID=devices;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres
- //"ConnectionString": "Server=ms-sql-server;Database=enmeshed;User Id=devices;Password=Passw0rd;TrustServerCertificate=True"
+ "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres
+// "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True"
},
"PushNotifications": {
"Provider": "Dummy"
@@ -58,8 +59,8 @@
"Infrastructure": {
"SqlDatabase": {
"Provider": "Postgres",
- "ConnectionString": "User ID=quotas;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres
- //"ConnectionString": "Server=ms-sql-server;Database=enmeshed;User Id=quotas;Password=Passw0rd;TrustServerCertificate=True"
+ "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres
+// "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True"
}
}
}
diff --git a/Backbone.sln b/Backbone.sln
index 79075c4d6c..d9245ade7a 100644
--- a/Backbone.sln
+++ b/Backbone.sln
@@ -297,6 +297,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventHandlerService", "Even
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventHandlerService.Tests", "EventHandlerService\test\EventHandlerService.Tests\EventHandlerService.Tests.csproj", "{D47E0FE1-23A0-4A96-AF57-E3CE71A132AD}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DatabaseMigrator", "DatabaseMigrator\DatabaseMigrator.csproj", "{143EAC38-A2D0-4F74-88F1-3EF27413A8C6}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -715,6 +717,10 @@ Global
{D47E0FE1-23A0-4A96-AF57-E3CE71A132AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D47E0FE1-23A0-4A96-AF57-E3CE71A132AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D47E0FE1-23A0-4A96-AF57-E3CE71A132AD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {143EAC38-A2D0-4F74-88F1-3EF27413A8C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {143EAC38-A2D0-4F74-88F1-3EF27413A8C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {143EAC38-A2D0-4F74-88F1-3EF27413A8C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {143EAC38-A2D0-4F74-88F1-3EF27413A8C6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/BuildingBlocks/src/BuildingBlocks.API/Extensions/HostExtensions.cs b/BuildingBlocks/src/BuildingBlocks.API/Extensions/HostExtensions.cs
index 896869d690..87b0c4d78e 100644
--- a/BuildingBlocks/src/BuildingBlocks.API/Extensions/HostExtensions.cs
+++ b/BuildingBlocks/src/BuildingBlocks.API/Extensions/HostExtensions.cs
@@ -5,7 +5,6 @@
using Microsoft.Extensions.Logging;
using Npgsql;
using Polly;
-using Polly.Retry;
namespace Backbone.BuildingBlocks.API.Extensions;
diff --git a/ConsumerApi/Program.cs b/ConsumerApi/Program.cs
index cad2de10e4..3ebc9804d7 100644
--- a/ConsumerApi/Program.cs
+++ b/ConsumerApi/Program.cs
@@ -98,16 +98,19 @@ static WebApplication CreateApp(string[] args)
var app = builder.Build();
Configure(app);
- app
- .MigrateDbContext()
- .MigrateDbContext()
- .MigrateDbContext()
- .MigrateDbContext()
- .MigrateDbContext()
- .MigrateDbContext()
- .MigrateDbContext()
- .MigrateDbContext()
- .MigrateDbContext();
+ if ((app.Environment.IsLocal() || app.Environment.IsDevelopment()) && app.Configuration.GetValue("RunMigrations"))
+ {
+ app
+ .MigrateDbContext()
+ .MigrateDbContext()
+ .MigrateDbContext()
+ .MigrateDbContext()
+ .MigrateDbContext()
+ .MigrateDbContext()
+ .MigrateDbContext()
+ .MigrateDbContext()
+ .MigrateDbContext();
+ }
app
.SeedDbContext()
diff --git a/ConsumerApi/appsettings.override.json b/ConsumerApi/appsettings.override.json
index 367cdb9cc1..057fcb9f23 100644
--- a/ConsumerApi/appsettings.override.json
+++ b/ConsumerApi/appsettings.override.json
@@ -1,4 +1,5 @@
{
+ "RunMigrations": true,
"Authentication": {
"JwtSigningCertificate": "", // can be empty to use an auto generated development certificate; however, in production scenarios this should definitely be set! Vertical scaling will not work without a fix signing certificate, because each instance would generate its own certificate
"JwtLifetimeInSeconds": 300
@@ -29,8 +30,8 @@
"Infrastructure": {
"SqlDatabase": {
"Provider": "Postgres",
- "ConnectionString": "User ID=challenges;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres
- // "ConnectionString": "Server=ms-sql-server;Database=enmeshed;User Id=challenges;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
+ "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres
+// "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
}
}
},
@@ -38,8 +39,8 @@
"Infrastructure": {
"SqlDatabase": {
"Provider": "Postgres",
- "ConnectionString": "User ID=quotas;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres
- // "ConnectionString": "Server=ms-sql-server;Database=enmeshed;User Id=quotas;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
+ "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres
+// "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
}
}
},
@@ -47,8 +48,8 @@
"Infrastructure": {
"SqlDatabase": {
"Provider": "Postgres",
- "ConnectionString": "User ID=devices;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres
- // "ConnectionString": "Server=ms-sql-server;Database=enmeshed;User Id=devices;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
+ "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres
+// "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
},
"PushNotifications": {
"Provider": "Dummy"
@@ -59,8 +60,8 @@
"Infrastructure": {
"SqlDatabase": {
"Provider": "Postgres",
- "ConnectionString": "User ID=files;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres
- // "ConnectionString": "Server=ms-sql-server;Database=enmeshed;User Id=files;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
+ "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres
+// "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
},
"BlobStorage": {
"CloudProvider": "Azure",
@@ -73,8 +74,8 @@
"Infrastructure": {
"SqlDatabase": {
"Provider": "Postgres",
- "ConnectionString": "User ID=messages;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres
- // "ConnectionString": "Server=ms-sql-server;Database=enmeshed;User Id=messages;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
+ "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres
+// "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
}
}
},
@@ -82,8 +83,8 @@
"Infrastructure": {
"SqlDatabase": {
"Provider": "Postgres",
- "ConnectionString": "User ID=relationships;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres
- // "ConnectionString": "Server=ms-sql-server;Database=enmeshed;User Id=relationships;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
+ "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres
+// "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
}
}
},
@@ -91,8 +92,8 @@
"Infrastructure": {
"SqlDatabase": {
"Provider": "Postgres",
- "ConnectionString": "User ID=synchronization;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres
- // "ConnectionString": "Server=ms-sql-server;Database=enmeshed;User Id=synchronization;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
+ "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres
+// "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
}
}
},
@@ -100,8 +101,8 @@
"Infrastructure": {
"SqlDatabase": {
"Provider": "Postgres",
- "ConnectionString": "User ID=tokens;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres
- // "ConnectionString": "Server=ms-sql-server;Database=enmeshed;User Id=tokens;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
+ "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres
+// "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
}
}
}
diff --git a/DatabaseMigrator/Configuration.cs b/DatabaseMigrator/Configuration.cs
new file mode 100644
index 0000000000..5075043b4d
--- /dev/null
+++ b/DatabaseMigrator/Configuration.cs
@@ -0,0 +1,24 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace Backbone.DatabaseMigrator;
+
+public class Configuration
+{
+ [Required]
+ public InfrastructureConfiguration Infrastructure { get; set; } = null!;
+}
+
+public class InfrastructureConfiguration
+{
+ [Required]
+ public SqlDatabaseConfiguration SqlDatabase { get; set; } = null!;
+}
+
+public class SqlDatabaseConfiguration
+{
+ [Required]
+ public string Provider { get; set; } = null!;
+
+ [Required]
+ public string ConnectionString { get; set; } = null!;
+}
diff --git a/DatabaseMigrator/DatabaseMigrator.csproj b/DatabaseMigrator/DatabaseMigrator.csproj
new file mode 100644
index 0000000000..e35173675b
--- /dev/null
+++ b/DatabaseMigrator/DatabaseMigrator.csproj
@@ -0,0 +1,56 @@
+
+
+
+ Exe
+ Linux
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DatabaseMigrator/Dockerfile b/DatabaseMigrator/Dockerfile
new file mode 100644
index 0000000000..c5a6dcddfb
--- /dev/null
+++ b/DatabaseMigrator/Dockerfile
@@ -0,0 +1,83 @@
+FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine3.18 AS base
+WORKDIR /app
+
+FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
+WORKDIR /src
+
+COPY ["Directory.Build.props", "."]
+COPY ["Modules/Directory.Build.props", "Modules/"]
+COPY ["DatabaseMigrator/DatabaseMigrator.csproj", "DatabaseMigrator/"]
+COPY ["AdminApi/src/AdminApi.Infrastructure/AdminApi.Infrastructure.csproj", "AdminApi/src/AdminApi.Infrastructure/"]
+COPY ["AdminApi/src/AdminApi.Infrastructure.Database.Postgres/AdminApi.Infrastructure.Database.Postgres.csproj", "AdminApi/src/AdminApi.Infrastructure.Database.Postgres/"]
+COPY ["AdminApi/src/AdminApi.Infrastructure.Database.SqlServer/AdminApi.Infrastructure.Database.SqlServer.csproj", "AdminApi/src/AdminApi.Infrastructure.Database.SqlServer/"]
+COPY ["BuildingBlocks/src/BuildingBlocks.Infrastructure/BuildingBlocks.Infrastructure.csproj", "BuildingBlocks/src/BuildingBlocks.Infrastructure/"]
+COPY ["BuildingBlocks/src/BuildingBlocks.Application.Abstractions/BuildingBlocks.Application.Abstractions.csproj", "BuildingBlocks/src/BuildingBlocks.Application.Abstractions/"]
+COPY ["BuildingBlocks/src/DevelopmentKit.Identity/DevelopmentKit.Identity.csproj", "BuildingBlocks/src/DevelopmentKit.Identity/"]
+COPY ["BuildingBlocks/src/BuildingBlocks.Domain/BuildingBlocks.Domain.csproj", "BuildingBlocks/src/BuildingBlocks.Domain/"]
+COPY ["BuildingBlocks/src/Tooling/Tooling.csproj", "BuildingBlocks/src/Tooling/"]
+COPY ["Modules/Tokens/src/Tokens.Infrastructure.Database.SqlServer/Tokens.Infrastructure.Database.SqlServer.csproj", "Modules/Tokens/src/Tokens.Infrastructure.Database.SqlServer/"]
+COPY ["Modules/Tokens/src/Tokens.Infrastructure/Tokens.Infrastructure.csproj", "Modules/Tokens/src/Tokens.Infrastructure/"]
+COPY ["Modules/Tokens/src/Tokens.Application/Tokens.Application.csproj", "Modules/Tokens/src/Tokens.Application/"]
+COPY ["BuildingBlocks/src/BuildingBlocks.Application/BuildingBlocks.Application.csproj", "BuildingBlocks/src/BuildingBlocks.Application/"]
+COPY ["Common/src/Common.Infrastructure/Common.Infrastructure.csproj", "Common/src/Common.Infrastructure/"]
+COPY ["Modules/Tokens/src/Tokens.Domain/Tokens.Domain.csproj", "Modules/Tokens/src/Tokens.Domain/"]
+COPY ["Modules/Tokens/src/Tokens.Infrastructure.Database.Postgres/Tokens.Infrastructure.Database.Postgres.csproj", "Modules/Tokens/src/Tokens.Infrastructure.Database.Postgres/"]
+COPY ["Modules/Synchronization/src/Synchronization.Infrastructure.Database.SqlServer/Synchronization.Infrastructure.Database.SqlServer.csproj", "Modules/Synchronization/src/Synchronization.Infrastructure.Database.SqlServer/"]
+COPY ["Modules/Synchronization/src/Synchronization.Infrastructure/Synchronization.Infrastructure.csproj", "Modules/Synchronization/src/Synchronization.Infrastructure/"]
+COPY ["Modules/Synchronization/src/Synchronization.Application/Synchronization.Application.csproj", "Modules/Synchronization/src/Synchronization.Application/"]
+COPY ["Modules/Synchronization/src/Synchronization.Domain/Synchronization.Domain.csproj", "Modules/Synchronization/src/Synchronization.Domain/"]
+COPY ["Modules/Synchronization/src/Synchronization.Infrastructure.Database.Postgres/Synchronization.Infrastructure.Database.Postgres.csproj", "Modules/Synchronization/src/Synchronization.Infrastructure.Database.Postgres/"]
+COPY ["Modules/Challenges/src/Challenges.Infrastructure/Challenges.Infrastructure.csproj", "Modules/Challenges/src/Challenges.Infrastructure/"]
+COPY ["Modules/Challenges/src/Challenges.Application/Challenges.Application.csproj", "Modules/Challenges/src/Challenges.Application/"]
+COPY ["Modules/Challenges/src/Challenges.Domain/Challenges.Domain.csproj", "Modules/Challenges/src/Challenges.Domain/"]
+COPY ["Modules/Devices/src/Devices.Infrastructure/Devices.Infrastructure.csproj", "Modules/Devices/src/Devices.Infrastructure/"]
+COPY ["Modules/Devices/src/Devices.Application/Devices.Application.csproj", "Modules/Devices/src/Devices.Application/"]
+COPY ["BuildingBlocks/src/Crypto/Crypto.csproj", "BuildingBlocks/src/Crypto/"]
+COPY ["Modules/Devices/src/Devices.Domain/Devices.Domain.csproj", "Modules/Devices/src/Devices.Domain/"]
+COPY ["Modules/Files/src/Files.Infrastructure/Files.Infrastructure.csproj", "Modules/Files/src/Files.Infrastructure/"]
+COPY ["Modules/Files/src/Files.Application/Files.Application.csproj", "Modules/Files/src/Files.Application/"]
+COPY ["Modules/Files/src/Files.Domain/Files.Domain.csproj", "Modules/Files/src/Files.Domain/"]
+COPY ["Modules/Messages/src/Messages.Infrastructure/Messages.Infrastructure.csproj", "Modules/Messages/src/Messages.Infrastructure/"]
+COPY ["Modules/Messages/src/Messages.Application/Messages.Application.csproj", "Modules/Messages/src/Messages.Application/"]
+COPY ["Modules/Messages/src/Messages.Domain/Messages.Domain.csproj", "Modules/Messages/src/Messages.Domain/"]
+COPY ["Modules/Quotas/src/Quotas.Infrastructure/Quotas.Infrastructure.csproj", "Modules/Quotas/src/Quotas.Infrastructure/"]
+COPY ["Modules/Quotas/src/Quotas.Application/Quotas.Application.csproj", "Modules/Quotas/src/Quotas.Application/"]
+COPY ["Modules/Quotas/src/Quotas.Domain/Quotas.Domain.csproj", "Modules/Quotas/src/Quotas.Domain/"]
+COPY ["Modules/Relationships/src/Relationships.Infrastructure/Relationships.Infrastructure.csproj", "Modules/Relationships/src/Relationships.Infrastructure/"]
+COPY ["Modules/Relationships/src/Relationships.Application/Relationships.Application.csproj", "Modules/Relationships/src/Relationships.Application/"]
+COPY ["Modules/Relationships/src/Relationships.Common/Relationships.Common.csproj", "Modules/Relationships/src/Relationships.Common/"]
+COPY ["Modules/Relationships/src/Relationships.Domain/Relationships.Domain.csproj", "Modules/Relationships/src/Relationships.Domain/"]
+COPY ["Modules/Relationships/src/Relationships.Infrastructure.Database.SqlServer/Relationships.Infrastructure.Database.SqlServer.csproj", "Modules/Relationships/src/Relationships.Infrastructure.Database.SqlServer/"]
+COPY ["Modules/Relationships/src/Relationships.Infrastructure.Database.Postgres/Relationships.Infrastructure.Database.Postgres.csproj", "Modules/Relationships/src/Relationships.Infrastructure.Database.Postgres/"]
+COPY ["Modules/Quotas/src/Quotas.Infrastructure.Database.SqlServer/Quotas.Infrastructure.Database.SqlServer.csproj", "Modules/Quotas/src/Quotas.Infrastructure.Database.SqlServer/"]
+COPY ["Modules/Quotas/src/Quotas.Infrastructure.Database.Postgres/Quotas.Infrastructure.Database.Postgres.csproj", "Modules/Quotas/src/Quotas.Infrastructure.Database.Postgres/"]
+COPY ["Modules/Messages/src/Messages.Infrastructure.Database.SqlServer/Messages.Infrastructure.Database.SqlServer.csproj", "Modules/Messages/src/Messages.Infrastructure.Database.SqlServer/"]
+COPY ["Modules/Messages/src/Messages.Infrastructure.Database.Postgres/Messages.Infrastructure.Database.Postgres.csproj", "Modules/Messages/src/Messages.Infrastructure.Database.Postgres/"]
+COPY ["Modules/Files/src/Files.Infrastructure.Database.SqlServer/Files.Infrastructure.Database.SqlServer.csproj", "Modules/Files/src/Files.Infrastructure.Database.SqlServer/"]
+COPY ["Modules/Files/src/Files.Infrastructure.Database.Postgres/Files.Infrastructure.Database.Postgres.csproj", "Modules/Files/src/Files.Infrastructure.Database.Postgres/"]
+COPY ["Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/Devices.Infrastructure.Database.SqlServer.csproj", "Modules/Devices/src/Devices.Infrastructure.Database.SqlServer/"]
+COPY ["Modules/Devices/src/Devices.Infrastructure.Database.Postgres/Devices.Infrastructure.Database.Postgres.csproj", "Modules/Devices/src/Devices.Infrastructure.Database.Postgres/"]
+COPY ["Modules/Challenges/src/Challenges.Infrastructure.Database.SqlServer/Challenges.Infrastructure.Database.SqlServer.csproj", "Modules/Challenges/src/Challenges.Infrastructure.Database.SqlServer/"]
+COPY ["Modules/Challenges/src/Challenges.Infrastructure.Database.Postgres/Challenges.Infrastructure.Database.Postgres.csproj", "Modules/Challenges/src/Challenges.Infrastructure.Database.Postgres/"]
+COPY ["AdminApi/src/AdminApi.Infrastructure.Database.SqlServer/AdminApi.Infrastructure.Database.SqlServer.csproj", "AdminApi/src/AdminApi.Infrastructure.Database.SqlServer/"]
+COPY ["AdminApi/src/AdminApi.Infrastructure.Database.Postgres/AdminApi.Infrastructure.Database.Postgres.csproj", "AdminApi/src/AdminApi.Infrastructure.Database.Postgres/"]
+
+RUN dotnet restore "DatabaseMigrator/DatabaseMigrator.csproj"
+
+COPY . .
+
+WORKDIR "/src/DatabaseMigrator"
+RUN dotnet build "DatabaseMigrator.csproj" -c Release --output /app/build --no-restore
+
+FROM build AS publish
+
+RUN dotnet publish -c Release --output /app/publish --no-restore "DatabaseMigrator.csproj"
+
+FROM base AS final
+
+RUN apk add icu-libs
+ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=0
+
+WORKDIR /app
+COPY --from=publish /app/publish .
+ENTRYPOINT ["dotnet", "Backbone.DatabaseMigrator.dll"]
diff --git a/DatabaseMigrator/Executor.cs b/DatabaseMigrator/Executor.cs
new file mode 100644
index 0000000000..2bc8366ed7
--- /dev/null
+++ b/DatabaseMigrator/Executor.cs
@@ -0,0 +1,246 @@
+using System.Data.SqlClient;
+using Backbone.AdminApi.Infrastructure.Persistence.Database;
+using Backbone.Modules.Challenges.Infrastructure.Persistence.Database;
+using Backbone.Modules.Devices.Infrastructure.Persistence.Database;
+using Backbone.Modules.Files.Infrastructure.Persistence.Database;
+using Backbone.Modules.Messages.Infrastructure.Persistence.Database;
+using Backbone.Modules.Quotas.Infrastructure.Persistence.Database;
+using Backbone.Modules.Relationships.Infrastructure.Persistence.Database;
+using Backbone.Modules.Synchronization.Infrastructure.Persistence.Database;
+using Backbone.Modules.Tokens.Infrastructure.Persistence.Database;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Npgsql;
+using Polly;
+using Polly.Retry;
+
+namespace Backbone.DatabaseMigrator;
+
+public class Executor
+{
+ private readonly IServiceProvider _serviceProvider;
+ private readonly ILogger _logger;
+
+ private readonly Stack<(Type dbContextType, string? migrationBeforeChanges)> _migratedDbContexts = new();
+ private readonly RetryPolicy _retryPolicy;
+
+ public Executor(IServiceProvider serviceProvider, ILogger logger)
+ {
+ _serviceProvider = serviceProvider;
+ _logger = logger;
+
+ _retryPolicy = Policy.Handle().Or()
+ .WaitAndRetry([
+ TimeSpan.FromSeconds(5),
+ TimeSpan.FromSeconds(10),
+ TimeSpan.FromSeconds(15)
+ ]);
+ }
+
+ public async Task Execute()
+ {
+ _logger.StartApplyingMigrations();
+
+ try
+ {
+ await MigrateDbContext();
+ await MigrateDbContext();
+ await MigrateDbContext();
+ await MigrateDbContext();
+ await MigrateDbContext();
+ await MigrateDbContext();
+ await MigrateDbContext();
+ await MigrateDbContext();
+ await MigrateDbContext();
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorWhileApplyingMigrations(ex);
+ await RollbackAlreadyMigratedDbContexts();
+ Environment.Exit(1);
+ }
+
+ _logger.SuccessfullyAppliedMigrations();
+ }
+
+ private async Task MigrateDbContext(string? targetMigration = null) where TContext : DbContext
+ {
+ await using var context = _serviceProvider.GetDbContext();
+
+ if (targetMigration == null)
+ _logger.MigratingDbContextToLatestMigration(typeof(TContext).Name);
+ else
+ _logger.MigratingDbContextToTargetMigration(typeof(TContext).Name, targetMigration);
+
+ var pendingMigrations = await context.Database.GetPendingMigrationsAsync();
+ if (!pendingMigrations.Any())
+ return;
+
+ var migrationBeforeChanges = await context.GetLastAppliedMigration();
+
+ try
+ {
+ await _retryPolicy.Execute(() => context.MigrateTo(targetMigration));
+ }
+ catch (Exception ex)
+ {
+ if (targetMigration == null)
+ _logger.ErrorWhileApplyingMigrationToLatestMigration(ex, typeof(TContext).Name);
+ else
+ _logger.ErrorWhileApplyingMigrationToTargetMigration(ex, typeof(TContext).Name, targetMigration);
+ throw;
+ }
+ finally
+ {
+ _migratedDbContexts.Push((context.GetType(), migrationBeforeChanges));
+ }
+
+ if (targetMigration == null)
+ _logger.SuccessfullyMigratedDbContextToLatestMigration(typeof(TContext).Name);
+ else
+ _logger.SuccessfullyMigratedDbContextToTargetMigration(typeof(TContext).Name, targetMigration);
+ }
+
+ private async Task RollbackAlreadyMigratedDbContexts()
+ {
+ while (_migratedDbContexts.Count != 0)
+ {
+ var (contextType, migrationBeforeChanges) = _migratedDbContexts.Peek();
+
+ await using var context = _serviceProvider.GetDbContext(contextType);
+
+ // if the migrationBeforeChanges is null, this means that it was the first migration; EF Core doesn't allow unapplying the first migration. But it's no problem because
+ // if there is only one migration, it means that in case of a rollback of the application version, there will be nothing that needs the tables from the first migration.
+ if (migrationBeforeChanges == null)
+ continue;
+
+ _logger.RollingBackDbContext(contextType.Name, migrationBeforeChanges);
+
+ try
+ {
+ await context.MigrateTo(migrationBeforeChanges);
+ }
+ catch (Exception ex)
+ {
+ var remainingDbContexts = string.Join(", ", _migratedDbContexts.Select(c => c.dbContextType.Name));
+
+ _logger.ErrorOnRollback(ex, context.GetType().Name, migrationBeforeChanges, remainingDbContexts);
+ }
+
+ _migratedDbContexts.Pop();
+ }
+ }
+}
+
+file static class Extensions
+{
+ public static async Task MigrateTo(this DbContext dbContext, string? targetMigration = null)
+ {
+ var migrator = dbContext.GetInfrastructure().GetRequiredService();
+ await migrator.MigrateAsync(targetMigration);
+ }
+
+ public static async Task GetLastAppliedMigration(this DbContext dbContext)
+ {
+ var stateBeforeMigration = await dbContext.Database.GetAppliedMigrationsAsync();
+ var migrationBeforeChanges = stateBeforeMigration.LastOrDefault();
+ return migrationBeforeChanges;
+ }
+
+ public static DbContext GetDbContext(this IServiceProvider serviceProvider) where T : DbContext
+ {
+ return serviceProvider.GetDbContext(typeof(T));
+ }
+
+ public static DbContext GetDbContext(this IServiceProvider serviceProvider, Type type)
+ {
+ var scope = serviceProvider.CreateScope();
+ var context = (DbContext)scope.ServiceProvider.GetRequiredService(type);
+ return context;
+ }
+}
+
+internal static partial class ExecutorLogs
+{
+ [LoggerMessage(
+ EventId = 561100,
+ EventName = "DatabaseMigrator.Executor.StartApplyingMigrations",
+ Level = LogLevel.Information,
+ Message = "Start applying migrations...")]
+ public static partial void StartApplyingMigrations(this ILogger logger);
+
+ [LoggerMessage(
+ EventId = 561101,
+ EventName = "DatabaseMigrator.Executor.SuccessfullyAppliedMigrations",
+ Level = LogLevel.Information,
+ Message = "All migrations were successfully applied")]
+ public static partial void SuccessfullyAppliedMigrations(this ILogger logger);
+
+ [LoggerMessage(
+ EventId = 561102,
+ EventName = "DatabaseMigrator.Executor.ErrorWhileApplyingMigrations",
+ Level = LogLevel.Critical,
+ Message = "An error occurred while migrating the database. Rolling back already migrated DbContexts...")]
+ public static partial void ErrorWhileApplyingMigrations(this ILogger logger, Exception ex);
+
+ [LoggerMessage(
+ EventId = 561103,
+ EventName = "DatabaseMigrator.Executor.MigratingDbContextToLatestMigration",
+ Level = LogLevel.Information,
+ Message = "Migrating database associated with context '{context}' to the latest migration...")]
+ public static partial void MigratingDbContextToLatestMigration(this ILogger logger, string context);
+
+ [LoggerMessage(
+ EventId = 561104,
+ EventName = "DatabaseMigrator.Executor.MigratingDbContextToTargetMigration",
+ Level = LogLevel.Information,
+ Message = "Migrating database associated with context '{context}' to target migration '{targetMigration}'...")]
+ public static partial void MigratingDbContextToTargetMigration(this ILogger logger, string context, string targetMigration);
+
+ [LoggerMessage(
+ EventId = 561105,
+ EventName = "DatabaseMigrator.Executor.SuccessfullyMigratedDbContextToLatestMigration",
+ Level = LogLevel.Information,
+ Message = "Migrating database associated with context '{context}' to the latest migration...")]
+ public static partial void SuccessfullyMigratedDbContextToLatestMigration(this ILogger logger, string context);
+
+ [LoggerMessage(
+ EventId = 561106,
+ EventName = "DatabaseMigrator.Executor.SuccessfullyMigratedDbContextToTargetMigration",
+ Level = LogLevel.Information,
+ Message = "Migrating database associated with context '{context}' to target migration '{targetMigration}'...")]
+ public static partial void SuccessfullyMigratedDbContextToTargetMigration(this ILogger logger, string context, string targetMigration);
+
+ [LoggerMessage(
+ EventId = 561108,
+ EventName = "DatabaseMigrator.Executor.ErrorWhileApplyingMigrationToLatestMigration",
+ Level = LogLevel.Critical,
+ Message =
+ "An error occurred while migrating the database associated with context '{context}' to the latest migration'")]
+ public static partial void ErrorWhileApplyingMigrationToLatestMigration(this ILogger logger, Exception ex, string context);
+
+ [LoggerMessage(
+ EventId = 561107,
+ EventName = "DatabaseMigrator.Executor.ErrorWhileApplyingMigrationToTargetMigration",
+ Level = LogLevel.Critical,
+ Message =
+ "An error occurred while migrating the database associated with context '{context}' to target migration '{targetMigration}'")]
+ public static partial void ErrorWhileApplyingMigrationToTargetMigration(this ILogger logger, Exception ex, string context, string targetMigration);
+
+ [LoggerMessage(
+ EventId = 561109,
+ EventName = "DatabaseMigrator.Executor.RollingBackDbContext",
+ Level = LogLevel.Information,
+ Message =
+ "Rolling back context '{context}' to migration '{migrationBeforeChanges}'....")]
+ public static partial void RollingBackDbContext(this ILogger logger, string context, string migrationBeforeChanges);
+
+ [LoggerMessage(
+ EventId = 561110,
+ EventName = "DatabaseMigrator.Executor.ErrorOnRollback",
+ Level = LogLevel.Critical,
+ Message =
+ "There was an error while rolling back the migration of context '{context}' to migration '{migrationBeforeChanges}'. The following DbContexts couldn't be rolled back: {remainingDbContexts}")]
+ public static partial void ErrorOnRollback(this ILogger logger, Exception ex, string context, string migrationBeforeChanges, string remainingDbContexts);
+}
diff --git a/DatabaseMigrator/Program.cs b/DatabaseMigrator/Program.cs
new file mode 100644
index 0000000000..56e7c5f7c5
--- /dev/null
+++ b/DatabaseMigrator/Program.cs
@@ -0,0 +1,137 @@
+using System.Reflection;
+using Autofac.Extensions.DependencyInjection;
+using Backbone.DatabaseMigrator;
+using Microsoft.Extensions.Options;
+using Serilog;
+using Serilog.Exceptions;
+using Serilog.Exceptions.Core;
+using Serilog.Exceptions.EntityFrameworkCore.Destructurers;
+using Serilog.Settings.Configuration;
+using IServiceCollectionExtensions = Backbone.Modules.Challenges.Infrastructure.Persistence.IServiceCollectionExtensions;
+
+Log.Logger = new LoggerConfiguration()
+ .WriteTo.Console()
+ .CreateBootstrapLogger();
+
+try
+{
+ var app = CreateHostBuilder(args).Build();
+
+ var executor = app.Services.GetRequiredService();
+
+ await executor.Execute();
+
+ return 0;
+}
+catch (Exception ex)
+{
+ Log.Fatal(ex, "Host terminated unexpectedly");
+ return 1;
+}
+finally
+{
+ await Log.CloseAndFlushAsync();
+}
+
+
+static IHostBuilder CreateHostBuilder(string[] args)
+{
+ return Host.CreateDefaultBuilder(args)
+ .ConfigureAppConfiguration((hostContext, configuration) =>
+ {
+ configuration.Sources.Clear();
+ var env = hostContext.HostingEnvironment;
+
+ configuration
+ .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
+ .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
+ .AddJsonFile("appsettings.override.json", optional: true, reloadOnChange: true);
+
+ if (env.IsDevelopment())
+ {
+ var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
+ configuration.AddUserSecrets(appAssembly, optional: true);
+ }
+
+ configuration.AddEnvironmentVariables();
+ configuration.AddCommandLine(args);
+ })
+ .ConfigureServices((hostContext, services) =>
+ {
+ var configuration = hostContext.Configuration;
+
+ services.ConfigureAndValidate(configuration.Bind);
+ var parsedConfiguration = services.BuildServiceProvider().GetRequiredService>().Value;
+
+ services.AddSingleton();
+
+ # region Add db contexts
+
+ IServiceCollectionExtensions.AddDatabase(services, options =>
+ {
+ options.Provider = parsedConfiguration.Infrastructure.SqlDatabase.Provider;
+ options.DbConnectionString = parsedConfiguration.Infrastructure.SqlDatabase.ConnectionString;
+ });
+
+ Backbone.Modules.Devices.Infrastructure.Persistence.IServiceCollectionExtensions.AddDatabase(services, options =>
+ {
+ options.Provider = parsedConfiguration.Infrastructure.SqlDatabase.Provider;
+ options.ConnectionString = parsedConfiguration.Infrastructure.SqlDatabase.ConnectionString;
+ });
+
+ Backbone.Modules.Files.Infrastructure.Persistence.Database.IServiceCollectionExtensions.AddDatabase(services, options =>
+ {
+ options.Provider = parsedConfiguration.Infrastructure.SqlDatabase.Provider;
+ options.DbConnectionString = parsedConfiguration.Infrastructure.SqlDatabase.ConnectionString;
+ });
+
+ Backbone.Modules.Messages.Infrastructure.Persistence.Database.IServiceCollectionExtensions.AddDatabase(services, options =>
+ {
+ options.Provider = parsedConfiguration.Infrastructure.SqlDatabase.Provider;
+ options.DbConnectionString = parsedConfiguration.Infrastructure.SqlDatabase.ConnectionString;
+ });
+
+ Backbone.Modules.Quotas.Infrastructure.Persistence.Database.IServiceCollectionExtensions.AddDatabase(services, options =>
+ {
+ options.Provider = parsedConfiguration.Infrastructure.SqlDatabase.Provider;
+ options.DbConnectionString = parsedConfiguration.Infrastructure.SqlDatabase.ConnectionString;
+ });
+
+ Backbone.Modules.Relationships.Infrastructure.Persistence.Database.IServiceCollectionExtensions.AddDatabase(services, options =>
+ {
+ options.Provider = parsedConfiguration.Infrastructure.SqlDatabase.Provider;
+ options.DbConnectionString = parsedConfiguration.Infrastructure.SqlDatabase.ConnectionString;
+ });
+
+ Backbone.Modules.Synchronization.Infrastructure.Persistence.Database.IServiceCollectionExtensions.AddDatabase(services, options =>
+ {
+ options.Provider = parsedConfiguration.Infrastructure.SqlDatabase.Provider;
+ options.DbConnectionString = parsedConfiguration.Infrastructure.SqlDatabase.ConnectionString;
+ });
+
+ Backbone.Modules.Tokens.Infrastructure.Persistence.Database.IServiceCollectionExtensions.AddDatabase(services, options =>
+ {
+ options.Provider = parsedConfiguration.Infrastructure.SqlDatabase.Provider;
+ options.DbConnectionString = parsedConfiguration.Infrastructure.SqlDatabase.ConnectionString;
+ });
+
+ Backbone.AdminApi.Infrastructure.Persistence.IServiceCollectionExtensions.AddDatabase(services, options =>
+ {
+ options.Provider = parsedConfiguration.Infrastructure.SqlDatabase.Provider;
+ options.ConnectionString = parsedConfiguration.Infrastructure.SqlDatabase.ConnectionString;
+ });
+
+ #endregion
+ })
+ .UseServiceProviderFactory(new AutofacServiceProviderFactory())
+ .UseSerilog((context, configuration) => configuration
+ .ReadFrom.Configuration(context.Configuration, new ConfigurationReaderOptions { SectionName = "Logging" })
+ .Enrich.WithDemystifiedStackTraces()
+ .Enrich.FromLogContext()
+ .Enrich.WithProperty("service", "databasemigrator")
+ .Enrich.WithExceptionDetails(new DestructuringOptionsBuilder()
+ .WithDefaultDestructurers()
+ .WithDestructurers(new[] { new DbUpdateExceptionDestructurer() })
+ )
+ );
+}
diff --git a/DatabaseMigrator/appsettings.json b/DatabaseMigrator/appsettings.json
new file mode 100644
index 0000000000..ee2039925d
--- /dev/null
+++ b/DatabaseMigrator/appsettings.json
@@ -0,0 +1,15 @@
+{
+ "Logging": {
+ "MinimumLevel": {
+ "Default": "Information",
+ },
+ "WriteTo": {
+ "Console": {
+ "Name": "Console",
+ "Args": {
+ "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact"
+ }
+ }
+ }
+ }
+}
diff --git a/DatabaseMigrator/appsettings.override.json b/DatabaseMigrator/appsettings.override.json
new file mode 100644
index 0000000000..f9955cd341
--- /dev/null
+++ b/DatabaseMigrator/appsettings.override.json
@@ -0,0 +1,28 @@
+{
+ "Infrastructure": {
+ "SqlDatabase": {
+ "Provider": "Postgres",
+ "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres,
+// "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
+ }
+ },
+ "Logging": {
+ "MinimumLevel": {
+ "Default": "Information",
+ "Override": {
+ "Backbone": "Debug"
+ }
+ },
+ "WriteTo": {
+ "Seq": {
+ "Name": "Seq",
+ "Args": {
+ "ServerUrl": "http://localhost:5341"
+ }
+ },
+ "Debug": {
+ "Name": "Debug"
+ }
+ }
+ }
+}
diff --git a/EventHandlerService/src/EventHandlerService/EventHandlerService.csproj b/EventHandlerService/src/EventHandlerService/EventHandlerService.csproj
index c511107aa1..43d6c8b872 100644
--- a/EventHandlerService/src/EventHandlerService/EventHandlerService.csproj
+++ b/EventHandlerService/src/EventHandlerService/EventHandlerService.csproj
@@ -1,7 +1,7 @@
- Exe
+ Exe
Linux
..\..\..
diff --git a/EventHandlerService/src/EventHandlerService/appsettings.override.json b/EventHandlerService/src/EventHandlerService/appsettings.override.json
index 40cf03c8d0..7bef826456 100644
--- a/EventHandlerService/src/EventHandlerService/appsettings.override.json
+++ b/EventHandlerService/src/EventHandlerService/appsettings.override.json
@@ -17,8 +17,8 @@
"Infrastructure": {
"SqlDatabase": {
"Provider": "Postgres",
- "ConnectionString": "User ID=challenges;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres
- // "ConnectionString": "Server=localhost;Database=enmeshed;User Id=challenges;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
+ "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres
+ // "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
}
}
},
@@ -26,8 +26,8 @@
"Infrastructure": {
"SqlDatabase": {
"Provider": "Postgres",
- "ConnectionString": "User ID=quotas;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres
- // "ConnectionString": "Server=localhost;Database=enmeshed;User Id=quotas;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
+ "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres
+ // "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
}
}
},
@@ -35,8 +35,8 @@
"Infrastructure": {
"SqlDatabase": {
"Provider": "Postgres",
- "ConnectionString": "User ID=devices;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres
- // "ConnectionString": "Server=localhost;Database=enmeshed;User Id=devices;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
+ "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres
+ // "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
},
"PushNotifications": {
"Provider": "Dummy"
@@ -47,8 +47,8 @@
"Infrastructure": {
"SqlDatabase": {
"Provider": "Postgres",
- "ConnectionString": "User ID=files;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres
- // "ConnectionString": "Server=localhost;Database=enmeshed;User Id=files;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
+ "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres
+ // "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
},
"BlobStorage": {
"CloudProvider": "Azure",
@@ -61,8 +61,8 @@
"Infrastructure": {
"SqlDatabase": {
"Provider": "Postgres",
- "ConnectionString": "User ID=messages;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres
- // "ConnectionString": "Server=localhost;Database=enmeshed;User Id=messages;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
+ "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres
+ // "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
}
}
},
@@ -70,8 +70,8 @@
"Infrastructure": {
"SqlDatabase": {
"Provider": "Postgres",
- "ConnectionString": "User ID=relationships;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres
- // "ConnectionString": "Server=localhost;Database=enmeshed;User Id=relationships;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
+ "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres
+ // "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
}
}
},
@@ -79,8 +79,8 @@
"Infrastructure": {
"SqlDatabase": {
"Provider": "Postgres",
- "ConnectionString": "User ID=synchronization;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres
- // "ConnectionString": "Server=localhost;Database=enmeshed;User Id=synchronization;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
+ "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres
+ // "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
}
}
},
@@ -88,8 +88,8 @@
"Infrastructure": {
"SqlDatabase": {
"Provider": "Postgres",
- "ConnectionString": "User ID=tokens;Password=Passw0rd;Server=localhost;Port=5432;Database=enmeshed;" // postgres
- // "ConnectionString": "Server=localhost;Database=enmeshed;User Id=tokens;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
+ "ConnectionString": "User ID=postgres;Password=admin;Server=localhost;Port=5432;Database=enmeshed;" // postgres
+ // "ConnectionString": "Server=localhost;Database=enmeshed;User Id=sa;Password=Passw0rd;TrustServerCertificate=True" // sqlserver
}
}
}
diff --git a/docker-compose/docker-compose.yml b/docker-compose/docker-compose.yml
index b4bb341a09..7480bc5ac8 100644
--- a/docker-compose/docker-compose.yml
+++ b/docker-compose/docker-compose.yml
@@ -34,7 +34,7 @@ services:
- postgres-volume:/var/lib/postgresql/data
ports:
- 5432:5432
-
+
rabbitmq:
container_name: bkb-rabbitmq
hostname: rabbitmq
diff --git a/helm/templates/admincli/templates/deployment.yaml b/helm/templates/admincli/deployment.yaml
similarity index 89%
rename from helm/templates/admincli/templates/deployment.yaml
rename to helm/templates/admincli/deployment.yaml
index 5b872db345..b913d78906 100644
--- a/helm/templates/admincli/templates/deployment.yaml
+++ b/helm/templates/admincli/deployment.yaml
@@ -1,15 +1,15 @@
apiVersion: apps/v1
kind: Deployment
metadata:
- name: {{ include "global.name" . }}
+ name: {{ .Values.admincli.name }}
labels:
{{- include "global.labels" . | nindent 4 }}
- app: {{ include "global.name" . }}
+ app: {{ .Values.admincli.name }}
spec:
replicas: 1
selector:
matchLabels:
- app: {{ include "global.name" . }}
+ app: {{ .Values.admincli.name }}
template:
metadata:
{{- with .Values.admincli.podAnnotations }}
@@ -17,7 +17,7 @@ spec:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
- app: {{ include "global.name" . }}
+ app: {{ .Values.admincli.name }}
spec:
{{- with .Values.admincli.podSecurityContext }}
securityContext:
@@ -28,7 +28,7 @@ spec:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- - name: {{ include "global.name" . }}
+ - name: {{ .Values.admincli.name }}
{{- with .Values.admincli.securityContext }}
securityContext:
{{- toYaml .Values.admincli.securityContext | nindent 8 }}
diff --git a/helm/templates/adminui/templates/deployment.yaml b/helm/templates/adminui/deployment.yaml
similarity index 94%
rename from helm/templates/adminui/templates/deployment.yaml
rename to helm/templates/adminui/deployment.yaml
index 43aba0b988..40a64bb5f9 100644
--- a/helm/templates/adminui/templates/deployment.yaml
+++ b/helm/templates/adminui/deployment.yaml
@@ -1,10 +1,10 @@
apiVersion: apps/v1
kind: Deployment
metadata:
- name: {{ include "global.name" . }}
+ name: {{ .Values.adminui.name }}
labels:
{{- include "global.labels" . | nindent 4 }}
- app: {{ include "global.name" . }}
+ app: {{ .Values.adminui.name }}
spec:
replicas: {{ .Values.adminui.replicas }}
strategy:
@@ -14,7 +14,7 @@ spec:
maxUnavailable: {{ .Values.adminui.maxUnavailable }}
selector:
matchLabels:
- app: {{ include "global.name" . }}
+ app: {{ .Values.adminui.name }}
template:
metadata:
annotations:
@@ -24,7 +24,7 @@ spec:
{{- end }}
labels:
{{- include "global.labels" . | nindent 8 }}
- app: {{ include "global.name" . }}
+ app: {{ .Values.adminui.name }}
spec:
{{- with .Values.global.serviceAccount.name}}
serviceAccountName: {{ . }}
@@ -46,7 +46,7 @@ spec:
configMap:
name: configuration
containers:
- - name: {{ include "global.name" . }}
+ - name: {{ .Values.adminui.name }}
{{- with .Values.adminui.securityContext }}
securityContext:
{{- toYaml .Values.adminui.securityContext | nindent 8 }}
diff --git a/helm/templates/adminui/templates/hpa.yaml b/helm/templates/adminui/hpa.yaml
similarity index 91%
rename from helm/templates/adminui/templates/hpa.yaml
rename to helm/templates/adminui/hpa.yaml
index a58f4203c3..badb60579e 100644
--- a/helm/templates/adminui/templates/hpa.yaml
+++ b/helm/templates/adminui/hpa.yaml
@@ -2,14 +2,14 @@
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
- name: {{ include "global.name" . }}
+ name: {{ .Values.adminui.name }}
labels:
{{- include "global.labels" . | nindent 4 }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
- name: {{ include "global.name" . }}
+ name: {{ .Values.adminui.name }}
minReplicas: {{ .Values.adminui.autoscaling.minReplicas }}
maxReplicas: {{ .Values.adminui.autoscaling.maxReplicas }}
metrics:
diff --git a/helm/templates/adminui/templates/service.yaml b/helm/templates/adminui/service.yaml
similarity index 59%
rename from helm/templates/adminui/templates/service.yaml
rename to helm/templates/adminui/service.yaml
index 4ef1b52b64..2bc84f5ef7 100644
--- a/helm/templates/adminui/templates/service.yaml
+++ b/helm/templates/adminui/service.yaml
@@ -1,13 +1,13 @@
apiVersion: v1
kind: Service
metadata:
- name: {{ include "global.name" . }}
+ name: {{ .Values.adminui.name }}
labels:
{{- include "global.labels" . | nindent 4 }}
- app: {{ include "global.name" . }}
+ app: {{ .Values.adminui.name }}
{{- if eq .Values.global.provider "GoogleCloud" }}
annotations:
- cloud.google.com/backend-config: '{"default": "{{ include "global.name" . }}"}'
+ cloud.google.com/backend-config: '{"default": "{{ .Values.adminui.name }}"}'
{{- end }}
spec:
type: {{ .Values.adminui.service.type }}
@@ -15,4 +15,4 @@ spec:
- port: 8080
targetPort: 8080
selector:
- app: {{ include "global.name" . }}
+ app: {{ .Values.adminui.name }}
diff --git a/helm/templates/consumerapi/templates/backendconfig.yaml b/helm/templates/consumerapi/backendconfig.yaml
similarity index 94%
rename from helm/templates/consumerapi/templates/backendconfig.yaml
rename to helm/templates/consumerapi/backendconfig.yaml
index 05c998b615..fb416b9389 100644
--- a/helm/templates/consumerapi/templates/backendconfig.yaml
+++ b/helm/templates/consumerapi/backendconfig.yaml
@@ -4,7 +4,7 @@ kind: BackendConfig
metadata:
labels:
{{- include "global.labels" . | nindent 4 }}
- name: {{ include "global.name" . }}
+ name: {{ .Values.consumerapi.name }}
spec:
healthCheck:
checkIntervalSec: {{ .Values.consumerapi.backendConfig.healthCheck.checkIntervalSec }}
diff --git a/helm/templates/consumerapi/templates/deployment.yaml b/helm/templates/consumerapi/deployment.yaml
similarity index 94%
rename from helm/templates/consumerapi/templates/deployment.yaml
rename to helm/templates/consumerapi/deployment.yaml
index eeb699c772..bdd1d2fd9f 100644
--- a/helm/templates/consumerapi/templates/deployment.yaml
+++ b/helm/templates/consumerapi/deployment.yaml
@@ -1,10 +1,10 @@
apiVersion: apps/v1
kind: Deployment
metadata:
- name: {{ include "global.name" . }}
+ name: {{ .Values.consumerapi.name }}
labels:
{{- include "global.labels" . | nindent 4 }}
- app: {{ include "global.name" . }}
+ app: {{ .Values.consumerapi.name }}
spec:
replicas: {{ .Values.consumerapi.replicas }}
strategy:
@@ -14,7 +14,7 @@ spec:
maxUnavailable: {{ .Values.consumerapi.maxUnavailable }}
selector:
matchLabels:
- app: {{ include "global.name" . }}
+ app: {{ .Values.consumerapi.name }}
template:
metadata:
annotations:
@@ -24,7 +24,7 @@ spec:
{{- end }}
labels:
{{- include "global.labels" . | nindent 8 }}
- app: {{ include "global.name" . }}
+ app: {{ .Values.consumerapi.name }}
spec:
{{- with .Values.global.serviceAccount.name}}
serviceAccountName: {{ . }}
@@ -46,7 +46,7 @@ spec:
configMap:
name: configuration
containers:
- - name: {{ include "global.name" . }}
+ - name: {{ .Values.consumerapi.name }}
{{- with .Values.consumerapi.securityContext }}
securityContext:
{{- toYaml .Values.consumerapi.securityContext | nindent 8 }}
diff --git a/helm/templates/consumerapi/templates/hpa.yaml b/helm/templates/consumerapi/hpa.yaml
similarity index 91%
rename from helm/templates/consumerapi/templates/hpa.yaml
rename to helm/templates/consumerapi/hpa.yaml
index 816ad94b62..18c00417d9 100644
--- a/helm/templates/consumerapi/templates/hpa.yaml
+++ b/helm/templates/consumerapi/hpa.yaml
@@ -2,14 +2,14 @@
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
- name: {{ include "global.name" . }}
+ name: {{ .Values.consumerapi.name }}
labels:
{{- include "global.labels" . | nindent 4 }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
- name: {{ include "global.name" . }}
+ name: {{ .Values.consumerapi.name }}
minReplicas: {{ .Values.consumerapi.autoscaling.minReplicas }}
maxReplicas: {{ .Values.consumerapi.autoscaling.maxReplicas }}
metrics:
diff --git a/helm/templates/consumerapi/templates/httproute.yaml b/helm/templates/consumerapi/httproute.yaml
similarity index 88%
rename from helm/templates/consumerapi/templates/httproute.yaml
rename to helm/templates/consumerapi/httproute.yaml
index c1c7a7c46d..d59b0da7c2 100644
--- a/helm/templates/consumerapi/templates/httproute.yaml
+++ b/helm/templates/consumerapi/httproute.yaml
@@ -2,7 +2,7 @@
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
- name: {{ include "global.name" . }}
+ name: {{ .Values.consumerapi.name }}
labels:
{{- include "global.labels" . | nindent 4 }}
spec:
@@ -20,6 +20,6 @@ spec:
type: PathPrefix
value: /
backendRefs:
- - name: {{ include "global.name" . }}
+ - name: {{ .Values.consumerapi.name }}
port: 8080
{{- end }}
diff --git a/helm/templates/consumerapi/templates/ingress.yaml b/helm/templates/consumerapi/ingress.yaml
similarity index 84%
rename from helm/templates/consumerapi/templates/ingress.yaml
rename to helm/templates/consumerapi/ingress.yaml
index ed39cf7cca..6df847853e 100644
--- a/helm/templates/consumerapi/templates/ingress.yaml
+++ b/helm/templates/consumerapi/ingress.yaml
@@ -2,10 +2,10 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
- name: {{ include "global.name" . }}
+ name: {{ .Values.consumerapi.name }}
labels:
{{- include "global.labels" . | nindent 4 }}
- app: {{ include "global.name" . }}
+ app: {{ .Values.consumerapi.name }}
annotations:
kubernetes.io/ingress.class: azure/application-gateway
appgw.ingress.kubernetes.io/appgw-ssl-certificate: {{ .Values.consumerapi.ingress.certName }}
@@ -20,7 +20,7 @@ spec:
pathType: Prefix
backend:
service:
- name: {{ include "global.name" . }}
+ name: {{ .Values.consumerapi.name }}
port:
number: 8080
{{- end }}
diff --git a/helm/templates/consumerapi/templates/service.yaml b/helm/templates/consumerapi/service.yaml
similarity index 76%
rename from helm/templates/consumerapi/templates/service.yaml
rename to helm/templates/consumerapi/service.yaml
index b1de961c48..dcf5524d85 100644
--- a/helm/templates/consumerapi/templates/service.yaml
+++ b/helm/templates/consumerapi/service.yaml
@@ -1,13 +1,13 @@
apiVersion: v1
kind: Service
metadata:
- name: {{ include "global.name" . }}
+ name: {{ .Values.consumerapi.name }}
labels:
{{- include "global.labels" . | nindent 4 }}
- app: {{ include "global.name" . }}
+ app: {{ .Values.consumerapi.name }}
{{- if eq .Values.global.provider "GoogleCloud" }}
annotations:
- cloud.google.com/backend-config: '{"default": "{{ include "global.name" . }}"}'
+ cloud.google.com/backend-config: '{"default": "{{ .Values.consumerapi.name }}"}'
{{- end }}
{{- if eq .Values.consumerapi.service.type "LoadBalancer" }}
annotations:
@@ -22,4 +22,4 @@ spec:
- port: 8080
targetPort: 8080
selector:
- app: {{ include "global.name" . }}
+ app: {{ .Values.consumerapi.name }}
diff --git a/helm/templates/databasemigrator/configmap.yaml b/helm/templates/databasemigrator/configmap.yaml
new file mode 100644
index 0000000000..1ab3cb282b
--- /dev/null
+++ b/helm/templates/databasemigrator/configmap.yaml
@@ -0,0 +1,12 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: configuration-for-databasemigrator
+ labels: {{- include "global.labels" . | nindent 4 }}
+ annotations:
+ "helm.sh/hook": pre-install,pre-upgrade
+ "helm.sh/hook-weight": "0"
+ "helm.sh/hook-delete-policy": before-hook-creation
+data:
+ appsettings.override.json: |-
+ {{- mustToPrettyJson .Values.global.configuration | toString | nindent 4 }}
diff --git a/helm/templates/databasemigrator/job.yaml b/helm/templates/databasemigrator/job.yaml
new file mode 100644
index 0000000000..0ef615e075
--- /dev/null
+++ b/helm/templates/databasemigrator/job.yaml
@@ -0,0 +1,65 @@
+apiVersion: batch/v1
+kind: Job
+metadata:
+ name: {{ .Values.databasemigrator.name }}
+ labels:
+ {{- include "global.labels" . | nindent 4 }}
+ app: {{ .Values.databasemigrator.name }}
+ annotations:
+ "helm.sh/hook": pre-install,pre-upgrade
+ "helm.sh/hook-weight": "1"
+ "helm.sh/hook-delete-policy": before-hook-creation
+spec:
+ template:
+ metadata:
+ {{- with .Values.databasemigrator.podAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ labels:
+ app: {{ .Values.databasemigrator.name }}
+ spec:
+ restartPolicy: Never
+ {{- with .Values.databasemigrator.podSecurityContext }}
+ securityContext:
+ {{- toYaml .Values.databasemigrator.podSecurityContext | nindent 8 }}
+ {{- end }}
+ {{- with .Values.databasemigrator.image.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ volumes:
+ - name: settings-override
+ configMap:
+ name: configuration-for-databasemigrator
+ containers:
+ - name: {{ .Values.databasemigrator.name }}
+ {{- with .Values.databasemigrator.securityContext }}
+ securityContext:
+ {{- toYaml .Values.databasemigrator.securityContext | nindent 8 }}
+ {{- end }}
+ resources:
+ {{- toYaml .Values.databasemigrator.resources | nindent 12 }}
+ image: "{{ .Values.databasemigrator.image.repository }}:{{- default .Chart.AppVersion .Values.databasemigrator.image.tagOverride }}"
+ imagePullPolicy: {{ .Values.databasemigrator.image.pullPolicy }}
+ volumeMounts:
+ - name: settings-override
+ mountPath: /app/appsettings.override.json
+ subPath: appsettings.override.json
+ readOnly: true
+ env:
+ {{- with .Values.databasemigrator.env }}
+ {{- toYaml . | nindent 12 }}
+ {{- end }}
+ {{- with .Values.databasemigrator.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.databasemigrator.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.databasemigrator.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
diff --git a/helm/templates/eventhandler/templates/deployment.yaml b/helm/templates/eventhandler/deployment.yaml
similarity index 87%
rename from helm/templates/eventhandler/templates/deployment.yaml
rename to helm/templates/eventhandler/deployment.yaml
index 536c66ff82..2ede81542d 100644
--- a/helm/templates/eventhandler/templates/deployment.yaml
+++ b/helm/templates/eventhandler/deployment.yaml
@@ -1,15 +1,20 @@
apiVersion: apps/v1
kind: Deployment
metadata:
- name: {{ include "global.name" . }}
+ name: {{ .Values.eventhandler.name }}
labels:
{{- include "global.labels" . | nindent 4 }}
- app: {{ include "global.name" . }}
+ app: {{ .Values.eventhandler.name }}
spec:
replicas: 1
+ strategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxSurge: {{ .Values.maxSurge }}
+ maxUnavailable: {{ .Values.maxUnavailable }}
selector:
matchLabels:
- app: {{ include "global.name" . }}
+ app: {{ .Values.eventhandler.name }}
template:
metadata:
{{- with .Values.eventhandler.podAnnotations }}
@@ -17,7 +22,7 @@ spec:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
- app: {{ include "global.name" . }}
+ app: {{ .Values.eventhandler.name }}
spec:
{{- with .Values.eventhandler.podSecurityContext }}
securityContext:
@@ -32,7 +37,7 @@ spec:
configMap:
name: configuration
containers:
- - name: {{ include "global.name" . }}
+ - name: {{ .Values.eventhandler.name }}
{{- with .Values.eventhandler.securityContext }}
securityContext:
{{- toYaml .Values.eventhandler.securityContext | nindent 8 }}
diff --git a/helm/values.yaml b/helm/values.yaml
index b60b707fce..f46b6d3b24 100644
--- a/helm/values.yaml
+++ b/helm/values.yaml
@@ -1,5 +1,5 @@
consumerapi:
- nameOverride: ""
+ name: "consumerapi"
replicas: 1
maxSurge: 2
maxUnavailable: 0
@@ -99,7 +99,7 @@ consumerapi:
unhealthyThreshold: 2
adminui:
- nameOverride: ""
+ name: "adminui"
replicas: 1
maxSurge: 2
maxUnavailable: 0
@@ -189,7 +189,7 @@ adminui:
unhealthyThreshold: 2
eventhandler:
- nameOverride: ""
+ name: "eventhandler"
replicas: 1
maxSurge: 2
maxUnavailable: 0
@@ -236,8 +236,46 @@ eventhandler:
targetCPUUtilizationPercentage: 80
targetMemoryUtilizationPercentage: ""
+databasemigrator:
+ name: "databasemigrator"
+
+ image:
+ repository: "ghcr.io/nmshd/backbone-database-migrator"
+ tagOverride: ""
+ pullPolicy: "IfNotPresent"
+ imagePullSecrets: []
+
+ # resources - the resources for the Event Handler container (see https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#resources)
+ resources:
+ requests:
+ cpu: "50m"
+ memory: "64Mi"
+ limits:
+ cpu: "200m"
+ memory: "512Mi"
+
+ # securityContext - securityContext for the Consumer API container (see https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#security-context-1)
+ securityContext: {}
+
+ # podSecurityContext - securityContext for the pods deployed by the Deployment (see https://kubernetes.io/docs/tasks/configure-pod-container/security-context/)
+ podSecurityContext: {}
+
+ podAnnotations: {}
+
+ # env - environment variables for the Event Handler container (see https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/)
+ env: []
+
+ # the nodeSelector for the pods deployed by the Deployment (see https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector)
+ nodeSelector: {}
+
+ # the tolerations for the pods deployed by the Deployment (see https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/)
+ tolerations: []
+
+ # the affinity for the pods deployed by the Deployment (see https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#NodeAffinity)
+ affinity: {}
+
admincli:
- nameOverride: ""
+ name: "admincli"
configuration:
Database:
diff --git a/setup-db/setup-postgres.sql b/setup-db/setup-postgres.sql
index 3a7f87ff03..47dae177a0 100644
--- a/setup-db/setup-postgres.sql
+++ b/setup-db/setup-postgres.sql
@@ -130,73 +130,81 @@ $$;
/*+++++++++++++++++++++++++++++++++++++++++++++++++ Authorizations +++++++++++++++++++++++++++++++++++++++++++++++++*/
-/*GRANT CREATE ON SCHEMA Challenges, Devices, Messages, Synchronization, Tokens, Relationships, Files TO challenges, devices, messages, synchronization, tokens, relationships, files, Quotas;
-GRANT CREATE ON SCHEMA Relationships TO relationships;*/
-
-REVOKE USAGE, CREATE ON SCHEMA "Challenges" FROM synchronization, devices, messages, tokens, relationships, files, quotas;
-REVOKE USAGE, CREATE ON SCHEMA "Synchronization" FROM challenges, devices, messages, tokens, relationships, files, quotas;
-REVOKE USAGE, CREATE ON SCHEMA "Messages" FROM challenges, synchronization, devices, tokens, relationships, files, quotas;
-REVOKE USAGE, CREATE ON SCHEMA "Devices" FROM challenges, synchronization, messages, tokens, relationships, files, quotas;
-REVOKE USAGE, CREATE ON SCHEMA "Tokens" FROM challenges, synchronization, devices, messages, relationships, files, quotas;
-REVOKE USAGE, CREATE ON SCHEMA "Relationships" FROM challenges, synchronization, devices, messages, tokens, files, quotas;
-REVOKE USAGE, CREATE ON SCHEMA "Files" FROM challenges, synchronization, devices, messages, tokens, relationships, quotas;
-REVOKE USAGE, CREATE ON SCHEMA "Quotas" FROM challenges, synchronization, devices, messages, tokens, relationships, files;
+GRANT USAGE ON SCHEMA "Challenges" TO challenges;
+GRANT USAGE ON SCHEMA "Devices" TO devices;
+GRANT USAGE ON SCHEMA "Files" TO files;
+GRANT USAGE ON SCHEMA "Messages" TO messages;
+GRANT USAGE ON SCHEMA "Quotas" TO quotas;
+GRANT USAGE ON SCHEMA "Relationships" TO relationships;
+GRANT USAGE ON SCHEMA "Synchronization" TO synchronization;
+GRANT USAGE ON SCHEMA "Tokens" TO tokens;
+GRANT USAGE ON SCHEMA "AdminUi" TO "adminUi";
+
+ALTER DEFAULT PRIVILEGES IN SCHEMA "Challenges" GRANT ALL ON TABLES TO challenges;
+ALTER DEFAULT PRIVILEGES IN SCHEMA "Devices" GRANT ALL ON TABLES TO devices;
+ALTER DEFAULT PRIVILEGES IN SCHEMA "Files" GRANT ALL ON TABLES TO files;
+ALTER DEFAULT PRIVILEGES IN SCHEMA "Messages" GRANT ALL ON TABLES TO messages;
+ALTER DEFAULT PRIVILEGES IN SCHEMA "Quotas" GRANT ALL ON TABLES TO quotas;
+ALTER DEFAULT PRIVILEGES IN SCHEMA "Relationships" GRANT ALL ON TABLES TO relationships;
+ALTER DEFAULT PRIVILEGES IN SCHEMA "Synchronization" GRANT ALL ON TABLES TO synchronization;
+ALTER DEFAULT PRIVILEGES IN SCHEMA "Tokens" GRANT ALL ON TABLES TO tokens;
+ALTER DEFAULT PRIVILEGES IN SCHEMA "AdminUi" GRANT ALL ON TABLES TO "adminUi";
GRANT USAGE ON SCHEMA "Relationships" TO messages;
GRANT SELECT, REFERENCES, TRIGGER, TRUNCATE ON ALL TABLES IN SCHEMA "Relationships" TO messages;
-ALTER DEFAULT PRIVILEGES FOR ROLE relationships IN SCHEMA "Relationships" GRANT SELECT, REFERENCES, TRIGGER, TRUNCATE ON TABLES TO messages;
+ALTER DEFAULT PRIVILEGES IN SCHEMA "Relationships" GRANT SELECT, REFERENCES, TRIGGER, TRUNCATE ON TABLES TO messages;
GRANT USAGE ON SCHEMA "Challenges" TO devices;
GRANT SELECT ON ALL TABLES IN SCHEMA "Challenges" TO devices;
-ALTER DEFAULT PRIVILEGES FOR ROLE challenges IN SCHEMA "Challenges" GRANT SELECT ON TABLES TO devices;
+ALTER DEFAULT PRIVILEGES IN SCHEMA "Challenges" GRANT SELECT ON TABLES TO devices;
GRANT USAGE ON SCHEMA "Messages" TO quotas;
GRANT SELECT ON ALL TABLES IN SCHEMA "Messages" TO quotas;
-ALTER DEFAULT PRIVILEGES FOR ROLE messages IN SCHEMA "Messages" GRANT SELECT ON TABLES TO quotas;
+ALTER DEFAULT PRIVILEGES IN SCHEMA "Messages" GRANT SELECT ON TABLES TO quotas;
GRANT USAGE ON SCHEMA "Files" TO quotas;
GRANT SELECT ON ALL TABLES IN SCHEMA "Files" TO quotas;
-ALTER DEFAULT PRIVILEGES FOR ROLE files IN SCHEMA "Files" GRANT SELECT ON TABLES TO quotas;
+ALTER DEFAULT PRIVILEGES IN SCHEMA "Files" GRANT SELECT ON TABLES TO quotas;
GRANT USAGE ON SCHEMA "Relationships" TO quotas;
GRANT SELECT ON ALL TABLES IN SCHEMA "Relationships" TO quotas;
-ALTER DEFAULT PRIVILEGES FOR ROLE relationships IN SCHEMA "Relationships" GRANT SELECT ON TABLES TO quotas;
+ALTER DEFAULT PRIVILEGES IN SCHEMA "Relationships" GRANT SELECT ON TABLES TO quotas;
GRANT USAGE ON SCHEMA "Challenges" TO "adminUi";
GRANT SELECT ON ALL TABLES IN SCHEMA "Challenges" TO "adminUi";
-ALTER DEFAULT PRIVILEGES FOR ROLE challenges IN SCHEMA "Challenges" GRANT SELECT ON TABLES TO "adminUi";
+ALTER DEFAULT PRIVILEGES IN SCHEMA "Challenges" GRANT SELECT ON TABLES TO "adminUi";
GRANT USAGE ON SCHEMA "Synchronization" TO "adminUi";
GRANT SELECT ON ALL TABLES IN SCHEMA "Synchronization" TO "adminUi";
-ALTER DEFAULT PRIVILEGES FOR ROLE synchronization IN SCHEMA "Synchronization" GRANT SELECT ON TABLES TO "adminUi";
+ALTER DEFAULT PRIVILEGES IN SCHEMA "Synchronization" GRANT SELECT ON TABLES TO "adminUi";
GRANT USAGE ON SCHEMA "Messages" TO "adminUi";
GRANT SELECT ON ALL TABLES IN SCHEMA "Messages" TO "adminUi";
-ALTER DEFAULT PRIVILEGES FOR ROLE messages IN SCHEMA "Messages" GRANT SELECT ON TABLES TO "adminUi";
+ALTER DEFAULT PRIVILEGES IN SCHEMA "Messages" GRANT SELECT ON TABLES TO "adminUi";
GRANT USAGE ON SCHEMA "Devices" TO "adminUi";
GRANT SELECT ON ALL TABLES IN SCHEMA "Devices" TO "adminUi";
-ALTER DEFAULT PRIVILEGES FOR ROLE devices IN SCHEMA "Devices" GRANT SELECT ON TABLES TO "adminUi";
+ALTER DEFAULT PRIVILEGES IN SCHEMA "Devices" GRANT SELECT ON TABLES TO "adminUi";
GRANT USAGE ON SCHEMA "Tokens" TO "adminUi";
GRANT SELECT ON ALL TABLES IN SCHEMA "Tokens" TO "adminUi";
-ALTER DEFAULT PRIVILEGES FOR ROLE tokens IN SCHEMA "Tokens" GRANT SELECT ON TABLES TO "adminUi";
+ALTER DEFAULT PRIVILEGES IN SCHEMA "Tokens" GRANT SELECT ON TABLES TO "adminUi";
GRANT USAGE ON SCHEMA "Relationships" TO "adminUi";
GRANT SELECT ON ALL TABLES IN SCHEMA "Relationships" TO "adminUi";
-ALTER DEFAULT PRIVILEGES FOR ROLE relationships IN SCHEMA "Relationships" GRANT SELECT ON TABLES TO "adminUi";
+ALTER DEFAULT PRIVILEGES IN SCHEMA "Relationships" GRANT SELECT ON TABLES TO "adminUi";
GRANT USAGE ON SCHEMA "Files" TO "adminUi";
GRANT SELECT ON ALL TABLES IN SCHEMA "Files" TO "adminUi";
-ALTER DEFAULT PRIVILEGES FOR ROLE files IN SCHEMA "Files" GRANT SELECT ON TABLES TO "adminUi";
+ALTER DEFAULT PRIVILEGES IN SCHEMA "Files" GRANT SELECT ON TABLES TO "adminUi";
GRANT USAGE ON SCHEMA "Quotas" TO "adminUi";
GRANT SELECT ON ALL TABLES IN SCHEMA "Quotas" TO "adminUi";
-ALTER DEFAULT PRIVILEGES FOR ROLE quotas IN SCHEMA "Quotas" GRANT SELECT ON TABLES TO "adminUi";
+ALTER DEFAULT PRIVILEGES IN SCHEMA "Quotas" GRANT SELECT ON TABLES TO "adminUi";
GRANT USAGE ON SCHEMA "Tokens" TO quotas;
GRANT SELECT ON ALL TABLES IN SCHEMA "Tokens" TO quotas;
-ALTER DEFAULT PRIVILEGES FOR ROLE tokens IN SCHEMA "Tokens" GRANT SELECT ON TABLES TO quotas;
+ALTER DEFAULT PRIVILEGES IN SCHEMA "Tokens" GRANT SELECT ON TABLES TO quotas;
CREATE TABLE IF NOT EXISTS "Challenges"."__EFMigrationsHistory"
@@ -282,13 +290,3 @@ GRANT relationships TO "nmshdAdmin";
GRANT files TO "nmshdAdmin";
GRANT quotas TO "nmshdAdmin";
GRANT "adminUi" TO "nmshdAdmin";
-
-ALTER SCHEMA "Challenges" OWNER TO challenges;
-ALTER SCHEMA "Devices" OWNER TO devices;
-ALTER SCHEMA "Messages" OWNER TO messages;
-ALTER SCHEMA "Synchronization" OWNER TO synchronization;
-ALTER SCHEMA "Tokens" OWNER TO tokens;
-ALTER SCHEMA "Relationships" OWNER TO relationships;
-ALTER SCHEMA "Files" OWNER TO files;
-ALTER SCHEMA "Quotas" OWNER TO quotas;
-ALTER SCHEMA "AdminUi" OWNER TO "adminUi";
diff --git a/setup-db/setup-sqlserver.sql b/setup-db/setup-sqlserver.sql
index 3e75712272..f9ad347520 100644
--- a/setup-db/setup-sqlserver.sql
+++ b/setup-db/setup-sqlserver.sql
@@ -226,35 +226,18 @@ END
GO
-/*+++++++++++++++++++++++++++++++++++++++++++++++++ Schema Owners ++++++++++++++++++++++++++++++++++++++++++++++++++*/
-PRINT 'Start changing schema owners' ;
-ALTER AUTHORIZATION ON SCHEMA::Challenges TO challenges
-ALTER AUTHORIZATION ON SCHEMA::Devices TO devices
-ALTER AUTHORIZATION ON SCHEMA::Messages TO messages
-ALTER AUTHORIZATION ON SCHEMA::Synchronization TO synchronization
-ALTER AUTHORIZATION ON SCHEMA::Tokens TO tokens
-ALTER AUTHORIZATION ON SCHEMA::Relationships TO relationships
-ALTER AUTHORIZATION ON SCHEMA::Files TO files
-ALTER AUTHORIZATION ON SCHEMA::Quotas TO quotas
-ALTER AUTHORIZATION ON SCHEMA::AdminUi TO adminUi
-PRINT 'Finished changing schema owners' ;
-GO
-
/*+++++++++++++++++++++++++++++++++++++++++++++++++ Authorizations +++++++++++++++++++++++++++++++++++++++++++++++++*/
PRINT 'Start changing authorizations' ;
-GRANT CREATE TABLE TO challenges, devices, messages, synchronization, tokens, relationships, files, quotas, adminUi
-GRANT CREATE FUNCTION TO relationships
-GO
-
-DENY SELECT, INSERT, UPDATE, DELETE ON SCHEMA::Challenges TO synchronization, devices, messages, tokens, relationships, files, quotas
-DENY SELECT, INSERT, UPDATE, DELETE ON SCHEMA::Synchronization TO challenges, devices, messages, tokens, relationships, files, quotas
-DENY SELECT, INSERT, UPDATE, DELETE ON SCHEMA::Messages TO challenges, synchronization, devices, tokens, relationships, files, quotas
-DENY SELECT, INSERT, UPDATE, DELETE ON SCHEMA::Devices TO challenges, synchronization, messages, tokens, relationships, files, quotas
-DENY SELECT, INSERT, UPDATE, DELETE ON SCHEMA::Tokens TO challenges, synchronization, devices, messages, relationships, files, quotas
-DENY SELECT, INSERT, UPDATE, DELETE ON SCHEMA::Relationships TO challenges, synchronization, devices, messages, tokens, files, quotas
-DENY SELECT, INSERT, UPDATE, DELETE ON SCHEMA::Files TO challenges, synchronization, devices, messages, tokens, relationships, quotas
-DENY SELECT, INSERT, UPDATE, DELETE ON SCHEMA::Quotas TO challenges, synchronization, devices, messages, tokens, relationships, files
+GRANT SELECT, INSERT, UPDATE, DELETE, EXECUTE, REFERENCES, VIEW DEFINITION ON SCHEMA::Challenges TO challenges;
+GRANT SELECT, INSERT, UPDATE, DELETE, EXECUTE, REFERENCES, VIEW DEFINITION ON SCHEMA::Devices TO devices;
+GRANT SELECT, INSERT, UPDATE, DELETE, EXECUTE, REFERENCES, VIEW DEFINITION ON SCHEMA::Files TO files;
+GRANT SELECT, INSERT, UPDATE, DELETE, EXECUTE, REFERENCES, VIEW DEFINITION ON SCHEMA::Messages TO messages;
+GRANT SELECT, INSERT, UPDATE, DELETE, EXECUTE, REFERENCES, VIEW DEFINITION ON SCHEMA::Quotas TO quotas;
+GRANT SELECT, INSERT, UPDATE, DELETE, EXECUTE, REFERENCES, VIEW DEFINITION ON SCHEMA::Relationships TO relationships;
+GRANT SELECT, INSERT, UPDATE, DELETE, EXECUTE, REFERENCES, VIEW DEFINITION ON SCHEMA::Synchronization TO synchronization;
+GRANT SELECT, INSERT, UPDATE, DELETE, EXECUTE, REFERENCES, VIEW DEFINITION ON SCHEMA::Tokens TO tokens;
+GRANT SELECT, INSERT, UPDATE, DELETE, EXECUTE, REFERENCES, VIEW DEFINITION ON SCHEMA::AdminUi TO adminUi;
GRANT SELECT, REFERENCES ON SCHEMA::Relationships TO messages
GRANT SELECT, REFERENCES ON SCHEMA::Challenges TO devices