Skip to content

Adding missing integration from docs - #22

Merged
aaronpowell merged 1 commit into
mainfrom
doc-fix
Sep 16, 2024
Merged

aaronpowell merged 1 commit into
mainfrom
doc-fix

Conversation

@aaronpowell

Copy link
Copy Markdown
Member

No description provided.

@aaronpowell
aaronpowell merged commit ebe006d into main Sep 16, 2024
@aaronpowell
aaronpowell deleted the doc-fix branch September 16, 2024 03:59
andrey-noskov added a commit to andrey-noskov/Aspire-CommunityToolkit that referenced this pull request Apr 9, 2026
…mmunityToolkit#52)

Revives CommunityToolkit#35

Expands test coverage from 12 to 28 tests:

New test file - KindPublicApiTests.cs (8 tests):
Null argument validation for every public method.

New tests in AddKindClusterTests.cs (8 tests):
- KindConfigGenerator: YAML output for 0/3 workers, with/without K8s version
- ProcessHelper.Run: stdout capture, non-zero exit codes
- Edge cases: zero workers valid, kubeconfig path correctness

Adapted to use async GenerateConfigAsync API.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit ba3b5d7814442147de79bbb84dd8ce47aa68f1d4)
aaronpowell added a commit that referenced this pull request Jul 16, 2026
* feat: add Kind (Kubernetes in Docker) hosting integration

Add CommunityToolkit.Aspire.Hosting.Kind for managing Kind clusters
as Aspire resources with dashboard integration, health checks, and
WaitFor support.

Public API:
- AddKindCluster() - creates a Kind cluster resource
- WithKubernetesVersion() - configures the K8s version
- WithWorkerNodes() - configures additional worker nodes
- WithReference() - injects kubeconfig into dependent resources
- WithKindNetwork() - connects containers to Kind's Docker network

Includes unit tests, integration test with [RequiresKind] attribute,
and example AppHost.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit b93022434b0572d0dd14722558baaae6d8ba8af0)

* Extract KindContainerImageTags as public constants class

Create a public static KindContainerImageTags class with KindNodeImageRepository
and DefaultKubernetesVersion constants. Update KindConfigGenerator to reference
the new constant. Add tests to verify the constant values.

Co-authored-by: andrey-noskov <25082814+andrey-noskov@users.noreply.github.com>
Agent-Logs-Url: https://github.com/andrey-noskov/aspire-kind/sessions/08ed515c-3d80-4aa1-8963-69b98fa0ff72
(cherry picked from commit 6b2325ba4343cd801e6f86ef0de61c5bc34e6295)

* Remove trivial constant-value tests for KindContainerImageTags

Co-authored-by: andrey-noskov <25082814+andrey-noskov@users.noreply.github.com>
Agent-Logs-Url: https://github.com/andrey-noskov/aspire-kind/sessions/2f66ff2b-e50f-4afd-8f38-9d46998ea4b4
(cherry picked from commit 62fcd44c282f4fa6ef32dd22644b6fdd5ddf27ff)

* ci: add Hosting.Kind.Tests to test matrix

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit fcbc16381753cf3e7d63b5f6927e412aa335fa71)

* Replace tautological tests with KindConfigGenerator YAML wiring test

Co-authored-by: andrey-noskov <25082814+andrey-noskov@users.noreply.github.com>
Agent-Logs-Url: https://github.com/andrey-noskov/aspire-kind/sessions/1a2ac257-4765-4e55-b0ab-1e66a90b76a0
(cherry picked from commit 1359dcf7c94749d9180bda31f3c79da8ab0fa17c)

* feat: add cluster lifecycle management with WithClusterLifetime

- Add ClusterLifetime enum (Session/Persistent) and ClusterLifetimeAnnotation
- Register IHostApplicationLifetime.ApplicationStopping cleanup for Session lifetime
- Delete Kind cluster and kubeconfig files on AppHost shutdown
- Default to Session (ephemeral) lifetime; Persistent reuses existing clusters

Closes microsoft/aspire-kind#1

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit eb42868f7e8c26177f8aac5b3fcf56a715a032a5)

* feat: add pre-flight Kind CLI availability check

Verify that the Kind CLI is installed and on PATH at builder time
(inside AddKindCluster) before any cluster operations are attempted.
If missing, throw InvalidOperationException with install URL.

Add synchronous ProcessHelper.Run overload for use in sync builder
methods without requiring sync-over-async.

Closes #10

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit c6fa4cca03522b1242744de9f9416d9a6b696b03)

* feat: make KindConfigGenerator async (#25) (#51)

Makes GenerateConfig() async:
- Renamed to GenerateConfigAsync with CancellationToken parameter
- Uses File.WriteAllTextAsync instead of synchronous File.WriteAllText
- Updated KindClusterManager caller to await the async method
- Updated test to match the new async signature

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit d06e2adcb8d0311a0567c401385e8724b1a3469d)

* test: expand unit test coverage to 28 tests (#22) (#52)

Revives #35

Expands test coverage from 12 to 28 tests:

New test file - KindPublicApiTests.cs (8 tests):
Null argument validation for every public method.

New tests in AddKindClusterTests.cs (8 tests):
- KindConfigGenerator: YAML output for 0/3 workers, with/without K8s version
- ProcessHelper.Run: stdout capture, non-zero exit codes
- Edge cases: zero workers valid, kubeconfig path correctness

Adapted to use async GenerateConfigAsync API.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit ba3b5d7814442147de79bbb84dd8ce47aa68f1d4)

* docs: add README for Kind hosting integration (#23) (#53)

Revives #34

Adds README.md for the Kind hosting integration with:
- Prerequisites (Docker, Kind CLI)
- Basic usage (AddKindCluster)
- All builder extensions (WithWorkerNodes, WithKubernetesVersion, WithClusterLifetime, WithKindNetwork)
- WithReference environment variables (KUBECONFIG, K8S_CLUSTER_NAME)
- Full end-to-end example

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit 9acf4fbf5728b9bd0bccc84ecccbdc0438b051c9)

* refactor: replace StringBuilder with YamlDotNet in KindConfigGenerator (#39)

Replace manual string concatenation with typed model classes and
YamlDotNet serializer for Kind cluster config generation. This
improves type safety, null handling, and extensibility for future
features like port mappings and extra mounts.

Fixes microsoft/aspire-kind#38

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit e0a5239c8083d76fd76ac128dacfda867908b8eb)

* feat: add Helm chart support for Kind clusters (#37) (#54)

Adds first-class Helm chart deployment as child resources of
KindClusterResource, following Aspire's parent-child pattern.

New files:
- KindDeployedResource: abstract base for deployed resources
- KindHelmChartResource: Helm chart resource with values/version/namespace
- HelmManager: CLI wrapper (helm upgrade --install --wait)
- KindHelmChartResourceBuilderExtensions: AddHelmChart, WithChartVersion,
  WithHelmValue, WithHelmValuesFile, WithNamespace

Helm releases appear in the Aspire dashboard with lifecycle states
(NotStarted -> Starting -> Running / FailedToStart) and support
WaitFor() dependency ordering.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit 315c4adf18d32491bd4b59983631272a0ba32255)

* fix: make ProcessHelper tests cross-platform (Linux/Windows)

Use RuntimeInformation.IsOSPlatform to select cmd /c on Windows
and sh -c on Linux/Mac for ProcessHelper_Run_CapturesStdout and
ProcessHelper_Run_InvalidCommand_NonZeroExitCode tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit 55fe43d9cfc92143e09c00e7af66931345528693)

* feat: replace Helm --wait with Kubernetes health check (#55)

Replace helm --wait with an IHealthCheck that polls the Kubernetes API
directly using the C# Kubernetes client. This surfaces real-time workload
readiness in the Aspire dashboard instead of blocking on Helm.

Changes:
- Add KubernetesWorkloadHealthCheck (IHealthCheck polling K8s API)
- Add KubernetesWorkloadStatusClient (queries Deployments/StatefulSets)
- Add KubernetesObjectStatus/KubernetesWorkloadStatus model records
- Add WorkloadReadiness with per-kind readiness evaluation
- Remove --wait from helm install arguments in HelmManager
- Wait for parent Kind cluster before starting helm install
- Show 'Waiting' state while cluster initializes
- Add KubernetesClient 19.0.2 dependency
- Add 63 unit tests covering readiness logic and status projection

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit 03a9eccc4e861ce6c9627612de3a9639df747d8c)

* Replace ProcessHelper static with IProcessRunner DI (#75)

## Summary

Replaces the static `ProcessHelper` class with an `IProcessRunner` interface resolved from DI, making all process execution testable without shelling out to real CLI tools.

## Changes

The only change that isn't simple plumbing is the removal of the sync codepath. The only consumer was the kind CLI check. I instead moved that call to OnInitializeResource so it could be async, which I think is a better fit for the Aspire model, as we'd then fail to initialize the resource rather than throwing when creating the builder.

## Motivation

Follows the pattern from Aspire.Hosting.Azure (IProcessRunner / MockProcessRunner). Enables the compute environment branch to inject FakeProcessRunner in tests to verify pipeline step behavior (image loading, helm install) without requiring Kind/Helm/Docker in CI.

## Testing

- 51/51 tests pass
- ProcessHelper.Run tests rewritten as DefaultProcessRunner async tests

(cherry picked from commit 0937e7e6b1beff962f278e79962cb8ece8deff31)

* feat: expose Kind config as extensible builder pattern

Add WithKindConfig(Action<KindConfigModel>) extension method using the
annotation composition pattern from the main Aspire repo. Multiple calls
compose in order during config generation.

Expand internal config models to cover the full Kind v1alpha4 spec and
make them public: KindConfigModel, KindNodeModel, KindNetworkingModel,
KindMountModel, KindPortMappingModel.

Rewrite WithKubernetesVersion and WithWorkerNodes as thin wrappers.
WithKubernetesVersion uses a dedicated KubernetesVersionAnnotation
applied after all config callbacks, so version is set on every node
regardless of call order. WithWorkerNodes delegates to WithKindConfig.

Remove WorkerNodes and KubernetesVersion properties from
KindClusterResource — all config flows through annotations.

Closes microsoft/aspire-kind#6

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit 2226ef0afc3e3644fcb9160d60f4f748221b9926)

* Add Kind as a Kubernetes compute environment for aspire publish / aspire deploy (#73)

## Summary

Adds `.WithKind()` extension method on the existing `AddKubernetesEnvironment("k8s")`. This makes Kind a deployment target for `aspire publish` (generates Helm charts) and `aspire deploy` (creates a Kind cluster, builds project images, loads them into Kind, and installs the Helm chart).

This is separate from the existing `AddKindCluster()` which remains unchanged and serves a different use case (managed cluster dependency visible in the dashboard during F5).

## User scenarios

### Scenario 1: K8s developer (existing, unchanged)

```csharp
// Kind cluster as a managed dependency - shows in dashboard, injects KUBECONFIG
builder.AddKindCluster("dev-cluster")
    .WithKubernetesVersion("v1.32.2");

builder.AddProject<Projects.MyOperator>("operator")
    .WithReference(kind);
```

### Scenario 2: K8s consumer (new)

```csharp
// Kind as a compute environment for publish/deploy
builder.AddKubernetesEnvironment("k8s")
    .WithKind()
    .WithKubernetesVersion("v1.32.2")
    .WithWorkerNodes(1);

builder.AddContainer("redis", "redis", "7");
builder.AddProject<Projects.MyApi>("api");
```

Then from the CLI:

```bash
aspire publish --output-path ./charts   # generates Helm chart
aspire deploy                           # creates cluster + deploys everything
```

## What happens during aspire deploy

1. **publish-k8s** - Generates Helm chart (Deployments, Services, ConfigMaps) via Aspire.Hosting.Kubernetes
2. **kind-create-cluster** - Creates the Kind cluster (reuses existing if persistent)
3. **build** - Builds container images for project resources (dotnet publish /t:PublishContainer)
4. **kind-load-images** - Loads all images into Kind (kind load docker-image)
5. **kind-helm-install** - Deploys the Helm chart (helm install)

## Design decisions

- **Two independent entry points**: AddKindCluster (F5) and AddKubernetesEnvironment().WithKind() (publish/deploy) serve different personas and don't overlap
- **Composes with Aspire.Hosting.Kubernetes**: Delegates manifest generation to the first-party K8s package via its public API. Kind adds deploy-specific pipeline steps
- **IKindResource interface**: Shared fluent methods (WithKubernetesVersion, WithWorkerNodes, WithClusterLifetime) work on both resource types
- **KindEnvironmentResource surrogate**: Links to KubernetesEnvironmentResource via IResourceWithParent, following the Aspire pattern for surrogate resources
- **Invisible in F5**: WithKind() uses CreateResourceBuilder in run mode so the Kind environment doesn't appear in the dashboard
- **IProcessRunner seam**: Internal interface for process execution, following the pattern from Aspire.Hosting.Azure. Enables testing pipeline steps without shelling out to real CLI tools
- **Image name resolution**: Uses ContainerBuildOptionsCallbackAnnotation for project resources, respecting user customization via WithContainerBuildOptions

## Dependencies

- Adds Aspire.Hosting.Kubernetes package reference
- Adds Verify.XunitV3 for snapshot testing
- Adds `verify.tool` to dotnet-tools.json

## E2E verified

Both container and project resources deploy successfully to Kind:
- AddContainer("nginx", "nginx", "latest") → pulled from registry → pod Running
- AddProject<Projects.HelloApi>("api") → dotnet publish /t:PublishContainer → kind load → pod Running → HTTP 200

(cherry picked from commit 67e7e47c97838df24702dff3158c3e0a6754b3dc)

* feat: replace regex kubeconfig rewriting with YAML parser and improve Kind networking

- Replace regex-based kubeconfig rewriting with YamlDotNet/k8s YAML parser
  in KindContainerHelper (renamed from KindContainerKubeconfigRewriter)
- Rework WithKindNetwork to handle both container lifecycle paths:
  - ResourceReadyEvent: connects running containers to Kind network
  - ResourceStoppedEvent: connects + restarts crashed containers via
    ResourceCommandService instead of raw docker start
- Assign predictable container names (EnsureContainerName) so the
  docker network connect handler can identify the container
- Handle docker network connect race condition by treating 'already
  exists in network' as success
- Split extension methods by resource type:
  - KindContainerExtensions: WithReference(Container) + WithKindNetwork
  - KindClusterResourceBuilderExtensions: AddKindCluster, config, WithReference<T>
- Add networking model section to README with connectivity matrix
- Update example AppHost with Headlamp and netshoot containers
- Add KindContainerHelperTests for kubeconfig rewriting
- Add Kind-focused solution file and launch profiles

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit c049ea7201015561551e826b9e366f3ef45a07fd)

* chore: align Kind submission with toolkit conventions

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Bump Kind examples Aspire SDK

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Support Podman for Kind hosting

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Use Aspire container runtime resolver for Kind

* Fix Kind runtime resolver test build

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add comments for Kind Podman process behavior

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address Kind PR review comments

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Aaron Powell <me@aaron-powell.com>

* Updating to 13.4.3 and adding polyglot exports

* Removing unneeded slnx

* Fix duplicate KubernetesClient PackageVersion introduced by merge

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Add Kind Publish.AppHost to main solution

Addresses mitchdenny review: main slnx should include both AppHost and Publish.AppHost for the Kind example.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Address #1270 review feedback: process timeout handling, path quoting, public API collection types, kubeconfig dir, test assertions, MessagePack CPM

* Fix Kind container network restart

Restart the existing container through Docker or Podman so the Kind network attachment persists. Use the runtime network connection result instead of persistent resource state, leaving intentional stops stopped while allowing recreated containers to reconnect.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9c9ea56c-b82e-4f9a-b23e-aad21dfa873b

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: andrey-noskov <25082814+andrey-noskov@users.noreply.github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Matt Kotsenas <51421+MattKotsenas@users.noreply.github.com>
Co-authored-by: Aaron Powell <me@aaron-powell.com>
Co-authored-by: Copilot <Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant