Initial BinaryLane v2 API client

This commit is contained in:
2026-08-16 21:52:42 +10:00
commit fcd0d22b0d
91 changed files with 18691 additions and 0 deletions
+48
View File
@@ -0,0 +1,48 @@
# Server actions
Use a typed `ServerAction` to submit a server action. For example, this powers
on a server:
```csharp
using BinaryLane.Api.V2.Models;
var submission = await client.Servers.SubmitActionAsync(
serverId,
new PowerOnServerAction(),
cancellationToken);
```
Common action types include `PowerOnServerAction`, `PowerOffServerAction`,
`RebootServerAction`, `ResizeServerAction`, and `RebuildServerAction`.
## Waiting for completion
BinaryLane can accept an action before it has finished. When the response
contains an action, use its identifier to wait for the final status:
```csharp
if (submission.Action is { } action)
{
var completed = await client.Actions.WaitForCompletionAsync(
action.Id,
cancellationToken: cancellationToken);
}
```
Pass `ActionWaitOptions` when you need a different timeout or polling interval.
The default is a 15-minute timeout with a two-second polling interval.
## Status values
`BinaryLaneAction.Status` and `BinaryLaneAction.Type` are strings. Compare a
documented value with `BinaryLaneValues`:
```csharp
if (action.Status == BinaryLaneValues.ActionStatus.Completed)
{
// Continue with the next step.
}
```
If an action request has an uncertain outcome, retrieve the action or server
state before submitting it again.
+33
View File
@@ -0,0 +1,33 @@
# Maintainer guide: API coverage
This is a maintainer reference. Package consumers can start with the
[README](../README.md).
The SDK's scope is the BinaryLane v2 OpenAPI contract committed at
`eng/openapi/binarylane-v2.openapi.yaml`. The raw contract currently declares
version `0.39.1`; it is a developer-preview contract and may change without a
version change.
The raw document contains virtual paths such as
`/v2/servers/{server_id}/actions#PowerOn`. These are API-reference aliases for
action payload variants, not real HTTP routes. Coverage and generated-code
checks must use the normalized contract and count only the real
`POST /v2/servers/{server_id}/actions` route.
| API area | Public resource boundary |
| --- | --- |
| Account | `IAccountApi` |
| Balances, invoices, and unpaid invoices | `IBillingApi` |
| Actions | `IActionsApi` |
| Servers and server subresources | `IServersApi` |
| Images | `IImagesApi` |
| SSH keys | `ISshKeysApi` |
| DNS domains, nameservers, and records | `IDomainsApi` |
| Load balancers and forwarding rules | `ILoadBalancersApi` |
| VPCs and members | `IVpcsApi` |
| Regions, sizes, and software catalogues | `IRegionsApi`, `ISizesApi`, `ISoftwareApi` |
| Reverse names | `IReverseNamesApi` |
| Data usage | `IDataUsageApi` |
| Sample sets | `ISampleSetsApi` |
Keep this table and the related tests up to date when API support changes.
+72
View File
@@ -0,0 +1,72 @@
# Configuration
## Standard registration
In an ASP.NET Core or generic-host application, `AddBinaryLaneApi` configures
`IBinaryLaneClient` and the individual resource interfaces.
```csharp
builder.Services.AddBinaryLaneApi(options =>
{
options.ApiToken = builder.Configuration["BinaryLane:ApiToken"];
options.RequestTimeoutSeconds = 100;
});
```
| Setting | Default | Description |
| --- | --- | --- |
| `BaseUrl` | `https://api.binarylane.com.au/` | API base address. Leave unchanged for BinaryLane's public API. |
| `ApiToken` | none | Bearer token used by the default provider. |
| `RequestTimeoutSeconds` | `100` | Timeout for an individual HTTP request. |
The base URL must be an HTTPS URL without credentials, a query string, or a
fragment. Options are validated when the application starts.
## Rotating tokens
Register `IBinaryLaneTokenProvider` before calling `AddBinaryLaneApi` when the
token comes from a vault or changes during the lifetime of the application.
`VaultTokenProvider` below is your implementation of that interface.
```csharp
using BinaryLane.Api.V2.Authentication;
using BinaryLane.Api.V2.DependencyInjection;
builder.Services.AddSingleton<IBinaryLaneTokenProvider, VaultTokenProvider>();
builder.Services.AddBinaryLaneApi(options => options.RequestTimeoutSeconds = 100);
```
The provider is called for every request. Do not log the returned token.
## Use without dependency injection
```csharp
using BinaryLane.Api.V2;
using BinaryLane.Api.V2.Authentication;
using var httpClient = new HttpClient
{
BaseAddress = new Uri("https://api.binarylane.com.au/"),
};
var token = Environment.GetEnvironmentVariable("BINARYLANE_API_TOKEN")
?? throw new InvalidOperationException("Set BINARYLANE_API_TOKEN.");
var client = new BinaryLaneClient(
httpClient,
new StaticBinaryLaneTokenProvider(token));
```
## HTTP configuration
`AddBinaryLaneApi` returns an `IHttpClientBuilder`, so you can configure proxy,
telemetry, or other application-specific handlers.
```csharp
builder.Services.AddBinaryLaneApi(options => options.ApiToken = token)
.ConfigureHttpClient(client => client.DefaultRequestHeaders.Add("X-App", "my-service"));
```
Only add automatic retries when the request is safe to repeat. In particular,
POST, PUT, PATCH, and DELETE requests may have already been applied when a
network failure is reported.
+40
View File
@@ -0,0 +1,40 @@
# Error handling
All API failures derive from `BinaryLaneApiException`.
| Exception | When it is used |
| --- | --- |
| `BinaryLaneUnauthorizedException` | The token is missing, invalid, or expired. |
| `BinaryLaneForbiddenException` | The token does not have access to the resource. |
| `BinaryLaneNotFoundException` | The requested resource does not exist or is not visible to the token. |
| `BinaryLaneValidationException` | BinaryLane rejected the request payload. |
| `BinaryLaneApiException` | Any other non-success HTTP response. |
```csharp
using BinaryLane.Api.V2.Errors;
try
{
var server = await client.Servers.GetAsync(serverId, cancellationToken);
}
catch (BinaryLaneNotFoundException)
{
// Handle a missing server.
}
catch (BinaryLaneValidationException)
{
// Show an appropriate validation message to the caller.
}
catch (BinaryLaneApiException exception)
{
// Use exception.StatusCode to choose an application-specific response.
}
```
Each exception provides `StatusCode`, `RequestUri`, `Headers`, and, when
available, `Problem` and `ResponseBody`. Provider detail text can contain user
data. Do not write `Problem`, `Headers`, or `ResponseBody` to application logs
without appropriate redaction.
Successful JSON responses are limited to 16 MiB. A larger response throws
`HttpRequestException` before the client buffers it in memory.
+53
View File
@@ -0,0 +1,53 @@
# Getting started
`BinaryLane.Api` connects to BinaryLane's bearer-token v2 API at
`https://api.binarylane.com.au/v2/`.
## 1. Install the package
```bash
dotnet add package BinaryLane.Api --prerelease
```
## 2. Store the token safely
For local development, initialise user secrets for your application and add
the token:
```bash
dotnet user-secrets init
dotnet user-secrets set "BinaryLane:ApiToken" "your-token"
```
For hosted applications, use the platform's secret store or supply
`BINARYLANE_API_TOKEN` at runtime.
## 3. Register the client
```csharp
using BinaryLane.Api.V2;
using BinaryLane.Api.V2.DependencyInjection;
using BinaryLane.Api.V2.Models;
builder.Services.AddBinaryLaneApi(options =>
{
options.ApiToken = builder.Configuration["BinaryLane:ApiToken"]
?? Environment.GetEnvironmentVariable("BINARYLANE_API_TOKEN")
?? throw new InvalidOperationException("A BinaryLane API token is required.");
});
```
## 4. Make a request
Inject `IBinaryLaneClient`, then select the resource you need:
```csharp
public sealed class ServerReader(IBinaryLaneClient binaryLane)
{
public IAsyncEnumerable<Server> ListAsync(CancellationToken cancellationToken) =>
binaryLane.Servers.ListAllAsync(cancellationToken: cancellationToken);
}
```
See [Configuration](configuration.md) for custom token providers and
[Pagination](pagination.md) for page-by-page access.
+31
View File
@@ -0,0 +1,31 @@
# Pagination
List endpoints accept one-based `page` and `per_page` values. `per_page` can be
between 1 and 200.
Use `ListAsync` when you need a specific page or the provider's page links:
```csharp
using BinaryLane.Api.V2.Pagination;
var page = await client.Servers.ListAsync(
new PageRequest { Page = 1, PerPage = 50 },
cancellationToken);
foreach (var server in page.Items)
{
await ProcessAsync(server, cancellationToken);
}
```
Use `ListAllAsync` to process every page as it is needed:
```csharp
await foreach (var server in client.Servers.ListAllAsync(cancellationToken: cancellationToken))
{
await ProcessAsync(server, cancellationToken);
}
```
Pass a cancellation token from the calling request, worker, or command so a
stopped operation does not continue fetching pages.
+63
View File
@@ -0,0 +1,63 @@
# Maintainer guide: releases
This page is for package maintainers.
This repository publishes packages with NuGet trusted publishing and GitHub
OpenID Connect (OIDC). It must not use a long-lived NuGet API key.
## One-time setup
1. On NuGet.org, create or verify the trusted-publishing policy:
- publisher: `GitHubActions`;
- GitHub owner: `alexhopeoconnor`;
- repository: `binarylane-dotnet`;
- workflow: `publish.yml`;
- environment: `release`.
2. In GitHub, create a protected environment named `release` and require a
maintainer approval.
3. Create a protected `release` environment secret named `NUGET_USER` with
the NuGet.org username `alex.hope.oconnor`. It is an identifier, not an
API key.
4. Protect `main` with CI and restrict creation of `v*` tags.
The first successful OIDC publication must occur before NuGet's policy
activation window expires. After success, NuGet permanently activates the
policy for this exact repository/workflow/environment identity.
## Release checklist
1. Review BinaryLane contract changes and update the committed snapshot if
necessary.
2. Update code, tests, docs, API coverage, and `CHANGELOG.md`.
3. Set the package `<Version>` to the intended SemVer release.
4. Open and merge the release pull request after CI succeeds.
5. Tag the exact merge commit. The tag must equal the package version with a
leading `v`.
```bash
git tag -a v0.1.0-beta.1 -m "BinaryLane.Api 0.1.0-beta.1"
git push origin v0.1.0-beta.1
```
6. Approve the protected `release` environment in GitHub Actions.
7. Verify the package page, rendered README, icon, license, repository link,
symbols, package ownership, and GitHub Release.
## What the release workflow does
`publish.yml` validates the tag, package version, and changelog heading; it
then restores, builds, tests, packs, and compiles the maintained demo against
the resulting local `.nupkg`. Only then does `NuGet/login@v1` exchange the
GitHub OIDC identity for a short-lived one-time publish key. The key is used
only in memory by the job.
The GitHub Release job runs after NuGet publishing and receives no OIDC
permission. It attaches the package files and uses the matching changelog
section for release notes.
## Recovery
NuGet packages cannot be overwritten. If a release has a packaging defect,
unlist it if appropriate, publish a new version, and document the correction
in the changelog. Do not retag a version or attempt to reuse a published
package version.
+48
View File
@@ -0,0 +1,48 @@
# Maintainer guide: upstream API contract
This page describes SDK maintenance. Package consumers can start with the
[README](../README.md).
The source of truth for BinaryLane's API is its published OpenAPI document:
<https://api.binarylane.com.au/reference/openapi.yaml>
The committed raw snapshot is intentionally reviewable:
```text
eng/openapi/binarylane-v2.openapi.yaml
eng/openapi/contract.json
```
`contract.json` records the source URL, provider-declared version, SHA-256,
and retrieval time. It describes an upstream artifact; it does not set the
NuGet package version.
## Snapshot purpose
BinaryLane's preview API can change without a version change. The committed
snapshot makes those changes visible during SDK maintenance.
## Normalization
The raw document includes virtual `#ActionName` paths for individual server
action variants. They exist to improve the provider's reference UI but are not
HTTP paths. `eng/normalize-openapi.sh` strips them when producing a normalized
document for code generation or coverage checks. Do not issue requests to
those virtual paths.
## Monitoring and updating
The scheduled `contract-monitor.yml` workflow downloads the live document and
runs `eng/verify-openapi-contract.sh`. If the SHA-256 or provider-declared
version differs, it opens one issue rather than silently updating the SDK.
To intentionally refresh the snapshot after review:
```bash
./eng/refresh-openapi-contract.sh
git diff -- eng/openapi docs/api-coverage.md
```
Then update affected models, coverage documentation, changelog, and tests in
the same pull request. Review the change before merging it.