Skip to content

Add external cluster support to skip ephemeral startup#76

Merged
Mpdreamz merged 1 commit intomasterfrom
feature/external-es-tunit
Feb 19, 2026
Merged

Add external cluster support to skip ephemeral startup#76
Mpdreamz merged 1 commit intomasterfrom
feature/external-es-tunit

Conversation

@Mpdreamz
Copy link
Copy Markdown
Member

Adds the ability to skip starting a local ephemeral Elasticsearch cluster
when a remote cluster is already available. This dramatically reduces
integration test iteration time during development (no ~60s bootstrap wait).

How it works

ElasticsearchCluster<TConfiguration>.InitializeAsync() now checks for an
external cluster before launching an ephemeral one. Resolution order:

  1. TryUseExternalCluster() virtual method (programmatic hook)
  2. TEST_ELASTICSEARCH_URL environment variable
  3. Fall through to ephemeral startup (existing behavior)

Environment variable usage (zero code changes)

# Point at a running cluster — no code changes needed
TEST_ELASTICSEARCH_URL=https://localhost:9200 dotnet run --project MyTests/

# With API key authentication
TEST_ELASTICSEARCH_URL=https://localhost:9200 \
TEST_ELASTICSEARCH_API_KEY=your-api-key-here \
dotnet run --project MyTests/

Programmatic hook

Override TryUseExternalCluster() for custom logic (service discovery,
config files, per-developer overrides, etc.):

public class MyTestCluster : ElasticsearchCluster
{
    public MyTestCluster() : base(new ElasticsearchConfiguration("latest-9")) { }

    protected override ExternalClusterConfiguration TryUseExternalCluster()
    {
        var url = Environment.GetEnvironmentVariable("MY_DEV_CLUSTER_URL");
        if (string.IsNullOrEmpty(url))
            return null; // fall through to ephemeral startup

        return new ExternalClusterConfiguration(
            new Uri(url),
            Environment.GetEnvironmentVariable("MY_DEV_CLUSTER_KEY")
        );
    }
}

Changes

  • New ExternalClusterConfiguration class (URI + optional API key + connectivity
    validation via GET /)
  • ElasticsearchCluster<TConfiguration>:
    • TryUseExternalCluster() — virtual hook, returns null by default
    • TEST_ELASTICSEARCH_URL / TEST_ELASTICSEARCH_API_KEY env var detection
    • NodesUris() override returns external URI when in external mode
    • DisposeAsync() is a no-op for external clusters
    • IsExternal / ExternalApiKey properties for inspection
  • ElasticsearchCluster (non-generic): default Client auto-wires API key auth
  • Complex example: added ProgrammaticExternalCluster demo, API key handling
    in TestGenericCluster
  • Updated READMEs for both Core and Elasticsearch packages

Co-authored-by: Cursor [email protected]

Adds the ability to skip starting a local ephemeral Elasticsearch cluster
when a remote cluster is already available. This dramatically reduces
integration test iteration time during development (no ~60s bootstrap wait).

## How it works

`ElasticsearchCluster<TConfiguration>.InitializeAsync()` now checks for an
external cluster before launching an ephemeral one. Resolution order:

1. `TryUseExternalCluster()` virtual method (programmatic hook)
2. `TEST_ELASTICSEARCH_URL` environment variable
3. Fall through to ephemeral startup (existing behavior)

## Environment variable usage (zero code changes)

```bash
# Point at a running cluster — no code changes needed
TEST_ELASTICSEARCH_URL=https://localhost:9200 dotnet run --project MyTests/

# With API key authentication
TEST_ELASTICSEARCH_URL=https://localhost:9200 \
TEST_ELASTICSEARCH_API_KEY=your-api-key-here \
dotnet run --project MyTests/
```

## Programmatic hook

Override `TryUseExternalCluster()` for custom logic (service discovery,
config files, per-developer overrides, etc.):

```csharp
public class MyTestCluster : ElasticsearchCluster
{
    public MyTestCluster() : base(new ElasticsearchConfiguration("latest-9")) { }

    protected override ExternalClusterConfiguration TryUseExternalCluster()
    {
        var url = Environment.GetEnvironmentVariable("MY_DEV_CLUSTER_URL");
        if (string.IsNullOrEmpty(url))
            return null; // fall through to ephemeral startup

        return new ExternalClusterConfiguration(
            new Uri(url),
            Environment.GetEnvironmentVariable("MY_DEV_CLUSTER_KEY")
        );
    }
}
```

## Changes

- New `ExternalClusterConfiguration` class (URI + optional API key + connectivity
  validation via GET `/`)
- `ElasticsearchCluster<TConfiguration>`:
  - `TryUseExternalCluster()` — virtual hook, returns null by default
  - `TEST_ELASTICSEARCH_URL` / `TEST_ELASTICSEARCH_API_KEY` env var detection
  - `NodesUris()` override returns external URI when in external mode
  - `DisposeAsync()` is a no-op for external clusters
  - `IsExternal` / `ExternalApiKey` properties for inspection
- `ElasticsearchCluster` (non-generic): default `Client` auto-wires API key auth
- Complex example: added `ProgrammaticExternalCluster` demo, API key handling
  in `TestGenericCluster`
- Updated READMEs for both Core and Elasticsearch packages

Co-authored-by: Cursor <[email protected]>
@Mpdreamz Mpdreamz merged commit 2e96230 into master Feb 19, 2026
3 checks passed
@Mpdreamz Mpdreamz deleted the feature/external-es-tunit branch February 19, 2026 14:24
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