From ff79b236721161b8a78be6da989e347929ba522f Mon Sep 17 00:00:00 2001
From: Patrick Evers
Date: Mon, 19 Jan 2026 15:33:23 +0100
Subject: [PATCH 1/4] Cleanup
---
README.md | 429 +++++++++++++++---
examples/SimpleOperator/Dockerfile | 1 +
examples/SimpleOperator/Program.cs | 11 +-
.../Properties/launchSettings.json | 20 +-
examples/SimpleOperator/SimpleOperator.csproj | 2 +
.../Builder/ControllerBuilder.cs | 2 +
src/K8sOperator.NET/Commands/CreateCommand.cs | 37 ++
.../Commands/GenerateDockerfileCommand.cs | 167 +++----
.../Commands/GenerateLaunchSettingsCommand.cs | 4 +-
.../Commands/InstallCommand.cs | 67 +--
.../Commands/VersionCommand.cs | 10 +-
src/K8sOperator.NET/EventWatcher.cs | 73 +--
.../Generation/ClusterRoleBindingBuilder.cs | 14 -
.../ClusterRoleBindingBuilderExtensions.cs | 4 +-
.../Generation/ClusterRoleBuilder.cs | 14 -
.../ClusterRoleBuilderExtensions.cs | 4 +-
.../Generation/ContainerBuilder.cs | 8 -
.../CustomResourceDefinitionBuilder.cs | 15 -
...stomResourceDefinitionBuilderExtensions.cs | 54 +--
.../Generation/DeploymentBuilder.cs | 27 --
.../Generation/DeploymentBuilderExtensions.cs | 79 ++--
.../Generation/KubernetesObjectBuilder.cs | 38 +-
.../KubernetesObjectBuilderExtentions.cs | 6 +-
.../KubernetesObjectBuilderWithMetaData.cs | 24 -
...etesObjectBuilderWithMetadataExtentions.cs | 3 +-
.../Generation/LeaseBuilderExtensions.cs | 53 +++
.../Generation/MetadataExtensions.cs | 213 ++++-----
.../Generation/PolicyRuleBuilder.cs | 8 -
.../Generation/PolicyRuleBuilderExtensions.cs | 6 +-
src/K8sOperator.NET/ILeaderElectionService.cs | 13 +
src/K8sOperator.NET/K8sOperator.NET.csproj | 7 +-
src/K8sOperator.NET/LaunchSettings.json | 37 --
src/K8sOperator.NET/LeaderLectionService.cs | 139 ++++++
.../Metadata/FinalizerAttribute.cs | 2 +-
.../Metadata/LabelSelectorAttribute.cs | 2 +
.../Metadata/ScopedAttribute.cs | 13 +
src/K8sOperator.NET/Operator.targets | 8 +-
src/K8sOperator.NET/OperatorExtensions.cs | 38 +-
src/K8sOperator.NET/OperatorService.cs | 52 +++
.../Templates/.dockerignore.template | 48 ++
.../Templates/Dockerfile.template | 45 ++
.../K8sOperator.NET.Target.Tests.csproj | 6 +-
.../Properties/launchSettings.json | 47 +-
.../OperatorExtensions_Tests.cs | 6 +-
44 files changed, 1208 insertions(+), 648 deletions(-)
create mode 100644 src/K8sOperator.NET/Commands/CreateCommand.cs
delete mode 100644 src/K8sOperator.NET/Generation/ClusterRoleBindingBuilder.cs
delete mode 100644 src/K8sOperator.NET/Generation/ClusterRoleBuilder.cs
delete mode 100644 src/K8sOperator.NET/Generation/ContainerBuilder.cs
delete mode 100644 src/K8sOperator.NET/Generation/CustomResourceDefinitionBuilder.cs
delete mode 100644 src/K8sOperator.NET/Generation/DeploymentBuilder.cs
delete mode 100644 src/K8sOperator.NET/Generation/KubernetesObjectBuilderWithMetaData.cs
create mode 100644 src/K8sOperator.NET/Generation/LeaseBuilderExtensions.cs
delete mode 100644 src/K8sOperator.NET/Generation/PolicyRuleBuilder.cs
create mode 100644 src/K8sOperator.NET/ILeaderElectionService.cs
delete mode 100644 src/K8sOperator.NET/LaunchSettings.json
create mode 100644 src/K8sOperator.NET/LeaderLectionService.cs
create mode 100644 src/K8sOperator.NET/Metadata/ScopedAttribute.cs
create mode 100644 src/K8sOperator.NET/Templates/.dockerignore.template
create mode 100644 src/K8sOperator.NET/Templates/Dockerfile.template
diff --git a/README.md b/README.md
index 23a6cae..6509777 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# K8sOperator.NET
+# K8sOperator.NET


@@ -7,7 +7,6 @@

[](https://github.com/pmdevers/K8sOperator.NET/actions/workflows/security-analysis.yml)
-
K8sOperator.NET is a powerful and intuitive library designed for creating Kubernetes Operators using C#. It simplifies the development of robust, cloud-native operators by leveraging the full capabilities of the .NET ecosystem, making it easier than ever to manage complex Kubernetes workloads with custom automation.

@@ -16,117 +15,431 @@ K8sOperator.NET is a powerful and intuitive library designed for creating Kubern
- [Features](#features)
- [Installation](#installation)
+- [Quick Start](#quick-start)
- [Usage](#usage)
+ - [Creating a Custom Resource](#creating-a-custom-resource)
+ - [Implementing a Controller](#implementing-a-controller)
+ - [Setting Up the Operator](#setting-up-the-operator)
+- [Commands](#commands)
- [Configuration](#configuration)
+ - [MSBuild Properties](#msbuild-properties)
+ - [Auto-Generated Files](#auto-generated-files)
+- [Docker Support](#docker-support)
- [Contributing](#contributing)
- [License](#license)
## Features
-- Easy integration
+- 🚀 **Easy Integration** - Simple, intuitive API for building Kubernetes operators
+- 🎯 **Custom Resource Support** - Built-in support for Custom Resource Definitions (CRDs)
+- 🔄 **Automatic Reconciliation** - Event-driven reconciliation with finalizer support
+- 📦 **MSBuild Integration** - Automatic generation of manifests, Docker files, and launch settings
+- 🐳 **Docker Ready** - Generate optimized Dockerfiles with best practices
+- 🛠️ **Built-in Commands** - Help, version, install, and code generation commands
+- 🔐 **Security First** - Non-root containers, RBAC support, and security best practices
+- 📝 **Source Generators** - Compile-time generation of boilerplate code
+- 🎨 **Flexible Configuration** - MSBuild properties for operator customization
+- 🧪 **Testable** - Built with testing in mind
## Installation
-To install the package, use the following command in your .NET Core project:
+To install K8sOperator.NET, add the package to your .NET project:
```bash
dotnet add package K8sOperator.NET
-dotnet add package K8sOperator.NET.Generators
```
-Alternatively, you can add it manually to your `.csproj` file:
+Or add it manually to your `.csproj` file:
```xml
-
-
+
+```
+
+## Quick Start
+
+Create a new ASP.NET Core Web Application and add K8sOperator.NET:
+
+```bash
+dotnet new web -n MyOperator
+cd MyOperator
+dotnet add package K8sOperator.NET
+```
+
+Update your `Program.cs`:
+
+```csharp
+using K8sOperator.NET;
+
+var builder = WebApplication.CreateBuilder(args);
+builder.Services.AddOperator();
+
+var app = builder.Build();
+
+// Map your controllers here
+// app.MapController();
+
+await app.RunOperatorAsync();
```
## Usage
-Here are some basic examples of how to use the library:
+### Creating a Custom Resource
+
+Define your custom resource by inheriting from `CustomResource`:
+
+```csharp
+using K8sOperator.NET;
+
+[KubernetesEntity(
+ Group = "example.com",
+ ApiVersion = "v1",
+ Kind = "MyResource",
+ PluralName = "myresources")]
+public class MyResource : CustomResource
+{
+ public class MySpec
+ {
+ public string Name { get; set; } = string.Empty;
+ public int Replicas { get; set; } = 1;
+ }
+
+ public class MyStatus
+ {
+ public string Phase { get; set; } = "Pending";
+ public DateTime? LastUpdated { get; set; }
+ }
+}
+```
+
+### Implementing a Controller
+
+Create a controller to handle your custom resource:
-### Setup
+```csharp
+using K8sOperator.NET;
+using Microsoft.Extensions.Logging;
+
+public class MyController : OperatorController
+{
+ private readonly ILogger _logger;
+
+ public MyController(ILogger logger)
+ {
+ _logger = logger;
+ }
+
+ public override async Task AddOrModifyAsync(
+ MyResource resource,
+ CancellationToken cancellationToken)
+ {
+ _logger.LogInformation(
+ "Reconciling {Name} with {Replicas} replicas",
+ resource.Spec.Name,
+ resource.Spec.Replicas);
+
+ // Your reconciliation logic here
+ resource.Status = new MyResource.MyStatus
+ {
+ Phase = "Running",
+ LastUpdated = DateTime.UtcNow
+ };
+
+ await Task.CompletedTask;
+ }
+
+ public override async Task DeleteAsync(
+ MyResource resource,
+ CancellationToken cancellationToken)
+ {
+ _logger.LogInformation("Deleting {Name}", resource.Metadata.Name);
+
+ // Cleanup logic here
+ await Task.CompletedTask;
+ }
+
+ public override async Task FinalizeAsync(
+ MyResource resource,
+ CancellationToken cancellationToken)
+ {
+ _logger.LogInformation("Finalizing {Name}", resource.Metadata.Name);
+
+ // Finalization logic here
+ await Task.CompletedTask;
+ }
+}
+```
+
+### Setting Up the Operator
+
+Wire everything together in `Program.cs`:
```csharp
using K8sOperator.NET;
+using MyOperator;
-var builder = OperatorHost.CreateOperatorApplicationBuilder(args);
+var builder = WebApplication.CreateBuilder(args);
-builder.AddController()
- .WithFinalizer("project.local.finalizer");
+// Add operator services
+builder.Services.AddOperator();
var app = builder.Build();
-app.AddInstall();
+// Map the controller to watch MyResource
+app.MapController();
+
+// Run the operator
+await app.RunOperatorAsync();
+```
+
+## Commands
+
+K8sOperator.NET includes several built-in commands:
+
+| Command | Description | Availability |
+|---------|-------------|--------------|
+| `operator` | Run the operator (watches for resources) | All builds |
+| `install` | Generate Kubernetes installation manifests | All builds |
+| `version` | Display version information | All builds |
+| `help` | Show available commands | All builds |
+| `generate-launchsettings` | Generate Visual Studio launch profiles | Debug only |
+| `generate-dockerfile` | Generate optimized Dockerfile | Debug only |
+
+**Note:** The `generate-*` commands are development tools and are only available in Debug builds. They are automatically excluded from Release builds to keep your production operator lean.
-await app.RunAsync();
+### Running Commands
+```bash
+# Run the operator
+dotnet run -- operator
+
+# Generate installation manifests
+dotnet run -- install > install.yaml
+
+# Show version
+dotnet run -- version
+
+# Generate launch settings (Debug only)
+dotnet run -c Debug -- generate-launchsettings
+
+# Generate Dockerfile (Debug only)
+dotnet run -c Debug -- generate-dockerfile
```
-### add custom launchSettings.json
+## Configuration
-```json
+### MSBuild Properties
+
+K8sOperator.NET uses MSBuild properties to configure your operator. Add these to your `.csproj` file:
+
+```xml
+
+
+ my-operator
+ my-namespace
+
+
+ ghcr.io
+ myorg/my-operator
+ 1.0.0
+ alpine
+
+
+ true
+ true
+
+```
+
+#### Available Properties
+
+| Property | Default | Description |
+|----------|---------|-------------|
+| `OperatorName` | `{project-name}` | Name of the operator |
+| `OperatorNamespace` | `{project-name}-system` | Kubernetes namespace |
+| `ContainerRegistry` | `ghcr.io` | Container registry URL |
+| `ContainerRepository` | `{Company}/{OperatorName}` | Repository path |
+| `ContainerImageTag` | `{Version}` | Image tag |
+| `ContainerFamily` | (empty) | Image variant (e.g., `alpine`, `distroless`) |
+| `CreateOperatorLaunchSettings` | `false` | Auto-generate launch profiles |
+| `GenerateOperatorDockerfile` | `false` | Auto-generate Dockerfile |
+### Auto-Generated Files
+
+When enabled, K8sOperator.NET automatically generates:
+
+#### 1. Assembly Attributes
+
+Metadata is embedded in your assembly:
+
+```csharp
+[assembly: OperatorNameAttribute("my-operator")]
+[assembly: NamespaceAttribute("my-namespace")]
+[assembly: DockerImageAttribute("ghcr.io", "myorg/my-operator", "1.0.0-alpine")]
+```
+
+#### 2. Launch Settings (`Properties/launchSettings.json`)
+
+Visual Studio launch profiles for all registered commands:
+
+```json
{
- "profiles": {
- "Operator": {
- "commandName": "Project",
- "commandLineArgs": "operator",
- "environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "Development"
- },
- "dotnetRunMessages": true
- },
- "Install": {
- "commandName": "Project",
- "commandLineArgs": "install > ./install.yaml",
- "environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "Development"
- },
- "dotnetRunMessages": true
- },
- "Help": {
- "commandName": "Project",
- "commandLineArgs": "",
- "environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "Development"
- },
- "dotnetRunMessages": true
- },
- "Version": {
- "commandName": "Project",
- "commandLineArgs": "version",
- "environmentVariables": {
- "ASPNETCORE_ENVIRONMENT": "Development"
- },
- "dotnetRunMessages": true
- }
+ "profiles": {
+ "Operator": {
+ "commandName": "Project",
+ "commandLineArgs": "operator",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
},
- "$schema": "http://json.schemastore.org/launchsettings.json"
+ "Install": {
+ "commandName": "Project",
+ "commandLineArgs": "install > ./install.yaml"
+ }
+ }
}
+```
+#### 3. Dockerfile
+
+Optimized multi-stage Dockerfile with security best practices:
+
+```dockerfile
+FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
+WORKDIR /src
+COPY ["MyOperator.csproj", "./"]
+RUN dotnet restore
+COPY . .
+RUN dotnet publish -c Release -o /app/publish
+
+FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS final
+WORKDIR /app
+RUN groupadd -r operator && useradd -r -g operator operator
+COPY --from=build /app/publish .
+RUN chown -R operator:operator /app
+USER operator
+ENTRYPOINT ["dotnet", "MyOperator.dll"]
+CMD ["operator"]
```
-## Configuration
+#### 4. .dockerignore
+
+Optimized Docker ignore file to reduce image size.
+
+## Docker Support
-By running the `Install` profile will create the install.yaml file in the root of the project. This file can be used to install the operator in a Kubernetes cluster.
+### Building Docker Images
+
+K8sOperator.NET generates production-ready Dockerfiles with:
+
+- ✅ Multi-stage builds for smaller images
+- ✅ Non-root user for security
+- ✅ Health checks
+- ✅ .NET 10 runtime
+- ✅ Optimized layer caching
+
+Generate a Dockerfile:
+
+```bash
+dotnet run -- generate-dockerfile
+```
+
+Build the image:
+
+```bash
+docker build -t ghcr.io/myorg/my-operator:1.0.0 .
+```
+
+Push to registry:
+
+```bash
+docker push ghcr.io/myorg/my-operator:1.0.0
+```
+
+### Installing in Kubernetes
+
+Generate installation manifests:
+
+```bash
+dotnet run -- install > install.yaml
+```
+
+The generated manifest includes:
+- Custom Resource Definitions (CRDs)
+- ServiceAccount
+- ClusterRole and ClusterRoleBinding
+- Deployment
+
+Apply to your cluster:
-Run the following command to install the operator:
```bash
kubectl apply -f install.yaml
```
+### Verify Installation
+
+```bash
+# Check if operator is running
+kubectl get pods -n my-namespace
+
+# View operator logs
+kubectl logs -n my-namespace deployment/my-operator -f
+
+# Check CRDs
+kubectl get crds
+
+# Create a custom resource
+kubectl apply -f my-resource.yaml
+```
+
+
## Contributing
Contributions are welcome! Please feel free to submit a pull request or open an issue if you encounter any bugs or have feature requests.
+### Development Setup
+
+1. Clone the repository
+ ```bash
+ git clone https://github.com/pmdevers/K8sOperator.NET.git
+ cd K8sOperator.NET
+ ```
+
+2. Build the solution
+ ```bash
+ dotnet build
+ ```
+
+3. Run tests
+ ```bash
+ dotnet test
+ ```
+
+4. Run the example operator
+ ```bash
+ cd examples/SimpleOperator
+ dotnet run -- operator
+ ```
+
+### Contribution Guidelines
+
1. Fork the repository
-2. Create your feature branch (`git checkout -b feature/fooBar`)
-3. Commit your changes (`git commit -am 'Add some fooBar'`)
-4. Push to the branch (`git push origin feature/fooBar`)
-5. Create a new Pull Request
+2. Create your feature branch (`git checkout -b feature/amazing-feature`)
+3. Commit your changes (`git commit -m 'Add some amazing feature'`)
+4. Push to the branch (`git push origin feature/amazing-feature`)
+5. Open a Pull Request
+
+Please ensure:
+- ✅ All tests pass
+- ✅ Code follows existing style conventions
+- ✅ New features include tests
+- ✅ Documentation is updated
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE.md) file for details.
+
+---
+
+**Built with ❤️ using .NET 10**
+
+For more examples and documentation, visit the [GitHub repository](https://github.com/pmdevers/K8sOperator.NET).
diff --git a/examples/SimpleOperator/Dockerfile b/examples/SimpleOperator/Dockerfile
index 22d9682..1d097e8 100644
--- a/examples/SimpleOperator/Dockerfile
+++ b/examples/SimpleOperator/Dockerfile
@@ -42,3 +42,4 @@ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
# Entrypoint
ENTRYPOINT ["dotnet", "SimpleOperator.dll"]
CMD ["operator"]
+
diff --git a/examples/SimpleOperator/Program.cs b/examples/SimpleOperator/Program.cs
index a44848d..551631c 100644
--- a/examples/SimpleOperator/Program.cs
+++ b/examples/SimpleOperator/Program.cs
@@ -1,12 +1,19 @@
using K8sOperator.NET;
+using K8sOperator.NET.Generation;
using SimpleOperator.Controllers;
var builder = WebApplication.CreateBuilder(args);
-builder.Services.AddOperator();
+builder.Services.AddOperator(x =>
+{
+ //x.LeaderElection.Add(x => x.Enabled = true);
+ x.LeaderElection.Add(x => x.LeaseNamespace = "default");
+});
var app = builder.Build();
-app.MapController();
+app.MapController()
+ .WithNamespaceScope();
+//.WithFinalizer("todo.example.com/finalizer");
await app.RunOperatorAsync();
diff --git a/examples/SimpleOperator/Properties/launchSettings.json b/examples/SimpleOperator/Properties/launchSettings.json
index d9d9d4e..bda3e33 100644
--- a/examples/SimpleOperator/Properties/launchSettings.json
+++ b/examples/SimpleOperator/Properties/launchSettings.json
@@ -9,24 +9,32 @@
"dotnetRunMessages": true
},
"Operator": {
+ "commandName": "Project",
+ "commandLineArgs": "operator",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "dotnetRunMessages": true
+ },
+ "Install": {
"commandName": "Project",
- "commandLineArgs": "operator",
+ "commandLineArgs": "install",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true
},
- "Install": {
+ "Version": {
"commandName": "Project",
- "commandLineArgs": "install",
+ "commandLineArgs": "version",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true
},
- "Version": {
+ "Create": {
"commandName": "Project",
- "commandLineArgs": "version",
+ "commandLineArgs": "create",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
@@ -50,4 +58,4 @@
}
},
"schema": "http://json.schemastore.org/launchsettings.json"
-}
\ No newline at end of file
+}
diff --git a/examples/SimpleOperator/SimpleOperator.csproj b/examples/SimpleOperator/SimpleOperator.csproj
index 878d5ca..712f7b1 100644
--- a/examples/SimpleOperator/SimpleOperator.csproj
+++ b/examples/SimpleOperator/SimpleOperator.csproj
@@ -16,8 +16,10 @@
simple-operator
simple-system
+
alpha
diff --git a/src/K8sOperator.NET/Builder/ControllerBuilder.cs b/src/K8sOperator.NET/Builder/ControllerBuilder.cs
index c3d4acc..4c04173 100644
--- a/src/K8sOperator.NET/Builder/ControllerBuilder.cs
+++ b/src/K8sOperator.NET/Builder/ControllerBuilder.cs
@@ -28,3 +28,5 @@ public IOperatorController Build()
}
public List