init k8s guide

This commit is contained in:
2023-08-25 17:20:30 +02:00
parent e1a53522e5
commit d3f2d706f2
2 changed files with 274 additions and 6 deletions

View File

@ -1129,7 +1129,7 @@ Damn, I think we're done 🎉 ! It's time retest the full process. Add new contr
{{< highlight host="kuberocks-demo" file="src/KubeRocks.WebApi/Controllers/WeatherForecastController.cs" >}}
```csharp
```cs
//...
public class WeatherForecastController : ControllerBase
{

View File

@ -12,11 +12,279 @@ Be free from AWS/Azure/GCP by building a production grade On-Premise Kubernetes
This is the **Part VIII** of more global topic tutorial. [Back to first part]({{< ref "/posts/10-build-your-own-kubernetes-cluster" >}}) for intro.
1. Real DB App sample
2. Production grade deployment (liveness, readiness, healthcheck, resource limits, logging)
3. Unit Testing
4. SonarQube
5. CodeCoverage
## Real DB App sample
Before go any further, let's add some DB usage to our sample app. We'll use the classical `Articles<->Authors<->Comments` relationships. First create `docker-compose.yml` file in root of demo project:
{{< highlight host="kuberocks-demo" file="docker-compose.yml" >}}
```yaml
version: "3"
services:
db:
image: postgres:15
environment:
POSTGRES_USER: main
POSTGRES_PASSWORD: main
POSTGRES_DB: main
ports:
- 5432:5432
db_test:
image: postgres:15
environment:
POSTGRES_USER: main
POSTGRES_PASSWORD: main
POSTGRES_DB: main
ports:
- 54320:5432
```
{{< /highlight >}}
Here we create 2 PostgreSQL instances, one for local development and one for integration testing. Launch them with `docker compose up -d` and check they are both running with `docker ps`.
Time to create basic code that list plenty of articles from an API endpoint. Go back to `kuberocks-demo` and create a new separate project dedicated to app logic:
```sh
dotnet new classlib -o src/KubeRocks.Application
dotnet sln add src/KubeRocks.Application
dotnet add src/KubeRocks.WebApi reference src/KubeRocks.Application
dotnet add src/KubeRocks.Application package Microsoft.EntityFrameworkCore
dotnet add src/KubeRocks.Application package Npgsql.EntityFrameworkCore.PostgreSQL
dotnet add src/KubeRocks.WebApi package Microsoft.EntityFrameworkCore.Design
```
{{< alert >}}
This is not a DDD course ! We will keep it simple and focus on Kubernetes part.
{{< /alert >}}
### Define the entities
{{< highlight host="kuberocks-demo" file="src/KubeRocks.Application/Entities/Article.cs" >}}
```cs
using System.ComponentModel.DataAnnotations;
namespace KubeRocks.Application.Entities;
public class Article
{
public int Id { get; set; }
public required User Author { get; set; }
[MaxLength(255)]
public required string Title { get; set; }
[MaxLength(255)]
public required string Slug { get; set; }
public required string Description { get; set; }
public required string Body { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
public ICollection<Comment> Comments { get; } = new List<Comment>();
}
```
{{< /highlight >}}
{{< highlight host="kuberocks-demo" file="src/KubeRocks.Application/Entities/Comment.cs" >}}
```cs
namespace KubeRocks.Application.Entities;
public class Comment
{
public int Id { get; set; }
public required Article Article { get; set; }
public required User Author { get; set; }
public required string Body { get; set; }
public DateTime CreatedAt { get; set; }
}
```
{{< /highlight >}}
{{< highlight host="kuberocks-demo" file="src/KubeRocks.Application/Entities/User.cs" >}}
```cs
using System.ComponentModel.DataAnnotations;
namespace KubeRocks.Application.Entities;
public class User
{
public int Id { get; set; }
[MaxLength(255)]
public required string Username { get; set; }
[MaxLength(255)]
public required string Email { get; set; }
public ICollection<Article> Articles { get; } = new List<Article>();
public ICollection<Comment> Comments { get; } = new List<Comment>();
}
```
{{< /highlight >}}
{{< highlight host="kuberocks-demo" file="src/KubeRocks.Application/Contexts/AppDbContext.cs" >}}
```cs
namespace KubeRocks.Application.Contexts;
using KubeRocks.Application.Entities;
using Microsoft.EntityFrameworkCore;
public class AppDbContext : DbContext
{
public DbSet<User> Users => Set<User>();
public DbSet<Article> Articles => Set<Article>();
public DbSet<Comment> Comments => Set<Comment>();
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>()
.HasIndex(u => u.Email).IsUnique()
;
modelBuilder.Entity<Article>()
.HasIndex(u => u.Slug).IsUnique()
;
}
}
```
{{< /highlight >}}
{{< highlight host="kuberocks-demo" file="src/KubeRocks.Application/Extensions/ServiceExtensions.cs" >}}
```cs
using KubeRocks.Application.Contexts;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace KubeRocks.Application.Extensions;
public static class ServiceExtensions
{
public static IServiceCollection AddKubeRocksServices(this IServiceCollection services, IConfiguration configuration)
{
return services.AddDbContext<AppDbContext>((options) =>
{
options.UseNpgsql(configuration.GetConnectionString("DefaultConnection"));
});
}
}
```
{{< /highlight >}}
{{< highlight host="kuberocks-demo" file="src/KubeRocks.WebApi/Program.cs" >}}
```cs
using KubeRocks.Application.Extensions;
//...
// Add services to the container.
builder.Services.AddKubeRocksServices(builder.Configuration);
//...
```
{{< /highlight >}}
{{< highlight host="kuberocks-demo" file="src/KubeRocks.WebApi/appsettings.Development.json" >}}
```json
{
//...
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Port=5432;User Id=main;Password=main;Database=main;"
}
}
```
{{< /highlight >}}
Now as all models are created, we can generate migrations and update database accordingly:
```sh
dotnet new tool-manifest
dotnet tool install dotnet-ef
dotnet dotnet-ef -p src/KubeRocks.Application -s src/KubeRocks.WebApi migrations add InitialCreate
dotnet dotnet-ef -p src/KubeRocks.Application -s src/KubeRocks.WebApi database update
```
### Inject some dummy data
```sh
dotnet new console -o src/KubeRocks.Console
dotnet sln add src/KubeRocks.Console
dotnet add src/KubeRocks.WebApi reference src/KubeRocks.Application
dotnet add src/KubeRocks.Console package Bogus
dotnet add src/KubeRocks.Console package ConsoleAppFramework
dotnet add src/KubeRocks.Console package Respawn
```
{{< highlight host="kuberocks-demo" file="src/KubeRocks.Console/appsettings.json" >}}
```json
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Port=5432;User Id=main;Password=main;Database=main;"
}
}
```
{{< /highlight >}}
{{< highlight host="kuberocks-demo" file="src/KubeRocks.Console/Commands/SeederCommand" >}}
```cs
```
{{< /highlight >}}
### Define endpoint access
## Production grade deployment
### Liveness & readiness
(liveness, readiness, resource limits, logging)
## Unit & integration Testing
### xUnit
### CI configuration
## Code Metrics
### SonarQube installation
### Project configuration
### Code Coverage
## 7th check ✅