diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 77f2b71f..8e0315ec 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -51,6 +51,13 @@ services: ports: - "5106:80" + attendance.api: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=http://0.0.0.0:80 + ports: + - "5108:80" + webstatus: environment: - ASPNETCORE_ENVIRONMENT=Development diff --git a/docker-compose.yml b/docker-compose.yml index f3570497..38e50671 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -47,6 +47,14 @@ services: depends_on: - sql.data + attendance.api: + image: ${REGISTRY:-eschool}/attendance.api:${TAG:-latest} + build: + context: . + dockerfile: src/Services/Attendance/Attendance.API/Dockerfile + depends_on: + - sql.data + webstatus: image: ${REGISTRY:-eschool}/webstatus:${TAG:-latest} build: diff --git a/eSchool.sln b/eSchool.sln index 7f349905..d9c6114e 100644 --- a/eSchool.sln +++ b/eSchool.sln @@ -62,6 +62,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ResultProcessing", "ResultP EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ResultProcessing.API", "src\Services\ResultProcessing\ResultProcessing.API\ResultProcessing.API.csproj", "{B9816645-F349-434D-A67D-98861B32249C}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Attendance", "Attendance", "{C2F37C86-3190-4261-AB1D-AC911B24CF2A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Attendance.API", "src\Services\Attendance\Attendance.API\Attendance.API.csproj", "{7B48DB8F-C668-4510-90A8-13B6170C262F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -264,6 +268,18 @@ Global {B9816645-F349-434D-A67D-98861B32249C}.Release|x64.Build.0 = Release|Any CPU {B9816645-F349-434D-A67D-98861B32249C}.Release|x86.ActiveCfg = Release|Any CPU {B9816645-F349-434D-A67D-98861B32249C}.Release|x86.Build.0 = Release|Any CPU + {7B48DB8F-C668-4510-90A8-13B6170C262F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7B48DB8F-C668-4510-90A8-13B6170C262F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7B48DB8F-C668-4510-90A8-13B6170C262F}.Debug|x64.ActiveCfg = Debug|Any CPU + {7B48DB8F-C668-4510-90A8-13B6170C262F}.Debug|x64.Build.0 = Debug|Any CPU + {7B48DB8F-C668-4510-90A8-13B6170C262F}.Debug|x86.ActiveCfg = Debug|Any CPU + {7B48DB8F-C668-4510-90A8-13B6170C262F}.Debug|x86.Build.0 = Debug|Any CPU + {7B48DB8F-C668-4510-90A8-13B6170C262F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7B48DB8F-C668-4510-90A8-13B6170C262F}.Release|Any CPU.Build.0 = Release|Any CPU + {7B48DB8F-C668-4510-90A8-13B6170C262F}.Release|x64.ActiveCfg = Release|Any CPU + {7B48DB8F-C668-4510-90A8-13B6170C262F}.Release|x64.Build.0 = Release|Any CPU + {7B48DB8F-C668-4510-90A8-13B6170C262F}.Release|x86.ActiveCfg = Release|Any CPU + {7B48DB8F-C668-4510-90A8-13B6170C262F}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -294,6 +310,8 @@ Global {6B655445-4A8B-465E-82C8-A3C9CF3D983E} = {C06D4DA8-7465-4D00-BC85-D594CB4996D2} {D9A25D85-43C9-4F05-876B-12A146E85447} = {1C120673-72F4-4679-AC4C-68286E9091A5} {B9816645-F349-434D-A67D-98861B32249C} = {D9A25D85-43C9-4F05-876B-12A146E85447} + {C2F37C86-3190-4261-AB1D-AC911B24CF2A} = {1C120673-72F4-4679-AC4C-68286E9091A5} + {7B48DB8F-C668-4510-90A8-13B6170C262F} = {C2F37C86-3190-4261-AB1D-AC911B24CF2A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E418719F-3193-403E-AF58-9BE9F94FD8BE} diff --git a/src/Services/Attendance/Attendance.API/Attendance.API.csproj b/src/Services/Attendance/Attendance.API/Attendance.API.csproj new file mode 100644 index 00000000..bbb5f5cb --- /dev/null +++ b/src/Services/Attendance/Attendance.API/Attendance.API.csproj @@ -0,0 +1,13 @@ + + + net5.0 + + + + + + + + + + diff --git a/src/Services/Attendance/Attendance.API/Controllers/HelloWorldController.cs b/src/Services/Attendance/Attendance.API/Controllers/HelloWorldController.cs new file mode 100644 index 00000000..c6898046 --- /dev/null +++ b/src/Services/Attendance/Attendance.API/Controllers/HelloWorldController.cs @@ -0,0 +1,15 @@ +using Microsoft.AspNetCore.Mvc; + +namespace Attendance.API.Controllers +{ + [ApiController] + [Route("[controller]")] + public class HelloWorldController : ControllerBase + { + [HttpGet] + public ActionResult Ping() + { + return Ok("Pong"); + } + } +} diff --git a/src/Services/Attendance/Attendance.API/Dockerfile b/src/Services/Attendance/Attendance.API/Dockerfile new file mode 100644 index 00000000..35fd23d4 --- /dev/null +++ b/src/Services/Attendance/Attendance.API/Dockerfile @@ -0,0 +1,24 @@ +#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. + +FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base +WORKDIR /app +EXPOSE 80 + +FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build +WORKDIR /src + +COPY ["src/Services/Attendance/Attendance.API/Attendance.API.csproj", "src/Services/Attendance/Attendance.API/"] + +RUN dotnet restore "src/Services/Attendance/Attendance.API/Attendance.API.csproj" + +COPY . . +WORKDIR "/src/src/Services/Attendance/Attendance.API" +RUN dotnet build "Attendance.API.csproj" -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Attendance.API.csproj" -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Attendance.API.dll"] diff --git a/src/Services/Attendance/Attendance.API/Program.cs b/src/Services/Attendance/Attendance.API/Program.cs new file mode 100644 index 00000000..e1acdd26 --- /dev/null +++ b/src/Services/Attendance/Attendance.API/Program.cs @@ -0,0 +1,81 @@ +using System; +using System.Diagnostics; +using System.IO; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using Serilog; +using Serilog.Enrichers.Span; + +namespace Attendance.API +{ + public static class Program + { + public static readonly string Namespace = typeof(Program).Namespace!; + public static readonly string AppName = Namespace[(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1)..]; + + [System.Diagnostics.CodeAnalysis.SuppressMessage( + "Design", + "CA1031:Do not catch general exception types", + Justification = "Top level all exception catcher")] + public static int Main(string[] args) + { + Activity.DefaultIdFormat = ActivityIdFormat.W3C; + + var configuration = GetConfiguration(); + Log.Logger = CreateSerilogLogger(configuration); + + try + { + Log.Information("Configuring web host ({ApplicationContext})...", AppName); + var host = CreateHostBuilder(configuration, args).Build(); + + Log.Information("Starting web host ({ApplicationContext})...", AppName); + host.Run(); + + return 0; + } + catch (Exception ex) + { + Log.Fatal(ex, "Host terminated unexpectedly"); + return 1; + } + finally + { + Log.CloseAndFlush(); + } + } + + public static IHostBuilder CreateHostBuilder(IConfiguration configuration, string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + webBuilder.UseConfiguration(configuration); + webBuilder.UseSerilog(); + }); + + private static ILogger CreateSerilogLogger(IConfiguration configuration) + { + return new LoggerConfiguration() + .MinimumLevel.Verbose() + .Enrich.WithProperty("ApplicationContext", AppName) + .Enrich.FromLogContext() + .Enrich.WithSpan() + .WriteTo.Console() + .WriteTo.Seq("http://seq") + .ReadFrom.Configuration(configuration) + .CreateLogger(); + } + + private static IConfiguration GetConfiguration() + { + var builder = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddEnvironmentVariables(); + + return builder.Build(); + } + } +} diff --git a/src/Services/Attendance/Attendance.API/Startup.cs b/src/Services/Attendance/Attendance.API/Startup.cs new file mode 100644 index 00000000..37cf6f91 --- /dev/null +++ b/src/Services/Attendance/Attendance.API/Startup.cs @@ -0,0 +1,56 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.OpenApi.Models; + +namespace Attendance.API +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + public void ConfigureServices(IServiceCollection services) + { + services.AddControllers(); + services.AddSwaggerGen(c => + { + c.SwaggerDoc( + "v1", + new OpenApiInfo + { + Title = "Attendance.API", + Version = "v1", + }); + }); + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseSwagger(); + app.UseSwaggerUI( + c => c.SwaggerEndpoint( + "/swagger/v1/swagger.json", "Attendance.API v1")); + + app.UseRouting(); + + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + } + } +} diff --git a/src/Services/Attendance/Attendance.API/appsettings.Development.json b/src/Services/Attendance/Attendance.API/appsettings.Development.json new file mode 100644 index 00000000..8983e0fc --- /dev/null +++ b/src/Services/Attendance/Attendance.API/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/src/Services/Attendance/Attendance.API/appsettings.json b/src/Services/Attendance/Attendance.API/appsettings.json new file mode 100644 index 00000000..d9d9a9bf --- /dev/null +++ b/src/Services/Attendance/Attendance.API/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +}