Add unit tests for KubernetesCluster, Tenant, ServiceInstance, and RegisterClusterHandler
- Implement tests for KubernetesCluster including registration, connectivity status, and error handling. - Create tests for Tenant creation, member management, and status changes. - Add tests for ServiceInstance provisioning and state management. - Introduce RegisterClusterHandler tests to validate registration requests and error scenarios. - Set up project files for new test projects with necessary dependencies.
This commit is contained in:
114
.github/copilot-instructions.md
vendored
114
.github/copilot-instructions.md
vendored
@@ -400,60 +400,91 @@ If the service or project you are working on does not have a corresponding test
|
||||
|
||||
## Architecture
|
||||
|
||||
### Modular Monolith with Blazor
|
||||
### Microservices with Blazor BFF
|
||||
|
||||
EntKube is a **modular monolith** — a single deployable Blazor application with clearly separated domain modules internally. This keeps deployment simple while maintaining clean boundaries between concerns.
|
||||
EntKube follows a **microservices architecture** with a Blazor BFF (Backend-for-Frontend) as the user-facing entry point. Each service owns its bounded context, has its own data store, and can be deployed and scaled independently. This is NOT a nano-services architecture — we split by meaningful business boundaries, not by technical layers.
|
||||
|
||||
#### Core Principles
|
||||
- **Domain modules within one application**: Each business capability (cluster management, service provisioning, tenant management, etc.) lives in its own namespace/folder but deploys as part of the single application
|
||||
- **Clear module boundaries**: Modules communicate through well-defined interfaces — never reach directly into another module's internals
|
||||
- **Shared database with schema separation**: The single application owns its database, but each module owns its tables/schema area
|
||||
- **Extract to a service only when necessary**: If a module genuinely needs independent scaling or a separate lifecycle, extract it then — not before
|
||||
- **4 services, each with a clear responsibility**: Web (BFF), Clusters, Provisioning, Identity
|
||||
- **Each service owns its data**: No shared databases between services
|
||||
- **Services communicate via HTTP APIs**: Simple REST calls between services, with resilient retry policies
|
||||
- **SharedKernel for contracts only**: Shared types (Result, ApiResponse, base Entity) live in a shared library — but no shared business logic
|
||||
- **Feature folders over layer folders**: Each feature is a vertical slice (handler + endpoint + related types in one folder)
|
||||
|
||||
#### When to Extract a Module to a Separate Service
|
||||
- The module has drastically different scaling requirements
|
||||
- The module needs to be deployed on a different cadence
|
||||
- The module introduces an external integration that benefits from fault isolation
|
||||
#### Service Boundaries
|
||||
|
||||
| Service | Responsibility | Port (dev) |
|
||||
|---------|---------------|-------------|
|
||||
| **EntKube.Web** | Blazor BFF — serves UI, proxies API calls to backend services, owns user auth session | 5000 |
|
||||
| **EntKube.Clusters** | Kubernetes cluster registration, health monitoring, API connectivity | 5010 |
|
||||
| **EntKube.Provisioning** | Shared service lifecycle (MinIO, CNPG, Keycloak) — provisioning, reconciliation, teardown | 5020 |
|
||||
| **EntKube.Identity** | Tenant management, user membership, roles, Keycloak integration | 5030 |
|
||||
|
||||
#### Anti-Patterns to Avoid
|
||||
```
|
||||
# ❌ BAD: Premature microservices for a platform that deploys as one unit
|
||||
Services/
|
||||
├── ClusterService/
|
||||
├── TenantService/
|
||||
├── MonitoringService/
|
||||
└── ProvisioningService/ # All deployed together anyway
|
||||
# ❌ BAD: Nano-services — splitting too granularly
|
||||
MinIOService/
|
||||
CloudNativePGService/
|
||||
KeycloakService/
|
||||
HealthCheckService/ # These belong together under "Provisioning"
|
||||
|
||||
# ✅ GOOD: Modules within the monolith with clear boundaries
|
||||
EntKube/
|
||||
├── Clusters/ # Cluster management module
|
||||
├── Tenants/ # Multi-tenant module
|
||||
├── Monitoring/ # Observability module
|
||||
├── Provisioning/ # Service provisioning module
|
||||
└── Shared/ # Cross-cutting concerns
|
||||
# ❌ BAD: Shared database between services
|
||||
# Services must own their own data — cross-service queries go through APIs
|
||||
|
||||
# ✅ GOOD: Meaningful service boundaries with feature folders
|
||||
src/
|
||||
├── EntKube.Web/ # Blazor BFF
|
||||
├── EntKube.Clusters/ # Cluster management service
|
||||
│ ├── Domain/ # Aggregates, value objects, repository contracts
|
||||
│ ├── Features/ # Vertical slices (RegisterCluster/, GetClusters/, etc.)
|
||||
│ └── Infrastructure/ # Repository implementations, external integrations
|
||||
├── EntKube.Provisioning/ # Service provisioning service
|
||||
│ ├── Domain/
|
||||
│ ├── Features/
|
||||
│ └── Infrastructure/
|
||||
├── EntKube.Identity/ # Identity & tenant service
|
||||
│ ├── Domain/
|
||||
│ ├── Features/
|
||||
│ └── Infrastructure/
|
||||
└── EntKube.SharedKernel/ # Shared contracts (Result, ApiResponse, base Entity)
|
||||
```
|
||||
|
||||
### Project Structure
|
||||
```
|
||||
Solution/
|
||||
├── EntKube/ # Blazor Server host (BFF)
|
||||
│ ├── Components/ # Razor components, layouts, pages
|
||||
│ ├── Data/ # EF Core DbContext and migrations
|
||||
│ ├── Clusters/ # Kubernetes cluster management
|
||||
│ ├── Provisioning/ # Shared service provisioning (MinIO, CNPG, Keycloak)
|
||||
│ ├── Tenants/ # Multi-tenant configuration
|
||||
│ ├── Monitoring/ # Health, metrics, observability
|
||||
│ └── Pipelines/ # CI/CD pipeline integration
|
||||
├── EntKube.Client/ # Blazor WebAssembly client
|
||||
│ ├── Pages/ # Interactive WASM pages
|
||||
│ └── wwwroot/ # Client static assets
|
||||
├── Charts/ # Helm charts for deployment
|
||||
├── src/
|
||||
│ ├── EntKube.SharedKernel/ # Shared types and contracts between services
|
||||
│ │ ├── Domain/ # Result, Entity base class
|
||||
│ │ └── Contracts/ # ApiResponse envelope, DTOs
|
||||
│ ├── EntKube.Web/ # Blazor Server BFF
|
||||
│ │ ├── Components/ # Razor components, layouts, pages
|
||||
│ │ ├── Data/ # EF Core DbContext (Identity only)
|
||||
│ │ └── wwwroot/ # Static assets
|
||||
│ ├── EntKube.Web.Client/ # Blazor WebAssembly client
|
||||
│ │ └── Pages/ # Interactive WASM pages
|
||||
│ ├── EntKube.Clusters/ # Cluster management API
|
||||
│ │ ├── Domain/ # KubernetesCluster aggregate
|
||||
│ │ ├── Features/ # RegisterCluster/, GetClusters/
|
||||
│ │ └── Infrastructure/ # Repository implementations
|
||||
│ ├── EntKube.Provisioning/ # Service provisioning API
|
||||
│ │ ├── Domain/ # ServiceInstance aggregate
|
||||
│ │ ├── Features/ # ProvisionService/, GetServices/
|
||||
│ │ └── Infrastructure/ # Repository implementations
|
||||
│ └── EntKube.Identity/ # Identity & tenant API
|
||||
│ ├── Domain/ # Tenant aggregate
|
||||
│ ├── Features/ # CreateTenant/
|
||||
│ └── Infrastructure/ # Repository implementations
|
||||
├── tests/
|
||||
│ ├── EntKube.Clusters.Tests/ # Unit + integration tests
|
||||
│ ├── EntKube.Provisioning.Tests/
|
||||
│ ├── EntKube.Identity.Tests/
|
||||
│ └── EntKube.Web.Tests/
|
||||
├── Charts/ # Helm charts for deployment
|
||||
│ └── entkube/
|
||||
│ ├── Chart.yaml
|
||||
│ ├── values.yaml
|
||||
│ └── templates/
|
||||
└── Tests/
|
||||
└── *.Tests/ # xUnit test projects
|
||||
└── .gitea/workflows/ # Gitea Actions CI/CD
|
||||
```
|
||||
|
||||
### Deployment & Infrastructure
|
||||
@@ -511,10 +542,11 @@ jobs:
|
||||
```
|
||||
|
||||
### Communication Patterns
|
||||
- Internal module communication via dependency injection and in-process calls
|
||||
- Kubernetes API communication for cluster management operations
|
||||
- HTTP APIs exposed for external integrations
|
||||
- Use resilient connections with retry policies (Polly) for external calls
|
||||
- **Service-to-service**: HTTP REST via typed HttpClient with Polly retry policies
|
||||
- **BFF-to-service**: The Web BFF proxies user requests to the appropriate backend service
|
||||
- **Kubernetes API**: The Clusters service communicates with k8s API servers using the official .NET client
|
||||
- **Async workflows**: Background services within each microservice handle reconciliation loops (e.g., provisioning, health checks)
|
||||
- **No message bus yet**: Start with synchronous HTTP; extract to async messaging (NATS, RabbitMQ) only when proven necessary
|
||||
|
||||
### Database
|
||||
|
||||
|
||||
Reference in New Issue
Block a user