(feature): ship 1.1.0 with full libpod api, typed dtos, streaming attach/progress, and maksit results on net10

This commit is contained in:
Maksym Sadovnychyy 2026-06-04 19:35:27 +02:00
parent b1c6c6cb44
commit 995d144e3c
205 changed files with 10679 additions and 2201 deletions

View File

@ -0,0 +1,9 @@
{
"$schema": "homelab-maksit-skills-manifest-v1",
"skillsRootRelative": "E:\\Users\\maksym\\source\\repos\\private\\homelab\\ai\\skills",
"skills": [
"common/csharp",
"common/maksit-repo-maintenance",
"local-ollama"
]
}

View File

@ -0,0 +1,13 @@
---
description: Load MaksIT agent skills from homelab (deterministic)
globs: "**/*.{cs,csproj,slnx,md}"
alwaysApply: true
---
# MaksIT skills (podman-client-dotnet)
1. `E:\Users\maksym\source\repos\private\homelab\ai\skills\common\csharp\SKILL.md`
2. `E:\Users\maksym\source\repos\private\homelab\ai\skills\common\maksit-repo-maintenance\SKILL.md`
3. `E:\Users\maksym\source\repos\private\homelab\ai\skills\local-ollama\SKILL.md`
Manifest: `.cursor/maksit-skills.json`.

5
.gitignore vendored
View File

@ -261,6 +261,5 @@ paket-files/
__pycache__/
*.pyc
**/*docker-compose/LetsEncryptServer/acme
**/*docker-compose/LetsEncryptServer/cache
#Custom
![Uu]tils/**

9
AGENTS.md Normal file
View File

@ -0,0 +1,9 @@
# Agent instructions (PodmanClient.DotNet)
| Skill | Path |
|-------|--------|
| csharp | [SKILL.md](E:\Users\maksym\source\repos\private\homelab\ai\skills\common\csharp\SKILL.md) |
| maksit-repo-maintenance | [SKILL.md](E:\Users\maksym\source\repos\private\homelab\ai\skills\common\maksit-repo-maintenance\SKILL.md) |
| local-ollama | [SKILL.md](E:\Users\maksym\source\repos\private\homelab\ai\skills\local-ollama\SKILL.md) |
Manifest: `.cursor/maksit-skills.json`.

70
CHANGELOG.md Normal file
View File

@ -0,0 +1,70 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.1.0] - 2026-06-04
### Added
- Full **Libpod API** coverage (~86 endpoints) via domain interfaces: `IPodmanSystemClient`, `IPodmanContainersClient`, `IPodmanImagesClient`, `IPodmanVolumesClient`, `IPodmanNetworksClient`, `IPodmanPodsClient`, `IPodmanExecClient`, `IPodmanBuildClient`, `IPodmanManifestsClient`, `IPodmanGenerateClient` (composed by `IPodmanClient`).
- Typed API responses under `Dtos/` (`*Dto` suffix); request/spec payloads remain in `Models/`.
- **Streaming APIs:** `AttachContainerSessionAsync`, `StartExecSessionAsync` (`IPodmanAttachSession`), `PullImageWithProgressAsync`, `BuildImageWithProgressAsync` (`IPodmanProgressSession<T>`), plus hijack connection and multiplex protocol internals.
- Shared HTTP helpers in `PodmanClient.Http.cs` and NDJSON stream handling in `PodmanNdjsonStreams`.
- `IPodmanClientConfiguration`, `AddPodmanClient` (`IHttpClientFactory` / `AddHttpClient`); host apps supply their own configuration implementation.
- Unit tests for streaming, NDJSON, and hijack mock server; integration tests tagged `Category=Integration` (skip without `PODMAN_TEST_URL`).
- `CHANGELOG.md`, `CONTRIBUTING.md`, coverage badge assets, and `utils/` (RepoUtils test/release engines).
### Changed
- Target framework upgraded to **.NET 10** (`net10.0`).
- API methods return **MaksIT.Results** `Result` / `Result<T>` instead of throwing on Podman HTTP errors.
- Added **MaksIT.Core** and **MaksIT.Results** dependencies; removed local `Extensions` (`ToJson` / `ToObject`) in favor of `MaksIT.Core.Extensions`.
- `PodmanClient` split into partials (`PodmanClient.Http.cs`, `PodmanClient.Containers.Api.cs`, etc.); solution file migrated to `PodmanClientDotNet.slnx`.
- Package metadata, Source Link, symbol packages, and documentation generation aligned with [maksit-core](https://github.com/MAKS-IT-COM/maksit-core) standards.
- Registry auth (`X-Registry-Auth`) applied per HTTP request instead of mutating shared `HttpClient.DefaultRequestHeaders`.
- Replaced legacy `src/Release-NuGetPackage.*` scripts and `.nuspec` with SDK-style pack + `utils/` release tooling.
### Fixed
- Pull, push, and build endpoints consume NDJSON progress streams correctly; `BuildImageAsync` no longer deserializes a multi-line build stream as a single JSON object.
- Attach hijack requests include the `tty` query parameter.
- Manual `PodmanClient` constructor preserves caller-configured `HttpClient.Timeout` (no longer truncated via integer minutes cast).
### Removed
- Concrete `PodmanClientConfiguration` type from the library package.
- Monolithic `PodmanClientContainer.cs`, `PodmanClientExec.cs`, and `PodmanClientImage.cs` (superseded by partials).
### Breaking
- Method return types changed from `Task` / `Task<T?>` to `Result` / `Result<T?>`.
- Response types moved to `Dtos/`; update usings from `Models.*` response classes.
- Removed `PodmanClientConfiguration`; bind `IPodmanClientConfiguration` with a host-owned options class.
- Prefer `IPodmanClient` and `AddPodmanClient` for DI; manual `PodmanClient` constructors remain for tests and simple hosts.
## [1.0.4] - 2024-08-18
### Added
- Integration tests for container lifecycle, exec, and image pull/tag.
### Fixed
- Empty-string JSON parse issue in HTTP response handling.
### Changed
- Package readme and repository documentation updates.
## [1.0.2] - 2024-08-17
### Added
- Initial **PodmanClient.DotNet** library on **.NET 8** (`net8.0`).
- Container operations: create, start, stop, delete, archive copy.
- Exec operations: create, start, inspect.
- Image operations: pull, tag.
- NuGet packaging (`.nuspec`, `Release-NuGetPackage` scripts) and README.

63
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,63 @@
# Contributing to PodmanClient.DotNet
Thank you for contributing. This repo follows MaksIT conventions (see `AGENTS.md` and homelab `common/csharp` / `common/maksit-repo-maintenance` skills).
## Development setup
### Prerequisites
- .NET 10 SDK
- Git
- Optional: reachable Podman API for integration tests (`PODMAN_TEST_URL` or `PODMAN_INTEGRATION_URL`)
### Build
```bash
dotnet build src/PodmanClientDotNet.slnx
```
### Tests
**RepoUtils test engine** (coverage + badges):
```bash
utils/Invoke-TestEngine.bat
```
**Direct:**
```bash
dotnet test src/PodmanClientDotNet.Tests/PodmanClientDotNet.Tests.csproj
```
When coverage changes and the test engine runs **CoverageBadges**, commit updated SVGs under `assets/badges/` (cited in `README.md`).
## Commit message format
```text
(type): description
```
Types: `(feature):`, `(bugfix):`, `(refactor):`, `(perf):`, `(test):`, `(docs):`, `(build):`, `(ci):`, `(style):`, `(revert):`, `(chore):`.
- Lowercase description; no trailing period.
## Code style
- **.NET 10**, nullable reference types, implicit usings.
- **Root namespace**: `MaksIT.$(MSBuildProjectName)` in `PodmanClientDotNet.csproj`; omit `namespace` when it matches the root (client partials, abstractions).
- **MaksIT.Results** for API outcomes; **MaksIT.Core.Extensions** for JSON (`ToJson` / `ToObject<T>`).
- File-scoped namespaces and same-line braces; **Models/** use nullable reference types (`string?`, `List<T>?`, …) for optional JSON fields.
- XML documentation on public types (DTOs, interfaces, entry types). Method-level docs on large interfaces are optional (`CS1591` suppressed).
- Model layout helpers: `utils/tools/Polish-PodmanClientSources.ps1`, `utils/tools/Enable-ModelsNullable.ps1`.
## Pull requests
1. Build and tests pass.
2. Update **README.md** / **CHANGELOG.md** when behavior or public API changes.
3. Refresh **`assets/badges/*.svg`** when coverage badges change.
4. Keep diffs scoped.
## Versioning
[Semantic Versioning](https://semver.org): bump `Version` in `src/PodmanClient/PodmanClientDotNet.csproj` with **CHANGELOG.md** for releases. Use `utils/Invoke-ReleasePackage.bat` when releasing.

155
README.md
View File

@ -1,5 +1,7 @@
# PodmanClient.DotNet
![Line Coverage](assets/badges/coverage-lines.svg) ![Branch Coverage](assets/badges/coverage-branches.svg) ![Method Coverage](assets/badges/coverage-methods.svg)
## Description
`PodmanClient.DotNet` is a .NET library designed to provide seamless interaction with the Podman API, allowing developers to manage and control containers directly from their .NET applications. This client library wraps the Podman API endpoints, offering a .NET-friendly interface to perform common container operations such as creating, starting, stopping, deleting containers, and more.
@ -10,13 +12,12 @@ The primary goal of `PodmanClient.DotNet` is to simplify the integration of Podm
## Key Features
- **Container Management:** Create, start, stop, and delete containers with straightforward methods.
- **Image Operations:** Pull, tag, and manage images using the Podman API.
- **Exec Support:** Execute commands inside running containers, with support for attaching input/output streams.
- **Volume and Network Management:** Manage container volumes and networks as needed.
- **Streamlined Error Handling:** Provides detailed error handling, with informative responses based on HTTP status codes.
- **Customizable HTTP Client:** Easily configure and inject your own `HttpClient` instance for extended control and customization.
- **Full Libpod API surface:** System, containers, images, volumes, networks, pods, exec, build, manifests, and generate/play/kube (see `IPodmanClient` and domain interfaces under `Abstractions/`).
- **Domain-oriented API:** `IPodmanContainersClient`, `IPodmanImagesClient`, `IPodmanVolumesClient`, and related interfaces; `IPodmanClient` composes them all.
- **Structured results:** API methods return `MaksIT.Results.Result` / `Result<T>` instead of throwing on Podman HTTP errors.
- **Dependency injection:** Register with `AddHttpClient` via `AddPodmanClient` and inject `IPodmanClient`.
- **Logging Support:** Integrated logging support via `Microsoft.Extensions.Logging` for better observability.
- **Streaming:** Full-duplex attach/exec sessions (`IPodmanAttachSession`) and NDJSON progress for pull/build (`IPodmanProgressSession<T>`).
## Installation
@ -28,20 +29,64 @@ dotnet add package PodmanClient.DotNet
## Usage Examples
### Initialize the PodmanClient
### Dependency injection (recommended)
`appsettings.json`:
```json
{
"PodmanClient": {
"ServerUrl": "http://localhost:8080",
"ApiVersion": "v1.41",
"TimeoutMinutes": 5
}
}
```
```csharp
using MaksIT.PodmanClientDotNet;
using MaksIT.PodmanClientDotNet.Extensions;
// Host-owned options type (not shipped in this package)
public sealed class PodmanClientOptions : IPodmanClientConfiguration {
public string ServerUrl { get; set; } = string.Empty;
public string ApiVersion { get; set; } = "v1.41";
public int TimeoutMinutes { get; set; } = 60;
}
var podmanConfiguration = builder.Configuration
.GetSection(IPodmanClientConfiguration.SectionName)
.Get<PodmanClientOptions>()
?? throw new InvalidOperationException("PodmanClient configuration is missing.");
builder.Services.AddPodmanClient(podmanConfiguration);
// Inject IPodmanClient where needed
public sealed class ContainerService(IPodmanClient podman) {
public async Task<Result> RunAsync() {
var create = await podman.CreateContainerAsync("my-container", "alpine:latest");
if (!create.IsSuccess)
return create.ToResult();
return await podman.StartContainerAsync(create.Value!.Id);
}
}
```
### Manual construction
```csharp
using Microsoft.Extensions.Logging;
using MaksIT.PodmanClient.DotNet;
using MaksIT.PodmanClientDotNet;
var logger = LoggerFactory.Create(builder => builder.AddConsole()).CreateLogger<PodmanClient>();
var podmanClient = new PodmanClient(logger, "http://localhost:8080", 5);
IPodmanClient podmanClient = new PodmanClient(logger, "http://localhost:8080", 5);
```
### Create and Start a Container
```csharp
var createResponse = await podmanClient.CreateContainerAsync(
var createResult = await podmanClient.CreateContainerAsync(
name: "my-container",
image: "alpine:latest",
command: new List<string> { "/bin/sh" },
@ -49,20 +94,24 @@ var createResponse = await podmanClient.CreateContainerAsync(
remove: true
);
await podmanClient.StartContainerAsync(createResponse.Id);
if (!createResult.IsSuccess)
return createResult.ToActionResult(); // in ASP.NET Core controllers
await podmanClient.StartContainerAsync(createResult.Value!.Id);
```
### Execute a Command in a Container
```csharp
var execResponse = await podmanClient.CreateExecAsync(createResponse.Id, new[] { "echo", "Hello, World!" });
await podmanClient.StartExecAsync(execResponse.Id);
var execResult = await podmanClient.CreateExecAsync(createResult.Value!.Id, new[] { "echo", "Hello, World!" });
if (execResult.IsSuccess)
await podmanClient.StartExecAsync(execResult.Value!.Id);
```
### Pull an Image
```csharp
await podmanClient.PullImageAsync("alpine:latest");
var pullResult = await podmanClient.PullImageAsync("alpine:latest");
```
### Tag an Image
@ -71,28 +120,60 @@ await podmanClient.PullImageAsync("alpine:latest");
await podmanClient.TagImageAsync("alpine:latest", "myrepo", "mytag");
```
### Full-duplex attach (container or exec)
Use session APIs for multiplexed stdin/stdout/stderr (or raw TTY) instead of a one-shot `Stream`:
```csharp
var attach = await podmanClient.AttachContainerSessionAsync(
containerId, stream: true, stdout: true, stderr: true, stdin: true, tty: false);
if (!attach.IsSuccess) return;
await using var session = attach.Value!;
while (await session.ReadFrameAsync() is { } frame)
Console.Write(frame.StreamType + ": " + Encoding.UTF8.GetString(frame.Data));
await session.WriteStdinAsync("input"u8.ToArray());
await session.CloseWriteAsync();
```
Exec hijack: `CreateExecAsync``StartExecSessionAsync(execId, tty: false)`.
Pull/build progress (NDJSON): `PullImageWithProgressAsync` / `BuildImageWithProgressAsync` return `IPodmanProgressSession<T>`; enumerate with `await foreach (var line in session.ReadProgressAsync())`.
## Available Methods
### `PodmanClient`
### `IPodmanClient`
- **Container Management**
- `Task<CreateContainerResponse> CreateContainerAsync(...)`: Creates a new container.
- `Task StartContainerAsync(string containerId, string detachKeys = "ctrl-p,ctrl-q")`: Starts an existing container.
- `Task StopContainerAsync(string containerId, int timeout = 10, bool ignoreAlreadyStopped = false)`: Stops a running container.
- `Task DeleteContainerAsync(string containerId, bool depend = false, bool ignore = false, int timeout = 10)`: Deletes a container.
- `Task ForceDeleteContainerAsync(string containerId, bool deleteVolumes = false, int timeout = 10)`: Forcefully deletes a container, optionally removing associated volumes.
Register with `AddPodmanClient` or construct `PodmanClient` manually. Methods return `Result` / `Result<T>` from **MaksIT.Results**.
- **Exec Management**
- `Task<CreateExecResponse> CreateExecAsync(...)`: Creates an exec instance in a running container.
- `Task StartExecAsync(string execId, bool detach = false, bool tty = false, int? height = null, int? width = null)`: Starts an exec instance.
- `Task<InspectExecResponse?> InspectExecAsync(string execId)`: Inspects an exec instance to retrieve its details.
| Interface | Coverage |
|-----------|----------|
| `IPodmanSystemClient` | ping, version, info, events, disk usage, system prune |
| `IPodmanContainersClient` | create, list, inspect, lifecycle, logs, stats, archive, attach, commit, checkpoint, prune, … |
| `IPodmanImagesClient` | pull, push, list, inspect, tag, untag, search, load, import, export, prune, … |
| `IPodmanVolumesClient` | create, list, inspect, delete, prune |
| `IPodmanNetworksClient` | create, list, inspect, delete, connect, disconnect |
| `IPodmanPodsClient` | create, list, inspect, lifecycle, stats, prune, … |
| `IPodmanExecClient` | create, start, resize, inspect |
| `IPodmanBuildClient` | `BuildImageAsync` |
| `IPodmanManifestsClient` | create, inspect, add, push, delete |
| `IPodmanGenerateClient` | systemd unit, kube yaml, play kube |
- **Image Operations**
- `Task PullImageAsync(...)`: Pulls an image from a container registry.
- `Task TagImageAsync(string image, string repo, string tag)`: Tags an existing image with a new repository and tag.
API responses are typed under `Dtos/` (for example `ContainerInspectDto`, `ImageInspectDto`, `InfoDto`). Request/spec payloads remain in `Models/`.
- **File Operations**
- `Task ExtractArchiveToContainerAsync(string containerId, Stream tarStream, string path, bool pause = true)`: Extracts files from a tar stream into a container.
## Tests
Unit tests cover multiplex framing, attach sessions, NDJSON progress, and a local hijack mock server. Integration tests require a reachable Podman API:
```shell
$env:PODMAN_TEST_URL = "http://localhost:8080"
dotnet test src/PodmanClientDotNet.Tests/PodmanClientDotNet.Tests.csproj
```
Without `PODMAN_TEST_URL` (or `PODMAN_INTEGRATION_URL`), integration tests are skipped automatically. Filter them in CI with `--filter "Category!=Integration"`.
**Note:** Full-duplex attach/exec sessions use a raw TCP hijack connection and do not flow through `HttpClient` delegating handlers (proxy, client certificates, etc.). Configure network access accordingly.
## Documentation (TODO: Agile)
@ -100,18 +181,11 @@ For detailed documentation on each method, including parameter descriptions and
## Contribution
Contributions to this project are welcome! Please fork the repository and submit a pull request with your changes. If you encounter any issues or have feature requests, feel free to open an issue on GitHub.
## Contact
If you have any questions or need further assistance, feel free to reach out:
- **Email**: [maksym.sadovnychyy@gmail.com](mailto:maksym.sadovnychyy@gmail.com)
- **Reddit**: [PodmanClient.DotNet: A .NET Library for Streamlined Podman API Integration](https://www.reddit.com/r/MaksIT/comments/1evel9z/podmanclientdotnet_a_net_library_for_streamlined/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button)
Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for build/test commands, commit format, and PR expectations. Open an issue on GitHub for bugs or feature requests.
## License
This project is licensed under the MIT License. See the full license text below.
This project is licensed under the MIT License. See [LICENSE.md](LICENSE.md).
---
@ -143,4 +217,5 @@ SOFTWARE.
## Contact
For any questions or inquiries, please reach out via GitHub or [email](mailto:maksym.sadovnychyy@gmail.com).
- **Email**: [maksym.sadovnychyy@gmail.com](mailto:maksym.sadovnychyy@gmail.com)
- **Reddit**: [PodmanClient.DotNet: A .NET Library for Streamlined Podman API Integration](https://www.reddit.com/r/MaksIT/comments/1evel9z/podmanclientdotnet_a_net_library_for_streamlined/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button)

View File

@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" width="150" height="20" role="img" aria-label="Branch Coverage: 20.9%">
<title>Branch Coverage: 20.9%</title>
<linearGradient id="s" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<clipPath id="r">
<rect width="150" height="20" rx="3" fill="#fff"/>
</clipPath>
<g clip-path="url(#r)">
<rect width="107.5" height="20" fill="#555"/>
<rect x="107.5" width="42.5" height="20" fill="#dfb317"/>
<rect width="150" height="20" fill="url(#s)"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="11">
<text aria-hidden="true" x="53.75" y="15" fill="#010101" fill-opacity=".3">Branch Coverage</text>
<text x="53.75" y="14" fill="#fff">Branch Coverage</text>
<text aria-hidden="true" x="128.75" y="15" fill="#010101" fill-opacity=".3">20.9%</text>
<text x="128.75" y="14" fill="#fff">20.9%</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" width="134.5" height="20" role="img" aria-label="Line Coverage: 10%">
<title>Line Coverage: 10%</title>
<linearGradient id="s" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<clipPath id="r">
<rect width="134.5" height="20" rx="3" fill="#fff"/>
</clipPath>
<g clip-path="url(#r)">
<rect width="94.5" height="20" fill="#555"/>
<rect x="94.5" width="40" height="20" fill="#fe7d37"/>
<rect width="134.5" height="20" fill="url(#s)"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="11">
<text aria-hidden="true" x="47.25" y="15" fill="#010101" fill-opacity=".3">Line Coverage</text>
<text x="47.25" y="14" fill="#fff">Line Coverage</text>
<text aria-hidden="true" x="114.5" y="15" fill="#010101" fill-opacity=".3">10%</text>
<text x="114.5" y="14" fill="#fff">10%</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" width="147.5" height="20" role="img" aria-label="Method Coverage: 3.9%">
<title>Method Coverage: 3.9%</title>
<linearGradient id="s" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<clipPath id="r">
<rect width="147.5" height="20" rx="3" fill="#fff"/>
</clipPath>
<g clip-path="url(#r)">
<rect width="107.5" height="20" fill="#555"/>
<rect x="107.5" width="40" height="20" fill="#e05d44"/>
<rect width="147.5" height="20" fill="url(#s)"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="11">
<text aria-hidden="true" x="53.75" y="15" fill="#010101" fill-opacity=".3">Method Coverage</text>
<text x="53.75" y="14" fill="#fff">Method Coverage</text>
<text aria-hidden="true" x="127.5" y="15" fill="#010101" fill-opacity=".3">3.9%</text>
<text x="127.5" y="14" fill="#fff">3.9%</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

View File

@ -0,0 +1,38 @@
using MaksIT.PodmanClientDotNet.Dtos.Build;
using MaksIT.PodmanClientDotNet.Streaming;
using MaksIT.Results;
/// <summary>
/// Image build endpoints (including streaming progress).
/// </summary>
public interface IPodmanBuildClient {
Task<Result<BuildReportDto?>> BuildImageAsync(
string dockerfile,
Stream? context = null,
bool pull = false,
bool rm = true,
bool forcerm = false,
bool nocache = false,
string? remote = null,
string? t = null,
string? platform = null,
string? buildargs = null,
string? labels = null,
CancellationToken cancellationToken = default
);
Task<Result<IPodmanProgressSession<BuildProgressLineDto>?>> BuildImageWithProgressAsync(
string dockerfile,
Stream? context = null,
bool pull = false,
bool rm = true,
bool forcerm = false,
bool nocache = false,
string? remote = null,
string? t = null,
string? platform = null,
string? buildargs = null,
string? labels = null,
CancellationToken cancellationToken = default
);
}

View File

@ -0,0 +1,244 @@
using MaksIT.PodmanClientDotNet.Dtos.Common;
using MaksIT.PodmanClientDotNet.Dtos.Container;
using MaksIT.PodmanClientDotNet.Models;
using MaksIT.PodmanClientDotNet.Models.Container;
using MaksIT.PodmanClientDotNet.Streaming;
using MaksIT.Results;
/// <summary>
/// Container lifecycle, inspection, attach, logs, archive, and related libpod endpoints.
/// </summary>
public interface IPodmanContainersClient {
Task<Result<CreateContainerResponseDto?>> CreateContainerAsync(
string name,
string image,
List<string>? command = null,
Dictionary<string, string>? env = null,
bool? remove = null,
bool? stdin = null,
bool? terminal = null,
List<Mount>? mounts = null,
bool? privileged = null,
string? hostname = null,
Namespace? netns = null,
List<PortMapping>? portMappings = null,
string? restartPolicy = null,
ulong? stopTimeout = null,
List<string>? capAdd = null,
List<string>? capDrop = null,
List<string>? dnsServers = null,
List<string>? dnsSearch = null,
List<string>? dnsOptions = null,
bool? publishImagePorts = null,
List<string>? cniNetworks = null,
Dictionary<string, string>? labels = null,
bool? readOnlyFilesystem = null,
List<POSIXRlimit>? rLimits = null,
List<LinuxDevice>? devices = null,
string? ociRuntime = null,
string? pod = null,
bool? noNewPrivileges = null,
string? cgroupsMode = null,
Dictionary<string, string>? storageOpts = null,
bool? unsetenvall = null,
Dictionary<string, string>? secretEnv = null,
string? timezone = null,
Dictionary<string, string>? sysctl = null,
string? seccompProfilePath = null,
string? seccompPolicy = null,
Dictionary<string, string>? annotations = null,
string? apparmorProfile = null,
string? baseHostsFile = null,
string? cgroupParent = null,
Namespace? cgroupns = null,
List<string>? chrootDirectories = null,
string? conmonPidFile = null,
List<string>? containerCreateCommand = null,
bool? createWorkingDir = null,
List<string>? dependencyContainers = null,
List<LinuxDeviceCgroup>? deviceCgroupRule = null,
List<string>? devicesFrom = null,
List<string>? entrypoint = null,
bool? envHost = null,
List<string>? envMerge = null,
Dictionary<ushort, string>? expose = null,
string? groupEntry = null,
List<string>? groups = null,
long? healthCheckOnFailureAction = null,
Schema2HealthConfig? healthConfig = null,
List<LinuxDevice>? hostDeviceList = null,
List<string>? hostAdd = null,
List<string>? hostUsers = null,
bool? envHTTPProxy = null,
IDMappingOptions? idMappings = null,
string? imageArch = null,
string? imageOS = null,
string? imageVariant = null,
string? imageVolumeMode = null,
List<ImageVolume>? imageVolumes = null,
bool? init = null,
string? initContainerType = null,
string? initPath = null,
LinuxIntelRdt? intelRdt = null,
Namespace? ipcns = null,
bool? labelNested = null,
LogConfigLibpod? logConfiguration = null,
bool? managePassword = null,
List<string>? mask = null,
Dictionary<string, string>? networkOptions = null,
Dictionary<string, NetworkSettings>? networks = null,
long? oomScoreAdj = null,
List<OverlayVolume>? overlayVolumes = null,
string? passwdEntry = null,
LinuxPersonality? personality = null,
Namespace? pidns = null,
string? rawImageName = null,
bool? readWriteTmpfs = null,
LinuxResources? resourceLimits = null,
ulong? restartTries = null,
string? rootfs = null,
string? rootfsMapping = null,
bool? rootfsOverlay = null,
string? rootfsPropagation = null,
string? sdnotifyMode = null,
List<SecretProp>? secrets = null,
List<string>? selinuxOpts = null,
long? shmSize = null,
long? shmSizeSystemd = null,
StartupHealthConfig? startupHealthConfig = null,
long? stopSignal = null,
string? systemd = null,
Dictionary<string, ulong>? throttleReadBpsDevice = null,
Dictionary<string, ulong>? throttleReadIopsDevice = null,
Dictionary<string, ulong>? throttleWriteBpsDevice = null,
Dictionary<string, ulong>? throttleWriteIopsDevice = null,
ulong? timeout = null,
string? umask = null,
Dictionary<string, string>? unified = null,
List<string>? unmask = null,
bool? useImageHosts = null,
bool? useImageResolvConf = null,
string? user = null,
Namespace? userns = null,
Namespace? utsns = null,
bool? volatileFlag = null,
List<NamedVolume>? volumes = null,
List<string>? volumesFrom = null,
Dictionary<string, ulong>? weightDevice = null,
string? workDir = null
);
Task<Result> StartContainerAsync(string containerId, string detachKeys = "ctrl-p,ctrl-q");
Task<Result> StopContainerAsync(string containerId, int timeout = 10, bool ignoreAlreadyStopped = false);
Task<Result<DeleteContainerResponseDto[]?>> ForceDeleteContainerAsync(string containerId, bool deleteVolumes = false, int timeout = 10);
Task<Result<DeleteContainerResponseDto[]?>> DeleteContainerAsync(string containerId, bool depend = false, bool ignore = false, int timeout = 10);
Task<Result> ExtractArchiveToContainerAsync(string containerId, Stream tarStream, string path, bool pause = true);
Task<Result<List<ContainerListEntryDto>?>> ListContainersAsync(
bool all = false,
int? limit = null,
bool size = false,
bool sync = false,
string? filters = null,
CancellationToken cancellationToken = default
);
Task<Result<ContainerInspectDto?>> InspectContainerAsync(string name, CancellationToken cancellationToken = default);
Task<Result> ContainerExistsAsync(string name, CancellationToken cancellationToken = default);
Task<Result> RestartContainerAsync(string name, int timeout = 10, CancellationToken cancellationToken = default);
Task<Result> KillContainerAsync(string name, string signal = "TERM", CancellationToken cancellationToken = default);
Task<Result> PauseContainerAsync(string name, CancellationToken cancellationToken = default);
Task<Result> UnpauseContainerAsync(string name, CancellationToken cancellationToken = default);
Task<Result<ContainerWaitDto?>> WaitContainerAsync(string name, string? condition = null, CancellationToken cancellationToken = default);
Task<Result<Stream?>> GetContainerLogsAsync(
string name,
bool follow = false,
bool stdout = true,
bool stderr = true,
bool timestamps = false,
string? since = null,
string? until = null,
string? tail = null,
CancellationToken cancellationToken = default
);
Task<Result<ContainerStatsDto?>> GetContainerStatsAsync(string name, bool stream = false, CancellationToken cancellationToken = default);
Task<Result<Dictionary<string, ContainerStatsDto>?>> GetContainersStatsAsync(
IEnumerable<string>? containers = null,
bool stream = false,
CancellationToken cancellationToken = default
);
Task<Result<PruneReportDto?>> PruneContainersAsync(string? filters = null, CancellationToken cancellationToken = default);
Task<Result> RenameContainerAsync(string name, string newName, CancellationToken cancellationToken = default);
Task<Result> InitContainerAsync(string name, CancellationToken cancellationToken = default);
Task<Result<Stream?>> CheckpointContainerAsync(
string name,
bool keep = false,
bool leaveRunning = false,
bool tcpEstablished = false,
bool export = false,
bool ignoreRootFS = false,
CancellationToken cancellationToken = default
);
Task<Result> RestoreContainerAsync(
string name,
string? importPath = null,
bool keep = false,
bool leaveRunning = false,
bool tcpEstablished = false,
bool ignoreRootFS = false,
bool ignoreStaticIP = false,
bool ignoreStaticMAC = false,
CancellationToken cancellationToken = default
);
Task<Result<ContainerMountDto?>> MountContainerAsync(string name, CancellationToken cancellationToken = default);
Task<Result> UnmountContainerAsync(string name, CancellationToken cancellationToken = default);
Task<Result<Stream?>> ExportContainerAsync(string name, CancellationToken cancellationToken = default);
Task<Result<Stream?>> GetContainerArchiveAsync(string name, string path, CancellationToken cancellationToken = default);
Task<Result> PutContainerArchiveAsync(string containerId, Stream tarStream, string path, bool pause = true, CancellationToken cancellationToken = default);
Task<Result<Stream?>> AttachContainerAsync(
string name,
bool logs = false,
bool stream = true,
bool stdout = true,
bool stderr = true,
bool stdin = false,
string? detachKeys = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Opens a full-duplex attach session (multiplexed or raw TTY) over a hijacked HTTP connection.
/// </summary>
Task<Result<IPodmanAttachSession?>> AttachContainerSessionAsync(
string name,
bool logs = false,
bool stream = true,
bool stdout = true,
bool stderr = true,
bool stdin = true,
bool tty = false,
string? detachKeys = null,
CancellationToken cancellationToken = default
);
Task<Result<ContainerChangesDto?>> GetContainerChangesAsync(string name, CancellationToken cancellationToken = default);
Task<Result<ContainerCommitDto?>> CommitContainerAsync(
string container,
string? repo = null,
string? tag = null,
string? comment = null,
string? author = null,
bool pause = true,
IEnumerable<string>? changes = null,
string? format = null,
CancellationToken cancellationToken = default
);
Task<Result<ContainerHealthCheckDto?>> HealthCheckContainerAsync(string name, CancellationToken cancellationToken = default);
Task<Result<MountedContainersResponseDto?>> GetMountedContainersAsync(CancellationToken cancellationToken = default);
Task<Result<ContainerTopDto?>> TopContainerAsync(string name, string psArgs = "-ef", bool stream = true, CancellationToken cancellationToken = default);
}

View File

@ -0,0 +1,44 @@
using MaksIT.PodmanClientDotNet.Dtos.Exec;
using MaksIT.PodmanClientDotNet.Streaming;
using MaksIT.Results;
/// <summary>
/// Exec session create, start, resize, and inspect endpoints.
/// </summary>
public interface IPodmanExecClient {
Task<Result<CreateExecResponseDto?>> CreateExecAsync(
string containerName,
string[] cmd,
bool attachStderr = true,
bool attachStdin = false,
bool attachStdout = true,
string? detachKeys = null,
string[]? env = null,
bool privileged = false,
bool tty = false,
string? user = null,
string? workingDir = null
);
Task<Result> StartExecAsync(
string execId,
bool detach = false,
bool tty = false,
int? height = null,
int? width = null
);
Task<Result<InspectExecResponseDto?>> InspectExecAsync(string execId);
Task<Result> ResizeExecAsync(string execId, int height, int width, CancellationToken cancellationToken = default);
/// <summary>
/// Starts exec and returns a full-duplex attach session (requires <c>detach=false</c> on the wire).
/// </summary>
Task<Result<IPodmanAttachSession?>> StartExecSessionAsync(
string execId,
bool tty = false,
int? height = null,
int? width = null,
CancellationToken cancellationToken = default
);
}

View File

@ -0,0 +1,34 @@
using MaksIT.PodmanClientDotNet.Dtos.Generate;
using MaksIT.Results;
/// <summary>
/// Generate systemd units, kube YAML, and play-kube endpoints.
/// </summary>
public interface IPodmanGenerateClient {
Task<Result<GenerateSystemdDto?>> GenerateSystemdAsync(
string name,
bool useName = false,
bool createNew = false,
int? restartSec = null,
string? restartPolicy = null,
string? containerPrefix = null,
string? podPrefix = null,
string? separator = null,
CancellationToken cancellationToken = default
);
Task<Result<string?>> GenerateKubeAsync(
IEnumerable<string> names,
bool service = false,
CancellationToken cancellationToken = default
);
Task<Result<PlayKubeReportDto?>> PlayKubeAsync(
Stream yaml,
string? network = null,
bool tlsVerify = true,
bool start = true,
string? logDriver = null,
CancellationToken cancellationToken = default
);
}

View File

@ -0,0 +1,86 @@
using MaksIT.PodmanClientDotNet.Dtos.Common;
using MaksIT.PodmanClientDotNet.Dtos.Image;
using MaksIT.PodmanClientDotNet.Streaming;
using MaksIT.Results;
/// <summary>
/// Image pull, push, list, inspect, tag, search, load, import, export, and prune endpoints.
/// </summary>
public interface IPodmanImagesClient {
Task<Result> PullImageAsync(
string reference,
bool tlsVerify = true,
bool quiet = false,
string policy = "always",
string? arch = null,
string? os = null,
string? variant = null,
bool allTags = false,
string? authHeader = null
);
Task<Result> TagImageAsync(string image, string repo, string tag);
Task<Result<List<ImageListEntryDto>?>> ListImagesAsync(
bool all = false,
string? filters = null,
CancellationToken cancellationToken = default
);
Task<Result<ImageInspectDto?>> InspectImageAsync(string name, CancellationToken cancellationToken = default);
Task<Result> ImageExistsAsync(string name, CancellationToken cancellationToken = default);
Task<Result<ImageDeleteDto[]?>> DeleteImageAsync(string name, bool force = false, CancellationToken cancellationToken = default);
Task<Result<ImageDeleteDto[]?>> RemoveImagesAsync(
IEnumerable<string> images,
bool all = false,
bool force = false,
CancellationToken cancellationToken = default
);
Task<Result<PruneReportDto?>> PruneImagesAsync(CancellationToken cancellationToken = default);
Task<Result<List<ImageSearchResultDto>?>> SearchImagesAsync(string term, int? limit = null, CancellationToken cancellationToken = default);
Task<Result> PushImageAsync(
string name,
string? destination = null,
bool tlsVerify = true,
bool compress = false,
string? authHeader = null,
CancellationToken cancellationToken = default
);
Task<Result> UntagImageAsync(string name, string? repo = null, string? tag = null, CancellationToken cancellationToken = default);
Task<Result<List<ImageHistoryEntryDto>?>> GetImageHistoryAsync(string name, CancellationToken cancellationToken = default);
Task<Result<ImageTreeDto?>> GetImageTreeAsync(string name, CancellationToken cancellationToken = default);
Task<Result<ImageChangesDto?>> GetImageChangesAsync(string name, CancellationToken cancellationToken = default);
Task<Result<ImageImportDto?>> ImportImageAsync(
Stream? tarball = null,
string? changes = null,
string? message = null,
string? reference = null,
string? url = null,
CancellationToken cancellationToken = default
);
Task<Result<ImageLoadDto?>> LoadImageAsync(Stream tarball, CancellationToken cancellationToken = default);
Task<Result<Stream?>> ExportImagesAsync(
IEnumerable<string> references,
string? format = null,
bool compress = false,
CancellationToken cancellationToken = default
);
Task<Result<Stream?>> GetImageAsync(string name, string? format = null, bool compress = false, CancellationToken cancellationToken = default);
Task<Result<IPodmanProgressSession<PullImageResponseDto>?>> PullImageWithProgressAsync(
string reference,
bool tlsVerify = true,
bool quiet = false,
string policy = "always",
string? arch = null,
string? os = null,
string? variant = null,
bool allTags = false,
string? authHeader = null,
CancellationToken cancellationToken = default
);
}

View File

@ -0,0 +1,19 @@
using MaksIT.PodmanClientDotNet.Dtos.Manifest;
using MaksIT.Results;
/// <summary>
/// Manifest list create, inspect, add, push, and delete endpoints.
/// </summary>
public interface IPodmanManifestsClient {
Task<Result<ManifestCreateDto?>> CreateManifestAsync(
string name,
string? image = null,
bool all = false,
CancellationToken cancellationToken = default
);
Task<Result> DeleteManifestAsync(string name, string? digest = null, CancellationToken cancellationToken = default);
Task<Result<ManifestInspectDto?>> InspectManifestAsync(string name, CancellationToken cancellationToken = default);
Task<Result> AddToManifestAsync(string name, ManifestAddRequestDto request, CancellationToken cancellationToken = default);
Task<Result> PushManifestAsync(string name, string destination, bool all = false, CancellationToken cancellationToken = default);
}

View File

@ -0,0 +1,15 @@
using MaksIT.PodmanClientDotNet.Dtos.Network;
using MaksIT.PodmanClientDotNet.Models.Network;
using MaksIT.Results;
/// <summary>
/// Network create, list, inspect, delete, connect, and disconnect endpoints.
/// </summary>
public interface IPodmanNetworksClient {
Task<Result<NetworkListEntryDto?>> CreateNetworkAsync(NetworkCreateRequest request, CancellationToken cancellationToken = default);
Task<Result<List<NetworkListEntryDto>?>> ListNetworksAsync(CancellationToken cancellationToken = default);
Task<Result<NetworkInspectDto?>> InspectNetworkAsync(string name, CancellationToken cancellationToken = default);
Task<Result> DeleteNetworkAsync(string name, CancellationToken cancellationToken = default);
Task<Result> ConnectNetworkAsync(string name, NetworkConnectRequest request, CancellationToken cancellationToken = default);
Task<Result> DisconnectNetworkAsync(string name, NetworkDisconnectRequest request, CancellationToken cancellationToken = default);
}

View File

@ -0,0 +1,24 @@
using MaksIT.PodmanClientDotNet.Dtos.Common;
using MaksIT.PodmanClientDotNet.Dtos.Pod;
using MaksIT.PodmanClientDotNet.Models.Pod;
using MaksIT.Results;
/// <summary>
/// Pod create, list, inspect, lifecycle, stats, and prune endpoints.
/// </summary>
public interface IPodmanPodsClient {
Task<Result<PodListEntryDto?>> CreatePodAsync(PodCreateRequest request, CancellationToken cancellationToken = default);
Task<Result<List<PodListEntryDto>?>> ListPodsAsync(bool all = false, CancellationToken cancellationToken = default);
Task<Result<PodInspectDto?>> InspectPodAsync(string name, CancellationToken cancellationToken = default);
Task<Result> PodExistsAsync(string name, CancellationToken cancellationToken = default);
Task<Result> DeletePodAsync(string name, bool force = false, CancellationToken cancellationToken = default);
Task<Result> StartPodAsync(string name, CancellationToken cancellationToken = default);
Task<Result> StopPodAsync(string name, int timeout = 10, CancellationToken cancellationToken = default);
Task<Result> RestartPodAsync(string name, int timeout = 10, CancellationToken cancellationToken = default);
Task<Result> KillPodAsync(string name, string? signal = null, CancellationToken cancellationToken = default);
Task<Result> PausePodAsync(string name, CancellationToken cancellationToken = default);
Task<Result> UnpausePodAsync(string name, CancellationToken cancellationToken = default);
Task<Result<PruneReportDto?>> PrunePodsAsync(CancellationToken cancellationToken = default);
Task<Result<PodTopDto?>> TopPodAsync(string name, CancellationToken cancellationToken = default);
Task<Result<PodStatsResponseDto?>> GetPodsStatsAsync(CancellationToken cancellationToken = default);
}

View File

@ -0,0 +1,15 @@
using MaksIT.PodmanClientDotNet.Dtos.Common;
using MaksIT.PodmanClientDotNet.Dtos.System;
using MaksIT.Results;
/// <summary>
/// Podman system endpoints: ping, version, info, events, disk usage, and prune.
/// </summary>
public interface IPodmanSystemClient {
Task<Result<LibpodPingDto?>> PingAsync(CancellationToken cancellationToken = default);
Task<Result<LibpodVersionDto?>> GetVersionAsync(CancellationToken cancellationToken = default);
Task<Result<InfoDto?>> GetInfoAsync(CancellationToken cancellationToken = default);
Task<Result<SystemDfDto?>> GetSystemDiskUsageAsync(CancellationToken cancellationToken = default);
Task<Result<PruneReportDto?>> PruneSystemAsync(CancellationToken cancellationToken = default);
Task<Result<Stream?>> GetEventsAsync(CancellationToken cancellationToken = default);
}

View File

@ -0,0 +1,15 @@
using MaksIT.PodmanClientDotNet.Dtos.Common;
using MaksIT.PodmanClientDotNet.Dtos.Volume;
using MaksIT.PodmanClientDotNet.Models.Volume;
using MaksIT.Results;
/// <summary>
/// Volume create, list, inspect, delete, and prune endpoints.
/// </summary>
public interface IPodmanVolumesClient {
Task<Result<VolumeInspectResponseDto?>> CreateVolumeAsync(CreateVolumeRequest request, CancellationToken cancellationToken = default);
Task<Result<List<VolumeListEntryDto>?>> ListVolumesAsync(CancellationToken cancellationToken = default);
Task<Result<VolumeInspectResponseDto?>> InspectVolumeAsync(string name, CancellationToken cancellationToken = default);
Task<Result> DeleteVolumeAsync(string name, bool force = false, CancellationToken cancellationToken = default);
Task<Result<PruneReportDto?>> PruneVolumesAsync(CancellationToken cancellationToken = default);
}

View File

@ -0,0 +1,11 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Build;
/// <summary>
/// A single NDJSON line from the image build stream.
/// </summary>
public sealed class BuildProgressLineDto {
public string? Stream { get; set; }
public string? Error { get; set; }
public string? Status { get; set; }
public string? Id { get; set; }
}

View File

@ -0,0 +1,9 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Build;
/// <summary>
/// Deserialized Podman libpod API payload (Build Report).
/// </summary>
public sealed class BuildReportDto {
public string? Id { get; set; }
public string[]? Names { get; set; }
}

View File

@ -0,0 +1,9 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Common;
/// <summary>
/// Deserialized Podman libpod API payload (Error response).
/// </summary>
public sealed class ErrorResponseDto {
public string? Cause { get; set; }
public string? Message { get; set; }
}

View File

@ -0,0 +1,8 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Common;
/// <summary>
/// Deserialized Podman libpod API payload (Id response).
/// </summary>
public sealed class IdResponseDto {
public string? Id { get; set; }
}

View File

@ -0,0 +1,14 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Common;
/// <summary>Prune operation report (containers, images, volumes, pods, networks).</summary>
public sealed class PruneReportDto {
public string[]? Id { get; set; }
public string[]? IdDeleted { get; set; }
public ulong? Size { get; set; }
public ulong? SpaceReclaimed { get; set; }
public string[]? PodsDeleted { get; set; }
public string[]? NetworksDeleted { get; set; }
public string[]? VolumesDeleted { get; set; }
public string[]? ImagesDeleted { get; set; }
public string[]? ContainersDeleted { get; set; }
}

View File

@ -0,0 +1,9 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Common;
/// <summary>
/// Deserialized Podman libpod API payload (Report).
/// </summary>
public sealed class ReportDto {
public string[]? Id { get; set; }
public Dictionary<string, string>? Err { get; set; }
}

View File

@ -0,0 +1,5 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Container;
/// <summary>Podman returns a JSON array of filesystem change paths.</summary>
public sealed class ContainerChangesDto : List<string> {
}

View File

@ -0,0 +1,8 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Container;
/// <summary>
/// Deserialized Podman libpod API payload (Container Commit).
/// </summary>
public sealed class ContainerCommitDto {
public string? Id { get; set; }
}

View File

@ -0,0 +1,20 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Container;
/// <summary>
/// Deserialized Podman libpod API payload (Container Health Check).
/// </summary>
public sealed class ContainerHealthCheckDto {
public string? Status { get; set; }
public int FailingStreak { get; set; }
public ContainerHealthLogDto[]? Log { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Container Health Log).
/// </summary>
public sealed class ContainerHealthLogDto {
public string? Start { get; set; }
public string? End { get; set; }
public int ExitCode { get; set; }
public string? Output { get; set; }
}

View File

@ -0,0 +1,65 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Container;
/// <summary>
/// Deserialized Podman libpod API payload (Container Inspect).
/// </summary>
public sealed class ContainerInspectDto {
public string? Id { get; set; }
public string? Name { get; set; }
public string? Image { get; set; }
public string? ImageName { get; set; }
public string? Pod { get; set; }
public string? PodName { get; set; }
public ContainerStateDto? State { get; set; }
public ContainerConfigDto? Config { get; set; }
public string? MountLabel { get; set; }
public string? ProcessLabel { get; set; }
public string? AppArmorProfile { get; set; }
public string? HostnamePath { get; set; }
public string? HostsPath { get; set; }
public string? ResolvConfPath { get; set; }
public string? Driver { get; set; }
public string? OCIConfigPath { get; set; }
public string? OCIRuntime { get; set; }
public long Created { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Container State).
/// </summary>
public sealed class ContainerStateDto {
public string? Status { get; set; }
public bool Running { get; set; }
public bool Paused { get; set; }
public bool Restarting { get; set; }
public bool OOMKilled { get; set; }
public bool Dead { get; set; }
public int Pid { get; set; }
public int ExitCode { get; set; }
public string? Error { get; set; }
public string? StartedAt { get; set; }
public string? FinishedAt { get; set; }
public string? Health { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Container Config).
/// </summary>
public sealed class ContainerConfigDto {
public string? Hostname { get; set; }
public string? Domainname { get; set; }
public string? User { get; set; }
public bool AttachStdin { get; set; }
public bool AttachStdout { get; set; }
public bool AttachStderr { get; set; }
public string? Tty { get; set; }
public bool OpenStdin { get; set; }
public bool StdinOnce { get; set; }
public string[]? Env { get; set; }
public string[]? Cmd { get; set; }
public string? Image { get; set; }
public Dictionary<string, string>? Labels { get; set; }
public string? WorkingDir { get; set; }
public bool NetworkDisabled { get; set; }
public string? StopSignal { get; set; }
}

View File

@ -0,0 +1,18 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Container;
/// <summary>
/// Deserialized Podman libpod API payload (Container List Entry).
/// </summary>
public sealed class ContainerListEntryDto {
public string? Id { get; set; }
public string[]? Names { get; set; }
public string? Image { get; set; }
public string? ImageID { get; set; }
public string? Command { get; set; }
public long Created { get; set; }
public string? State { get; set; }
public string? Status { get; set; }
public string? Pod { get; set; }
public string? PodName { get; set; }
public bool AutoRemove { get; set; }
}

View File

@ -0,0 +1,8 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Container;
/// <summary>
/// Deserialized Podman libpod API payload (Container Mount).
/// </summary>
public sealed class ContainerMountDto {
public string? Id { get; set; }
}

View File

@ -0,0 +1,41 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Container;
/// <summary>
/// Deserialized Podman libpod API payload (Container Stats).
/// </summary>
public sealed class ContainerStatsDto {
public string? Name { get; set; }
public string? Id { get; set; }
public ContainerStatsCpuDto? CpuStats { get; set; }
public ContainerStatsMemoryDto? MemoryStats { get; set; }
public ContainerStatsNetworkDto[]? Networks { get; set; }
public string? Read { get; set; }
public string? Preread { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Container Stats Cpu).
/// </summary>
public sealed class ContainerStatsCpuDto {
public ulong TotalUsage { get; set; }
public ulong SystemUsage { get; set; }
public ulong KernelMode { get; set; }
public ulong UserMode { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Container Stats Memory).
/// </summary>
public sealed class ContainerStatsMemoryDto {
public ulong Usage { get; set; }
public ulong MaxUsage { get; set; }
public ulong Limit { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Container Stats Network).
/// </summary>
public sealed class ContainerStatsNetworkDto {
public ulong RxBytes { get; set; }
public ulong TxBytes { get; set; }
}

View File

@ -0,0 +1,9 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Container;
/// <summary>
/// Deserialized Podman libpod API payload (Container Top).
/// </summary>
public sealed class ContainerTopDto {
public string[]? Titles { get; set; }
public List<string[]>? Processes { get; set; }
}

View File

@ -0,0 +1,16 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Container;
/// <summary>
/// Deserialized Podman libpod API payload (Container Wait).
/// </summary>
public sealed class ContainerWaitDto {
public long StatusCode { get; set; }
public ContainerWaitErrorDto? Error { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Container Wait Error).
/// </summary>
public sealed class ContainerWaitErrorDto {
public string? Message { get; set; }
}

View File

@ -0,0 +1,9 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Container;
/// <summary>
/// Deserialized Podman libpod API payload (Create Container response).
/// </summary>
public sealed class CreateContainerResponseDto {
public string? Id { get; set; }
public string[]? Warnings { get; set; }
}

View File

@ -0,0 +1,9 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Container;
/// <summary>
/// Deserialized Podman libpod API payload (Delete Container response).
/// </summary>
public sealed class DeleteContainerResponseDto {
public string? Err { get; set; }
public string? Id { get; set; }
}

View File

@ -0,0 +1,17 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Container;
/// <summary>
/// Deserialized Podman libpod API payload (Mounted Container).
/// </summary>
public sealed class MountedContainerDto {
public string? Id { get; set; }
public string? Name { get; set; }
public string? Mountpoint { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Mounted Containers response).
/// </summary>
public sealed class MountedContainersResponseDto {
public List<MountedContainerDto>? Containers { get; set; }
}

View File

@ -0,0 +1,17 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Exec;
/// <summary>
/// Deserialized Podman libpod API payload (Create Exec response).
/// </summary>
public sealed class CreateExecResponseDto {
public string? Id { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Inspect Exec response).
/// </summary>
public sealed class InspectExecResponseDto {
public bool Running { get; set; }
public int ExitCode { get; set; }
public string? ProcessConfig { get; set; }
}

View File

@ -0,0 +1,27 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Generate;
/// <summary>
/// Deserialized Podman libpod API payload (Generate Systemd).
/// </summary>
public sealed class GenerateSystemdDto {
public Dictionary<string, string>? Units { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Systemd Unit).
/// </summary>
public sealed class SystemdUnitDto {
public string? Name { get; set; }
public string? Content { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Play Kube Report).
/// </summary>
public sealed class PlayKubeReportDto {
public string? Pod { get; set; }
public string[]? Containers { get; set; }
public string[]? Volumes { get; set; }
public string[]? Secrets { get; set; }
public string[]? Networks { get; set; }
}

View File

@ -0,0 +1,5 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Image;
/// <summary>Podman returns a JSON array of filesystem change paths.</summary>
public sealed class ImageChangesDto : List<string> {
}

View File

@ -0,0 +1,10 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Image;
/// <summary>
/// Deserialized Podman libpod API payload (Image Delete).
/// </summary>
public sealed class ImageDeleteDto {
public string? Deleted { get; set; }
public string[]? Untagged { get; set; }
public int ExitCode { get; set; }
}

View File

@ -0,0 +1,13 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Image;
/// <summary>
/// Deserialized Podman libpod API payload (Image History Entry).
/// </summary>
public sealed class ImageHistoryEntryDto {
public string? Id { get; set; }
public long Created { get; set; }
public string? CreatedBy { get; set; }
public string[]? Tags { get; set; }
public long Size { get; set; }
public string? Comment { get; set; }
}

View File

@ -0,0 +1,9 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Image;
/// <summary>
/// Deserialized Podman libpod API payload (Image Import).
/// </summary>
public sealed class ImageImportDto {
public string? Id { get; set; }
public string[]? Repotags { get; set; }
}

View File

@ -0,0 +1,40 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Image;
/// <summary>
/// Deserialized Podman libpod API payload (Image Inspect).
/// </summary>
public sealed class ImageInspectDto {
public string? Id { get; set; }
public string[]? RepoTags { get; set; }
public string[]? RepoDigests { get; set; }
public long Size { get; set; }
public string? Digest { get; set; }
public string? Parent { get; set; }
public string? Comment { get; set; }
public string? Created { get; set; }
public ImageConfigDto? Config { get; set; }
public ImageRootFsDto? RootFS { get; set; }
public string? Architecture { get; set; }
public string? Os { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Image Config).
/// </summary>
public sealed class ImageConfigDto {
public string? Hostname { get; set; }
public string? User { get; set; }
public string[]? Env { get; set; }
public string[]? Cmd { get; set; }
public string[]? Entrypoint { get; set; }
public string? WorkingDir { get; set; }
public Dictionary<string, string>? Labels { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Image Root Fs).
/// </summary>
public sealed class ImageRootFsDto {
public string? Type { get; set; }
public string[]? Layers { get; set; }
}

View File

@ -0,0 +1,27 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Image;
/// <summary>
/// Deserialized Podman libpod API payload (Image List Entry).
/// </summary>
public sealed class ImageListEntryDto {
public string? Id { get; set; }
public string[]? Names { get; set; }
public string? Digest { get; set; }
public long Created { get; set; }
public long Size { get; set; }
public long SharedSize { get; set; }
public string? ParentId { get; set; }
public string? RepoTags { get; set; }
public string? RepoDigests { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Image Search Result).
/// </summary>
public sealed class ImageSearchResultDto {
public string? Name { get; set; }
public string? Description { get; set; }
public int Stars { get; set; }
public bool IsOfficial { get; set; }
public bool IsAutomated { get; set; }
}

View File

@ -0,0 +1,9 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Image;
/// <summary>
/// Deserialized Podman libpod API payload (Image Load).
/// </summary>
public sealed class ImageLoadDto {
public string[]? Names { get; set; }
public string[]? LoadedImages { get; set; }
}

View File

@ -0,0 +1,8 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Image;
/// <summary>
/// Deserialized Podman libpod API payload (Image Remove response).
/// </summary>
public sealed class ImageRemoveResponseDto {
public ImageDeleteDto[]? DeletedImages { get; set; }
}

View File

@ -0,0 +1,18 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Image;
/// <summary>
/// Deserialized Podman libpod API payload (Image Tree).
/// </summary>
public sealed class ImageTreeDto {
public string? Id { get; set; }
public ImageTreeLayerDto[]? Layers { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Image Tree Layer).
/// </summary>
public sealed class ImageTreeLayerDto {
public string? Id { get; set; }
public string? Parent { get; set; }
public string[]? Tags { get; set; }
}

View File

@ -0,0 +1,12 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Image;
/// <summary>
/// Deserialized Podman libpod API payload (Pull Image response).
/// </summary>
public sealed class PullImageResponseDto {
public string? Error { get; set; }
public string? Id { get; set; }
public string? Status { get; set; }
public List<string>? Images { get; set; }
public string? Stream { get; set; }
}

View File

@ -0,0 +1,36 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Manifest;
/// <summary>
/// Deserialized Podman libpod API payload (Manifest Create).
/// </summary>
public sealed class ManifestCreateDto {
public string? Id { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Manifest Inspect).
/// </summary>
public sealed class ManifestInspectDto {
public string? Name { get; set; }
public ManifestListSpecDto[]? Manifests { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Manifest List Spec).
/// </summary>
public sealed class ManifestListSpecDto {
public string? Digest { get; set; }
public string? Image { get; set; }
public string? Platform { get; set; }
public string? Os { get; set; }
public string? Arch { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Manifest Add request).
/// </summary>
public sealed class ManifestAddRequestDto {
public string Image { get; set; } = "";
public bool All { get; set; }
public string? Operation { get; set; }
}

View File

@ -0,0 +1,43 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Network;
/// <summary>
/// Deserialized Podman libpod API payload (Network List Entry).
/// </summary>
public sealed class NetworkListEntryDto {
public string? Name { get; set; }
public string? Id { get; set; }
public string? Driver { get; set; }
public DateTime Created { get; set; }
public Dictionary<string, string>? Labels { get; set; }
public Dictionary<string, object>? Options { get; set; }
public bool? IPv6Enabled { get; set; }
public bool? Internal { get; set; }
public bool? DNSEnabled { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Network Inspect).
/// </summary>
public sealed class NetworkInspectDto {
public string? Name { get; set; }
public string? Id { get; set; }
public string? Driver { get; set; }
public DateTime Created { get; set; }
public Dictionary<string, string>? Labels { get; set; }
public Dictionary<string, object>? Options { get; set; }
public bool? IPv6Enabled { get; set; }
public bool? Internal { get; set; }
public bool? DNSEnabled { get; set; }
public Dictionary<string, NetworkInspectContainerDto>? Containers { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Network Inspect Container).
/// </summary>
public sealed class NetworkInspectContainerDto {
public string? Name { get; set; }
public string? EndpointID { get; set; }
public string? MacAddress { get; set; }
public string? IPv4Address { get; set; }
public string? IPv6Address { get; set; }
}

View File

@ -0,0 +1,70 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Pod;
/// <summary>
/// Deserialized Podman libpod API payload (Pod List Entry).
/// </summary>
public sealed class PodListEntryDto {
public string? Id { get; set; }
public string? Name { get; set; }
public string? Status { get; set; }
public string? CgroupParent { get; set; }
public DateTime Created { get; set; }
public Dictionary<string, string>? Labels { get; set; }
public string? Namespace { get; set; }
public string? RestartPolicy { get; set; }
public ulong? StopTimeout { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Pod Kill Report).
/// </summary>
public sealed class PodKillReportDto {
public string[]? Ids { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Pod Inspect).
/// </summary>
public sealed class PodInspectDto {
public string? Id { get; set; }
public string? Name { get; set; }
public string? Status { get; set; }
public string? CgroupParent { get; set; }
public DateTime Created { get; set; }
public Dictionary<string, string>? Labels { get; set; }
public string? Namespace { get; set; }
public string? RestartPolicy { get; set; }
public ulong? StopTimeout { get; set; }
public string[]? Containers { get; set; }
public string? InfraContainerId { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Pod Top).
/// </summary>
public sealed class PodTopDto {
public string[]? Titles { get; set; }
public List<string[]>? Processes { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Pod Stats).
/// </summary>
public sealed class PodStatsDto {
public string? Id { get; set; }
public string? Name { get; set; }
public string? CPU { get; set; }
public string? MemUsage { get; set; }
public string? MemLimit { get; set; }
public string? MemPercent { get; set; }
public string? NetIO { get; set; }
public string? BlockIO { get; set; }
public string? PIDs { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Pod Stats response).
/// </summary>
public sealed class PodStatsResponseDto {
public Dictionary<string, PodStatsDto>? Stats { get; set; }
}

View File

@ -0,0 +1,52 @@
namespace MaksIT.PodmanClientDotNet.Dtos.System;
/// <summary>
/// Deserialized Podman libpod API payload (Info).
/// </summary>
public sealed class InfoDto {
public InfoHostDto? Host { get; set; }
public InfoStoreDto? Store { get; set; }
public Dictionary<string, object>? Version { get; set; }
public InfoPluginsDto? Plugins { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Info Host).
/// </summary>
public sealed class InfoHostDto {
public string? Arch { get; set; }
public string? BuildahVersion { get; set; }
public long Containers { get; set; }
public string? Distribution { get; set; }
public string? Kernel { get; set; }
public string? MemTotal { get; set; }
public int MemFree { get; set; }
public string? OSType { get; set; }
public string? OS { get; set; }
public int CPUs { get; set; }
public string? PodmanVersion { get; set; }
public string? Machine { get; set; }
public string? Hostname { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Info Store).
/// </summary>
public sealed class InfoStoreDto {
public string? GraphRoot { get; set; }
public string? GraphDriverName { get; set; }
public Dictionary<string, string>? GraphOptions { get; set; }
public long ImageStoreNumber { get; set; }
public long RunRoot { get; set; }
public long VolumePath { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Info Plugins).
/// </summary>
public sealed class InfoPluginsDto {
public string[]? Volume { get; set; }
public string[]? Network { get; set; }
public string[]? Log { get; set; }
public string[]? Authorization { get; set; }
}

View File

@ -0,0 +1,8 @@
namespace MaksIT.PodmanClientDotNet.Dtos.System;
/// <summary>
/// Deserialized Podman libpod API payload (Libpod Ping).
/// </summary>
public sealed class LibpodPingDto {
public bool Ping { get; set; }
}

View File

@ -0,0 +1,18 @@
namespace MaksIT.PodmanClientDotNet.Dtos.System;
/// <summary>
/// Deserialized Podman libpod API payload (Libpod Version).
/// </summary>
public sealed class LibpodVersionDto {
public VersionComponentsDto? Version { get; set; }
public string? Platform { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Version Components).
/// </summary>
public sealed class VersionComponentsDto {
public int Major { get; set; }
public int Minor { get; set; }
public int Micro { get; set; }
}

View File

@ -0,0 +1,18 @@
namespace MaksIT.PodmanClientDotNet.Dtos.System;
/// <summary>
/// Deserialized Podman libpod API payload (System Df).
/// </summary>
public sealed class SystemDfDto {
public SystemDfEntryDto[]? Images { get; set; }
public SystemDfEntryDto[]? Containers { get; set; }
public SystemDfEntryDto[]? Volumes { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (System Df Entry).
/// </summary>
public sealed class SystemDfEntryDto {
public long Size { get; set; }
public long Reclaimable { get; set; }
}

View File

@ -0,0 +1,46 @@
namespace MaksIT.PodmanClientDotNet.Dtos.Volume;
/// <summary>
/// Deserialized Podman libpod API payload (Volume List Entry).
/// </summary>
public sealed class VolumeListEntryDto {
public string? Name { get; set; }
public string? Driver { get; set; }
public string? Mountpoint { get; set; }
public DateTime Created { get; set; }
public Dictionary<string, string>? Labels { get; set; }
public string? Scope { get; set; }
public VolumeListOptionsDto? Options { get; set; }
public VolumeUsageDataDto? UsageData { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Volume List Options).
/// </summary>
public sealed class VolumeListOptionsDto {
public string? Device { get; set; }
public string? Type { get; set; }
public string? Label { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Volume Usage Data).
/// </summary>
public sealed class VolumeUsageDataDto {
public long Size { get; set; }
public long RefCount { get; set; }
}
/// <summary>
/// Deserialized Podman libpod API payload (Volume Inspect response).
/// </summary>
public sealed class VolumeInspectResponseDto {
public string? Name { get; set; }
public string? Driver { get; set; }
public string? Mountpoint { get; set; }
public DateTime Created { get; set; }
public Dictionary<string, string>? Labels { get; set; }
public string? Scope { get; set; }
public VolumeListOptionsDto? Options { get; set; }
public VolumeUsageDataDto? UsageData { get; set; }
}

View File

@ -1,36 +0,0 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace MaksIT.PodmanClientDotNet.Extensions;
public static class ObjectExtensions {
/// <summary>
/// Converts object to json string
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
public static string ToJson<T>(this T? obj) => ToJson(obj, null);
/// <summary>
/// Converts object to json string
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <param name="converters"></param>
/// <returns></returns>
public static string ToJson<T>(T? obj, List<JsonConverter>? converters) {
if (obj == null)
return "{}";
var options = new JsonSerializerOptions {
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
};
converters?.ForEach(x => options.Converters.Add(x));
return JsonSerializer.Serialize(obj, options);
}
}

View File

@ -0,0 +1,29 @@
using Microsoft.Extensions.DependencyInjection;
namespace MaksIT.PodmanClientDotNet.Extensions;
/// <summary>
/// Registers <see cref="PodmanClient"/> with <see cref="IHttpClientFactory"/> for dependency injection.
/// </summary>
public static class ServiceCollectionExtensions {
/// <summary>
/// Adds a typed <see cref="HttpClient"/> for <see cref="IPodmanClient"/> / <see cref="PodmanClient"/>.
/// </summary>
/// <param name="services">The service collection.</param>
/// <param name="podmanClientConfiguration">Podman API settings (bound from configuration in the host application).</param>
public static void AddPodmanClient(
this IServiceCollection services,
IPodmanClientConfiguration podmanClientConfiguration
) {
ArgumentNullException.ThrowIfNull(podmanClientConfiguration);
if (string.IsNullOrWhiteSpace(podmanClientConfiguration.ServerUrl))
throw new ArgumentException(
$"{nameof(IPodmanClientConfiguration.ServerUrl)} must be configured.",
nameof(podmanClientConfiguration)
);
services.AddSingleton(podmanClientConfiguration);
services.AddHttpClient<IPodmanClient, PodmanClient>();
}
}

View File

@ -1,35 +0,0 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace MaksIT.PodmanClientDotNet.Extensions;
public static partial class StringExtensions {
/// <summary>
/// Converts JSON string to object
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="s"></param>
/// <returns></returns>
public static T? ToObject<T>(this string s) => ToObjectCore<T>(s, null);
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="s"></param>
/// <param name="converters"></param>
/// <returns></returns>
public static T? ToObject<T>(this string s, List<JsonConverter> converters) => ToObjectCore<T>(s, converters);
private static T? ToObjectCore<T>(string s, List<JsonConverter>? converters) {
var options = new JsonSerializerOptions {
PropertyNameCaseInsensitive = true
};
converters?.ForEach(x => options.Converters.Add(x));
return JsonSerializer.Deserialize<T>(s, options);
}
}

View File

@ -0,0 +1,14 @@
/// <summary>
/// Podman REST API client contract.
/// </summary>
public interface IPodmanClient
: IPodmanSystemClient,
IPodmanContainersClient,
IPodmanImagesClient,
IPodmanVolumesClient,
IPodmanNetworksClient,
IPodmanPodsClient,
IPodmanExecClient,
IPodmanBuildClient,
IPodmanManifestsClient,
IPodmanGenerateClient { }

View File

@ -0,0 +1,25 @@
/// <summary>
/// Configuration for <see cref="PodmanClient"/> when registered via dependency injection.
/// Implement in the host application (for example an options class bound from <c>appsettings.json</c>).
/// </summary>
public interface IPodmanClientConfiguration {
/// <summary>
/// Recommended configuration section name (for example <c>PodmanClient</c> in <c>appsettings.json</c>).
/// </summary>
public const string SectionName = "PodmanClient";
/// <summary>
/// Base URL of the Podman API (for example <c>http://localhost:8080</c>).
/// </summary>
string ServerUrl { get; set; }
/// <summary>
/// Podman API version segment used in request paths. Defaults to <c>v1.41</c>.
/// </summary>
string ApiVersion { get; set; }
/// <summary>
/// HTTP request timeout in minutes.
/// </summary>
int TimeoutMinutes { get; set; }
}

View File

@ -0,0 +1,96 @@
using System.Net.Security;
using System.Net.Sockets;
using System.Text;
namespace MaksIT.PodmanClientDotNet.Internal;
internal static class PodmanHijackConnection {
public static async Task<PodmanHijackStream> ConnectAsync(
Uri baseAddress,
string apiVersion,
HttpMethod method,
string libpodPath,
string? queryString,
byte[]? requestBody,
CancellationToken cancellationToken
) {
ArgumentNullException.ThrowIfNull(baseAddress);
var host = baseAddress.Host;
var port = baseAddress.IsDefaultPort
? baseAddress.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase) ? 443 : 80
: baseAddress.Port;
var tcpClient = new TcpClient();
await tcpClient.ConnectAsync(host, port, cancellationToken).ConfigureAwait(false);
Stream stream = tcpClient.GetStream();
if (baseAddress.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase)) {
var ssl = new SslStream(stream, leaveInnerStreamOpen: false);
await ssl.AuthenticateAsClientAsync(new SslClientAuthenticationOptions { TargetHost = host }, cancellationToken)
.ConfigureAwait(false);
stream = ssl;
}
var path = $"/{apiVersion.Trim('/')}{libpodPath}{queryString}";
var request = BuildRequest(method, path, host, requestBody);
await stream.WriteAsync(request, cancellationToken).ConfigureAwait(false);
await ReadResponseHeadersAsync(stream, cancellationToken).ConfigureAwait(false);
return new PodmanHijackStream(stream, tcpClient);
}
private static byte[] BuildRequest(HttpMethod method, string path, string host, byte[]? body) {
var sb = new StringBuilder();
sb.Append(method.Method).Append(' ').Append(path).Append(" HTTP/1.1\r\n");
sb.Append("Host: ").Append(host).Append("\r\n");
sb.Append("Connection: Upgrade\r\n");
sb.Append("Upgrade: tcp\r\n");
sb.Append("Accept: application/vnd.docker.raw-stream\r\n");
if (body is { Length: > 0 }) {
sb.Append("Content-Type: application/json\r\n");
sb.Append("Content-Length: ").Append(body.Length).Append("\r\n");
}
sb.Append("\r\n");
var headerBytes = Encoding.ASCII.GetBytes(sb.ToString());
if (body is null or { Length: 0 })
return headerBytes;
var combined = new byte[headerBytes.Length + body.Length];
headerBytes.CopyTo(combined, 0);
body.CopyTo(combined, headerBytes.Length);
return combined;
}
private static async Task ReadResponseHeadersAsync(Stream stream, CancellationToken cancellationToken) {
var statusLine = await ReadAsciiLineAsync(stream, cancellationToken).ConfigureAwait(false)
?? throw new IOException("Empty response from Podman hijack endpoint.");
if (!statusLine.Contains(" 200 ", StringComparison.Ordinal) && !statusLine.Contains(" 101 ", StringComparison.Ordinal))
throw new IOException($"Podman hijack failed: {statusLine}");
while (true) {
var line = await ReadAsciiLineAsync(stream, cancellationToken).ConfigureAwait(false);
if (line is null || line.Length == 0)
break;
}
}
private static async Task<string?> ReadAsciiLineAsync(Stream stream, CancellationToken cancellationToken) {
var buffer = new StringBuilder();
while (true) {
var single = new byte[1];
var read = await stream.ReadAsync(single, cancellationToken).ConfigureAwait(false);
if (read == 0)
return buffer.Length == 0 ? null : buffer.ToString();
var b = single[0];
if (b == '\n') {
if (buffer.Length > 0 && buffer[^1] == '\r')
buffer.Length--;
return buffer.ToString();
}
buffer.Append((char)b);
}
}
}

View File

@ -0,0 +1,53 @@
using System.Net.Sockets;
namespace MaksIT.PodmanClientDotNet.Internal;
/// <summary>
/// Duplex network stream returned from a hijacked Podman HTTP connection.
/// </summary>
internal sealed class PodmanHijackStream : Stream {
private readonly Stream _inner;
private readonly TcpClient? _tcpClient;
public PodmanHijackStream(Stream inner, TcpClient? tcpClient = null) {
_inner = inner;
_tcpClient = tcpClient;
}
public override bool CanRead => _inner.CanRead;
public override bool CanSeek => false;
public override bool CanWrite => _inner.CanWrite;
public override long Length => throw new NotSupportedException();
public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); }
public void CloseWrite() {
if (_tcpClient?.Client.Connected == true)
_tcpClient.Client.Shutdown(SocketShutdown.Send);
}
public override void Flush() => _inner.Flush();
public override int Read(byte[] buffer, int offset, int count) => _inner.Read(buffer, offset, count);
public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
public override void SetLength(long value) => throw new NotSupportedException();
public override void Write(byte[] buffer, int offset, int count) => _inner.Write(buffer, offset, count);
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) =>
_inner.ReadAsync(buffer, offset, count, cancellationToken);
public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default) =>
_inner.ReadAsync(buffer, cancellationToken);
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) =>
_inner.WriteAsync(buffer, offset, count, cancellationToken);
public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default) =>
_inner.WriteAsync(buffer, cancellationToken);
protected override void Dispose(bool disposing) {
if (disposing) {
_inner.Dispose();
_tcpClient?.Dispose();
}
base.Dispose(disposing);
}
}

View File

@ -0,0 +1,81 @@
using System.Net;
using Microsoft.Extensions.Logging;
using MaksIT.Core.Extensions;
using MaksIT.PodmanClientDotNet.Dtos.Common;
using MaksIT.Results;
namespace MaksIT.PodmanClientDotNet.Internal;
internal static class PodmanHttpResults {
public static string GetErrorMessage(string content) {
if (string.IsNullOrWhiteSpace(content))
return "Podman API request failed.";
var error = content.ToObject<ErrorResponseDto>();
return string.IsNullOrWhiteSpace(error?.Message) ? content : error.Message;
}
public static Result<T?> Success<T>(HttpStatusCode statusCode, T? value, params string[] messages) =>
statusCode switch {
HttpStatusCode.Created => Result<T?>.Created(value, messages),
HttpStatusCode.NoContent => Result<T?>.NoContent(value, messages),
HttpStatusCode.Accepted => Result<T?>.Accepted(value, messages),
_ => Result<T?>.Ok(value, messages),
};
public static Result Success(HttpStatusCode statusCode, params string[] messages) =>
statusCode switch {
HttpStatusCode.Created => Result.Created(messages),
HttpStatusCode.NoContent => Result.NoContent(messages),
HttpStatusCode.Accepted => Result.Accepted(messages),
_ => Result.Ok(messages),
};
public static Result<T?> Failure<T>(HttpStatusCode statusCode, string message) =>
statusCode switch {
HttpStatusCode.BadRequest => Result<T?>.BadRequest(default, message),
HttpStatusCode.Unauthorized => Result<T?>.Unauthorized(default, message),
HttpStatusCode.Forbidden => Result<T?>.Forbidden(default, message),
HttpStatusCode.NotFound => Result<T?>.NotFound(default, message),
HttpStatusCode.Conflict => Result<T?>.Conflict(default, message),
HttpStatusCode.InternalServerError => Result<T?>.InternalServerError(default, message),
HttpStatusCode.ServiceUnavailable => Result<T?>.ServiceUnavailable(default, message),
HttpStatusCode.GatewayTimeout => Result<T?>.GatewayTimeout(default, message),
_ when (int)statusCode >= 500 => Result<T?>.InternalServerError(default, message),
_ => Result<T?>.BadRequest(default, message),
};
public static Result Failure(HttpStatusCode statusCode, string message) =>
statusCode switch {
HttpStatusCode.BadRequest => Result.BadRequest(message),
HttpStatusCode.Unauthorized => Result.Unauthorized(message),
HttpStatusCode.Forbidden => Result.Forbidden(message),
HttpStatusCode.NotFound => Result.NotFound(message),
HttpStatusCode.Conflict => Result.Conflict(message),
HttpStatusCode.InternalServerError => Result.InternalServerError(message),
HttpStatusCode.ServiceUnavailable => Result.ServiceUnavailable(message),
HttpStatusCode.GatewayTimeout => Result.GatewayTimeout(message),
_ when (int)statusCode >= 500 => Result.InternalServerError(message),
_ => Result.BadRequest(message),
};
public static void LogFailure(ILogger logger, HttpStatusCode statusCode, string operation, string message) {
switch (statusCode) {
case HttpStatusCode.NotFound:
logger.LogWarning("{Operation} failed: {Message}", operation, message);
break;
case HttpStatusCode.Conflict:
case HttpStatusCode.NotModified:
logger.LogWarning("{Operation}: {Message}", operation, message);
break;
default:
if ((int)statusCode >= 500)
logger.LogError("{Operation} failed: {Message}", operation, message);
else
logger.LogError("{Operation} failed ({StatusCode}): {Message}", operation, (int)statusCode, message);
break;
}
}
}

View File

@ -0,0 +1,64 @@
using Microsoft.Extensions.Logging;
using MaksIT.Core.Extensions;
using MaksIT.PodmanClientDotNet.Dtos.Build;
using MaksIT.PodmanClientDotNet.Dtos.Image;
using MaksIT.Results;
namespace MaksIT.PodmanClientDotNet.Internal;
internal static class PodmanNdjsonStreams {
public static async Task<Result> DrainPullOrPushAsync(
Stream stream,
ILogger logger,
string operation,
CancellationToken cancellationToken = default
) {
await using var owned = stream;
using var reader = new StreamReader(stream, leaveOpen: false);
while (await reader.ReadLineAsync(cancellationToken).ConfigureAwait(false) is { } line) {
if (string.IsNullOrWhiteSpace(line))
continue;
if (!line.Contains("\"error\"", StringComparison.Ordinal))
continue;
var errorDetails = line.ToObject<PullImageResponseDto>();
var message = errorDetails?.Error ?? $"{operation} failed.";
logger.LogError("{Operation} failed: {Message}", operation, message);
return Result.BadRequest(message);
}
return Result.Ok($"{operation} completed successfully.");
}
public static async Task<Result<BuildReportDto?>> DrainBuildAsync(
Stream stream,
ILogger logger,
CancellationToken cancellationToken = default
) {
await using var owned = stream;
using var reader = new StreamReader(stream, leaveOpen: false);
BuildReportDto? report = null;
while (await reader.ReadLineAsync(cancellationToken).ConfigureAwait(false) is { } line) {
if (string.IsNullOrWhiteSpace(line))
continue;
var progress = line.ToObject<BuildProgressLineDto>();
if (progress is null)
continue;
if (!string.IsNullOrWhiteSpace(progress.Error)) {
logger.LogError("Build image failed: {Message}", progress.Error);
return Result<BuildReportDto?>.BadRequest(null, progress.Error);
}
if (!string.IsNullOrWhiteSpace(progress.Id))
report = new BuildReportDto { Id = progress.Id, Names = report?.Names };
}
return Result<BuildReportDto?>.Ok(report, "Image built successfully.");
}
}

View File

@ -0,0 +1,51 @@
namespace MaksIT.PodmanClientDotNet.Internal;
/// <summary>
/// Wraps a response stream and disposes the underlying <see cref="HttpResponseMessage"/> when done.
/// </summary>
internal sealed class PodmanOwnedResponseStream : Stream {
private readonly Stream _inner;
private readonly HttpResponseMessage _response;
private bool _disposed;
public PodmanOwnedResponseStream(Stream inner, HttpResponseMessage response) {
_inner = inner;
_response = response;
}
public override bool CanRead => _inner.CanRead;
public override bool CanSeek => _inner.CanSeek;
public override bool CanWrite => _inner.CanWrite;
public override long Length => _inner.Length;
public override long Position { get => _inner.Position; set => _inner.Position = value; }
public override void Flush() => _inner.Flush();
public override int Read(byte[] buffer, int offset, int count) => _inner.Read(buffer, offset, count);
public override long Seek(long offset, SeekOrigin origin) => _inner.Seek(offset, origin);
public override void SetLength(long value) => _inner.SetLength(value);
public override void Write(byte[] buffer, int offset, int count) => _inner.Write(buffer, offset, count);
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) =>
_inner.ReadAsync(buffer, offset, count, cancellationToken);
public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default) =>
_inner.ReadAsync(buffer, cancellationToken);
protected override void Dispose(bool disposing) {
if (!_disposed && disposing) {
_inner.Dispose();
_response.Dispose();
_disposed = true;
}
base.Dispose(disposing);
}
public override async ValueTask DisposeAsync() {
if (!_disposed) {
await _inner.DisposeAsync().ConfigureAwait(false);
_response.Dispose();
_disposed = true;
}
await base.DisposeAsync().ConfigureAwait(false);
}
}

View File

@ -1,12 +1,15 @@

namespace MaksIT.PodmanClientDotNet.Models {
public class AutoUserNsOptions {
public List<IDMapping> AdditionalGIDMappings { get; set; }
public List<IDMapping> AdditionalUIDMappings { get; set; }
public string GroupFile { get; set; }
public int InitialSize { get; set; }
public string PasswdFile { get; set; }
public int Size { get; set; }
}
}
namespace MaksIT.PodmanClientDotNet.Models;
/// <summary>
/// Libpod container or image specification model (Auto User Ns Options).
/// </summary>
public class AutoUserNsOptions {
public List<IDMapping>? AdditionalGIDMappings { get; set; }
public List<IDMapping>? AdditionalUIDMappings { get; set; }
public string? GroupFile { get; set; }
public int InitialSize { get; set; }
public string? PasswdFile { get; set; }
public int Size { get; set; }
}

View File

@ -1,16 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models {
public class BindOptions {
public bool CreateMountpoint { get; set; }
public bool NonRecursive { get; set; }
public string Propagation { get; set; }
public bool ReadOnlyForceRecursive { get; set; }
public bool ReadOnlyNonRecursive { get; set; }
}
namespace MaksIT.PodmanClientDotNet.Models;
}
/// <summary>
/// Libpod container or image specification model (Bind Options).
/// </summary>
public class BindOptions {
public bool CreateMountpoint { get; set; }
public bool NonRecursive { get; set; }
public string? Propagation { get; set; }
public bool ReadOnlyForceRecursive { get; set; }
public bool ReadOnlyNonRecursive { get; set; }
}

View File

@ -1,18 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models {
public class BlockIO {
public int LeafWeight { get; set; }
public List<ThrottleDevice> ThrottleReadBpsDevice { get; set; }
public List<ThrottleDevice> ThrottleReadIopsDevice { get; set; }
public List<ThrottleDevice> ThrottleWriteBpsDevice { get; set; }
public List<ThrottleDevice> ThrottleWriteIopsDevice { get; set; }
public int Weight { get; set; }
public List<WeightDevice> WeightDevice { get; set; }
}
namespace MaksIT.PodmanClientDotNet.Models;
}
/// <summary>
/// Libpod container or image specification model (Block I O).
/// </summary>
public class BlockIO {
public int LeafWeight { get; set; }
public List<ThrottleDevice>? ThrottleReadBpsDevice { get; set; }
public List<ThrottleDevice>? ThrottleReadIopsDevice { get; set; }
public List<ThrottleDevice>? ThrottleWriteBpsDevice { get; set; }
public List<ThrottleDevice>? ThrottleWriteIopsDevice { get; set; }
public int Weight { get; set; }
public List<WeightDevice>? WeightDevice { get; set; }
}

View File

@ -1,20 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models {
public class CPU {
public int Burst { get; set; }
public string Cpus { get; set; }
public int Idle { get; set; }
public string Mems { get; set; }
public int Period { get; set; }
public int Quota { get; set; }
public int RealtimePeriod { get; set; }
public int RealtimeRuntime { get; set; }
public int Shares { get; set; }
}
namespace MaksIT.PodmanClientDotNet.Models;
}
/// <summary>
/// Libpod container or image specification model (C P U).
/// </summary>
public class CPU {
public int Burst { get; set; }
public string? Cpus { get; set; }
public int Idle { get; set; }
public string? Mems { get; set; }
public int Period { get; set; }
public int Quota { get; set; }
public int RealtimePeriod { get; set; }
public int RealtimeRuntime { get; set; }
public int Shares { get; set; }
}

View File

@ -1,124 +1,127 @@

namespace MaksIT.PodmanClientDotNet.Models.Container {
public class CreateContainerRequest {
public Dictionary<string, string> Annotations { get; set; }
public string ApparmorProfile { get; set; }
public string BaseHostsFile { get; set; }
public List<string> CapAdd { get; set; }
public List<string> CapDrop { get; set; }
public string CgroupParent { get; set; }
public Namespace Cgroupns { get; set; }
public string CgroupsMode { get; set; }
public List<string> ChrootDirectories { get; set; }
public List<string> CNINetworks { get; set; }
public List<string> Command { get; set; }
public string ConmonPidFile { get; set; }
public List<string> ContainerCreateCommand { get; set; }
public bool? CreateWorkingDir { get; set; }
public List<string> DependencyContainers { get; set; }
public List<LinuxDeviceCgroup> DeviceCgroupRule { get; set; }
public List<LinuxDevice> Devices { get; set; }
public List<string> DevicesFrom { get; set; }
public List<string> DNSOption { get; set; }
public List<string> DNSSearch { get; set; }
public List<string> DNSServer { get; set; }
public List<string> Entrypoint { get; set; }
public Dictionary<string, string> Env { get; set; }
public bool? EnvHost { get; set; }
public List<string> EnvMerge { get; set; }
public Dictionary<ushort, string> Expose { get; set; }
public string GroupEntry { get; set; }
public List<string> Groups { get; set; }
public long? HealthCheckOnFailureAction { get; set; }
public Schema2HealthConfig HealthConfig { get; set; }
public List<LinuxDevice> HostDeviceList { get; set; }
public List<string> HostAdd { get; set; }
public string Hostname { get; set; }
public List<string> HostUsers { get; set; }
public bool? EnvHTTPProxy { get; set; }
public IDMappingOptions IDMappings { get; set; }
public string Image { get; set; }
public string ImageArch { get; set; }
public string ImageOS { get; set; }
public string ImageVariant { get; set; }
public string ImageVolumeMode { get; set; }
public List<ImageVolume> ImageVolumes { get; set; }
public bool? Init { get; set; }
public string InitContainerType { get; set; }
public string InitPath { get; set; }
public LinuxIntelRdt IntelRdt { get; set; }
public Namespace Ipcns { get; set; }
public bool? LabelNested { get; set; }
public Dictionary<string, string> Labels { get; set; }
public LogConfigLibpod LogConfiguration { get; set; }
public bool? ManagePassword { get; set; }
public List<string> Mask { get; set; }
public List<Mount> Mounts { get; set; }
public string Name { get; set; }
public Namespace Netns { get; set; }
public Dictionary<string, string> NetworkOptions { get; set; }
public Dictionary<string, NetworkSettings> Networks { get; set; }
public bool? NoNewPrivileges { get; set; }
public string OciRuntime { get; set; }
public long? OomScoreAdj { get; set; }
public List<OverlayVolume> OverlayVolumes { get; set; }
public string PasswdEntry { get; set; }
public LinuxPersonality Personality { get; set; }
public Namespace Pidns { get; set; }
public string Pod { get; set; }
public List<PortMapping> Portmappings { get; set; }
public bool? Privileged { get; set; }
public List<string> ProcfsOpts { get; set; }
public bool? PublishImagePorts { get; set; }
public List<POSIXRlimit> RLimits { get; set; }
public string RawImageName { get; set; }
public bool? ReadOnlyFilesystem { get; set; }
public bool? ReadWriteTmpfs { get; set; }
public bool? Remove { get; set; }
public LinuxResources ResourceLimits { get; set; }
public string RestartPolicy { get; set; }
public ulong? RestartTries { get; set; }
public string Rootfs { get; set; }
public string RootfsMapping { get; set; }
public bool? RootfsOverlay { get; set; }
public string RootfsPropagation { get; set; }
public string SdnotifyMode { get; set; }
public string SeccompPolicy { get; set; }
public string SeccompProfilePath { get; set; }
public Dictionary<string, string> SecretEnv { get; set; }
public List<SecretProp> Secrets { get; set; }
public List<string> SelinuxOpts { get; set; }
public long? ShmSize { get; set; }
public long? ShmSizeSystemd { get; set; }
public StartupHealthConfig StartupHealthConfig { get; set; }
public bool? Stdin { get; set; }
public long? StopSignal { get; set; }
public ulong? StopTimeout { get; set; }
public Dictionary<string, string> StorageOpts { get; set; }
public Dictionary<string, string> Sysctl { get; set; }
public string Systemd { get; set; }
public bool? Terminal { get; set; }
public Dictionary<string, ulong> ThrottleReadBpsDevice { get; set; }
public Dictionary<string, ulong> ThrottleReadIopsDevice { get; set; }
public Dictionary<string, ulong> ThrottleWriteBpsDevice { get; set; }
public Dictionary<string, ulong> ThrottleWriteIopsDevice { get; set; }
public ulong? Timeout { get; set; }
public string Timezone { get; set; }
public string Umask { get; set; }
public Dictionary<string, string> Unified { get; set; }
public List<string> Unmask { get; set; }
public List<string> Unsetenv { get; set; }
public bool? Unsetenvall { get; set; }
public bool? UseImageHosts { get; set; }
public bool? UseImageResolvConf { get; set; }
public string User { get; set; }
public Namespace Userns { get; set; }
public Namespace Utsns { get; set; }
public bool? Volatile { get; set; }
public List<NamedVolume> Volumes { get; set; }
public List<string> VolumesFrom { get; set; }
public Dictionary<string, ulong> WeightDevice { get; set; }
public string WorkDir { get; set; }
}
}
namespace MaksIT.PodmanClientDotNet.Models.Container;
/// <summary>
/// Libpod API request body for Create Container request.
/// </summary>
public class CreateContainerRequest {
public Dictionary<string, string>? Annotations { get; set; }
public string? ApparmorProfile { get; set; }
public string? BaseHostsFile { get; set; }
public List<string>? CapAdd { get; set; }
public List<string>? CapDrop { get; set; }
public string? CgroupParent { get; set; }
public Namespace? Cgroupns { get; set; }
public string? CgroupsMode { get; set; }
public List<string>? ChrootDirectories { get; set; }
public List<string>? CNINetworks { get; set; }
public List<string>? Command { get; set; }
public string? ConmonPidFile { get; set; }
public List<string>? ContainerCreateCommand { get; set; }
public bool? CreateWorkingDir { get; set; }
public List<string>? DependencyContainers { get; set; }
public List<LinuxDeviceCgroup>? DeviceCgroupRule { get; set; }
public List<LinuxDevice>? Devices { get; set; }
public List<string>? DevicesFrom { get; set; }
public List<string>? DNSOption { get; set; }
public List<string>? DNSSearch { get; set; }
public List<string>? DNSServer { get; set; }
public List<string>? Entrypoint { get; set; }
public Dictionary<string, string>? Env { get; set; }
public bool? EnvHost { get; set; }
public List<string>? EnvMerge { get; set; }
public Dictionary<ushort, string>? Expose { get; set; }
public string? GroupEntry { get; set; }
public List<string>? Groups { get; set; }
public long? HealthCheckOnFailureAction { get; set; }
public Schema2HealthConfig? HealthConfig { get; set; }
public List<LinuxDevice>? HostDeviceList { get; set; }
public List<string>? HostAdd { get; set; }
public string? Hostname { get; set; }
public List<string>? HostUsers { get; set; }
public bool? EnvHTTPProxy { get; set; }
public IDMappingOptions? IDMappings { get; set; }
public string? Image { get; set; }
public string? ImageArch { get; set; }
public string? ImageOS { get; set; }
public string? ImageVariant { get; set; }
public string? ImageVolumeMode { get; set; }
public List<ImageVolume>? ImageVolumes { get; set; }
public bool? Init { get; set; }
public string? InitContainerType { get; set; }
public string? InitPath { get; set; }
public LinuxIntelRdt? IntelRdt { get; set; }
public Namespace? Ipcns { get; set; }
public bool? LabelNested { get; set; }
public Dictionary<string, string>? Labels { get; set; }
public LogConfigLibpod? LogConfiguration { get; set; }
public bool? ManagePassword { get; set; }
public List<string>? Mask { get; set; }
public List<Mount>? Mounts { get; set; }
public string? Name { get; set; }
public Namespace? Netns { get; set; }
public Dictionary<string, string>? NetworkOptions { get; set; }
public Dictionary<string, NetworkSettings>? Networks { get; set; }
public bool? NoNewPrivileges { get; set; }
public string? OciRuntime { get; set; }
public long? OomScoreAdj { get; set; }
public List<OverlayVolume>? OverlayVolumes { get; set; }
public string? PasswdEntry { get; set; }
public LinuxPersonality? Personality { get; set; }
public Namespace? Pidns { get; set; }
public string? Pod { get; set; }
public List<PortMapping>? Portmappings { get; set; }
public bool? Privileged { get; set; }
public List<string>? ProcfsOpts { get; set; }
public bool? PublishImagePorts { get; set; }
public List<POSIXRlimit>? RLimits { get; set; }
public string? RawImageName { get; set; }
public bool? ReadOnlyFilesystem { get; set; }
public bool? ReadWriteTmpfs { get; set; }
public bool? Remove { get; set; }
public LinuxResources? ResourceLimits { get; set; }
public string? RestartPolicy { get; set; }
public ulong? RestartTries { get; set; }
public string? Rootfs { get; set; }
public string? RootfsMapping { get; set; }
public bool? RootfsOverlay { get; set; }
public string? RootfsPropagation { get; set; }
public string? SdnotifyMode { get; set; }
public string? SeccompPolicy { get; set; }
public string? SeccompProfilePath { get; set; }
public Dictionary<string, string>? SecretEnv { get; set; }
public List<SecretProp>? Secrets { get; set; }
public List<string>? SelinuxOpts { get; set; }
public long? ShmSize { get; set; }
public long? ShmSizeSystemd { get; set; }
public StartupHealthConfig? StartupHealthConfig { get; set; }
public bool? Stdin { get; set; }
public long? StopSignal { get; set; }
public ulong? StopTimeout { get; set; }
public Dictionary<string, string>? StorageOpts { get; set; }
public Dictionary<string, string>? Sysctl { get; set; }
public string? Systemd { get; set; }
public bool? Terminal { get; set; }
public Dictionary<string, ulong>? ThrottleReadBpsDevice { get; set; }
public Dictionary<string, ulong>? ThrottleReadIopsDevice { get; set; }
public Dictionary<string, ulong>? ThrottleWriteBpsDevice { get; set; }
public Dictionary<string, ulong>? ThrottleWriteIopsDevice { get; set; }
public ulong? Timeout { get; set; }
public string? Timezone { get; set; }
public string? Umask { get; set; }
public Dictionary<string, string>? Unified { get; set; }
public List<string>? Unmask { get; set; }
public List<string>? Unsetenv { get; set; }
public bool? Unsetenvall { get; set; }
public bool? UseImageHosts { get; set; }
public bool? UseImageResolvConf { get; set; }
public string? User { get; set; }
public Namespace? Userns { get; set; }
public Namespace? Utsns { get; set; }
public bool? Volatile { get; set; }
public List<NamedVolume>? Volumes { get; set; }
public List<string>? VolumesFrom { get; set; }
public Dictionary<string, ulong>? WeightDevice { get; set; }
public string? WorkDir { get; set; }
}

View File

@ -1,13 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models.Container {
public class CreateContainerResponse {
public string Id { get; set; }
namespace MaksIT.PodmanClientDotNet.Models.Container;
public string[] Warnings { get; set; }
}
}
/// <summary>
/// Libpod API response body for Create Container response.
/// </summary>
public class CreateContainerResponse {
public string? Id { get; set; }
public string[]? Warnings { get; set; }
}

View File

@ -1,12 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models.Container {
public class DeleteContainerResponse {
public string Err { get; set; }
public string Id { get; set; }
}
}
namespace MaksIT.PodmanClientDotNet.Models.Container;
/// <summary>
/// Libpod API response body for Delete Container response.
/// </summary>
public class DeleteContainerResponse {
public string? Err { get; set; }
public string? Id { get; set; }
}

View File

@ -1,13 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models {
public class DriverConfig {
public string Name { get; set; }
public Dictionary<string, string> Options { get; set; }
}
namespace MaksIT.PodmanClientDotNet.Models;
}
/// <summary>
/// Libpod container or image specification model (Driver Config).
/// </summary>
public class DriverConfig {
public string? Name { get; set; }
public Dictionary<string, string>? Options { get; set; }
}

View File

@ -1,13 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models {
public class ErrorResponse {
public string Cause { get; set; }
public string Message { get; set; }
public int Response { get; set; }
}
}
namespace MaksIT.PodmanClientDotNet.Models;
/// <summary>
/// Libpod API response body for Error response.
/// </summary>
public class ErrorResponse {
public string? Cause { get; set; }
public string? Message { get; set; }
public int Response { get; set; }
}

View File

@ -1,22 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models.Exec
{
public class CreateExecRequest
{
public bool AttachStderr { get; set; }
public bool AttachStdin { get; set; }
public bool AttachStdout { get; set; }
public string[] Cmd { get; set; }
public string DetachKeys { get; set; }
public string[] Env { get; set; }
public bool Privileged { get; set; }
public bool Tty { get; set; }
public string User { get; set; }
public string WorkingDir { get; set; }
}
}
namespace MaksIT.PodmanClientDotNet.Models.Exec;
/// <summary>
/// Libpod API request body for Create Exec request.
/// </summary>
public class CreateExecRequest {
public bool AttachStderr { get; set; }
public bool AttachStdin { get; set; }
public bool AttachStdout { get; set; }
public string[]? Cmd { get; set; }
public string? DetachKeys { get; set; }
public string[]? Env { get; set; }
public bool Privileged { get; set; }
public bool Tty { get; set; }
public string? User { get; set; }
public string? WorkingDir { get; set; }
}

View File

@ -1,12 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models.Exec {
public class CreateExecResponse {
public string Id { get; set; } // The ID of the exec instance
}
namespace MaksIT.PodmanClientDotNet.Models.Exec;
}
/// <summary>
/// Libpod API response body for Create Exec response.
/// </summary>
public class CreateExecResponse {
public string? Id { get; set; }
}

View File

@ -1,13 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models.Exec {
public class InspectExecResponse {
public bool Running { get; set; }
public int ExitCode { get; set; }
public string ProcessConfig { get; set; } // Additional fields can be added based on your needs
}
}
namespace MaksIT.PodmanClientDotNet.Models.Exec;
/// <summary>
/// Libpod API response body for Inspect Exec response.
/// </summary>
public class InspectExecResponse {
public bool Running { get; set; }
public int ExitCode { get; set; }
public string? ProcessConfig { get; set; }
}

View File

@ -1,14 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models.Exec {
public class StartExecRequest {
public bool Detach { get; set; }
public bool Tty { get; set; }
public int? Height { get; set; } // Optional, nullable if not provided
public int? Width { get; set; } // Optional, nullable if not provided
}
}
namespace MaksIT.PodmanClientDotNet.Models.Exec;
/// <summary>
/// Libpod API request body for Start Exec request.
/// </summary>
public class StartExecRequest {
public bool Detach { get; set; }
public bool Tty { get; set; }
public int? Height { get; set; } // Optional, nullable if not provided
public int? Width { get; set; } // Optional, nullable if not provided
}

View File

@ -1,12 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models {
public class HugepageLimit {
public long Limit { get; set; }
public string PageSize { get; set; }
}
}
namespace MaksIT.PodmanClientDotNet.Models;
/// <summary>
/// Libpod container or image specification model (Hugepage Limit).
/// </summary>
public class HugepageLimit {
public long Limit { get; set; }
public string? PageSize { get; set; }
}

View File

@ -1,14 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models {
public class IDMapping {
public int ContainerId { get; set; }
public int HostId { get; set; }
public int Size { get; set; }
}
namespace MaksIT.PodmanClientDotNet.Models;
}
/// <summary>
/// Libpod container or image specification model (I D Mapping).
/// </summary>
public class IDMapping {
public int ContainerId { get; set; }
public int HostId { get; set; }
public int Size { get; set; }
}

View File

@ -1,18 +1,15 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models {
public class IDMappingOptions {
public bool AutoUserNs { get; set; }
public AutoUserNsOptions AutoUserNsOpts { get; set; }
public List<IDMapping> GIDMap { get; set; }
public bool HostGIDMapping { get; set; }
public bool HostUIDMapping { get; set; }
public List<IDMapping> UIDMap { get; set; }
}
namespace MaksIT.PodmanClientDotNet.Models;
}
/// <summary>
/// Libpod container or image specification model (I D Mapping Options).
/// </summary>
public class IDMappingOptions {
public bool AutoUserNs { get; set; }
public AutoUserNsOptions? AutoUserNsOpts { get; set; }
public List<IDMapping>? GIDMap { get; set; }
public bool HostGIDMapping { get; set; }
public bool HostUIDMapping { get; set; }
public List<IDMapping>? UIDMap { get; set; }
}

View File

@ -1,32 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models.Image
{
public class PullImageResponse
namespace MaksIT.PodmanClientDotNet.Models.Image;
public class PullImageResponse
{
/// <summary>
/// Error contains text of errors from c/image.
/// </summary>
public string Error { get; set; }
public string? Error { get; set; }
/// <summary>
/// ID contains image ID (retained for backwards compatibility).
/// </summary>
public string Id { get; set; }
public string? Id { get; set; }
/// <summary>
/// Images contains the IDs of the images pulled.
/// </summary>
public List<string> Images { get; set; }
public List<string>? Images { get; set; }
/// <summary>
/// Stream used to provide output from c/image.
/// </summary>
public string Stream { get; set; }
public string? Stream { get; set; }
}
}

View File

@ -1,15 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models {
public class ImageVolume {
public string Destination { get; set; }
public bool ReadWrite { get; set; }
public string Source { get; set; }
public string SubPath { get; set; }
}
namespace MaksIT.PodmanClientDotNet.Models;
}
/// <summary>
/// Libpod container or image specification model (Image Volume).
/// </summary>
public class ImageVolume {
public string? Destination { get; set; }
public bool ReadWrite { get; set; }
public string? Source { get; set; }
public string? SubPath { get; set; }
}

View File

@ -1,16 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models {
public class IntelRdt {
public string ClosId { get; set; }
public bool EnableCMT { get; set; }
public bool EnableMBM { get; set; }
public string L3CacheSchema { get; set; }
public string MemBwSchema { get; set; }
}
namespace MaksIT.PodmanClientDotNet.Models;
}
/// <summary>
/// Libpod container or image specification model (Intel Rdt).
/// </summary>
public class IntelRdt {
public string? ClosId { get; set; }
public bool EnableCMT { get; set; }
public bool EnableMBM { get; set; }
public string? L3CacheSchema { get; set; }
public string? MemBwSchema { get; set; }
}

View File

@ -1,18 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models {
public class LinuxDevice {
public int FileMode { get; set; }
public int Gid { get; set; }
public int Major { get; set; }
public int Minor { get; set; }
public string Path { get; set; }
public string Type { get; set; }
public int Uid { get; set; }
}
namespace MaksIT.PodmanClientDotNet.Models;
}
/// <summary>
/// Libpod container or image specification model (Linux Device).
/// </summary>
public class LinuxDevice {
public int FileMode { get; set; }
public int Gid { get; set; }
public int Major { get; set; }
public int Minor { get; set; }
public string? Path { get; set; }
public string? Type { get; set; }
public int Uid { get; set; }
}

View File

@ -1,16 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models {
public class LinuxDeviceCgroup {
public string Access { get; set; }
public bool Allow { get; set; }
public int Major { get; set; }
public int Minor { get; set; }
public string Type { get; set; }
}
namespace MaksIT.PodmanClientDotNet.Models;
}
/// <summary>
/// Libpod container or image specification model (Linux Device Cgroup).
/// </summary>
public class LinuxDeviceCgroup {
public string? Access { get; set; }
public bool Allow { get; set; }
public int Major { get; set; }
public int Minor { get; set; }
public string? Type { get; set; }
}

View File

@ -1,16 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models {
public class LinuxIntelRdt {
public string ClosID { get; set; }
public bool EnableCMT { get; set; }
public bool EnableMBM { get; set; }
public string L3CacheSchema { get; set; }
public string MemBwSchema { get; set; }
}
namespace MaksIT.PodmanClientDotNet.Models;
}
/// <summary>
/// Libpod container or image specification model (Linux Intel Rdt).
/// </summary>
public class LinuxIntelRdt {
public string? ClosID { get; set; }
public bool EnableCMT { get; set; }
public bool EnableMBM { get; set; }
public string? L3CacheSchema { get; set; }
public string? MemBwSchema { get; set; }
}

View File

@ -1,13 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models {
public class LinuxPersonality {
public string Domain { get; set; }
public List<string> Flags { get; set; }
}
namespace MaksIT.PodmanClientDotNet.Models;
}
/// <summary>
/// Libpod container or image specification model (Linux Personality).
/// </summary>
public class LinuxPersonality {
public string? Domain { get; set; }
public List<string>? Flags { get; set; }
}

View File

@ -1,21 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models {
public class LinuxResources {
public BlockIO BlockIO { get; set; }
public CPU CPU { get; set; }
public List<LinuxDeviceCgroup> Devices { get; set; }
public List<HugepageLimit> HugepageLimits { get; set; }
public Memory Memory { get; set; }
public Network Network { get; set; }
public Pids Pids { get; set; }
public Dictionary<string, RdmaResource> Rdma { get; set; }
public Dictionary<string, string> Unified { get; set; }
}
namespace MaksIT.PodmanClientDotNet.Models;
}
/// <summary>
/// Libpod container or image specification model (Linux Resources).
/// </summary>
public class LinuxResources {
public BlockIO? BlockIO { get; set; }
public CPU? CPU { get; set; }
public List<LinuxDeviceCgroup>? Devices { get; set; }
public List<HugepageLimit>? HugepageLimits { get; set; }
public Memory? Memory { get; set; }
public LinuxNetwork? Network { get; set; }
public Pids? Pids { get; set; }
public Dictionary<string, RdmaResource>? Rdma { get; set; }
public Dictionary<string, string>? Unified { get; set; }
}

View File

@ -1,15 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models {
public class LogConfigLibpod {
public string Driver { get; set; }
public Dictionary<string, string> Options { get; set; }
public string Path { get; set; }
public long Size { get; set; }
}
namespace MaksIT.PodmanClientDotNet.Models;
}
/// <summary>
/// Libpod container or image specification model (Log Config Libpod).
/// </summary>
public class LogConfigLibpod {
public string? Driver { get; set; }
public Dictionary<string, string>? Options { get; set; }
public string? Path { get; set; }
public long Size { get; set; }
}

View File

@ -1,20 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models {
public class Memory {
public bool CheckBeforeUpdate { get; set; }
public bool DisableOOMKiller { get; set; }
public long Kernel { get; set; }
public long KernelTCP { get; set; }
public long Limit { get; set; }
public long Reservation { get; set; }
public long Swap { get; set; }
public int Swappiness { get; set; }
public bool UseHierarchy { get; set; }
}
namespace MaksIT.PodmanClientDotNet.Models;
}
/// <summary>
/// Libpod container or image specification model (Memory).
/// </summary>
public class Memory {
public bool CheckBeforeUpdate { get; set; }
public bool DisableOOMKiller { get; set; }
public long Kernel { get; set; }
public long KernelTCP { get; set; }
public long Limit { get; set; }
public long Reservation { get; set; }
public long Swap { get; set; }
public int Swappiness { get; set; }
public bool UseHierarchy { get; set; }
}

View File

@ -1,20 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models {
public class Mount {
public BindOptions BindOptions { get; set; }
public string Consistency { get; set; }
public bool ReadOnly { get; set; }
public string Source { get; set; }
public string Target { get; set; }
public TmpfsOptions TmpfsOptions { get; set; }
public string Type { get; set; }
public VolumeOptions VolumeOptions { get; set; }
}
namespace MaksIT.PodmanClientDotNet.Models;
}
/// <summary>
/// Libpod container or image specification model (Mount).
/// </summary>
public class Mount {
public BindOptions? BindOptions { get; set; }
public string? Consistency { get; set; }
public bool ReadOnly { get; set; }
public string? Source { get; set; }
public string? Target { get; set; }
public TmpfsOptions? TmpfsOptions { get; set; }
public string? Type { get; set; }
public VolumeOptions? VolumeOptions { get; set; }
}

View File

@ -1,16 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models {
public class NamedVolume {
public string Dest { get; set; }
public bool IsAnonymous { get; set; }
public string Name { get; set; }
public List<string> Options { get; set; }
public string SubPath { get; set; }
}
namespace MaksIT.PodmanClientDotNet.Models;
}
/// <summary>
/// Libpod container or image specification model (Named Volume).
/// </summary>
public class NamedVolume {
public string? Dest { get; set; }
public bool IsAnonymous { get; set; }
public string? Name { get; set; }
public List<string>? Options { get; set; }
public string? SubPath { get; set; }
}

View File

@ -1,13 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models {
public class Namespace {
public string Nsmode { get; set; }
public string Value { get; set; }
}
namespace MaksIT.PodmanClientDotNet.Models;
}
/// <summary>
/// Libpod container or image specification model (Namespace).
/// </summary>
public class Namespace {
public string? Nsmode { get; set; }
public string? Value { get; set; }
}

View File

@ -1,13 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MaksIT.PodmanClientDotNet.Models {
public class Network {
public int ClassID { get; set; }
public List<NetworkPriority> Priorities { get; set; }
}
namespace MaksIT.PodmanClientDotNet.Models;
/// <summary>
/// Linux network resource limits (class ID and priorities) for container creation.
/// </summary>
public class LinuxNetwork {
public int ClassID { get; set; }
public List<NetworkPriority>? Priorities { get; set; }
}

View File

@ -0,0 +1,40 @@
namespace MaksIT.PodmanClientDotNet.Models.Network;
/// <summary>
/// Libpod API request body for Network Create request.
/// </summary>
public sealed class NetworkCreateRequest {
public string? Name { get; set; }
public bool? DisableDNS { get; set; }
public string? Driver { get; set; }
public Dictionary<string, string>? Labels { get; set; }
public Dictionary<string, string>? Options { get; set; }
public bool? Internal { get; set; }
public List<string>? IPAMDriverConfigs { get; set; }
public List<string>? DNSServers { get; set; }
public List<string>? DNSSearchDomains { get; set; }
public List<string>? DNSOptions { get; set; }
public List<string>? Subnets { get; set; }
public List<string>? IPv6Subnets { get; set; }
public List<string>? NetworkInterface { get; set; }
public List<string>? NetworkID { get; set; }
public List<string>? NetworkName { get; set; }
public List<string>? OptionsList { get; set; }
}
/// <summary>
/// Libpod API request body to connect a container to networks.
/// </summary>
public sealed class NetworkConnectRequest {
public string? Container { get; set; }
public List<string>? Networks { get; set; }
}
/// <summary>
/// Libpod API request body to disconnect a container from a network.
/// </summary>
public sealed class NetworkDisconnectRequest {
public string? Container { get; set; }
public bool? Force { get; set; }
}

Some files were not shown because too many files have changed in this diff Show More