KubeOps.Generator
13.0.0-prerelease.3
See the version list below for details.
dotnet add package KubeOps.Generator --version 13.0.0-prerelease.3
NuGet\Install-Package KubeOps.Generator -Version 13.0.0-prerelease.3
<PackageReference Include="KubeOps.Generator" Version="13.0.0-prerelease.3"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="KubeOps.Generator" Version="13.0.0-prerelease.3" />
<PackageReference Include="KubeOps.Generator"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add KubeOps.Generator --version 13.0.0-prerelease.3
#r "nuget: KubeOps.Generator, 13.0.0-prerelease.3"
#:package KubeOps.Generator@13.0.0-prerelease.3
#addin nuget:?package=KubeOps.Generator&version=13.0.0-prerelease.3&prerelease
#tool nuget:?package=KubeOps.Generator&version=13.0.0-prerelease.3&prerelease
KubeOps Generator
This is a C# source generator for KubeOps and operators. It is used to generate convenience functions to help register resources within an operator.
Motivation
The primary goal of this generator is to reduce boilerplate code required in your operator's Program.cs (or startup logic). Instead of manually calling builder.AddController<...>() and builder.AddFinalizer<...>() for every component, the generator scans your project and creates extension methods that register all discovered components with a single call.
Usage
The generator is automatically used when the KubeOps.Generator package is referenced.
dotnet add package KubeOps.Generator
which results in the following csproj reference:
<ItemGroup>
<PackageReference Include="KubeOps.Generator" Version="...">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
Once referenced, you typically use the main generated extension method in your Program.cs:
using KubeOps.Operator;
var builder = WebApplication.CreateBuilder(args);
// Add KubeOps services and register all discovered components
builder.Services
.AddKubernetesOperator()
.RegisterComponents(); // <--- Generated extension method
// ... other service registrations
var app = builder.Build();
// ... configure middleware
app.RunOperatorAsync();
Generated Sources
The generator will automatically generate functions for the IOperatorBuilder.
By default, all shared classes (EntityDefinitions, EntityInitializer,
ControllerRegistrations, FinalizerRegistrations, OperatorBuilderExtensions) are generated
into the global namespace. Two general rules apply:
ControllerRegistrations/FinalizerRegistrations/EntityDefinitions/EntityInitializerare only generated when the compilation actually contains matching components.OperatorBuilderExtensions(theRegisterComponentsaggregate) andEntityInitializerareinternal: they are only meaningful for the compilation they are generated into.
Configuring the Target Namespace
When multiple projects of one solution reference the generator (e.g. a class library with
controllers and the operator itself), the generated class names must not conflict. Set the
KubeOpsGeneratorNamespace MSBuild property in the participating projects to generate the shared
classes into a distinct namespace instead of the global namespace:
<PropertyGroup>
<KubeOpsGeneratorNamespace>$(RootNamespace)</KubeOpsGeneratorNamespace>
</PropertyGroup>
Any namespace works ($(RootNamespace), $(AssemblyName) or a literal); invalid characters are
sanitized. Note that top-level Program.cs files then need a using directive for the configured
namespace so that RegisterComponents() resolves.
Multi-Assembly Composition
Controllers and finalizers may live in referenced class libraries that also use the generator.
Every assembly that contains such components is marked with an assembly-level
KubeOps.Abstractions.Builder.KubeOpsGeneratedRegistrationsAttribute pointing to its (public)
registration classes. These classes register only the components of their own assembly and
never chain into further assemblies.
The generated RegisterComponents method of the consuming compilation discovers these markers on
all transitively referenced assemblies and invokes every registration class exactly once via a
fully qualified call:
using KubeOps.Abstractions.Builder;
[assembly: global::KubeOps.Abstractions.Builder.KubeOpsGeneratedRegistrations("MyOperator.ControllerRegistrations", "MyOperator.FinalizerRegistrations")]
namespace MyOperator;
internal static class OperatorBuilderExtensions
{
public static IOperatorBuilder RegisterComponents(this IOperatorBuilder builder)
{
builder.RegisterControllers();
builder.RegisterFinalizers();
global::MyLibrary.ControllerRegistrations.RegisterControllers(builder);
return builder;
}
}
This flat, deduplicated composition guarantees that no component is registered twice, regardless of how the assemblies reference each other (e.g. app → LibA → LibB with components in all three).
If two assemblies in the chain generate registration classes with the same fully qualified name
(e.g. both use the global namespace default), the generator reports the warning KOG002
and skips the conflicting registration instead of emitting ambiguous code. Set
KubeOpsGeneratorNamespace in the conflicting projects to resolve it.
Entity Metadata / Entity Definitions
The generator creates a file named EntityDefinitions.g.cs (only when the compilation declares
entities). This file contains all entities that are annotated with the
KubernetesEntityAttribute and declared in the compilation itself - entities from referenced
assemblies are listed by their declaring assembly. The static class contains the
EntityMetadata for the entities.
Example
using KubeOps.Abstractions.Builder;
using KubeOps.Abstractions.Entities;
public static class EntityDefinitions
{
public static readonly EntityMetadata V1TestEntity = new("TestEntity", "v1", "testing.dev", null);
public static IOperatorBuilder RegisterEntities(this IOperatorBuilder builder)
{
builder.AddEntity<global::Operator.Entities.V1TestEntity>(V1TestEntity);
return builder;
}
}
Entity Initializer
All entities must have their Kind and ApiVersion fields set.
To achieve this, the generator creates an initializer file for each entity
that is annotated with the KubernetesEntityAttribute.
For each partial class that does not contain a default constructor,
the generator will create a default constructor that sets the Kind and ApiVersion fields.
For each non-partial class, a method extension is created that sets
the Kind and ApiVersion fields.
NOTE: Setting your class as partial is crucial for the generator to create the constructor. Also, if a default constructor is already present, the generator uses the method extension fallback.
Example
namespace Operator.Entities;
[KubernetesEntity(Group = "testing.dev", ApiVersion = "v1", Kind = "TestEntity")]
public partial class V1TestEntity : CustomKubernetesEntity
{
}
The partial defined entity above will generate the following V1TestEntity.init.g.cs file:
namespace Operator.Entities;
public partial class V1TestEntity
{
public V1TestEntity()
{
ApiVersion = "testing.dev/v1";
Kind = "TestEntity";
}
}
The non-partial defined entity below:
namespace Operator.Entities;
[KubernetesEntity(Group = "testing.dev", ApiVersion = "v1", Kind = "TestEntity")]
public class V1TestEntity : CustomKubernetesEntity
{
}
will generate a static method extension in EntityInitializer.g.cs
for the entity to initialize the fields:
public static class EntityInitializer
{
public static global::Operator.Entities.V1ClusterTestEntity Initialize(this global::Operator.Entities.V1ClusterTestEntity entity)
{
entity.ApiVersion = "testing.dev/v1";
entity.Kind = "ClusterTestEntity";
return entity;
}
}
Controller Registrations
The generator creates a file named ControllerRegistrations.g.cs (only when the compilation
contains controllers). This file contains a function to register all found controllers
(i.e., classes that implement the IResourceController<TEntity> interface).
Example
using KubeOps.Abstractions.Builder;
public static class ControllerRegistrations
{
public static IOperatorBuilder RegisterControllers(this IOperatorBuilder builder)
{
builder.AddController<global::Operator.Controller.V1TestEntityController, global::Operator.Entities.V1TestEntity>();
return builder;
}
}
Finalizer Registrations
The generator creates a file named FinalizerRegistrations.g.cs (only when the compilation
contains finalizers). This file contains all finalizers with generated finalizer identifiers.
Further, a function to register all finalizers (i.e., classes that implement IResourceFinalizer<TEntity>) is generated.
Example
using KubeOps.Abstractions.Builder;
public static class FinalizerRegistrations
{
public const string FinalizerOneIdentifier = "testing.dev/finalizeronefinalizer";
public const string FinalizerTwoIdentifier = "testing.dev/finalizertwofinalizer";
public static IOperatorBuilder RegisterFinalizers(this IOperatorBuilder builder)
{
builder.AddFinalizer<global::Operator.Finalizer.FinalizerOne, global::Operator.Entities.V1TestEntity>(FinalizerOneIdentifier);
builder.AddFinalizer<global::Operator.Finalizer.FinalizerTwo, global::Operator.Entities.V1TestEntity>(FinalizerTwoIdentifier);
return builder;
}
}
General Operator Extensions
The generator creates a file named OperatorBuilder.g.cs. It contains the internal
RegisterComponents convenience method that registers all generated sources: the components of
the own compilation (only the parts that exist) and the components of all marked referenced
assemblies (see Multi-Assembly Composition).
Example
using KubeOps.Abstractions.Builder;
[assembly: global::KubeOps.Abstractions.Builder.KubeOpsGeneratedRegistrations("ControllerRegistrations", "FinalizerRegistrations")]
internal static class OperatorBuilderExtensions
{
public static IOperatorBuilder RegisterComponents(this IOperatorBuilder builder)
{
builder.RegisterControllers();
builder.RegisterFinalizers();
return builder;
}
}
Troubleshooting
- Generated files not visible? Source generators add files during the build process. They might not appear directly in your Visual Studio Solution Explorer unless you explicitly look in the
obj/Debug/netX.Y/generated/KubeOps.Generatorfolder or use features like VS's "Show all files". - Changes not picked up? If you add a new controller/finalizer/webhook and it's not being registered, ensure your project compiles successfully and try rebuilding the solution.
- Entity Initializer not working? Make sure your entity class is marked as
partialand does not have an explicitly defined parameterless constructor if you want the generator to create one.
Learn more about Target Frameworks and .NET Standard.
This package has no dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories (1)
Showing the top 1 popular GitHub repositories that depend on KubeOps.Generator:
| Repository | Stars |
|---|---|
|
josephnhtam/live-streaming-server-net
A .NET implementation of RTMP live streaming server, supporting HTTP-FLV, WebSocket-FLV, HLS, Kubernetes, cloud storage services integration and more.
|
| Version | Downloads | Last Updated |
|---|---|---|
| 13.0.0 | 0 | 7/14/2026 |
| 13.0.0-prerelease.6 | 0 | 7/14/2026 |
| 13.0.0-prerelease.5 | 43 | 7/12/2026 |
| 13.0.0-prerelease.4 | 42 | 7/11/2026 |
| 13.0.0-prerelease.3 | 41 | 7/11/2026 |
| 13.0.0-prerelease.2 | 40 | 7/11/2026 |
| 13.0.0-prerelease.1 | 48 | 7/11/2026 |
| 12.1.0-prerelease.1 | 45 | 7/10/2026 |
| 12.0.1-prerelease.2 | 53 | 7/9/2026 |
| 12.0.1-prerelease.1 | 44 | 7/8/2026 |
| 12.0.0 | 255 | 7/7/2026 |
| 11.6.0-prerelease.1 | 61 | 7/3/2026 |
| 11.5.1-prerelease.2 | 59 | 7/2/2026 |
| 11.5.1-prerelease.1 | 56 | 7/2/2026 |
| 11.5.0 | 925 | 6/30/2026 |
| 11.5.0-prerelease.6 | 62 | 6/28/2026 |
| 11.5.0-prerelease.5 | 58 | 6/28/2026 |
| 11.5.0-prerelease.4 | 69 | 6/27/2026 |
| 11.5.0-prerelease.3 | 74 | 6/25/2026 |
| 11.5.0-prerelease.2 | 89 | 6/24/2026 |
'## [13.0.0-prerelease.3](https://github.com/dotnet/dotnet-operator-sdk/compare/v13.0.0-prerelease.2...v13.0.0-prerelease.3) (2026-07-11)
### Dependencies
* **ci:** update dependency semantic-release to v25.0.6 ([#1189](https://github.com/dotnet/dotnet-operator-sdk/issues/1189)) ([a83e7c2](https://github.com/dotnet/dotnet-operator-sdk/commit/a83e7c2fb9e235203ecfe2f0a3a7f7e27c6bfe38))
* **core:** update dependency sonaranalyzer.csharp to 10.29.0.143774 ([#1191](https://github.com/dotnet/dotnet-operator-sdk/issues/1191)) ([72a0d87](https://github.com/dotnet/dotnet-operator-sdk/commit/72a0d872a7be1ad9fb30a18da30323d4d3a8bea7))
'