Skip to content

Commit

Permalink
Merge pull request #144 from TomaszKandula/feat/mailcow-status-endpoint
Browse files Browse the repository at this point in the history
feat: add mailcow status endpoint
  • Loading branch information
TomaszKandula authored Feb 11, 2024
2 parents 7fc340c + 1c1bc8c commit c4c77df
Show file tree
Hide file tree
Showing 42 changed files with 674 additions and 116 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/dev_build_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ jobs:
DbConnect: "${{ secrets.DBCONNECT_TEST }}"
AZ_Storage_ContainerName: "${{ secrets.STORAGE_CONTAINER_NAME_TEST }}"
AZ_Storage_ConnectionString: "${{ secrets.STORAGE_CONNECTION_STRING }}"
Mailcow_API_Key: "${{ secrets.MAILCOW_API_KEY }}"
Mailcow_Status_Url: "${{ secrets.MAILCOW_STATUS_URL }}"

- name: Setup dotnet
uses: actions/setup-dotnet@v4
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/master_build_test_publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ jobs:
DbConnect: "${{ secrets.DBCONNECT_PROD }}"
AZ_Storage_ContainerName: "${{ secrets.STORAGE_CONTAINER_NAME_PROD }}"
AZ_Storage_ConnectionString: "${{ secrets.STORAGE_CONNECTION_STRING }}"
Mailcow_API_Key: "${{ secrets.MAILCOW_API_KEY }}"
Mailcow_Status_Url: "${{ secrets.MAILCOW_STATUS_URL }}"

- name: Production | Build Docker (prepare)
uses: azure/docker-login@v1.0.1
Expand All @@ -71,6 +73,7 @@ jobs:
- name: Production | Build Docker (execute with tests)
run: |
docker build . \
--build-arg "ENV_VALUE=Production" \
-t ${{ secrets.DOCKER_REGISTRY_SERVER_URL }}/${{ secrets.DOCKER_REGISTRY_SERVER_USERNAME }}:backend-production-${{ github.sha }}
- name: Production | Push Docker image (prepare)
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/stage_build_test_publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ jobs:
DbConnect: "${{ secrets.DBCONNECT_STAGE }}"
AZ_Storage_ContainerName: "${{ secrets.STORAGE_CONTAINER_NAME_STAGE }}"
AZ_Storage_ConnectionString: "${{ secrets.STORAGE_CONNECTION_STRING }}"
Mailcow_API_Key: "${{ secrets.MAILCOW_API_KEY }}"
Mailcow_Status_Url: "${{ secrets.MAILCOW_STATUS_URL }}"

- name: Staging | Build Docker (prepare)
uses: azure/docker-login@v1.0.1
Expand All @@ -32,7 +34,10 @@ jobs:
password: ${{ secrets.DOCKER_REGISTRY_SERVER_PASSWORD }}

- name: Staging | Build Docker (execute with tests)
run: docker build . -t ${{ secrets.DOCKER_REGISTRY_SERVER_URL }}/${{ secrets.DOCKER_REGISTRY_SERVER_USERNAME }}:backend-staging-${{ github.sha }}
run: |
docker build . \
--build-arg "ENV_VALUE=Staging" \
-t ${{ secrets.DOCKER_REGISTRY_SERVER_URL }}/${{ secrets.DOCKER_REGISTRY_SERVER_USERNAME }}:backend-staging-${{ github.sha }}
- name: Staging | Push Docker image (prepare)
uses: azure/docker-login@v1.0.1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

<ItemGroup>
<ProjectReference Include="..\..\EmailSender.Persistence\EmailSender.Persistence.Database\EmailSender.Persistence.Database.csproj" />
<ProjectReference Include="..\..\EmailSender.Services\EmailSender.Services.HttpClientService\EmailSender.Services.HttpClientService.csproj" />
<ProjectReference Include="..\EmailSender.Backend.Domain\EmailSender.Backend.Domain.csproj" />
<ProjectReference Include="..\EmailSender.Backend.Shared\EmailSender.Backend.Shared.csproj" />
<ProjectReference Include="..\..\EmailSender.Services\EmailSender.Services.SenderService\EmailSender.Services.SenderService.csproj" />
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using MediatR;

namespace EmailSender.Backend.Application.Mailcow;

public class GetMailcowStatusQuery : IRequest<GetMailcowStatusQueryResult> { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
using System.Reflection;
using EmailSender.Backend.Application.Mailcow.Models;
using EmailSender.Backend.Core.Utilities.LoggerService;
using EmailSender.Services.HttpClientService.Abstractions;
using EmailSender.Services.HttpClientService.Models;
using Microsoft.Extensions.Configuration;

namespace EmailSender.Backend.Application.Mailcow;

public class GetMailcowStatusQueryHandler : RequestHandler<GetMailcowStatusQuery, GetMailcowStatusQueryResult>
{
private readonly IHttpClientServiceFactory _httpClientServiceFactory;

private readonly ILoggerService _loggerService;

private readonly IConfiguration _configuration;

private const BindingFlags Flags = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetField;

public GetMailcowStatusQueryHandler(IHttpClientServiceFactory httpClientServiceFactory, ILoggerService loggerService, IConfiguration configuration)
{
_httpClientServiceFactory = httpClientServiceFactory;
_loggerService = loggerService;
_configuration = configuration;
}

public override async Task<GetMailcowStatusQueryResult> Handle(GetMailcowStatusQuery request, CancellationToken cancellationToken)
{
var headers = new Dictionary<string, string>
{
["X-API-Key"] = _configuration.GetValue<string>("Mailcow_API_Key")
};

var configuration = new Configuration
{
Url = _configuration.GetValue<string>("Mailcow_Status_Url"),
Method = "GET",
Headers = headers
};

var client = _httpClientServiceFactory.Create(false, _loggerService);
var result = await client.Execute<MailcowStatus>(configuration, cancellationToken);

var healthyCount = 0;
var unhealthyCount = 0;
var data = new List<StatusItem>();

var resultType = result.GetType();
var resultProps = resultType.GetProperties(Flags);

foreach (var prop in resultProps)
{
var item = prop.GetValue(result, null);
if (item is null)
continue;

var statusItem = item as StatusItem;
data.Add(statusItem!);

if (statusItem?.State == "running")
{
healthyCount += 1;
}
else
{
unhealthyCount += 1;
}
}

if (healthyCount == data.Count)
{
return new GetMailcowStatusQueryResult
{
Status = StatusTypes.Healthy,
Results = data
};
}

if (healthyCount != unhealthyCount)
{
return new GetMailcowStatusQueryResult
{
Status = StatusTypes.Degraded,
Results = data
};
}

if (healthyCount == 0)
{
return new GetMailcowStatusQueryResult
{
Status = StatusTypes.Unhealthy,
Results = data
};
}

return new GetMailcowStatusQueryResult
{
Status = StatusTypes.Unknown,
Results = data
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using EmailSender.Backend.Application.Mailcow.Models;

namespace EmailSender.Backend.Application.Mailcow;

public class GetMailcowStatusQueryResult
{
public StatusTypes Status { get; set; }

public IList<StatusItem>? Results { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using Newtonsoft.Json;

namespace EmailSender.Backend.Application.Mailcow.Models;

public class MailcowStatus
{
[JsonProperty("ipv6nat-mailcow")]
public StatusItem? Ipv6Nat { get; set; }

[JsonProperty("watchdog-mailcow")]
public StatusItem? Watchdog { get; set; }

[JsonProperty("acme-mailcow")]
public StatusItem? Acme { get; set; }

[JsonProperty("ofelia-mailcow")]
public StatusItem? Ofelia { get; set; }

[JsonProperty("rspamd-mailcow")]
public StatusItem? Rspamd { get; set; }

[JsonProperty("nginx-mailcow")]
public StatusItem? Nginx { get; set; }

[JsonProperty("postfix-mailcow")]
public StatusItem? Postfix { get; set; }

[JsonProperty("dovecot-mailcow")]
public StatusItem? DoveCot { get; set; }

[JsonProperty("php-fpm-mailcow")]
public StatusItem? PhpFpm { get; set; }

[JsonProperty("mysql-mailcow")]
public StatusItem? MySql { get; set; }

[JsonProperty("redis-mailcow")]
public StatusItem? Redis { get; set; }

[JsonProperty("solr-mailcow")]
public StatusItem? Solr { get; set; }

[JsonProperty("clamd-mailcow")]
public StatusItem? Clamd { get; set; }

[JsonProperty("dockerapi-mailcow")]
public StatusItem? DockerApi { get; set; }

[JsonProperty("memcached-mailcow")]
public StatusItem? MemCached { get; set; }

[JsonProperty("sogo-mailcow")]
public StatusItem? SoGo { get; set; }

[JsonProperty("unbound-mailcow")]
public StatusItem? Unbound { get; set; }

[JsonProperty("netfilter-mailcow")]
public StatusItem? NetFilter { get; set; }

[JsonProperty("olefy-mailcow")]
public StatusItem? Olefy { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Newtonsoft.Json;

namespace EmailSender.Backend.Application.Mailcow.Models;

public class StatusItem
{
[JsonProperty("type")]
public string? Type { get; set; }

[JsonProperty("container")]
public string? Container { get; set; }

[JsonProperty("state")]
public string? State { get; set; }

[JsonProperty("started_at")]
public DateTime? StartedAt { get; set; }

[JsonProperty("image")]
public string? Image { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace EmailSender.Backend.Application.Mailcow.Models;

public enum StatusTypes
{
Unknown,
Healthy,
Degraded,
Unhealthy
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit c4c77df

Please sign in to comment.