Skip to content

Commit a25a634

Browse files
authored
feat(web-operator): add conversion webhooks (#639)
This closes #137. This adds the preview version of conversion webhooks. The API is not stable yet and changes may happen in the future. They require the preview features flag to be set. BREAKING CHANGE: The CLI (which broke anyway...) does now generate everyting together and determines based on the project if there are webhooks or not. This results in one config folder instead of separate folders for CRD, RBAC, etc. With this, conversion webhooks can inject their configuration into the CRDs. Otherwise, this would be a cumbersome process. If the need for single topic generation arises again (for example only CRDs), then these generators can be added again.
1 parent 7aea3cd commit a25a634

File tree

74 files changed

+1498
-1166
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+1498
-1166
lines changed

.github/workflows/dotnet-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@ jobs:
2525
uses: helm/[email protected]
2626

2727
- name: Execute Tests
28-
run: dotnet test --configuration Release
28+
run: dotnet test --configuration ${{ runner.debug == '1' && 'Debug' || 'Release' }}

KubeOps.sln

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KubeOps.KubernetesClient",
4949
EndProject
5050
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KubeOps.KubernetesClient.Test", "test\KubeOps.KubernetesClient.Test\KubeOps.KubernetesClient.Test.csproj", "{25F767E5-7A74-459B-83CC-39519461F38B}"
5151
EndProject
52-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebhookOperator", "examples\WebhookOperator\WebhookOperator.csproj", "{4AD46831-1326-4711-83D0-6D7B4AF403DB}"
52+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConversionWebhookOperator", "examples\ConversionWebhookOperator\ConversionWebhookOperator.csproj", "{4AD46831-1326-4711-83D0-6D7B4AF403DB}"
5353
EndProject
5454
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KubeOps.Transpiler", "src\KubeOps.Transpiler\KubeOps.Transpiler.csproj", "{7229B71C-C5A5-41E0-85DB-A331A945703C}"
5555
EndProject
5656
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KubeOps.Transpiler.Test", "test\KubeOps.Transpiler.Test\KubeOps.Transpiler.Test.csproj", "{7F7744B2-CF3F-4309-9C2D-037278017D49}"
5757
EndProject
58+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebhookOperator", "examples\WebhookOperator\WebhookOperator.csproj", "{0BFE2297-9537-49BE-8B1F-431A8ACD654D}"
59+
EndProject
5860
Global
5961
GlobalSection(SolutionConfigurationPlatforms) = preSolution
6062
Debug|Any CPU = Debug|Any CPU
@@ -79,6 +81,7 @@ Global
7981
{4AD46831-1326-4711-83D0-6D7B4AF403DB} = {DC760E69-D0EA-417F-AE38-B12D0B04DE39}
8082
{7229B71C-C5A5-41E0-85DB-A331A945703C} = {4DB01062-6DC5-4028-BB72-C0619C2F5F2E}
8183
{7F7744B2-CF3F-4309-9C2D-037278017D49} = {C587731F-8191-4A19-8662-B89A60FE79A1}
84+
{0BFE2297-9537-49BE-8B1F-431A8ACD654D} = {DC760E69-D0EA-417F-AE38-B12D0B04DE39}
8285
EndGlobalSection
8386
GlobalSection(ProjectConfigurationPlatforms) = postSolution
8487
{E9A0B04E-D90E-4B94-90E0-DD3666B098FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@@ -141,5 +144,9 @@ Global
141144
{7F7744B2-CF3F-4309-9C2D-037278017D49}.Debug|Any CPU.Build.0 = Debug|Any CPU
142145
{7F7744B2-CF3F-4309-9C2D-037278017D49}.Release|Any CPU.ActiveCfg = Release|Any CPU
143146
{7F7744B2-CF3F-4309-9C2D-037278017D49}.Release|Any CPU.Build.0 = Release|Any CPU
147+
{0BFE2297-9537-49BE-8B1F-431A8ACD654D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
148+
{0BFE2297-9537-49BE-8B1F-431A8ACD654D}.Debug|Any CPU.Build.0 = Debug|Any CPU
149+
{0BFE2297-9537-49BE-8B1F-431A8ACD654D}.Release|Any CPU.ActiveCfg = Release|Any CPU
150+
{0BFE2297-9537-49BE-8B1F-431A8ACD654D}.Release|Any CPU.Build.0 = Release|Any CPU
144151
EndGlobalSection
145152
EndGlobal
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using KubeOps.Abstractions.Controller;
2+
using KubeOps.Abstractions.Rbac;
3+
4+
using ConversionWebhookOperator.Entities;
5+
6+
namespace ConversionWebhookOperator.Controller;
7+
8+
[EntityRbac(typeof(V1TestEntity), Verbs = RbacVerb.All)]
9+
public class V1TestEntityController(ILogger<V1TestEntityController> logger) : IEntityController<V1TestEntity>
10+
{
11+
public Task ReconcileAsync(V1TestEntity entity)
12+
{
13+
logger.LogInformation("Reconciling entity {Entity}.", entity);
14+
return Task.CompletedTask;
15+
}
16+
17+
public Task DeletedAsync(V1TestEntity entity)
18+
{
19+
logger.LogInformation("Deleted entity {Entity}.", entity);
20+
return Task.CompletedTask;
21+
}
22+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<EnablePreviewFeatures>true</EnablePreviewFeatures>
8+
<IsPackable>false</IsPackable>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<ProjectReference Include="..\..\src\KubeOps.Generator\KubeOps.Generator.csproj"
13+
OutputItemType="Analyzer"
14+
ReferenceOutputAssembly="false" />
15+
<ProjectReference Include="..\..\src\KubeOps.Operator.Web\KubeOps.Operator.Web.csproj" />
16+
</ItemGroup>
17+
18+
<!-- <PropertyGroup>-->
19+
<!-- <KubeOpsCli>dotnet run &#45;&#45;project ../../src/KubeOps.Cli/ &#45;&#45; </KubeOpsCli>-->
20+
<!-- </PropertyGroup>-->
21+
<!-- <Import Project="..\..\src\KubeOps.Operator\Build\KubeOps.Operator.targets" />-->
22+
23+
</Project>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using k8s.Models;
2+
3+
using KubeOps.Abstractions.Entities;
4+
5+
namespace ConversionWebhookOperator.Entities;
6+
7+
[KubernetesEntity(Group = "conversionwebhook.dev", ApiVersion = "v1", Kind = "TestEntity")]
8+
public partial class V1TestEntity : CustomKubernetesEntity<V1TestEntity.EntitySpec>
9+
{
10+
public override string ToString() => $"Test Entity v1 ({Metadata.Name}): {Spec.Name}";
11+
12+
public class EntitySpec
13+
{
14+
public string Name { get; set; } = string.Empty;
15+
}
16+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using k8s.Models;
2+
3+
using KubeOps.Abstractions.Entities;
4+
5+
namespace ConversionWebhookOperator.Entities;
6+
7+
[KubernetesEntity(Group = "conversionwebhook.dev", ApiVersion = "v2", Kind = "TestEntity")]
8+
public partial class V2TestEntity : CustomKubernetesEntity<V2TestEntity.EntitySpec>
9+
{
10+
public override string ToString() => $"Test Entity v2 ({Metadata.Name}): {Spec.Firstname} {Spec.Lastname}";
11+
12+
public class EntitySpec
13+
{
14+
public string Firstname { get; set; } = string.Empty;
15+
16+
public string Lastname { get; set; } = string.Empty;
17+
}
18+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using k8s.Models;
2+
3+
using KubeOps.Abstractions.Entities;
4+
5+
namespace ConversionWebhookOperator.Entities;
6+
7+
[KubernetesEntity(Group = "conversionwebhook.dev", ApiVersion = "v3", Kind = "TestEntity")]
8+
public partial class V3TestEntity : CustomKubernetesEntity<V3TestEntity.EntitySpec>
9+
{
10+
public override string ToString() => $"Test Entity v3 ({Metadata.Name}): {Spec.Firstname} {Spec.MiddleName} {Spec.Lastname}";
11+
12+
public class EntitySpec
13+
{
14+
public string Firstname { get; set; } = string.Empty;
15+
16+
public string Lastname { get; set; } = string.Empty;
17+
18+
public string? MiddleName { get; set; }
19+
}
20+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
apiVersion: conversionwebhook.dev/v1
2+
kind: TestEntity
3+
metadata:
4+
name: v1-entity
5+
spec:
6+
name: Max Muster
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using KubeOps.Operator;
2+
using KubeOps.Operator.Web.Builder;
3+
4+
var builder = WebApplication.CreateBuilder(args);
5+
builder.Services
6+
.AddKubernetesOperator()
7+
.RegisterComponents()
8+
#if DEBUG
9+
.AddDevelopmentTunnel(5000)
10+
#endif
11+
;
12+
13+
builder.Services
14+
.AddControllers();
15+
16+
var app = builder.Build();
17+
18+
app.UseRouting();
19+
app.UseDeveloperExceptionPage();
20+
app.MapControllers();
21+
22+
await app.RunAsync();
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"profiles": {
3+
"ConversionWebhookOperator": {
4+
"commandName": "Project",
5+
"dotnetRunMessages": true,
6+
"applicationUrl": "http://localhost:5000",
7+
"environmentVariables": {
8+
"ASPNETCORE_ENVIRONMENT": "Development"
9+
}
10+
}
11+
}
12+
}

0 commit comments

Comments
 (0)