From e3248a2c6d907653dc5461e45b7d0c4b38e3cc34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=90=D0=BB=D0=B5=D0=B9?= =?UTF-8?q?=D0=BA=D0=B8=D0=BD?= Date: Tue, 19 Nov 2024 15:20:55 +0400 Subject: [PATCH] aleikin_artem_lab_3 is ready --- aleikin_artem_lab_3/.dockerignore | 30 ++++++ .../Controllers/ProjectController.cs | 60 +++++++++++ .../ProjectEntityProject/Dockerfile | 29 ++++++ .../ProjectEntityProject/Entity/Project.cs | 10 ++ .../ProjectEntityProject/Entity/ProjectDto.cs | 4 + .../ProjectEntityProject/Program.cs | 46 +++++++++ .../ProjectEntityProject.csproj | 16 +++ .../ProjectEntityProject.csproj.user | 8 ++ .../ProjectEntityProject.http | 6 ++ .../Properties/launchSettings.json | 52 ++++++++++ .../appsettings.Development.json | 8 ++ .../ProjectEntityProject/appsettings.json | 9 ++ aleikin_artem_lab_3/RVIPLab3.sln | 31 ++++++ .../TaskProject/Controllers/TaskController.cs | 77 +++++++++++++++ aleikin_artem_lab_3/TaskProject/Dockerfile | 29 ++++++ .../TaskProject/Entity/Task.cs | 11 +++ .../TaskProject/Entity/TaskDto.cs | 4 + aleikin_artem_lab_3/TaskProject/Program.cs | 45 +++++++++ .../Properties/launchSettings.json | 52 ++++++++++ .../TaskProject/TaskProject.csproj | 16 +++ .../TaskProject/TaskProject.csproj.user | 8 ++ .../TaskProject/TaskProject.http | 6 ++ .../TaskProject/appsettings.Development.json | 8 ++ .../TaskProject/appsettings.json | 9 ++ aleikin_artem_lab_3/docker-compose.yml | 35 +++++++ aleikin_artem_lab_3/nginx/nginx.conf | 18 ++++ aleikin_artem_lab_3/readme.md | 99 +++++++++++++++++++ 27 files changed, 726 insertions(+) create mode 100644 aleikin_artem_lab_3/.dockerignore create mode 100644 aleikin_artem_lab_3/ProjectEntityProject/Controllers/ProjectController.cs create mode 100644 aleikin_artem_lab_3/ProjectEntityProject/Dockerfile create mode 100644 aleikin_artem_lab_3/ProjectEntityProject/Entity/Project.cs create mode 100644 aleikin_artem_lab_3/ProjectEntityProject/Entity/ProjectDto.cs create mode 100644 aleikin_artem_lab_3/ProjectEntityProject/Program.cs create mode 100644 aleikin_artem_lab_3/ProjectEntityProject/ProjectEntityProject.csproj create mode 100644 aleikin_artem_lab_3/ProjectEntityProject/ProjectEntityProject.csproj.user create mode 100644 aleikin_artem_lab_3/ProjectEntityProject/ProjectEntityProject.http create mode 100644 aleikin_artem_lab_3/ProjectEntityProject/Properties/launchSettings.json create mode 100644 aleikin_artem_lab_3/ProjectEntityProject/appsettings.Development.json create mode 100644 aleikin_artem_lab_3/ProjectEntityProject/appsettings.json create mode 100644 aleikin_artem_lab_3/RVIPLab3.sln create mode 100644 aleikin_artem_lab_3/TaskProject/Controllers/TaskController.cs create mode 100644 aleikin_artem_lab_3/TaskProject/Dockerfile create mode 100644 aleikin_artem_lab_3/TaskProject/Entity/Task.cs create mode 100644 aleikin_artem_lab_3/TaskProject/Entity/TaskDto.cs create mode 100644 aleikin_artem_lab_3/TaskProject/Program.cs create mode 100644 aleikin_artem_lab_3/TaskProject/Properties/launchSettings.json create mode 100644 aleikin_artem_lab_3/TaskProject/TaskProject.csproj create mode 100644 aleikin_artem_lab_3/TaskProject/TaskProject.csproj.user create mode 100644 aleikin_artem_lab_3/TaskProject/TaskProject.http create mode 100644 aleikin_artem_lab_3/TaskProject/appsettings.Development.json create mode 100644 aleikin_artem_lab_3/TaskProject/appsettings.json create mode 100644 aleikin_artem_lab_3/docker-compose.yml create mode 100644 aleikin_artem_lab_3/nginx/nginx.conf create mode 100644 aleikin_artem_lab_3/readme.md diff --git a/aleikin_artem_lab_3/.dockerignore b/aleikin_artem_lab_3/.dockerignore new file mode 100644 index 0000000..fe1152b --- /dev/null +++ b/aleikin_artem_lab_3/.dockerignore @@ -0,0 +1,30 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md +!**/.gitignore +!.git/HEAD +!.git/config +!.git/packed-refs +!.git/refs/heads/** \ No newline at end of file diff --git a/aleikin_artem_lab_3/ProjectEntityProject/Controllers/ProjectController.cs b/aleikin_artem_lab_3/ProjectEntityProject/Controllers/ProjectController.cs new file mode 100644 index 0000000..bcd0efb --- /dev/null +++ b/aleikin_artem_lab_3/ProjectEntityProject/Controllers/ProjectController.cs @@ -0,0 +1,60 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using ProjectEntityProject.Entity; + +namespace ProjectEntityProject.Controllers +{ + [ApiController] + [Route("projects")] + public class ProjectController : ControllerBase + { + private static readonly List Projects = new(); + + [HttpGet] + public ActionResult> GetProjects() => Ok(Projects); + + [HttpGet("{id}")] + public ActionResult GetProject([FromRoute] Guid id) + { + var project = Projects.FirstOrDefault(p => p.Id == id); + return project is null ? NotFound() : Ok(project); + } + + [HttpPost] + public ActionResult CreateProject([FromBody] ProjectDto projectdDto) + { + Project project = new Project + { + Name = projectdDto.Name, + Description = projectdDto.Description, + }; + Projects.Add(project); + return CreatedAtAction(nameof(GetProject), new { id = project.Id }, project); + } + + [HttpPut("{id}")] + public ActionResult UpdateProject(Guid id, [FromBody] ProjectDto projectDto) + { + var project = Projects.FirstOrDefault(p => p.Id == id); + if (project is null) return NotFound(); + + project.Name = projectDto.Name; + project.Description = projectDto.Description; + return Ok(project); + } + + [HttpDelete("{id}")] + public IActionResult DeleteProject(Guid id) + { + var project = Projects.FirstOrDefault(p => p.Id == id); + if (project is null) return NotFound(); + + Projects.Remove(project); + + var client = new HttpClient(); + var response = client.DeleteAsync($"http://nginx/taskservice/tasks/by-project/{id}").Result; + return response.IsSuccessStatusCode ? Ok() : StatusCode(500); + } + } + +} diff --git a/aleikin_artem_lab_3/ProjectEntityProject/Dockerfile b/aleikin_artem_lab_3/ProjectEntityProject/Dockerfile new file mode 100644 index 0000000..b56803d --- /dev/null +++ b/aleikin_artem_lab_3/ProjectEntityProject/Dockerfile @@ -0,0 +1,29 @@ +# См. статью по ссылке https://aka.ms/customizecontainer, чтобы узнать как настроить контейнер отладки и как Visual Studio использует этот Dockerfile для создания образов для ускорения отладки. + +# Этот этап используется при запуске из VS в быстром режиме (по умолчанию для конфигурации отладки) +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +USER app +WORKDIR /app +EXPOSE 5001 + + +# Этот этап используется для сборки проекта службы +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["ProjectEntityProject/ProjectEntityProject.csproj", "ProjectEntityProject/"] +RUN dotnet restore "./ProjectEntityProject/ProjectEntityProject.csproj" +COPY . . +WORKDIR "/src/ProjectEntityProject" +RUN dotnet build "./ProjectEntityProject.csproj" -c $BUILD_CONFIGURATION -o /app/build + +# Этот этап используется для публикации проекта службы, который будет скопирован на последний этап +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "./ProjectEntityProject.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false + +# Этот этап используется в рабочей среде или при запуске из VS в обычном режиме (по умолчанию, когда конфигурация отладки не используется) +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "ProjectEntityProject.dll"] \ No newline at end of file diff --git a/aleikin_artem_lab_3/ProjectEntityProject/Entity/Project.cs b/aleikin_artem_lab_3/ProjectEntityProject/Entity/Project.cs new file mode 100644 index 0000000..0fd1d5a --- /dev/null +++ b/aleikin_artem_lab_3/ProjectEntityProject/Entity/Project.cs @@ -0,0 +1,10 @@ +namespace ProjectEntityProject.Entity +{ + public class Project + { + public Guid Id { get; init; } = Guid.NewGuid(); + public string Name { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; + } + +} diff --git a/aleikin_artem_lab_3/ProjectEntityProject/Entity/ProjectDto.cs b/aleikin_artem_lab_3/ProjectEntityProject/Entity/ProjectDto.cs new file mode 100644 index 0000000..ea99f5b --- /dev/null +++ b/aleikin_artem_lab_3/ProjectEntityProject/Entity/ProjectDto.cs @@ -0,0 +1,4 @@ +namespace ProjectEntityProject.Entity +{ + public record ProjectDto(string Name, string Description) { } +} diff --git a/aleikin_artem_lab_3/ProjectEntityProject/Program.cs b/aleikin_artem_lab_3/ProjectEntityProject/Program.cs new file mode 100644 index 0000000..2a5ecbe --- /dev/null +++ b/aleikin_artem_lab_3/ProjectEntityProject/Program.cs @@ -0,0 +1,46 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.OpenApi.Models; + +var builder = WebApplication.CreateBuilder(args); + +builder.WebHost.ConfigureKestrel(serverOptions => +{ + serverOptions.ListenAnyIP(5001); +}); + +builder.Services.AddControllers(); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +builder.Services.AddCors(options => +{ + options.AddPolicy("AllowAll", policy => + { + policy.AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader(); + }); +}); + +var app = builder.Build(); + +app.UseCors("AllowAll"); + +app.UseSwagger(c => +{ + + c.PreSerializeFilters.Add((swaggerDoc, httpReq) => + { + swaggerDoc.Servers = new List { new OpenApiServer { Url = $"{httpReq.Scheme}://{httpReq.Host.Value}/projectservice" } }; + }); +}); +app.UseSwaggerUI(); + +app.UseHttpsRedirection(); + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git a/aleikin_artem_lab_3/ProjectEntityProject/ProjectEntityProject.csproj b/aleikin_artem_lab_3/ProjectEntityProject/ProjectEntityProject.csproj new file mode 100644 index 0000000..11a1b3c --- /dev/null +++ b/aleikin_artem_lab_3/ProjectEntityProject/ProjectEntityProject.csproj @@ -0,0 +1,16 @@ + + + + net8.0 + enable + enable + 8c799772-d663-4c4a-8e6b-cce6a75ee84e + Linux + + + + + + + + diff --git a/aleikin_artem_lab_3/ProjectEntityProject/ProjectEntityProject.csproj.user b/aleikin_artem_lab_3/ProjectEntityProject/ProjectEntityProject.csproj.user new file mode 100644 index 0000000..876eafe --- /dev/null +++ b/aleikin_artem_lab_3/ProjectEntityProject/ProjectEntityProject.csproj.user @@ -0,0 +1,8 @@ + + + + Container (Dockerfile) + MvcControllerWithActionsScaffolder + root/Common/MVC/Controller + + \ No newline at end of file diff --git a/aleikin_artem_lab_3/ProjectEntityProject/ProjectEntityProject.http b/aleikin_artem_lab_3/ProjectEntityProject/ProjectEntityProject.http new file mode 100644 index 0000000..6a8d729 --- /dev/null +++ b/aleikin_artem_lab_3/ProjectEntityProject/ProjectEntityProject.http @@ -0,0 +1,6 @@ +@ProjectEntityProject_HostAddress = http://localhost:5168 + +GET {{ProjectEntityProject_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/aleikin_artem_lab_3/ProjectEntityProject/Properties/launchSettings.json b/aleikin_artem_lab_3/ProjectEntityProject/Properties/launchSettings.json new file mode 100644 index 0000000..75f13c2 --- /dev/null +++ b/aleikin_artem_lab_3/ProjectEntityProject/Properties/launchSettings.json @@ -0,0 +1,52 @@ +{ + "profiles": { + "http": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5168" + }, + "https": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7265;http://localhost:5168" + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Container (Dockerfile)": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger", + "environmentVariables": { + "ASPNETCORE_HTTPS_PORTS": "8081", + "ASPNETCORE_HTTP_PORTS": "8080" + }, + "publishAllPorts": true, + "useSSL": true + } + }, + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:54970", + "sslPort": 44349 + } + } +} \ No newline at end of file diff --git a/aleikin_artem_lab_3/ProjectEntityProject/appsettings.Development.json b/aleikin_artem_lab_3/ProjectEntityProject/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/aleikin_artem_lab_3/ProjectEntityProject/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/aleikin_artem_lab_3/ProjectEntityProject/appsettings.json b/aleikin_artem_lab_3/ProjectEntityProject/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/aleikin_artem_lab_3/ProjectEntityProject/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/aleikin_artem_lab_3/RVIPLab3.sln b/aleikin_artem_lab_3/RVIPLab3.sln new file mode 100644 index 0000000..ef52a95 --- /dev/null +++ b/aleikin_artem_lab_3/RVIPLab3.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.11.35312.102 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TaskProject", "TaskProject\TaskProject.csproj", "{D175ACE5-8DAA-41B0-A0F1-BA27B5F0426F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectEntityProject", "ProjectEntityProject\ProjectEntityProject.csproj", "{86A5B199-BE0A-4575-A4E9-664AA5D9ADDE}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D175ACE5-8DAA-41B0-A0F1-BA27B5F0426F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D175ACE5-8DAA-41B0-A0F1-BA27B5F0426F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D175ACE5-8DAA-41B0-A0F1-BA27B5F0426F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D175ACE5-8DAA-41B0-A0F1-BA27B5F0426F}.Release|Any CPU.Build.0 = Release|Any CPU + {86A5B199-BE0A-4575-A4E9-664AA5D9ADDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {86A5B199-BE0A-4575-A4E9-664AA5D9ADDE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {86A5B199-BE0A-4575-A4E9-664AA5D9ADDE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {86A5B199-BE0A-4575-A4E9-664AA5D9ADDE}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3B478466-7705-4F87-B871-52F7F7EF02A6} + EndGlobalSection +EndGlobal diff --git a/aleikin_artem_lab_3/TaskProject/Controllers/TaskController.cs b/aleikin_artem_lab_3/TaskProject/Controllers/TaskController.cs new file mode 100644 index 0000000..e3b1d63 --- /dev/null +++ b/aleikin_artem_lab_3/TaskProject/Controllers/TaskController.cs @@ -0,0 +1,77 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System.Net.Http; +using TaskProject.Entity; +using static System.Runtime.InteropServices.JavaScript.JSType; +using Task = TaskProject.Entity.Task; + +namespace TaskProject.Controllers +{ + [ApiController] + [Route("tasks")] + public class TaskController : ControllerBase + { + private static readonly List Tasks = new(); + + [HttpGet] + public ActionResult> GetTasks() => Ok(Tasks); + + [HttpGet("{id}")] + public ActionResult GetTask(Guid id) + { + var task = Tasks.FirstOrDefault(t => t.Id == id); + return task is null ? NotFound() : Ok(task); + } + + [HttpPost] + public ActionResult CreateTask([FromBody] TaskDto taskDto) + { + Task task = new Task + { + Title = taskDto.Title, + Description = taskDto.Description, + ProjectId = taskDto.ProjectId, + }; + var client = new HttpClient(); + var response = client.GetAsync($"http://nginx/projectservice/projects/{task.ProjectId}").Result; + if (!response.IsSuccessStatusCode) return BadRequest("Project not found"); + + Tasks.Add(task); + return CreatedAtAction(nameof(GetTask), new { id = task.Id }, task); + } + + [HttpPut("{id}")] + public ActionResult UpdateTask(Guid id, [FromBody] TaskDto taskDto) + { + var task = Tasks.FirstOrDefault(t => t.Id == id); + if (task is null) return NotFound(); + + var client = new HttpClient(); + var response = client.GetAsync($"http://nginx/projectservice/projects/{task.ProjectId}").Result; + if (!response.IsSuccessStatusCode) return BadRequest("Project not found"); + + task.Title = taskDto.Title; + task.Description = taskDto.Description; + task.ProjectId = taskDto.ProjectId; + return Ok(task); + } + + [HttpDelete("{id}")] + public IActionResult DeleteTask(Guid id) + { + var task = Tasks.FirstOrDefault(t => t.Id == id); + if (task is null) return NotFound(); + + Tasks.Remove(task); + return Ok(); + } + + [HttpDelete("by-project/{projectId}")] + public IActionResult DeleteTasksByProject(Guid projectId) + { + Tasks.RemoveAll(t => t.ProjectId == projectId); + return Ok(); + } + } + +} diff --git a/aleikin_artem_lab_3/TaskProject/Dockerfile b/aleikin_artem_lab_3/TaskProject/Dockerfile new file mode 100644 index 0000000..aa25849 --- /dev/null +++ b/aleikin_artem_lab_3/TaskProject/Dockerfile @@ -0,0 +1,29 @@ +# См. статью по ссылке https://aka.ms/customizecontainer, чтобы узнать как настроить контейнер отладки и как Visual Studio использует этот Dockerfile для создания образов для ускорения отладки. + +# Этот этап используется при запуске из VS в быстром режиме (по умолчанию для конфигурации отладки) +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +USER app +WORKDIR /app +EXPOSE 5002 + + +# Этот этап используется для сборки проекта службы +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["TaskProject/TaskProject.csproj", "TaskProject/"] +RUN dotnet restore "./TaskProject/TaskProject.csproj" +COPY . . +WORKDIR "/src/TaskProject" +RUN dotnet build "./TaskProject.csproj" -c $BUILD_CONFIGURATION -o /app/build + +# Этот этап используется для публикации проекта службы, который будет скопирован на последний этап +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "./TaskProject.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false + +# Этот этап используется в рабочей среде или при запуске из VS в обычном режиме (по умолчанию, когда конфигурация отладки не используется) +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "TaskProject.dll"] \ No newline at end of file diff --git a/aleikin_artem_lab_3/TaskProject/Entity/Task.cs b/aleikin_artem_lab_3/TaskProject/Entity/Task.cs new file mode 100644 index 0000000..422cf7a --- /dev/null +++ b/aleikin_artem_lab_3/TaskProject/Entity/Task.cs @@ -0,0 +1,11 @@ +namespace TaskProject.Entity +{ + public class Task + { + public Guid Id { get; init; } = Guid.NewGuid(); + public string Title { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; + public Guid ProjectId { get; set; } + } + +} diff --git a/aleikin_artem_lab_3/TaskProject/Entity/TaskDto.cs b/aleikin_artem_lab_3/TaskProject/Entity/TaskDto.cs new file mode 100644 index 0000000..522b40f --- /dev/null +++ b/aleikin_artem_lab_3/TaskProject/Entity/TaskDto.cs @@ -0,0 +1,4 @@ +namespace TaskProject.Entity +{ + public record TaskDto(string Title, string Description, Guid ProjectId) {} +} diff --git a/aleikin_artem_lab_3/TaskProject/Program.cs b/aleikin_artem_lab_3/TaskProject/Program.cs new file mode 100644 index 0000000..1b223d4 --- /dev/null +++ b/aleikin_artem_lab_3/TaskProject/Program.cs @@ -0,0 +1,45 @@ +using Microsoft.OpenApi.Models; + +var builder = WebApplication.CreateBuilder(args); + +builder.WebHost.ConfigureKestrel(serverOptions => +{ + serverOptions.ListenAnyIP(5002); +}); + +builder.Services.AddCors(options => +{ + options.AddPolicy("AllowAll", policy => + { + policy.AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader(); + }); +}); + +builder.Services.AddControllers(); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +var app = builder.Build(); + +app.UseCors("AllowAll"); + +app.UseSwagger(c => +{ + + c.PreSerializeFilters.Add((swaggerDoc, httpReq) => + { + swaggerDoc.Servers = new List { new OpenApiServer { Url = $"{httpReq.Scheme}://{httpReq.Host.Value}/taskservice" } }; + }); +}); +app.UseSwaggerUI(); + +app.UseHttpsRedirection(); + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); \ No newline at end of file diff --git a/aleikin_artem_lab_3/TaskProject/Properties/launchSettings.json b/aleikin_artem_lab_3/TaskProject/Properties/launchSettings.json new file mode 100644 index 0000000..0f16720 --- /dev/null +++ b/aleikin_artem_lab_3/TaskProject/Properties/launchSettings.json @@ -0,0 +1,52 @@ +{ + "profiles": { + "http": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5079" + }, + "https": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7111;http://localhost:5079" + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Container (Dockerfile)": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger", + "environmentVariables": { + "ASPNETCORE_HTTPS_PORTS": "8081", + "ASPNETCORE_HTTP_PORTS": "8080" + }, + "publishAllPorts": true, + "useSSL": true + } + }, + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:54012", + "sslPort": 44337 + } + } +} \ No newline at end of file diff --git a/aleikin_artem_lab_3/TaskProject/TaskProject.csproj b/aleikin_artem_lab_3/TaskProject/TaskProject.csproj new file mode 100644 index 0000000..cb9be1e --- /dev/null +++ b/aleikin_artem_lab_3/TaskProject/TaskProject.csproj @@ -0,0 +1,16 @@ + + + + net8.0 + enable + enable + 735c8756-0d0c-4166-875d-9dfbf7cf10c4 + Linux + + + + + + + + diff --git a/aleikin_artem_lab_3/TaskProject/TaskProject.csproj.user b/aleikin_artem_lab_3/TaskProject/TaskProject.csproj.user new file mode 100644 index 0000000..876eafe --- /dev/null +++ b/aleikin_artem_lab_3/TaskProject/TaskProject.csproj.user @@ -0,0 +1,8 @@ + + + + Container (Dockerfile) + MvcControllerWithActionsScaffolder + root/Common/MVC/Controller + + \ No newline at end of file diff --git a/aleikin_artem_lab_3/TaskProject/TaskProject.http b/aleikin_artem_lab_3/TaskProject/TaskProject.http new file mode 100644 index 0000000..96f5f89 --- /dev/null +++ b/aleikin_artem_lab_3/TaskProject/TaskProject.http @@ -0,0 +1,6 @@ +@TaskProject_HostAddress = http://localhost:5079 + +GET {{TaskProject_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/aleikin_artem_lab_3/TaskProject/appsettings.Development.json b/aleikin_artem_lab_3/TaskProject/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/aleikin_artem_lab_3/TaskProject/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/aleikin_artem_lab_3/TaskProject/appsettings.json b/aleikin_artem_lab_3/TaskProject/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/aleikin_artem_lab_3/TaskProject/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/aleikin_artem_lab_3/docker-compose.yml b/aleikin_artem_lab_3/docker-compose.yml new file mode 100644 index 0000000..bbf55f1 --- /dev/null +++ b/aleikin_artem_lab_3/docker-compose.yml @@ -0,0 +1,35 @@ +services: + nginx: + image: nginx + depends_on: + - projectservice + - taskservice + volumes: + - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf + networks: + - app-network + ports: + - 80:80 + + projectservice: + build: + context: . + dockerfile: ProjectEntityProject/Dockerfile + networks: + - app-network + ports: + - 5001:8080 + taskservice: + build: + context: . + dockerfile: TaskProject/Dockerfile + networks: + - app-network + ports: + - 5002:8080 + depends_on: + - projectservice + +networks: + app-network: + driver: bridge \ No newline at end of file diff --git a/aleikin_artem_lab_3/nginx/nginx.conf b/aleikin_artem_lab_3/nginx/nginx.conf new file mode 100644 index 0000000..c626689 --- /dev/null +++ b/aleikin_artem_lab_3/nginx/nginx.conf @@ -0,0 +1,18 @@ +server { + listen 80; + server_name localhost; + + location /projectservice/ { + proxy_pass http://projectservice:5001/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /taskservice/ { + proxy_pass http://taskservice:5002/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + } +} \ No newline at end of file diff --git a/aleikin_artem_lab_3/readme.md b/aleikin_artem_lab_3/readme.md new file mode 100644 index 0000000..9f37765 --- /dev/null +++ b/aleikin_artem_lab_3/readme.md @@ -0,0 +1,99 @@ +# Лабораторная работа 3 - REST API, Gateway и синхронный обмен между микросервисами +## ПИбд-42 || Алейкин Артем + +### Описание +В данной лабораторной работе мы разворачиваем два микросервиса: +ProjectEntityProject - проект содержащий логику работы с сущностью 'Проект - Project'. +TaskProject - проект содержащий логику работы с сущностью 'Задача - Task'. + +### Файлы-конфигурации +1. docker-compose +``` +services: + nginx: + image: nginx + depends_on: + - projectservice + - taskservice + volumes: + - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf + networks: + - app-network + ports: + - 80:80 + + projectservice: + build: + context: . + dockerfile: ProjectEntityProject/Dockerfile + networks: + - app-network + ports: + - 5001:8080 + taskservice: + build: + context: . + dockerfile: TaskProject/Dockerfile + networks: + - app-network + ports: + - 5002:8080 + depends_on: + - projectservice + +networks: + app-network: + driver: bridge +``` + +nginx: Сервис, который работает как обратный прокси-сервер и маршрутизирует запросы к другим сервисам (projectservice и taskservice), слушая на порту 80. + +Зависит от двух других сервисов: projectservice и taskservice. +Прокси-сервер использует конфигурацию, предоставленную в nginx.conf. +projectservice: Сервис, отвечающий за логику работы с проектами, доступный на порту 8080 внутри контейнера (проброшен на порт 5001). + +Этот сервис будет обрабатывать запросы, связанные с проектами. +taskservice: Сервис, отвечающий за логику работы с задачами, доступный на порту 8080 внутри контейнера (проброшен на порт 5002). + +Этот сервис будет обрабатывать запросы, связанные с задачами. +Зависит от projectservice, так как задачи связаны с проектами. +Сервис nginx будет проксировать запросы с путями /projectservice/ и /taskservice/ на соответствующие контейнеры с сервисами. + + +2. nginx.conf +``` +server { + listen 80; + server_name localhost; + + location /projectservice/ { + proxy_pass http://projectservice:5001/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /taskservice/ { + proxy_pass http://taskservice:5002/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + } +} +``` + +Этот файл конфигурирует Nginx для маршрутизации запросов: + +location /projectservice/: Все запросы, начинающиеся с /projectservice/, будут проксироваться к сервису projectservice, который работает на порту 5001. Заголовки, такие как Host, X-Real-IP и X-Forwarded-Proto, устанавливаются для правильной передачи информации о запросе. + +location /taskservice/: Все запросы, начинающиеся с /taskservice/, будут проксироваться к сервису taskservice, который работает на порту 5002. Аналогично, заголовки проксируются для корректной передачи данных. + +Этот конфигурационный файл гарантирует, что запросы к путям /projectservice/ и /taskservice/ будут перенаправляться на соответствующие сервисы через прокси-сервер Nginx. + +### Шаги для запуска: +Переходим в корневую папку всего решения и пишем команду: +``` +docker-compose up --build +``` + +Видео демонстрации работы: https://vk.com/video248424990_456239610?list=ln-Doqjb41FQlfo377LN0 \ No newline at end of file