8 Commits

Author SHA1 Message Date
7c85e338fa Json Parsing 2025-10-29 07:57:13 +01:00
c01401eb07 Logik um ServiceDiscovery Payload zu verarbeiten soweit gemacht, JSON Input wird aber nocht nicht geparsed 2025-10-28 15:25:08 +01:00
7c06f7ee06 Merge pull request 'enhancement/Dokumentation' (#31) from enhancement/Dokumentation into staging
All checks were successful
Gitea CI/CD / dotnet-build-and-test (push) Successful in 54s
Gitea CI/CD / Set Tag Name (push) Successful in 5s
Gitea CI/CD / docker-build-and-push (push) Successful in 6m27s
Gitea CI/CD / Create Tag (push) Successful in 5s
Reviewed-on: #31
2025-10-27 11:51:36 +01:00
6eed3c764e swagger working /api/v1/swagger 2025-10-21 19:15:16 +02:00
f207440ae6 added swagger for automatic API Documentation 2025-10-10 18:00:41 +02:00
ef187f8750 Basic Structure of new Background Service SystemManagement 2025-10-09 20:27:37 +02:00
570b5abfa0 Merge pull request 'pipeline job umbenannt' (#29) from bugix/pipeline into staging
All checks were successful
Gitea CI/CD / dotnet-build-and-test (push) Successful in 55s
Gitea CI/CD / Set Tag Name (push) Successful in 5s
Gitea CI/CD / docker-build-and-push (push) Successful in 6m17s
Gitea CI/CD / Create Tag (push) Successful in 5s
Reviewed-on: #29
2025-10-04 19:08:22 +02:00
8f938f999e pipeline job umbenannt 2025-10-04 19:07:49 +02:00
7 changed files with 161 additions and 34 deletions

View File

@@ -17,7 +17,7 @@ concurrency:
cancel-in-progress: true cancel-in-progress: true
jobs: jobs:
build-and-test: dotnet-build-and-test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code
@@ -43,7 +43,7 @@ jobs:
set-tag: set-tag:
name: Set Tag Name name: Set Tag Name
needs: [build-and-test] needs: [dotnet-build-and-test]
#if: ${{ !failure() && !cancelled() && github.event_name != 'pull_request' }} #if: ${{ !failure() && !cancelled() && github.event_name != 'pull_request' }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
outputs: outputs:
@@ -95,7 +95,7 @@ jobs:
docker-build-and-push: docker-build-and-push:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [build-and-test, set-tag] needs: [dotnet-build-and-test, set-tag]
if: | if: |
needs.set-tag.outputs.should_tag == 'true' && needs.set-tag.outputs.should_tag == 'true' &&
github.event_name != 'pull_request' github.event_name != 'pull_request'

View File

@@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Text.Json;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@@ -80,10 +81,8 @@ public class MetricDto
public class ServiceDto public class ServiceDto
{ {
public int ServerId { get; set; } // Vom Watcher-Server zugewiesene ID des Hosts public required int Server_id { get; set; } // Vom Watcher-Server zugewiesene ID des Hosts
public String? ContainerId { get; set; } public required JsonContent Containers { get; set; }
public String? Image { get; set; }
public String? Name { get; set; }
} }
[ApiController] [ApiController]
@@ -234,33 +233,77 @@ public class MonitoringController : Controller
.Select(e => e.ErrorMessage) .Select(e => e.ErrorMessage)
.ToList(); .ToList();
_logger.LogError("Ungültiger ServiceDetection-Payload."); _logger.LogError("Invalid ServiceDetection-Payload.");
return BadRequest(new { error = "Ungültiger Payload", details = errors }); return BadRequest(new { error = "Invalid Payload", details = errors });
} }
// Metrics für Container, die zu ServerId gehören, löschen // Json zu was brauchbarem machen
string containersJson = await dto.Containers.ReadAsStringAsync();
List<Container> newContainers = JsonSerializer.Deserialize<List<Container>>(containersJson)?? new List<Container>();;
// Container, die zu ServerId gehören löschen foreach (Container c in newContainers)
// Container neu in Datenbank einlesen
try
{ {
Container container = new Container c.ServerId = dto.Server_id;
// Debug Logs
// TODO entfernen wenn fertig getestet
Console.WriteLine("---------");
Console.WriteLine("ServerId: " + c.ServerId);
Console.WriteLine("ContainerId: " + c.ContainerId);
Console.WriteLine("Name: " + c.Name);
Console.WriteLine("Image: " + c.Image);
Console.WriteLine("---------");
}
// Container Objekte erstellen
//List<Container> newContainers = ParseServiceDiscoveryInput(dto.Server_id, containers);
// Liste aller Container, die bereits der übergebenen ServerId zugewiesen sind
List<Container> existingContainers = _context.Containers
.Where(c => c.ServerId == dto.Server_id)
.ToList();
// Logik, um Container, die mit dem Payload kamen zu verarbeiten
foreach (Container c in newContainers)
{
// Überprüfen, ob ein übergebener Container bereits für den Host registriert ist
if (existingContainers.Contains(c))
{ {
ServerId = dto.ServerId, _logger.LogInformation("Container with id " + c.ContainerId + " already exists.");
ContainerId = dto.ContainerId, }
Image = dto.Name, // Container auf einen Host/Server registrieren
Name = dto.Name else
}; {
// Container in Datenbank einlesen
_logger.LogInformation(container.Name + " added for Host " + container.ServerId); try
{
_context.Containers.Add(container); _context.Containers.Add(c);
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
_logger.LogInformation(c.Name + " added for Host " + c.ServerId);
}
catch (SqliteException e)
{
_logger.LogError("Error writing new Containers to Database: " + e.Message);
}
}
} }
catch (SqliteException e)
// Logik um abgeschaltene Container aus der Datenbank zu entfernen
foreach (Container c in existingContainers)
{ {
_logger.LogError("ServiceDiscovery failed: " + e.Message); // Abfrage, ob bereits vorhandener Container im Payload vorhanden war
if (!newContainers.Contains(c))
{
// Container entfernen
_context.Containers.Remove(c);
await _context.SaveChangesAsync();
// Metrics für den Container entfernen
//Todo
_logger.LogInformation("Container " + c.Name + " (" + c.Id + ") on Host-Id " + c.ServerId + " was successfully removed from the database.");
}
} }
return Ok(); return Ok();
@@ -268,7 +311,6 @@ public class MonitoringController : Controller
} }
// Durchschnittliche Werte Berechnen // Durchschnittliche Werte Berechnen
[HttpGet("median")]
public async Task<IActionResult> CalculateMedian(string Metric, int HoursToMonitor, int ServerId) public async Task<IActionResult> CalculateMedian(string Metric, int HoursToMonitor, int ServerId)
{ {
// Aktuelle Zeit - X Stunden = letzter Wert, der berücksichtigt werden soll // Aktuelle Zeit - X Stunden = letzter Wert, der berücksichtigt werden soll
@@ -368,4 +410,13 @@ public class MonitoringController : Controller
return metric_input; return metric_input;
} }
private List<Container> ParseServiceDiscoveryInput(int server_id, List<Container> containers)
{
List<Container> containerList = new List<Container>();
// JSON-Objekt auslesen und Container-Objekte erstellen
return containerList;
}
} }

View File

@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.OpenApi.Models;
using Serilog; using Serilog;
@@ -36,11 +37,17 @@ builder.Services.AddHttpContextAccessor();
// Storage Singleton // Storage Singleton
builder.Services.AddSingleton<IDashboardStore, DashboardStore>(); builder.Services.AddSingleton<IDashboardStore, DashboardStore>();
builder.Services.AddSingleton<ISystemStore, SystemStore>();
// Background Services // Background Services
builder.Services.AddHostedService<NetworkCheck>(); builder.Services.AddHostedService<NetworkCheck>();
builder.Services.AddHostedService<DatabaseCheck>(); builder.Services.AddHostedService<DatabaseCheck>();
// Swagger API-Dokumentation
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo { Title = "Watcher-Server API", Version = "v1" });
});
// ---------- Konfiguration ---------- // ---------- Konfiguration ----------
DotNetEnv.Env.Load(); DotNetEnv.Env.Load();
@@ -204,22 +211,30 @@ using (var scope = app.Services.CreateScope())
if (!app.Environment.IsDevelopment()) if (!app.Environment.IsDevelopment())
{ {
app.UseExceptionHandler("/Home/Error"); app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts(); app.UseHsts();
} }
app.UseHttpsRedirection(); app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting(); app.UseRouting();
// 🔹 Swagger aktivieren
app.UseSwagger();
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Watcher-Server API v1");
options.RoutePrefix = "api/v1/swagger";
});
// 🔹 Authentifizierung & Autorisierung
app.UseAuthentication(); app.UseAuthentication();
app.UseAuthorization(); app.UseAuthorization();
app.UseStaticFiles(); // 🔹 MVC-Routing
app.MapControllerRoute( app.MapControllerRoute(
name: "default", name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}" pattern: "{controller=Home}/{action=Index}/{id?}"
); );
app.Run(); app.Run();

View File

@@ -0,0 +1,9 @@
namespace Watcher.Services;
public interface ISystemStore
{
Boolean NewVersionAvailable { get; set; }
Double DatabaseSize { get; set; }
}

View File

@@ -0,0 +1,42 @@
using System.Net.Http;
namespace Watcher.Services;
public class SystemManagement : BackgroundService
{
private readonly ILogger<NetworkCheck> _logger;
private ISystemStore _SystemStore;
public SystemManagement(ILogger<NetworkCheck> logger, ISystemStore SystemStore)
{
_logger = logger;
_SystemStore = SystemStore;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
// Todo: Umstellen auf einmal alle 24h
var timer = new PeriodicTimer(TimeSpan.FromSeconds(30));
while (await timer.WaitForNextTickAsync(stoppingToken))
{
// Hintergrundprozess abwarten
await checkForNewDockerImageVersion();
// 5 Sekdunden Offset
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
}
}
public Task checkForNewDockerImageVersion()
{
return Task.CompletedTask;
}
public Task createDailySqliteBackup()
{
return Task.CompletedTask;
}
}

View File

@@ -0,0 +1,9 @@
namespace Watcher.Services;
public class SystemStore: ISystemStore
{
public Boolean NewVersionAvailable { get; set; }
public Double DatabaseSize { get; set; }
}

View File

@@ -23,6 +23,7 @@
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="8.0.6" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="8.0.6" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" /> <PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" /> <PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.6" />
</ItemGroup> </ItemGroup>
</Project> </Project>