-
Notifications
You must be signed in to change notification settings - Fork 1
Rewritten #85
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rewritten #85
Changes from all commits
a9987e2
ec22793
1a46742
51158bc
ec90520
c7093c9
4ef3029
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| <Solution> | ||
| <Folder Name="/examples/"> | ||
| <Project Path="examples/SimpleOperator/SimpleOperator.csproj" Id="ed579abf-9eb5-4f74-95e3-8f4ac03f760a" /> | ||
| </Folder> | ||
| <Folder Name="/src/"> | ||
| <Project Path="src/K8sOperator.NET/K8sOperator.NET.csproj" /> | ||
| </Folder> | ||
| <Folder Name="/test/"> | ||
| <Project Path="test/K8sOperator.NET.Target.Tests/K8sOperator.NET.Target.Tests.csproj" /> | ||
| <Project Path="test/K8sOperator.NET.Tests/K8sOperator.NET.Tests.csproj" /> | ||
| </Folder> | ||
| </Solution> |
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <Project> | ||
| <!-- Import the parent Directory.Build.props if it exists --> | ||
| <Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" | ||
| Condition="Exists($([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../')))"/> | ||
|
|
||
| <!-- For example projects that reference K8sOperator.NET as a project reference --> | ||
| <Import Project="$(MSBuildThisFileDirectory)..\src\K8sOperator.NET\Operator.targets" | ||
| Condition="Exists('$(MSBuildThisFileDirectory)..\src\K8sOperator.NET\Operator.targets')" /> | ||
| </Project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| # Git | ||
| .git | ||
| .gitignore | ||
| .gitattributes | ||
|
|
||
| # Build results | ||
| bin/ | ||
| obj/ | ||
| [Bb]uild/ | ||
| [Dd]ebug/ | ||
| [Rr]elease/ | ||
|
|
||
| # Visual Studio | ||
| .vs/ | ||
| .vscode/ | ||
| *.user | ||
| *.suo | ||
| *.userosscache | ||
| *.sln.docstates | ||
|
|
||
| # Test results | ||
| [Tt]est[Rr]esult*/ | ||
| [Bb]uild[Ll]og.* | ||
| TestResults/ | ||
|
|
||
| # NuGet | ||
| *.nupkg | ||
| *.snupkg | ||
| packages/ | ||
|
|
||
| # Docker | ||
| Dockerfile | ||
| .dockerignore | ||
|
|
||
| # Kubernetes | ||
| *.yaml | ||
| *.yml | ||
|
|
||
| # Documentation | ||
| *.md | ||
| README* | ||
| LICENSE | ||
|
|
||
| # IDE | ||
| .idea/ | ||
| *.swp | ||
| *.swo | ||
| *~ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| using K8sOperator.NET; | ||
| using SimpleOperator.Resources; | ||
|
|
||
| namespace SimpleOperator.Controllers; | ||
|
|
||
| public class TodoController : OperatorController<TodoItem> | ||
| { | ||
| private readonly ILogger<TodoController> _logger; | ||
|
|
||
| public TodoController(ILogger<TodoController> logger) | ||
| { | ||
| _logger = logger; | ||
| } | ||
|
|
||
| public override async Task AddOrModifyAsync(TodoItem resource, CancellationToken cancellationToken) | ||
| { | ||
| _logger.LogInformation( | ||
| "Processing TodoItem: {Name} - Title: {Title}, Priority: {Priority}", | ||
| resource.Metadata.Name, | ||
| resource.Spec.Title, | ||
| resource.Spec.Priority); | ||
|
|
||
| // Initialize status if needed | ||
| if (resource.Status == null) | ||
| { | ||
| resource.Status = new TodoItem.TodoStatus(); | ||
| } | ||
|
|
||
| // Update reconciliation count | ||
| resource.Status.ReconciliationCount++; | ||
|
|
||
| // Business logic: Auto-complete if due date is passed | ||
| if (resource.Spec.DueDate.HasValue && | ||
| resource.Spec.DueDate.Value < DateTime.UtcNow && | ||
| resource.Status.State != "completed") | ||
| { | ||
| resource.Status.State = "overdue"; | ||
| resource.Status.Message = $"Task is overdue by {(DateTime.UtcNow - resource.Spec.DueDate.Value).Days} days"; | ||
| _logger.LogWarning("TodoItem {Name} is overdue!", resource.Metadata.Name); | ||
| } | ||
| else if (resource.Status.State == "pending") | ||
| { | ||
| resource.Status.State = "in-progress"; | ||
| resource.Status.Message = "Task is being processed"; | ||
| _logger.LogInformation("TodoItem {Name} moved to in-progress", resource.Metadata.Name); | ||
| } | ||
|
|
||
| // Simulate some async work | ||
| await Task.Delay(100, cancellationToken); | ||
| } | ||
|
|
||
| public override async Task DeleteAsync(TodoItem resource, CancellationToken cancellationToken) | ||
| { | ||
| _logger.LogInformation( | ||
| "Deleting TodoItem: {Name}. Final state was: {State}", | ||
| resource.Metadata.Name, | ||
| resource.Status?.State ?? "unknown"); | ||
|
|
||
| // Cleanup logic here (e.g., remove external resources) | ||
| await Task.CompletedTask; | ||
| } | ||
|
|
||
| public override async Task FinalizeAsync(TodoItem resource, CancellationToken cancellationToken) | ||
| { | ||
| _logger.LogInformation( | ||
| "Finalizing TodoItem: {Name}", | ||
| resource.Metadata.Name); | ||
|
|
||
| // Perform cleanup before resource is completely deleted | ||
| // For example: remove related resources, notify external systems, etc. | ||
|
|
||
| await Task.CompletedTask; | ||
| } | ||
|
|
||
| public override async Task ErrorAsync(TodoItem resource, CancellationToken cancellationToken) | ||
| { | ||
| _logger.LogError( | ||
| "Error occurred for TodoItem: {Name}", | ||
| resource.Metadata.Name); | ||
|
|
||
| if (resource.Status != null) | ||
| { | ||
| resource.Status.State = "error"; | ||
| resource.Status.Message = "An error occurred during reconciliation"; | ||
| } | ||
|
|
||
| await Task.CompletedTask; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| # Build stage | ||
| FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build | ||
| WORKDIR /src | ||
|
|
||
| # Copy project file and restore dependencies | ||
| COPY ["SimpleOperator.csproj", "./"] | ||
| RUN dotnet restore | ||
|
|
||
| # Copy source code and build | ||
| COPY . . | ||
| RUN dotnet build -c Release -o /app/build | ||
|
|
||
| # Publish stage | ||
| FROM build AS publish | ||
| RUN dotnet publish -c Release -o /app/publish /p:UseAppHost=false | ||
|
|
||
| # Runtime stage | ||
| FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS final | ||
| WORKDIR /app | ||
|
|
||
| # Create non-root user | ||
| RUN groupadd -r operator && useradd -r -g operator operator | ||
|
|
||
| # Copy published app | ||
| COPY --from=publish /app/publish . | ||
|
|
||
| # Set ownership | ||
| RUN chown -R operator:operator /app | ||
|
|
||
| # Switch to non-root user | ||
| USER operator | ||
|
|
||
| # Set environment variables | ||
| ENV ASPNETCORE_ENVIRONMENT=Production \ | ||
| DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false \ | ||
| DOTNET_EnableDiagnostics=0 | ||
|
|
||
| # Health check | ||
| HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ | ||
| CMD dotnet SimpleOperator.dll version || exit 1 | ||
|
Comment on lines
+38
to
+40
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: find examples/SimpleOperator -type f -name "*.cs" | head -20Repository: pmdevers/K8sOperator.NET Length of output: 202 🏁 Script executed: rg -n "version" examples/SimpleOperator/ --type cs -B 2 -A 2Repository: pmdevers/K8sOperator.NET Length of output: 50 🏁 Script executed: # Also check if there's a Program.cs or main entry point
find examples/SimpleOperator -name "Program.cs" -o -name "Program.fs" -o -name "Main.cs"Repository: pmdevers/K8sOperator.NET Length of output: 102 🏁 Script executed: cat -n examples/SimpleOperator/Program.csRepository: pmdevers/K8sOperator.NET Length of output: 389 Fix the health check command—the The HEALTHCHECK command attempts to run 🤖 Prompt for AI Agents |
||
|
|
||
| # Entrypoint | ||
| ENTRYPOINT ["dotnet", "SimpleOperator.dll"] | ||
| CMD ["operator"] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,21 +1,12 @@ | ||
| using K8sOperator.NET; | ||
| using K8sOperator.NET.Extensions; | ||
| using K8sOperator.NET.Generators; | ||
| using SimpleOperator.Projects; | ||
| using SimpleOperator.Controllers; | ||
|
|
||
| var builder = WebApplication.CreateBuilder(args); | ||
|
|
||
| var builder = OperatorHost.CreateOperatorApplicationBuilder(args) | ||
| //.WithName("simple-operator") | ||
| .WithNamespace("simple-ops-system"); | ||
|
|
||
| builder.AddController<TestItemController>() | ||
| .WithFinalizer("testitem.local.finalizer"); | ||
|
|
||
| builder.AddController<ProjectController>() | ||
| .WithFinalizer("project.local.finalizer"); | ||
| builder.Services.AddOperator(); | ||
|
|
||
| var app = builder.Build(); | ||
|
|
||
| app.AddInstall(); | ||
| app.MapController<TodoController>(); | ||
|
|
||
| await app.RunAsync(); | ||
| await app.RunOperatorAsync(); |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Guard against null
Specto avoid reconciliation crashes.Line 18 and Line 33 dereference
resource.Specwithout a null check. A malformed CRD will throw and break the controller loop.🛠️ Suggested fix
public override async Task AddOrModifyAsync(TodoItem resource, CancellationToken cancellationToken) { + if (resource.Spec is null) + { + _logger.LogWarning( + "TodoItem {Name} has no spec; skipping reconciliation", + resource.Metadata?.Name ?? "<unknown>"); + return; + } + _logger.LogInformation( "Processing TodoItem: {Name} - Title: {Title}, Priority: {Priority}", resource.Metadata.Name, resource.Spec.Title,📝 Committable suggestion
🤖 Prompt for AI Agents