Skip to content

Development Guide

ToolVersionNotes
.NET SDK10.0+Download
DockerAny recentFor building images
kubectlCluster-matchingDownload
Helm3.14+For chart work
Bun1.3+Install — docs site only
A Kubernetes cluster1.25+kind/k3d/Docker Desktop work well

Optional but useful:

  • kind or k3d for a local cluster
  • k9s for cluster introspection
  • A C# IDE (Rider, Visual Studio, VS Code with C# Dev Kit)
Terminal window
git clone https://github.com/danihengeveld/mc-operator.git
cd mc-operator
# Restore .NET tool chain
dotnet tool restore
# Restore NuGet packages
dotnet restore mc-operator.slnx

Tests use TUnit and run via dotnet run:

Terminal window
# Run all tests
dotnet run --project src/McOperator.Tests/
# Run a specific test class
dotnet run --project src/McOperator.Tests/ -- \
--treenode-filter "*/*/ValidationWebhookTests/*"

Tests cover:

  • Webhook validation logic (ValidationWebhookTests)
  • Memory parsing helpers (MemoryParsingTests)
  • StatefulSet builder output (StatefulSetBuilderTests)
  • Service builder output (ServiceBuilderTests)
  • ConfigMap builder output (ConfigMapBuilderTests)

The operator runs as a standard ASP.NET Core application and uses the active kubeconfig to connect to Kubernetes:

Terminal window
# Apply the CRD to your local cluster
kubectl apply -f manifests/crd/minecraftservers.yaml
# Apply RBAC
kubectl apply -f manifests/rbac/
# Run the operator (watches the current kubeconfig context)
dotnet run --project src/McOperator/ -- --environment Development
Terminal window
docker build -t ghcr.io/danihengeveld/mc-operator:dev .
# Test the image
docker run --rm ghcr.io/danihengeveld/mc-operator:dev --help

After changing the CRD entity classes, regenerate the YAML manifests:

Terminal window
# Install KubeOps CLI (if not already installed)
dotnet tool restore
# Regenerate all manifests
dotnet kubeops generate operator "mc-operator" \
src/McOperator/McOperator.csproj \
--out manifests/ \
--docker-image "ghcr.io/danihengeveld/mc-operator" \
--docker-image-tag "latest"

Always review generated changes before committing — the generator may produce diffs in formatting or ordering that are worth cleaning up.

src/
├── McOperator/
│ ├── Builders/ # StatefulSetBuilder, ServiceBuilder, ConfigMapBuilder
│ ├── Controllers/ # MinecraftServerController (reconciler)
│ ├── Entities/ # MinecraftServer, MinecraftServerSpec, MinecraftServerStatus
│ ├── Extensions/ # MinecraftServerExtensions (owner reference helper)
│ ├── Finalizers/ # MinecraftServerFinalizer (PVC cleanup)
│ ├── Webhooks/ # MinecraftServerValidationWebhook, MinecraftServerMutationWebhook
│ └── Program.cs # Startup and DI registration
└── McOperator.Tests/
├── ConfigMapBuilderTests.cs
├── MemoryParsingTests.cs
├── ServiceBuilderTests.cs
├── StatefulSetBuilderTests.cs
└── ValidationWebhookTests.cs
  • Language: C# 13 with nullable reference types enabled
  • Framework: .NET 10, ASP.NET Core minimal hosting
  • Tests: TUnit ([Test], [Arguments], await Assert.That(...))
  • Formatting: Standard C# conventions; see .editorconfig at the repo root
  • Packages: All NuGet versions centralized in Directory.Packages.props
  • Build props: All shared MSBuild properties in Directory.Build.props
  1. Add the field to the relevant class in src/McOperator/Entities/MinecraftServerSpec.cs
  2. If it maps to an environment variable, add it in StatefulSetBuilder.cs
  3. If it needs validation, add it in MinecraftServerValidationWebhook.cs
  4. If it has a default, add it in MinecraftServerMutationWebhook.cs
  5. Add/update tests
  6. Regenerate CRD YAML
  7. Update the CRD reference docs
Terminal window
kubectl get minecraftserver <name> -n minecraft -o yaml

The mutating webhook runs before the resource is stored, so the stored spec reflects all applied defaults.

The operator logs all webhook invocations at Information level. Look for ValidationWebhook or MutationWebhook in the operator pod logs.

Terminal window
kubectl logs -n mc-operator-system -l app.kubernetes.io/name=mc-operator -f

Look for lines containing Reconciling to trace individual reconcile cycles.