From f503b8143f8caf92f12cb7e81042346319521c97 Mon Sep 17 00:00:00 2001 From: codemazeblog Date: Tue, 24 Apr 2018 21:08:18 +0200 Subject: [PATCH 01/12] Initial commit --- .gitignore | 5 ++ AccountOwnerServer.sln | 63 ++++++++++++++++- AccountOwnerServer/AccountOwnerServer.csproj | 1 + .../Controllers/AccountController.cs | 67 +++++++++++++++++++ .../Controllers/OwnerController.cs | 4 +- .../Extensions/ServiceExtensions.cs | 7 +- AccountOwnerServer/Startup.cs | 16 ++++- AccountOwnerServer/appsettings.json | 2 +- AccountOwnerServer/nlog.config | 4 +- Contracts/IAccountRepository.cs | 3 + README.md | 2 +- Repository/AccountRepository.cs | 16 +++++ Tests/OwnerRepositoryTests.cs | 42 ++++++++++++ Tests/Tests.csproj | 21 ++++++ 14 files changed, 236 insertions(+), 17 deletions(-) create mode 100644 AccountOwnerServer/Controllers/AccountController.cs create mode 100644 Tests/OwnerRepositoryTests.cs create mode 100644 Tests/Tests.csproj diff --git a/.gitignore b/.gitignore index b14f7ce..6c3ac39 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /AccountOwnerServer/obj /AccountOwnerServer/bin +/AccountOwnerServer/Projects /Contracts/obj /Contracts/bin /Entities/obj @@ -8,3 +9,7 @@ /LoggerService/bin /Repository/obj /Repository/bin +/Tests/bin +/Tests/obj +/.vs + diff --git a/AccountOwnerServer.sln b/AccountOwnerServer.sln index 7620715..601977b 100644 --- a/AccountOwnerServer.sln +++ b/AccountOwnerServer.sln @@ -1,7 +1,6 @@ - Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26730.3 +VisualStudioVersion = 15.0.27130.2010 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AccountOwnerServer", "AccountOwnerServer\AccountOwnerServer.csproj", "{73FB08B8-4033-4116-B3AC-EC8253B024D4}" EndProject @@ -11,34 +10,92 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LoggerService", "LoggerServ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Entities", "Entities\Entities.csproj", "{8CD97B3F-C616-469C-80A2-A1B366611487}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Repository", "Repository\Repository.csproj", "{CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Repository", "Repository\Repository.csproj", "{CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{89CF5113-7F84-40B8-A81C-B918F00183AD}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Debug|x64.ActiveCfg = Debug|Any CPU + {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Debug|x64.Build.0 = Debug|Any CPU + {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Debug|x86.ActiveCfg = Debug|Any CPU + {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Debug|x86.Build.0 = Debug|Any CPU {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Release|Any CPU.ActiveCfg = Release|Any CPU {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Release|Any CPU.Build.0 = Release|Any CPU + {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Release|x64.ActiveCfg = Release|Any CPU + {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Release|x64.Build.0 = Release|Any CPU + {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Release|x86.ActiveCfg = Release|Any CPU + {73FB08B8-4033-4116-B3AC-EC8253B024D4}.Release|x86.Build.0 = Release|Any CPU {52725034-B791-4DF1-A227-02EDB5BF78E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {52725034-B791-4DF1-A227-02EDB5BF78E0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {52725034-B791-4DF1-A227-02EDB5BF78E0}.Debug|x64.ActiveCfg = Debug|Any CPU + {52725034-B791-4DF1-A227-02EDB5BF78E0}.Debug|x64.Build.0 = Debug|Any CPU + {52725034-B791-4DF1-A227-02EDB5BF78E0}.Debug|x86.ActiveCfg = Debug|Any CPU + {52725034-B791-4DF1-A227-02EDB5BF78E0}.Debug|x86.Build.0 = Debug|Any CPU {52725034-B791-4DF1-A227-02EDB5BF78E0}.Release|Any CPU.ActiveCfg = Release|Any CPU {52725034-B791-4DF1-A227-02EDB5BF78E0}.Release|Any CPU.Build.0 = Release|Any CPU + {52725034-B791-4DF1-A227-02EDB5BF78E0}.Release|x64.ActiveCfg = Release|Any CPU + {52725034-B791-4DF1-A227-02EDB5BF78E0}.Release|x64.Build.0 = Release|Any CPU + {52725034-B791-4DF1-A227-02EDB5BF78E0}.Release|x86.ActiveCfg = Release|Any CPU + {52725034-B791-4DF1-A227-02EDB5BF78E0}.Release|x86.Build.0 = Release|Any CPU {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Debug|x64.ActiveCfg = Debug|Any CPU + {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Debug|x64.Build.0 = Debug|Any CPU + {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Debug|x86.ActiveCfg = Debug|Any CPU + {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Debug|x86.Build.0 = Debug|Any CPU {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Release|Any CPU.ActiveCfg = Release|Any CPU {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Release|Any CPU.Build.0 = Release|Any CPU + {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Release|x64.ActiveCfg = Release|Any CPU + {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Release|x64.Build.0 = Release|Any CPU + {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Release|x86.ActiveCfg = Release|Any CPU + {A190AF01-84DC-40A8-BEF3-C015825C8B30}.Release|x86.Build.0 = Release|Any CPU {8CD97B3F-C616-469C-80A2-A1B366611487}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8CD97B3F-C616-469C-80A2-A1B366611487}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8CD97B3F-C616-469C-80A2-A1B366611487}.Debug|x64.ActiveCfg = Debug|Any CPU + {8CD97B3F-C616-469C-80A2-A1B366611487}.Debug|x64.Build.0 = Debug|Any CPU + {8CD97B3F-C616-469C-80A2-A1B366611487}.Debug|x86.ActiveCfg = Debug|Any CPU + {8CD97B3F-C616-469C-80A2-A1B366611487}.Debug|x86.Build.0 = Debug|Any CPU {8CD97B3F-C616-469C-80A2-A1B366611487}.Release|Any CPU.ActiveCfg = Release|Any CPU {8CD97B3F-C616-469C-80A2-A1B366611487}.Release|Any CPU.Build.0 = Release|Any CPU + {8CD97B3F-C616-469C-80A2-A1B366611487}.Release|x64.ActiveCfg = Release|Any CPU + {8CD97B3F-C616-469C-80A2-A1B366611487}.Release|x64.Build.0 = Release|Any CPU + {8CD97B3F-C616-469C-80A2-A1B366611487}.Release|x86.ActiveCfg = Release|Any CPU + {8CD97B3F-C616-469C-80A2-A1B366611487}.Release|x86.Build.0 = Release|Any CPU {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Debug|x64.ActiveCfg = Debug|Any CPU + {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Debug|x64.Build.0 = Debug|Any CPU + {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Debug|x86.ActiveCfg = Debug|Any CPU + {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Debug|x86.Build.0 = Debug|Any CPU {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Release|Any CPU.ActiveCfg = Release|Any CPU {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Release|Any CPU.Build.0 = Release|Any CPU + {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Release|x64.ActiveCfg = Release|Any CPU + {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Release|x64.Build.0 = Release|Any CPU + {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Release|x86.ActiveCfg = Release|Any CPU + {CC0B1C81-CB8A-412C-BD48-BCBC3F1A1CD0}.Release|x86.Build.0 = Release|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Debug|x64.ActiveCfg = Debug|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Debug|x64.Build.0 = Debug|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Debug|x86.ActiveCfg = Debug|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Debug|x86.Build.0 = Debug|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Release|Any CPU.Build.0 = Release|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Release|x64.ActiveCfg = Release|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Release|x64.Build.0 = Release|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Release|x86.ActiveCfg = Release|Any CPU + {89CF5113-7F84-40B8-A81C-B918F00183AD}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/AccountOwnerServer/AccountOwnerServer.csproj b/AccountOwnerServer/AccountOwnerServer.csproj index beffa6b..b0d65a5 100644 --- a/AccountOwnerServer/AccountOwnerServer.csproj +++ b/AccountOwnerServer/AccountOwnerServer.csproj @@ -11,6 +11,7 @@ + diff --git a/AccountOwnerServer/Controllers/AccountController.cs b/AccountOwnerServer/Controllers/AccountController.cs new file mode 100644 index 0000000..0675f09 --- /dev/null +++ b/AccountOwnerServer/Controllers/AccountController.cs @@ -0,0 +1,67 @@ +using Contracts; +using Entities.Extensions; +using Entities.Models; +using Microsoft.AspNetCore.Mvc; +using System; + +namespace AccountOwnerServer.Controllers +{ + [Route("api/[controller]")] + public class AccountController : Controller + { + private ILoggerManager _logger; + private IRepositoryWrapper _repository; + + public AccountController(ILoggerManager logger, IRepositoryWrapper repository) + { + _logger = logger; + _repository = repository; + } + + [HttpGet] + public IActionResult GetAllAccounts() + { + try + { + var accounts = _repository.Account.GetAllAccounts(); + + _logger.LogInfo($"Returned all accounts from database."); + + return Ok(accounts); + } + catch (Exception ex) + { + _logger.LogError($"Something went wrong inside GetAllAccounts action: {ex}"); + return StatusCode(500, "Internal server error"); + } + } + + [HttpPost] + public IActionResult CreateOwner([FromBody]Account account) + { + try + { + if (account.IsObjectNull()) + { + _logger.LogError("Object sent from client is null."); + return BadRequest("Object is null"); + } + + if (!ModelState.IsValid) + { + _logger.LogError("Invalid object sent from client."); + return BadRequest("Invalid model object"); + } + + _repository.Account.CreateAccount(account); + + return CreatedAtRoute("AccountById", new { id = account.Id }, account); + } + catch (Exception ex) + { + _logger.LogError($"Something went wrong inside CreateAccount action: {ex}"); + return StatusCode(500, "Internal server error"); + } + } + } +} diff --git a/AccountOwnerServer/Controllers/OwnerController.cs b/AccountOwnerServer/Controllers/OwnerController.cs index dc2850c..e26f275 100644 --- a/AccountOwnerServer/Controllers/OwnerController.cs +++ b/AccountOwnerServer/Controllers/OwnerController.cs @@ -31,7 +31,7 @@ public IActionResult GetAllOwners() } catch (Exception ex) { - _logger.LogError($"Something went wrong inside GetAllOwners action: {ex.Message}"); + _logger.LogError($"Something went wrong inside GetAllOwners action: {ex}"); return StatusCode(500, "Internal server error"); } } @@ -62,7 +62,7 @@ public IActionResult GetOwnerById(Guid id) } [HttpGet("{id}/account")] - public IActionResult GetOwnerWithDetails(Guid id) + public IActionResult GetOwnerAccounts(Guid id) { try { diff --git a/AccountOwnerServer/Extensions/ServiceExtensions.cs b/AccountOwnerServer/Extensions/ServiceExtensions.cs index 89ac3a5..3acce2b 100644 --- a/AccountOwnerServer/Extensions/ServiceExtensions.cs +++ b/AccountOwnerServer/Extensions/ServiceExtensions.cs @@ -6,10 +6,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Repository; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; namespace AccountOwnerServer.Extensions { @@ -42,8 +38,7 @@ public static void ConfigureLoggerService(this IServiceCollection services) public static void ConfigureMySqlContext(this IServiceCollection services, IConfiguration config) { - var connectionString = config["mysqlconnection:connectionString"]; - services.AddDbContext(o => o.UseMySql(connectionString)); + services.AddDbContext(o => o.UseInMemoryDatabase("accountowner")); } public static void ConfigureRepositoryWrapper(this IServiceCollection services) diff --git a/AccountOwnerServer/Startup.cs b/AccountOwnerServer/Startup.cs index 3a86fc4..fa74191 100644 --- a/AccountOwnerServer/Startup.cs +++ b/AccountOwnerServer/Startup.cs @@ -12,7 +12,7 @@ using Microsoft.AspNetCore.HttpOverrides; using System.IO; using NLog.Extensions.Logging; -using Contracts; +using Swashbuckle.AspNetCore.Swagger; namespace AccountOwnerServer { @@ -39,6 +39,11 @@ public void ConfigureServices(IServiceCollection services) services.ConfigureRepositoryWrapper(); services.AddMvc(); + + services.AddSwaggerGen(c => + { + c.SwaggerDoc("v1", new Info { Title = "AccountOwner API", Version = "v1" }); + }); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) @@ -47,7 +52,7 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseDeveloperExceptionPage(); } - + app.UseCors("CorsPolicy"); app.UseForwardedHeaders(new ForwardedHeadersOptions @@ -70,6 +75,13 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env) app.UseStaticFiles(); app.UseMvc(); + + app.UseSwagger(); + + app.UseSwaggerUI(c => + { + c.SwaggerEndpoint("/swagger/v1/swagger.json", "AccountOwner API V1"); + }); } } } diff --git a/AccountOwnerServer/appsettings.json b/AccountOwnerServer/appsettings.json index 934ec46..900bf6b 100644 --- a/AccountOwnerServer/appsettings.json +++ b/AccountOwnerServer/appsettings.json @@ -13,6 +13,6 @@ } }, "mysqlconnection": { - "connectionString": "server=localhost;userid=dbuser;password=pass;database=accountowner;" + "connectionString": "server=localhost;port=3306;userid=root;password=root;database=accountowner;" } } diff --git a/AccountOwnerServer/nlog.config b/AccountOwnerServer/nlog.config index 91c2174..69efc94 100644 --- a/AccountOwnerServer/nlog.config +++ b/AccountOwnerServer/nlog.config @@ -3,7 +3,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true" internalLogLevel="Trace" - internalLogFile="d:Projects\Blog-AccountOwner\Project\internal_logs\internallog.txt"> + internalLogFile="internallog.txt"> @@ -11,7 +11,7 @@ diff --git a/Contracts/IAccountRepository.cs b/Contracts/IAccountRepository.cs index 825a4fb..945b7f5 100644 --- a/Contracts/IAccountRepository.cs +++ b/Contracts/IAccountRepository.cs @@ -1,8 +1,11 @@ using Entities.Models; +using System.Collections.Generic; namespace Contracts { public interface IAccountRepository { + IEnumerable GetAllAccounts(); + void CreateAccount(Account account); } } diff --git a/README.md b/README.md index 226a577..80c22d1 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# Docker Series +# Docker Kubernetes Series diff --git a/Repository/AccountRepository.cs b/Repository/AccountRepository.cs index 9dcb2d5..0cd0be0 100644 --- a/Repository/AccountRepository.cs +++ b/Repository/AccountRepository.cs @@ -1,6 +1,9 @@ using Contracts; using Entities; using Entities.Models; +using System; +using System.Collections.Generic; +using System.Linq; namespace Repository { @@ -10,5 +13,18 @@ public AccountRepository(RepositoryContext repositoryContext) :base(repositoryContext) { } + + public IEnumerable GetAllAccounts() + { + return FindAll() + .OrderBy(ac => ac.DateCreated); + } + + public void CreateAccount(Account account) + { + account.Id = Guid.NewGuid(); + Create(account); + Save(); + } } } diff --git a/Tests/OwnerRepositoryTests.cs b/Tests/OwnerRepositoryTests.cs new file mode 100644 index 0000000..81d3133 --- /dev/null +++ b/Tests/OwnerRepositoryTests.cs @@ -0,0 +1,42 @@ +using Contracts; +using Entities.Models; +using Moq; +using System; +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace Tests +{ + public class OwnerRepositoryTests + { + [Fact] + public void GetAllOwners_ReturnsListOfOwners_WithSingleOwner() + { + // Arrange + var mockRepo = new Mock(); + mockRepo.Setup(repo => (repo.GetAllOwners())).Returns(GetOwners()); + + // Act + var result = mockRepo.Object.GetAllOwners().ToList(); + + // Assert + Assert.IsType>(result); + Assert.Single(result); + } + + public List GetOwners() + { + return new List + { + new Owner + { + Id = Guid.NewGuid(), + Name = "John Keen", + DateOfBirth = new DateTime(1980, 12, 05), + Address = "61 Wellfield Road" + } + }; + } + } +} diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj new file mode 100644 index 0000000..114ad4b --- /dev/null +++ b/Tests/Tests.csproj @@ -0,0 +1,21 @@ + + + + netcoreapp2.0 + + false + + + + + + + + + + + + + + + From 4d7a6b56165b5a785333caab2d245593dc0444d9 Mon Sep 17 00:00:00 2001 From: codemazeblog Date: Tue, 24 Apr 2018 21:11:35 +0200 Subject: [PATCH 02/12] connection string changes --- AccountOwnerServer/appsettings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AccountOwnerServer/appsettings.json b/AccountOwnerServer/appsettings.json index 900bf6b..934ec46 100644 --- a/AccountOwnerServer/appsettings.json +++ b/AccountOwnerServer/appsettings.json @@ -13,6 +13,6 @@ } }, "mysqlconnection": { - "connectionString": "server=localhost;port=3306;userid=root;password=root;database=accountowner;" + "connectionString": "server=localhost;userid=dbuser;password=pass;database=accountowner;" } } From e67ebb94158bce1d4bd5e6bdbce20e65fc316c8e Mon Sep 17 00:00:00 2001 From: codemazeblog Date: Sat, 5 May 2018 20:11:14 +0200 Subject: [PATCH 03/12] Initial Commit --- .dockerignore | 7 +++++ .gitignore | 2 +- .../Controllers/AccountController.cs | 2 +- Dockerfile | 27 +++++++++++++++++++ 4 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..341d071 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +**/bin/ +**/obj/ +**/global.json +**/Dockerfile* +**/.dockerignore* +**/*.user + diff --git a/.gitignore b/.gitignore index 6c3ac39..dab9784 100644 --- a/.gitignore +++ b/.gitignore @@ -11,5 +11,5 @@ /Repository/bin /Tests/bin /Tests/obj +publish /.vs - diff --git a/AccountOwnerServer/Controllers/AccountController.cs b/AccountOwnerServer/Controllers/AccountController.cs index 0675f09..4404b93 100644 --- a/AccountOwnerServer/Controllers/AccountController.cs +++ b/AccountOwnerServer/Controllers/AccountController.cs @@ -10,7 +10,7 @@ namespace AccountOwnerServer.Controllers public class AccountController : Controller { private ILoggerManager _logger; - private IRepositoryWrapper _repository; + private IRepositoryWrapper _repository; public AccountController(ILoggerManager logger, IRepositoryWrapper repository) { diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..98ac7b8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,27 @@ +FROM microsoft/aspnetcore-build as build-image + +WORKDIR /home/app + +COPY ./AccountOwnerServer/AccountOwnerServer.csproj ./AccountOwnerServer/ +COPY ./Contracts/Contracts.csproj ./Contracts/ +COPY ./Repository/Repository.csproj ./Repository/ +COPY ./Entities/Entities.csproj ./Entities/ +COPY ./LoggerService/LoggerService.csproj ./LoggerService/ +COPY ./Tests/Tests.csproj ./Tests/ +COPY ./AccountOwnerServer.sln . + +RUN dotnet restore + +COPY . . + +RUN dotnet test ./Tests/Tests.csproj + +RUN dotnet publish ./AccountOwnerServer/AccountOwnerServer.csproj -o /publish/ + +FROM microsoft/aspnetcore + +WORKDIR /publish + +COPY --from=build-image /publish . + +ENTRYPOINT ["dotnet", "AccountOwnerServer.dll"] \ No newline at end of file From 1d9c49289939fae369ba044119366c7c39caec1b Mon Sep 17 00:00:00 2001 From: codemazeblog Date: Sun, 6 May 2018 19:59:44 +0200 Subject: [PATCH 04/12] Optimizing Dockerfile --- Dockerfile | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/Dockerfile b/Dockerfile index 98ac7b8..e055560 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,27 +1,23 @@ FROM microsoft/aspnetcore-build as build-image - + WORKDIR /home/app - -COPY ./AccountOwnerServer/AccountOwnerServer.csproj ./AccountOwnerServer/ -COPY ./Contracts/Contracts.csproj ./Contracts/ -COPY ./Repository/Repository.csproj ./Repository/ -COPY ./Entities/Entities.csproj ./Entities/ -COPY ./LoggerService/LoggerService.csproj ./LoggerService/ -COPY ./Tests/Tests.csproj ./Tests/ -COPY ./AccountOwnerServer.sln . - + +COPY ./*.sln ./ +COPY ./*/*.csproj ./ +RUN for file in $(ls *.csproj); do mkdir -p ./${file%.*}/ && mv $file ./${file%.*}/; done + RUN dotnet restore - + COPY . . - + RUN dotnet test ./Tests/Tests.csproj - + RUN dotnet publish ./AccountOwnerServer/AccountOwnerServer.csproj -o /publish/ - + FROM microsoft/aspnetcore - + WORKDIR /publish - + COPY --from=build-image /publish . - + ENTRYPOINT ["dotnet", "AccountOwnerServer.dll"] \ No newline at end of file From e65081f6761cf865d71f33e24275b1ebb582e5ac Mon Sep 17 00:00:00 2001 From: codemazeblog Date: Sun, 13 May 2018 15:14:42 +0200 Subject: [PATCH 05/12] Initial commit --- .gitignore | 1 + .../Extensions/ServiceExtensions.cs | 3 ++- AccountOwnerServer/appsettings.json | 2 +- docker-compose.yml | 26 +++++++++++++++++++ 4 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 docker-compose.yml diff --git a/.gitignore b/.gitignore index dab9784..e32fc58 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ /Tests/obj publish /.vs +/AccountOwnerServer/internallog.txt diff --git a/AccountOwnerServer/Extensions/ServiceExtensions.cs b/AccountOwnerServer/Extensions/ServiceExtensions.cs index 3acce2b..ca6eb09 100644 --- a/AccountOwnerServer/Extensions/ServiceExtensions.cs +++ b/AccountOwnerServer/Extensions/ServiceExtensions.cs @@ -38,7 +38,8 @@ public static void ConfigureLoggerService(this IServiceCollection services) public static void ConfigureMySqlContext(this IServiceCollection services, IConfiguration config) { - services.AddDbContext(o => o.UseInMemoryDatabase("accountowner")); + var connectionString = config["mysqlconnection:connectionString"]; + services.AddDbContext(o => o.UseMySql(connectionString)); } public static void ConfigureRepositoryWrapper(this IServiceCollection services) diff --git a/AccountOwnerServer/appsettings.json b/AccountOwnerServer/appsettings.json index 934ec46..5935f76 100644 --- a/AccountOwnerServer/appsettings.json +++ b/AccountOwnerServer/appsettings.json @@ -13,6 +13,6 @@ } }, "mysqlconnection": { - "connectionString": "server=localhost;userid=dbuser;password=pass;database=accountowner;" + "connectionString": "server=db;port=3306;userid=dbuser;password=dbuserpassword;database=accountowner;" } } diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..a591245 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,26 @@ +version: '3.0' + +services: + db: + image: mysql:5.7 + environment: + MYSQL_RANDOM_ROOT_PASSWORD: 1 + MYSQL_DATABASE: accountowner + MYSQL_USER: dbuser + MYSQL_PASSWORD: dbuserpassword + volumes: + - dbdata:/var/lib/mysql + - ./_MySQL_Init_Script:/docker-entrypoint-initdb.d + restart: always + + accountownerapp: + depends_on: + - db + image: codemazeblog/accountownerapp + build: + context: . + ports: + - "8080:80" + +volumes: + dbdata: \ No newline at end of file From 259d73a9c0b21ce50c618007345815025b1c24b7 Mon Sep 17 00:00:00 2001 From: codemazeblog Date: Sat, 19 May 2018 12:44:11 +0200 Subject: [PATCH 06/12] Initial commit --- .gitignore | 1 + Infrastructure/Registry/docker-compose.yml | 13 +++++++++++++ README.md | 6 +++++- 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 Infrastructure/Registry/docker-compose.yml diff --git a/.gitignore b/.gitignore index e32fc58..290c85c 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ publish /.vs /AccountOwnerServer/internallog.txt +/AccountOwnerServer/*.user diff --git a/Infrastructure/Registry/docker-compose.yml b/Infrastructure/Registry/docker-compose.yml new file mode 100644 index 0000000..3a8d11b --- /dev/null +++ b/Infrastructure/Registry/docker-compose.yml @@ -0,0 +1,13 @@ +version: '3.0' + +services: + my-registry: + image: registry:latest + container_name: my-registry + volumes: + - registry:/var/lib/registry + ports: + - "50000:5000" + restart: unless-stopped +volumes: + registry: \ No newline at end of file diff --git a/README.md b/README.md index 80c22d1..6e8c788 100644 --- a/README.md +++ b/README.md @@ -1 +1,5 @@ -# Docker Kubernetes Series +# Docker Series +https://code-maze.com/docker-series/ + +## Part 5 of the Docker Series on CodeMaze blog +https://code-maze.com/docker-hub-vs-creating-docker-registry/ From 206e6f74ee00a2d40032bb2173b07a846d20ca81 Mon Sep 17 00:00:00 2001 From: codemazeblog Date: Mon, 28 May 2018 00:44:36 +0200 Subject: [PATCH 07/12] Initial commit --- .gitignore | 4 +++- Dockerfile | 16 +++++++-------- Infrastructure/TeamCity/docker-compose.yml | 23 ++++++++++++++++++++++ README.md | 4 ++-- 4 files changed, 36 insertions(+), 11 deletions(-) create mode 100644 Infrastructure/TeamCity/docker-compose.yml diff --git a/.gitignore b/.gitignore index 290c85c..3f49900 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,6 @@ publish /.vs /AccountOwnerServer/internallog.txt -/AccountOwnerServer/*.user +/AccountOwnerServer/2018-04-24_logfile.txt +/AccountOwnerServer/AccountOwnerServer.csproj.user +/Integration/Integration.csproj.user diff --git a/Dockerfile b/Dockerfile index e055560..b9c2c3d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ FROM microsoft/aspnetcore-build as build-image - + WORKDIR /home/app COPY ./*.sln ./ @@ -7,17 +7,17 @@ COPY ./*/*.csproj ./ RUN for file in $(ls *.csproj); do mkdir -p ./${file%.*}/ && mv $file ./${file%.*}/; done RUN dotnet restore - + COPY . . - + RUN dotnet test ./Tests/Tests.csproj - + RUN dotnet publish ./AccountOwnerServer/AccountOwnerServer.csproj -o /publish/ - + FROM microsoft/aspnetcore - + WORKDIR /publish - + COPY --from=build-image /publish . - + ENTRYPOINT ["dotnet", "AccountOwnerServer.dll"] \ No newline at end of file diff --git a/Infrastructure/TeamCity/docker-compose.yml b/Infrastructure/TeamCity/docker-compose.yml new file mode 100644 index 0000000..8005572 --- /dev/null +++ b/Infrastructure/TeamCity/docker-compose.yml @@ -0,0 +1,23 @@ +version: '3.1' + +services: + teamcity: + image: jetbrains/teamcity-server:latest + volumes: + - teamcity-server-datadir:/data/teamcity-server/datadir + - teamcity-server-logs:/opt/teamcity/logs + ports: + - 8111:8111 + teamcity-agent: + image: jetbrains/teamcity-agent:latest + environment: + SERVER_URL: http://teamcity:8111 + volumes: + - teamcity-agent-conf:/data/teamcity_agent/conf + - /var/run/docker.sock:/var/run/docker.sock + +volumes: + teamcity-server-datadir: + teamcity-server-logs: + teamcity-agent-conf: + \ No newline at end of file diff --git a/README.md b/README.md index 6e8c788..56f1c38 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Docker Series https://code-maze.com/docker-series/ -## Part 5 of the Docker Series on CodeMaze blog -https://code-maze.com/docker-hub-vs-creating-docker-registry/ +## Part 6 of the Docker Series on CodeMaze blog +https://code-maze.com/preparing-ci-environment-docker/ From 9e54efc3b9cdbf27d24d9e625f9ea7287b68e8c5 Mon Sep 17 00:00:00 2001 From: codemazeblog Date: Sun, 3 Jun 2018 23:04:14 +0200 Subject: [PATCH 08/12] Initial commit --- .gitignore | 8 ++-- AccountOwnerServer.sln | 16 ++++++- AccountOwnerServer/AccountOwnerServer.csproj | 9 ++++ Dockerfile | 16 ++++--- Dockerfile.Integration | 15 +++++++ Infrastructure/Registry/docker-compose.yml | 2 +- Infrastructure/TeamCity/agent/Dockerfile | 4 ++ Infrastructure/TeamCity/docker-compose.yml | 5 ++- Integration/Integration.csproj | 26 +++++++++++ Integration/IntegrationTests.cs | 47 ++++++++++++++++++++ Integration/TestContext.cs | 37 +++++++++++++++ README.md | 4 +- docker-compose.integration.yml | 32 +++++++++++++ 13 files changed, 207 insertions(+), 14 deletions(-) create mode 100644 Dockerfile.Integration create mode 100644 Infrastructure/TeamCity/agent/Dockerfile create mode 100644 Integration/Integration.csproj create mode 100644 Integration/IntegrationTests.cs create mode 100644 Integration/TestContext.cs create mode 100644 docker-compose.integration.yml diff --git a/.gitignore b/.gitignore index 3f49900..e710d6a 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,8 @@ publish /.vs /AccountOwnerServer/internallog.txt -/AccountOwnerServer/2018-04-24_logfile.txt -/AccountOwnerServer/AccountOwnerServer.csproj.user -/Integration/Integration.csproj.user +/Integration/obj +/Integration/bin +/AccountOwnerServer/*.user +/Tests/*.user +/Integration/*.user diff --git a/AccountOwnerServer.sln b/AccountOwnerServer.sln index 601977b..fff8a13 100644 --- a/AccountOwnerServer.sln +++ b/AccountOwnerServer.sln @@ -1,4 +1,4 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 +Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.27130.2010 MinimumVisualStudioVersion = 10.0.40219.1 @@ -14,6 +14,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Repository", "Repository\Re EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{89CF5113-7F84-40B8-A81C-B918F00183AD}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Integration", "Integration\Integration.csproj", "{35B4193F-04B2-4C75-BA9B-8221185D2F83}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -96,6 +98,18 @@ Global {89CF5113-7F84-40B8-A81C-B918F00183AD}.Release|x64.Build.0 = Release|Any CPU {89CF5113-7F84-40B8-A81C-B918F00183AD}.Release|x86.ActiveCfg = Release|Any CPU {89CF5113-7F84-40B8-A81C-B918F00183AD}.Release|x86.Build.0 = Release|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Debug|Any CPU.Build.0 = Debug|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Debug|x64.ActiveCfg = Debug|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Debug|x64.Build.0 = Debug|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Debug|x86.ActiveCfg = Debug|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Debug|x86.Build.0 = Debug|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Release|Any CPU.ActiveCfg = Release|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Release|Any CPU.Build.0 = Release|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Release|x64.ActiveCfg = Release|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Release|x64.Build.0 = Release|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Release|x86.ActiveCfg = Release|Any CPU + {35B4193F-04B2-4C75-BA9B-8221185D2F83}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/AccountOwnerServer/AccountOwnerServer.csproj b/AccountOwnerServer/AccountOwnerServer.csproj index b0d65a5..6a5cb7b 100644 --- a/AccountOwnerServer/AccountOwnerServer.csproj +++ b/AccountOwnerServer/AccountOwnerServer.csproj @@ -25,4 +25,13 @@ + + + PreserveNewest + + + PreserveNewest + + + diff --git a/Dockerfile b/Dockerfile index b9c2c3d..7c2aa52 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,16 +1,20 @@ FROM microsoft/aspnetcore-build as build-image WORKDIR /home/app - -COPY ./*.sln ./ -COPY ./*/*.csproj ./ -RUN for file in $(ls *.csproj); do mkdir -p ./${file%.*}/ && mv $file ./${file%.*}/; done - + +COPY ./AccountOwnerServer/AccountOwnerServer.csproj ./AccountOwnerServer/ +COPY ./Contracts/Contracts.csproj ./Contracts/ +COPY ./Repository/Repository.csproj ./Repository/ +COPY ./Entities/Entities.csproj ./Entities/ +COPY ./LoggerService/LoggerService.csproj ./LoggerService/ +COPY ./Tests/Tests.csproj ./Tests/ +COPY ./AccountOwnerServer.sln . + RUN dotnet restore COPY . . -RUN dotnet test ./Tests/Tests.csproj +RUN dotnet test --verbosity=normal ./Tests/Tests.csproj RUN dotnet publish ./AccountOwnerServer/AccountOwnerServer.csproj -o /publish/ diff --git a/Dockerfile.Integration b/Dockerfile.Integration new file mode 100644 index 0000000..88c3d4c --- /dev/null +++ b/Dockerfile.Integration @@ -0,0 +1,15 @@ +FROM microsoft/dotnet:2-sdk + +WORKDIR /home/app + +COPY ./*.sln ./ +COPY ./*/*.csproj ./ +RUN for file in $(ls *.csproj); do mkdir -p ./${file%.*}/ && mv $file ./${file%.*}/; done + +RUN dotnet restore + +COPY . . + +WORKDIR /home/app/Integration/ + +ENTRYPOINT ["dotnet", "test", "--verbosity=normal"] \ No newline at end of file diff --git a/Infrastructure/Registry/docker-compose.yml b/Infrastructure/Registry/docker-compose.yml index 3a8d11b..12a05cb 100644 --- a/Infrastructure/Registry/docker-compose.yml +++ b/Infrastructure/Registry/docker-compose.yml @@ -5,7 +5,7 @@ services: image: registry:latest container_name: my-registry volumes: - - registry:/var/lib/registry + - registry:/var/lib/registry3 ports: - "50000:5000" restart: unless-stopped diff --git a/Infrastructure/TeamCity/agent/Dockerfile b/Infrastructure/TeamCity/agent/Dockerfile new file mode 100644 index 0000000..0b1b82b --- /dev/null +++ b/Infrastructure/TeamCity/agent/Dockerfile @@ -0,0 +1,4 @@ +FROM jetbrains/teamcity-agent:latest + +RUN curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose \ + && chmod +x /usr/local/bin/docker-compose \ No newline at end of file diff --git a/Infrastructure/TeamCity/docker-compose.yml b/Infrastructure/TeamCity/docker-compose.yml index 8005572..56b4712 100644 --- a/Infrastructure/TeamCity/docker-compose.yml +++ b/Infrastructure/TeamCity/docker-compose.yml @@ -9,11 +9,14 @@ services: ports: - 8111:8111 teamcity-agent: - image: jetbrains/teamcity-agent:latest + image: codemazeblog/teamcity-agent-docker-compose:latest + build: ./agent environment: SERVER_URL: http://teamcity:8111 volumes: - teamcity-agent-conf:/data/teamcity_agent/conf + - /opt/buildagent/work:/opt/buildagent/work + - /opt/buildagent/temp:/opt/buildagent/temp - /var/run/docker.sock:/var/run/docker.sock volumes: diff --git a/Integration/Integration.csproj b/Integration/Integration.csproj new file mode 100644 index 0000000..a4bd719 --- /dev/null +++ b/Integration/Integration.csproj @@ -0,0 +1,26 @@ + + + + netcoreapp2.0 + + false + + + + + + + + + + + + + + + + + + + + diff --git a/Integration/IntegrationTests.cs b/Integration/IntegrationTests.cs new file mode 100644 index 0000000..ce62209 --- /dev/null +++ b/Integration/IntegrationTests.cs @@ -0,0 +1,47 @@ +using AccountOwnerServer; +using Entities.Models; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.Configuration; +using Newtonsoft.Json; +using System.Collections.Generic; +using System.Net; +using System.Threading.Tasks; +using Xunit; + +namespace Integration +{ + public class IntegrationTests + { + private readonly TestContext _context; + + public IntegrationTests() + { + _context = new TestContext(); + } + + [Fact] + public async Task GetAllOwners_ReturnsOkResponse() + { + // Act + var response = await _context.Client.GetAsync("/api/owner"); + response.EnsureSuccessStatusCode(); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } + + [Fact] + public async Task GetAllOwners_ReturnsAListOfOwners() + { + // Act + var response = await _context.Client.GetAsync("/api/owner"); + response.EnsureSuccessStatusCode(); + var responseString = await response.Content.ReadAsStringAsync(); + var owners = JsonConvert.DeserializeObject>(responseString); + + // Assert + Assert.NotEmpty(owners); + } + } +} diff --git a/Integration/TestContext.cs b/Integration/TestContext.cs new file mode 100644 index 0000000..33bc11b --- /dev/null +++ b/Integration/TestContext.cs @@ -0,0 +1,37 @@ +using AccountOwnerServer; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.Configuration; +using System; +using System.Net.Http; + +namespace Integration +{ + public class TestContext: IDisposable + { + private TestServer _server; + public HttpClient Client { get; private set; } + + public TestContext() + { + SetUpClient(); + } + + private void SetUpClient() + { + _server = new TestServer(new WebHostBuilder() + .UseConfiguration(new ConfigurationBuilder() + .AddJsonFile("appsettings.json") + .Build()) + .UseStartup()); + + Client = _server.CreateClient(); + } + + public void Dispose() + { + _server?.Dispose(); + Client?.Dispose(); + } + } +} diff --git a/README.md b/README.md index 56f1c38..2640ded 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Docker Series https://code-maze.com/docker-series/ -## Part 6 of the Docker Series on CodeMaze blog -https://code-maze.com/preparing-ci-environment-docker/ +## Part 7 of the Docker Series on CodeMaze blog +https://code-maze.com/ci-aspnetcoreapp-docker/ diff --git a/docker-compose.integration.yml b/docker-compose.integration.yml new file mode 100644 index 0000000..0727ec6 --- /dev/null +++ b/docker-compose.integration.yml @@ -0,0 +1,32 @@ +version: '3.1' + +services: + db: + image: mysql:5.7 + environment: + MYSQL_RANDOM_ROOT_PASSWORD: 1 + MYSQL_DATABASE: accountowner + MYSQL_USER: dbuser + MYSQL_PASSWORD: dbuserpassword + DEBUG: 1 + volumes: + - dbdata:/var/lib/mysql + - ./_MySQL_Init_Script:/docker-entrypoint-initdb.d + restart: always + accountownerapp: + depends_on: + - db + image: my-registry:50000/codemazeblog/accountownerapp:build-${BUILD_NUMBER_ACCOUNTOWNER} + build: + context: . + integration: + depends_on: + - accountownerapp + image: my-registry:50000/codemazeblog/accountownerapp:test + build: + context: . + dockerfile: Dockerfile.Integration + environment: + - TEAMCITY_PROJECT_NAME +volumes: + dbdata: \ No newline at end of file From 6e62390d609e0579bd026682995fab381121b93b Mon Sep 17 00:00:00 2001 From: codemazeblog Date: Mon, 4 Jun 2018 15:35:57 +0200 Subject: [PATCH 09/12] Added TEAMCITY_PROJECT_NAME env variable to Dockerfile --- Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dockerfile b/Dockerfile index 7c2aa52..2b067fc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,4 +24,6 @@ WORKDIR /publish COPY --from=build-image /publish . +ENV TEAMCITY_PROJECT_NAME = ${TEAMCITY_PROJECT_NAME} + ENTRYPOINT ["dotnet", "AccountOwnerServer.dll"] \ No newline at end of file From 29a6ef1bd15859ec2de2b2c227e52d0a3458ad20 Mon Sep 17 00:00:00 2001 From: codemazeblog Date: Thu, 7 Jun 2018 01:09:24 +0200 Subject: [PATCH 10/12] Dockerfile fixed --- Dockerfile | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2b067fc..e4ea5be 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,13 +2,9 @@ FROM microsoft/aspnetcore-build as build-image WORKDIR /home/app -COPY ./AccountOwnerServer/AccountOwnerServer.csproj ./AccountOwnerServer/ -COPY ./Contracts/Contracts.csproj ./Contracts/ -COPY ./Repository/Repository.csproj ./Repository/ -COPY ./Entities/Entities.csproj ./Entities/ -COPY ./LoggerService/LoggerService.csproj ./LoggerService/ -COPY ./Tests/Tests.csproj ./Tests/ -COPY ./AccountOwnerServer.sln . +COPY ./*.sln ./ +COPY ./*/*.csproj ./ +RUN for file in $(ls *.csproj); do mkdir -p ./${file%.*}/ && mv $file ./${file%.*}/; done RUN dotnet restore From 19b61d15640706c56fd6219e62386852df844c9e Mon Sep 17 00:00:00 2001 From: codemazeblog Date: Sun, 29 Jul 2018 10:12:38 +0200 Subject: [PATCH 11/12] Initial commit --- .gitignore | 1 + Dockerfile | 6 +- Infrastructure/TeamCity/agent/Dockerfile | 4 - Infrastructure/TeamCity/docker-compose.yml | 26 ------- Jenkinsfile | 25 ++++++ README.md | 4 +- docker-compose-registry.yml | 8 ++ docker-compose.ci.yml | 18 +++++ docker-compose.integration.yml | 6 +- jenkins-docker/master/Dockerfile | 14 ++++ jenkins-docker/master/default-user.groovy | 14 ++++ jenkins-docker/master/executors.groovy | 2 + jenkins-docker/slave/Dockerfile | 33 ++++++++ jenkins-docker/slave/slave.py | 90 ++++++++++++++++++++++ 14 files changed, 214 insertions(+), 37 deletions(-) delete mode 100644 Infrastructure/TeamCity/agent/Dockerfile delete mode 100644 Infrastructure/TeamCity/docker-compose.yml create mode 100644 Jenkinsfile create mode 100644 docker-compose-registry.yml create mode 100644 docker-compose.ci.yml create mode 100644 jenkins-docker/master/Dockerfile create mode 100644 jenkins-docker/master/default-user.groovy create mode 100644 jenkins-docker/master/executors.groovy create mode 100644 jenkins-docker/slave/Dockerfile create mode 100644 jenkins-docker/slave/slave.py diff --git a/.gitignore b/.gitignore index e710d6a..aa9d70d 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ publish /AccountOwnerServer/*.user /Tests/*.user /Integration/*.user +.vscode/settings.json diff --git a/Dockerfile b/Dockerfile index e4ea5be..16e6204 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,7 +10,7 @@ RUN dotnet restore COPY . . -RUN dotnet test --verbosity=normal ./Tests/Tests.csproj +RUN dotnet test --verbosity=normal --results-directory /TestResults/ --logger "trx;LogFileName=test_results.xml" ./Tests/Tests.csproj RUN dotnet publish ./AccountOwnerServer/AccountOwnerServer.csproj -o /publish/ @@ -20,6 +20,8 @@ WORKDIR /publish COPY --from=build-image /publish . +COPY --from=build-image /TestResults /TestResults + ENV TEAMCITY_PROJECT_NAME = ${TEAMCITY_PROJECT_NAME} -ENTRYPOINT ["dotnet", "AccountOwnerServer.dll"] \ No newline at end of file +ENTRYPOINT ["dotnet", "AccountOwnerServer.dll"] diff --git a/Infrastructure/TeamCity/agent/Dockerfile b/Infrastructure/TeamCity/agent/Dockerfile deleted file mode 100644 index 0b1b82b..0000000 --- a/Infrastructure/TeamCity/agent/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM jetbrains/teamcity-agent:latest - -RUN curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose \ - && chmod +x /usr/local/bin/docker-compose \ No newline at end of file diff --git a/Infrastructure/TeamCity/docker-compose.yml b/Infrastructure/TeamCity/docker-compose.yml deleted file mode 100644 index 56b4712..0000000 --- a/Infrastructure/TeamCity/docker-compose.yml +++ /dev/null @@ -1,26 +0,0 @@ -version: '3.1' - -services: - teamcity: - image: jetbrains/teamcity-server:latest - volumes: - - teamcity-server-datadir:/data/teamcity-server/datadir - - teamcity-server-logs:/opt/teamcity/logs - ports: - - 8111:8111 - teamcity-agent: - image: codemazeblog/teamcity-agent-docker-compose:latest - build: ./agent - environment: - SERVER_URL: http://teamcity:8111 - volumes: - - teamcity-agent-conf:/data/teamcity_agent/conf - - /opt/buildagent/work:/opt/buildagent/work - - /opt/buildagent/temp:/opt/buildagent/temp - - /var/run/docker.sock:/var/run/docker.sock - -volumes: - teamcity-server-datadir: - teamcity-server-logs: - teamcity-agent-conf: - \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..74521ba --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,25 @@ +node('docker') { + + stage 'Checkout' + checkout scm + stage 'Build & UnitTest' + sh "docker build -t accountownerapp:B${BUILD_NUMBER} -f Dockerfile ." + sh "docker build -t accountownerapp:test-B${BUILD_NUMBER} -f Dockerfile.Integration ." + + stage 'Pusblish UT Reports' + + containerID = sh ( + script: "docker run -d accountownerapp:B${BUILD_NUMBER}", + returnStdout: true + ).trim() + echo "Container ID is ==> ${containerID}" + sh "docker cp ${containerID}:/TestResults/test_results.xml test_results.xml" + sh "docker stop ${containerID}" + sh "docker rm ${containerID}" + step([$class: 'MSTestPublisher', failOnError: false, testResultsFile: 'test_results.xml']) + + stage 'Integration Test' + //sh 'docker-compose -f docker-compose.integration.yml up' + sh "docker-compose -f docker-compose.integration.yml up --force-recreate --abort-on-container-exit" + sh "docker-compose -f docker-compose.integration.yml down -v" +} diff --git a/README.md b/README.md index 2640ded..310e278 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Docker Series https://code-maze.com/docker-series/ -## Part 7 of the Docker Series on CodeMaze blog -https://code-maze.com/ci-aspnetcoreapp-docker/ +## Part 8 of the Docker Series on CodeMaze blog +https://code-maze.com/ci-jenkins-docker/ diff --git a/docker-compose-registry.yml b/docker-compose-registry.yml new file mode 100644 index 0000000..c1b218b --- /dev/null +++ b/docker-compose-registry.yml @@ -0,0 +1,8 @@ +version: '3.1' +services: + my-registry: + ports: + - '5000:5000' + restart: always + container_name: my-registry + image: 'registry:2' \ No newline at end of file diff --git a/docker-compose.ci.yml b/docker-compose.ci.yml new file mode 100644 index 0000000..c84ac12 --- /dev/null +++ b/docker-compose.ci.yml @@ -0,0 +1,18 @@ +version: '3.1' +services: + jenkins: + container_name: jenkins + ports: + - '8080:8080' + - '50000:50000' + image: localhost:5000/jenkins + jenkins-slave: + container_name: jenkins-slave + restart: always + environment: + - 'JENKINS_URL=http://jenkins:8080' + image: localhost:5000/jenkins-slave + volumes: + - /var/run/docker.sock:/var/run/docker.sock + depends_on: + - jenkins \ No newline at end of file diff --git a/docker-compose.integration.yml b/docker-compose.integration.yml index 0727ec6..f91b0f6 100644 --- a/docker-compose.integration.yml +++ b/docker-compose.integration.yml @@ -16,17 +16,17 @@ services: accountownerapp: depends_on: - db - image: my-registry:50000/codemazeblog/accountownerapp:build-${BUILD_NUMBER_ACCOUNTOWNER} + image: "accountownerapp:B${BUILD_NUMBER}" build: context: . integration: depends_on: - accountownerapp - image: my-registry:50000/codemazeblog/accountownerapp:test + image: "accountownerapp:test-B${BUILD_NUMBER}" build: context: . dockerfile: Dockerfile.Integration environment: - TEAMCITY_PROJECT_NAME volumes: - dbdata: \ No newline at end of file + dbdata: diff --git a/jenkins-docker/master/Dockerfile b/jenkins-docker/master/Dockerfile new file mode 100644 index 0000000..a7ecd22 --- /dev/null +++ b/jenkins-docker/master/Dockerfile @@ -0,0 +1,14 @@ +FROM jenkins/jenkins:latest + +RUN /usr/local/bin/install-plugins.sh git mstest matrix-auth workflow-aggregator docker-workflow blueocean credentials-binding + +ENV JENKINS_USER admin +ENV JENKINS_PASS admin + +# Skip initial setup +ENV JAVA_OPTS -Djenkins.install.runSetupWizard=false + +COPY executors.groovy /usr/share/jenkins/ref/init.groovy.d/ +COPY default-user.groovy /usr/share/jenkins/ref/init.groovy.d/ + +VOLUME /var/jenkins_home diff --git a/jenkins-docker/master/default-user.groovy b/jenkins-docker/master/default-user.groovy new file mode 100644 index 0000000..8d786fe --- /dev/null +++ b/jenkins-docker/master/default-user.groovy @@ -0,0 +1,14 @@ +import jenkins.model.* +import hudson.security.* + +def env = System.getenv() + +def jenkins = Jenkins.getInstance() +jenkins.setSecurityRealm(new HudsonPrivateSecurityRealm(false)) +jenkins.setAuthorizationStrategy(new GlobalMatrixAuthorizationStrategy()) + +def user = jenkins.getSecurityRealm().createAccount(env.JENKINS_USER, env.JENKINS_PASS) +user.save() + +jenkins.getAuthorizationStrategy().add(Jenkins.ADMINISTER, env.JENKINS_USER) +jenkins.save() diff --git a/jenkins-docker/master/executors.groovy b/jenkins-docker/master/executors.groovy new file mode 100644 index 0000000..0f6f064 --- /dev/null +++ b/jenkins-docker/master/executors.groovy @@ -0,0 +1,2 @@ +import jenkins.model.* +Jenkins.instance.setNumExecutors(0) diff --git a/jenkins-docker/slave/Dockerfile b/jenkins-docker/slave/Dockerfile new file mode 100644 index 0000000..ddcaccf --- /dev/null +++ b/jenkins-docker/slave/Dockerfile @@ -0,0 +1,33 @@ +FROM ubuntu:16.04 + +# Install Docker CLI +RUN apt-get update && apt-get install -y apt-transport-https ca-certificates +RUN apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D +RUN echo "deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable" > /etc/apt/sources.list.d/docker.list +RUN apt-get update && apt-get install -y docker-ce --allow-unauthenticated + +RUN apt-get update && apt-get install -y openjdk-8-jre curl python python-pip git +RUN easy_install jenkins-webapi + +# Get docker-compose in the agent container + +RUN curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose && chmod +x /usr/local/bin/docker-compose +RUN mkdir -p /home/jenkins +RUN mkdir -p /var/lib/jenkins + +ADD slave.py /var/lib/jenkins/slave.py + +WORKDIR /home/jenkins + +ENV JENKINS_URL "http://jenkins" +ENV JENKINS_SLAVE_ADDRESS "" +ENV JENKINS_USER "admin" +ENV JENKINS_PASS "admin" +ENV SLAVE_NAME "" +ENV SLAVE_SECRET "" +ENV SLAVE_EXECUTORS "1" +ENV SLAVE_LABELS "docker" +ENV SLAVE_WORING_DIR "" +ENV CLEAN_WORKING_DIR "true" + +CMD [ "python", "-u", "/var/lib/jenkins/slave.py" ] diff --git a/jenkins-docker/slave/slave.py b/jenkins-docker/slave/slave.py new file mode 100644 index 0000000..855d9f2 --- /dev/null +++ b/jenkins-docker/slave/slave.py @@ -0,0 +1,90 @@ +from jenkins import Jenkins, JenkinsError, NodeLaunchMethod +import os +import signal +import sys +import urllib +import subprocess +import shutil +import requests +import time + +slave_jar = '/var/lib/jenkins/slave.jar' +slave_name = os.environ['SLAVE_NAME'] if os.environ['SLAVE_NAME'] != '' else 'docker-slave-' + os.environ['HOSTNAME'] +jnlp_url = os.environ['JENKINS_URL'] + '/computer/' + slave_name + '/slave-agent.jnlp' +slave_jar_url = os.environ['JENKINS_URL'] + '/jnlpJars/slave.jar' +print(slave_jar_url) +process = None + +def clean_dir(dir): + for root, dirs, files in os.walk(dir): + for f in files: + os.unlink(os.path.join(root, f)) + for d in dirs: + shutil.rmtree(os.path.join(root, d)) + +def slave_create(node_name, working_dir, executors, labels): + j = Jenkins(os.environ['JENKINS_URL'], os.environ['JENKINS_USER'], os.environ['JENKINS_PASS']) + j.node_create(node_name, working_dir, num_executors = int(executors), labels = labels, launcher = NodeLaunchMethod.JNLP) + +def slave_delete(node_name): + j = Jenkins(os.environ['JENKINS_URL'], os.environ['JENKINS_USER'], os.environ['JENKINS_PASS']) + j.node_delete(node_name) + +def slave_download(target): + if os.path.isfile(slave_jar): + os.remove(slave_jar) + + loader = urllib.URLopener() + loader.retrieve(os.environ['JENKINS_URL'] + '/jnlpJars/slave.jar', '/var/lib/jenkins/slave.jar') + +def slave_run(slave_jar, jnlp_url): + params = [ 'java', '-jar', slave_jar, '-jnlpUrl', jnlp_url ] + if os.environ['JENKINS_SLAVE_ADDRESS'] != '': + params.extend([ '-connectTo', os.environ['JENKINS_SLAVE_ADDRESS' ] ]) + + if os.environ['SLAVE_SECRET'] == '': + params.extend([ '-jnlpCredentials', os.environ['JENKINS_USER'] + ':' + os.environ['JENKINS_PASS'] ]) + else: + params.extend([ '-secret', os.environ['SLAVE_SECRET'] ]) + return subprocess.Popen(params, stdout=subprocess.PIPE) + +def signal_handler(sig, frame): + if process != None: + process.send_signal(signal.SIGINT) + +signal.signal(signal.SIGINT, signal_handler) +signal.signal(signal.SIGTERM, signal_handler) + +def master_ready(url): + try: + r = requests.head(url, verify=False, timeout=None) + return r.status_code == requests.codes.ok + except: + return False + +while not master_ready(slave_jar_url): + print("Master not ready yet, sleeping for 10sec!") + time.sleep(10) + +slave_download(slave_jar) +print 'Downloaded Jenkins slave jar.' + +if os.environ['SLAVE_WORING_DIR']: + os.setcwd(os.environ['SLAVE_WORING_DIR']) + +if os.environ['CLEAN_WORKING_DIR'] == 'true': + clean_dir(os.getcwd()) + print "Cleaned up working directory." + +if os.environ['SLAVE_NAME'] == '': + slave_create(slave_name, os.getcwd(), os.environ['SLAVE_EXECUTORS'], os.environ['SLAVE_LABELS']) + print 'Created temporary Jenkins slave.' + +process = slave_run(slave_jar, jnlp_url) +print 'Started Jenkins slave with name "' + slave_name + '" and labels [' + os.environ['SLAVE_LABELS'] + '].' +process.wait() + +print 'Jenkins slave stopped.' +if os.environ['SLAVE_NAME'] == '': + slave_delete(slave_name) + print 'Removed temporary Jenkins slave.' From 150d269f1a000c83f89ae11c973f7348df9f98a2 Mon Sep 17 00:00:00 2001 From: Vladimir Pecanac Date: Thu, 24 Jan 2019 15:31:43 +0100 Subject: [PATCH 12/12] Fixed a security issue in ASP.NET Core --- AccountOwnerServer/AccountOwnerServer.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AccountOwnerServer/AccountOwnerServer.csproj b/AccountOwnerServer/AccountOwnerServer.csproj index 6a5cb7b..ec84190 100644 --- a/AccountOwnerServer/AccountOwnerServer.csproj +++ b/AccountOwnerServer/AccountOwnerServer.csproj @@ -9,7 +9,7 @@ - +