mirror of
https://github.com/MAKS-IT-COM/podman-client-dotnet.git
synced 2026-08-15 14:48:11 +02:00
feat: add System.Text.Json source generation for AOT/trim compatibility
- Add PodmanJsonContext (JsonSerializerContext) covering all ~70 DTOs and request models used by the library with PropertyNameCaseInsensitive=true - Replace MaksIT.Core ToJson()/ToObject<T>() with explicit JsonTypeInfo<T> parameters threaded through all internal HTTP helper methods - Update all call sites in PodmanClient partial classes - Update PodmanProgressSession<T> constructor to accept JsonTypeInfo<T> - Remove MaksIT.Core package reference (no longer needed) - Enable IsAotCompatible=true in project file to activate trim/AOT analyzers - All 13 unit tests pass, 0 build warnings
This commit is contained in:
parent
1553524cbc
commit
bbba014602
@ -1,8 +1,8 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
using MaksIT.Core.Extensions;
|
|
||||||
using MaksIT.PodmanClientDotNet.Dtos.Common;
|
using MaksIT.PodmanClientDotNet.Dtos.Common;
|
||||||
using MaksIT.Results;
|
using MaksIT.Results;
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ internal static class PodmanHttpResults {
|
|||||||
if (string.IsNullOrWhiteSpace(content))
|
if (string.IsNullOrWhiteSpace(content))
|
||||||
return "Podman API request failed.";
|
return "Podman API request failed.";
|
||||||
|
|
||||||
var error = content.ToObject<ErrorResponseDto>();
|
var error = JsonSerializer.Deserialize(content, PodmanJsonContext.Default.ErrorResponseDto);
|
||||||
return string.IsNullOrWhiteSpace(error?.Message) ? content : error.Message;
|
return string.IsNullOrWhiteSpace(error?.Message) ? content : error.Message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
using MaksIT.Core.Extensions;
|
|
||||||
using MaksIT.PodmanClientDotNet.Dtos.Build;
|
using MaksIT.PodmanClientDotNet.Dtos.Build;
|
||||||
using MaksIT.PodmanClientDotNet.Dtos.Image;
|
using MaksIT.PodmanClientDotNet.Dtos.Image;
|
||||||
using MaksIT.Results;
|
using MaksIT.Results;
|
||||||
@ -24,7 +25,7 @@ internal static class PodmanNdjsonStreams {
|
|||||||
if (!line.Contains("\"error\"", StringComparison.Ordinal))
|
if (!line.Contains("\"error\"", StringComparison.Ordinal))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var errorDetails = line.ToObject<PullImageResponseDto>();
|
var errorDetails = JsonSerializer.Deserialize(line, PodmanJsonContext.Default.PullImageResponseDto);
|
||||||
var message = errorDetails?.Error ?? $"{operation} failed.";
|
var message = errorDetails?.Error ?? $"{operation} failed.";
|
||||||
logger.LogError("{Operation} failed: {Message}", operation, message);
|
logger.LogError("{Operation} failed: {Message}", operation, message);
|
||||||
return Result.BadRequest(message);
|
return Result.BadRequest(message);
|
||||||
@ -46,7 +47,7 @@ internal static class PodmanNdjsonStreams {
|
|||||||
if (string.IsNullOrWhiteSpace(line))
|
if (string.IsNullOrWhiteSpace(line))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var progress = line.ToObject<BuildProgressLineDto>();
|
var progress = JsonSerializer.Deserialize(line, PodmanJsonContext.Default.BuildProgressLineDto);
|
||||||
if (progress is null)
|
if (progress is null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
|
using MaksIT.PodmanClientDotNet;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
using MaksIT.Core.Extensions;
|
|
||||||
using MaksIT.PodmanClientDotNet.Internal;
|
using MaksIT.PodmanClientDotNet.Internal;
|
||||||
using MaksIT.PodmanClientDotNet.Models;
|
using MaksIT.PodmanClientDotNet.Models;
|
||||||
using MaksIT.PodmanClientDotNet.Dtos.Container;
|
using MaksIT.PodmanClientDotNet.Dtos.Container;
|
||||||
@ -251,7 +252,9 @@ public partial class PodmanClient {
|
|||||||
return await PostJsonAsync<CreateContainerRequest, CreateContainerResponseDto>(
|
return await PostJsonAsync<CreateContainerRequest, CreateContainerResponseDto>(
|
||||||
"/libpod/containers/create",
|
"/libpod/containers/create",
|
||||||
"Create container",
|
"Create container",
|
||||||
createContainerParameters
|
createContainerParameters,
|
||||||
|
PodmanJsonContext.Default.CreateContainerRequest,
|
||||||
|
PodmanJsonContext.Default.CreateContainerResponseDto
|
||||||
).ConfigureAwait(false);
|
).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,7 +317,7 @@ public partial class PodmanClient {
|
|||||||
|
|
||||||
if (response.IsSuccessStatusCode) {
|
if (response.IsSuccessStatusCode) {
|
||||||
var value = !string.IsNullOrWhiteSpace(jsonResponse)
|
var value = !string.IsNullOrWhiteSpace(jsonResponse)
|
||||||
? jsonResponse.ToObject<DeleteContainerResponseDto[]>()
|
? JsonSerializer.Deserialize(jsonResponse, PodmanJsonContext.Default.DeleteContainerResponseDtoArray)
|
||||||
: null;
|
: null;
|
||||||
return PodmanHttpResults.Success(response.StatusCode, value);
|
return PodmanHttpResults.Success(response.StatusCode, value);
|
||||||
}
|
}
|
||||||
@ -336,7 +339,7 @@ public partial class PodmanClient {
|
|||||||
|
|
||||||
if (response.IsSuccessStatusCode) {
|
if (response.IsSuccessStatusCode) {
|
||||||
var value = !string.IsNullOrWhiteSpace(jsonResponse)
|
var value = !string.IsNullOrWhiteSpace(jsonResponse)
|
||||||
? jsonResponse.ToObject<DeleteContainerResponseDto[]>()
|
? JsonSerializer.Deserialize(jsonResponse, PodmanJsonContext.Default.DeleteContainerResponseDtoArray)
|
||||||
: null;
|
: null;
|
||||||
return PodmanHttpResults.Success(response.StatusCode, value);
|
return PodmanHttpResults.Success(response.StatusCode, value);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
using MaksIT.PodmanClientDotNet;
|
||||||
using MaksIT.PodmanClientDotNet.Dtos.Common;
|
using MaksIT.PodmanClientDotNet.Dtos.Common;
|
||||||
using MaksIT.PodmanClientDotNet.Dtos.Container;
|
using MaksIT.PodmanClientDotNet.Dtos.Container;
|
||||||
using MaksIT.Results;
|
using MaksIT.Results;
|
||||||
@ -16,6 +17,7 @@ public partial class PodmanClient {
|
|||||||
GetJsonAsync<List<ContainerListEntryDto>>(
|
GetJsonAsync<List<ContainerListEntryDto>>(
|
||||||
"/libpod/containers/json",
|
"/libpod/containers/json",
|
||||||
"List containers",
|
"List containers",
|
||||||
|
PodmanJsonContext.Default.ListContainerListEntryDto,
|
||||||
[
|
[
|
||||||
("all", all.ToString().ToLowerInvariant()),
|
("all", all.ToString().ToLowerInvariant()),
|
||||||
("limit", limit?.ToString()),
|
("limit", limit?.ToString()),
|
||||||
@ -27,7 +29,7 @@ public partial class PodmanClient {
|
|||||||
);
|
);
|
||||||
|
|
||||||
public Task<Result<ContainerInspectDto?>> InspectContainerAsync(string name, CancellationToken cancellationToken = default) =>
|
public Task<Result<ContainerInspectDto?>> InspectContainerAsync(string name, CancellationToken cancellationToken = default) =>
|
||||||
GetJsonAsync<ContainerInspectDto>($"{ContainerPath(name)}/json", "Inspect container", cancellationToken: cancellationToken);
|
GetJsonAsync<ContainerInspectDto>($"{ContainerPath(name)}/json", "Inspect container", PodmanJsonContext.Default.ContainerInspectDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result> ContainerExistsAsync(string name, CancellationToken cancellationToken = default) =>
|
public Task<Result> ContainerExistsAsync(string name, CancellationToken cancellationToken = default) =>
|
||||||
GetWithoutBodyAsync($"{ContainerPath(name)}/exists", "Container exists", cancellationToken: cancellationToken);
|
GetWithoutBodyAsync($"{ContainerPath(name)}/exists", "Container exists", cancellationToken: cancellationToken);
|
||||||
@ -58,6 +60,7 @@ public partial class PodmanClient {
|
|||||||
PostLibpodAsync<ContainerWaitDto>(
|
PostLibpodAsync<ContainerWaitDto>(
|
||||||
$"{ContainerPath(name)}/wait",
|
$"{ContainerPath(name)}/wait",
|
||||||
"Wait container",
|
"Wait container",
|
||||||
|
PodmanJsonContext.Default.ContainerWaitDto,
|
||||||
query: condition is null ? null : [("condition", condition)],
|
query: condition is null ? null : [("condition", condition)],
|
||||||
cancellationToken: cancellationToken
|
cancellationToken: cancellationToken
|
||||||
);
|
);
|
||||||
@ -92,6 +95,7 @@ public partial class PodmanClient {
|
|||||||
GetJsonAsync<ContainerStatsDto>(
|
GetJsonAsync<ContainerStatsDto>(
|
||||||
$"{ContainerPath(name)}/stats",
|
$"{ContainerPath(name)}/stats",
|
||||||
"Get container stats",
|
"Get container stats",
|
||||||
|
PodmanJsonContext.Default.ContainerStatsDto,
|
||||||
[("stream", stream.ToString().ToLowerInvariant())],
|
[("stream", stream.ToString().ToLowerInvariant())],
|
||||||
cancellationToken
|
cancellationToken
|
||||||
);
|
);
|
||||||
@ -107,13 +111,14 @@ public partial class PodmanClient {
|
|||||||
query.Add(("containers", c));
|
query.Add(("containers", c));
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetJsonAsync<Dictionary<string, ContainerStatsDto>>("/libpod/containers/stats", "Get containers stats", query, cancellationToken);
|
return GetJsonAsync<Dictionary<string, ContainerStatsDto>>("/libpod/containers/stats", "Get containers stats", PodmanJsonContext.Default.DictionaryStringContainerStatsDto, query, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<Result<PruneReportDto?>> PruneContainersAsync(string? filters = null, CancellationToken cancellationToken = default) =>
|
public Task<Result<PruneReportDto?>> PruneContainersAsync(string? filters = null, CancellationToken cancellationToken = default) =>
|
||||||
PostLibpodAsync<PruneReportDto>(
|
PostLibpodAsync<PruneReportDto>(
|
||||||
"/libpod/containers/prune",
|
"/libpod/containers/prune",
|
||||||
"Prune containers",
|
"Prune containers",
|
||||||
|
PodmanJsonContext.Default.PruneReportDto,
|
||||||
query: filters is null ? null : [("filters", filters)],
|
query: filters is null ? null : [("filters", filters)],
|
||||||
cancellationToken: cancellationToken
|
cancellationToken: cancellationToken
|
||||||
);
|
);
|
||||||
@ -178,7 +183,7 @@ public partial class PodmanClient {
|
|||||||
);
|
);
|
||||||
|
|
||||||
public Task<Result<ContainerMountDto?>> MountContainerAsync(string name, CancellationToken cancellationToken = default) =>
|
public Task<Result<ContainerMountDto?>> MountContainerAsync(string name, CancellationToken cancellationToken = default) =>
|
||||||
PostLibpodAsync<ContainerMountDto>($"{ContainerPath(name)}/mount", "Mount container", cancellationToken: cancellationToken);
|
PostLibpodAsync<ContainerMountDto>($"{ContainerPath(name)}/mount", "Mount container", PodmanJsonContext.Default.ContainerMountDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result> UnmountContainerAsync(string name, CancellationToken cancellationToken = default) =>
|
public Task<Result> UnmountContainerAsync(string name, CancellationToken cancellationToken = default) =>
|
||||||
PostWithoutBodyAsync($"{ContainerPath(name)}/unmount", "Unmount container", cancellationToken: cancellationToken);
|
PostWithoutBodyAsync($"{ContainerPath(name)}/unmount", "Unmount container", cancellationToken: cancellationToken);
|
||||||
@ -228,7 +233,7 @@ public partial class PodmanClient {
|
|||||||
);
|
);
|
||||||
|
|
||||||
public Task<Result<ContainerChangesDto?>> GetContainerChangesAsync(string name, CancellationToken cancellationToken = default) =>
|
public Task<Result<ContainerChangesDto?>> GetContainerChangesAsync(string name, CancellationToken cancellationToken = default) =>
|
||||||
GetJsonAsync<ContainerChangesDto>($"{ContainerPath(name)}/changes", "Get container changes", cancellationToken: cancellationToken);
|
GetJsonAsync<ContainerChangesDto>($"{ContainerPath(name)}/changes", "Get container changes", PodmanJsonContext.Default.ContainerChangesDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result<ContainerCommitDto?>> CommitContainerAsync(
|
public Task<Result<ContainerCommitDto?>> CommitContainerAsync(
|
||||||
string container,
|
string container,
|
||||||
@ -255,14 +260,14 @@ public partial class PodmanClient {
|
|||||||
query.Add(("changes", change));
|
query.Add(("changes", change));
|
||||||
}
|
}
|
||||||
|
|
||||||
return PostLibpodAsync<ContainerCommitDto>("/libpod/commit", "Commit container", query: query, cancellationToken: cancellationToken);
|
return PostLibpodAsync<ContainerCommitDto>("/libpod/commit", "Commit container", PodmanJsonContext.Default.ContainerCommitDto, query: query, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<Result<ContainerHealthCheckDto?>> HealthCheckContainerAsync(string name, CancellationToken cancellationToken = default) =>
|
public Task<Result<ContainerHealthCheckDto?>> HealthCheckContainerAsync(string name, CancellationToken cancellationToken = default) =>
|
||||||
GetJsonAsync<ContainerHealthCheckDto>($"{ContainerPath(name)}/healthcheck", "Health check container", cancellationToken: cancellationToken);
|
GetJsonAsync<ContainerHealthCheckDto>($"{ContainerPath(name)}/healthcheck", "Health check container", PodmanJsonContext.Default.ContainerHealthCheckDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result<MountedContainersResponseDto?>> GetMountedContainersAsync(CancellationToken cancellationToken = default) =>
|
public Task<Result<MountedContainersResponseDto?>> GetMountedContainersAsync(CancellationToken cancellationToken = default) =>
|
||||||
GetJsonAsync<MountedContainersResponseDto>("/libpod/containers/showmounted", "Get mounted containers", cancellationToken: cancellationToken);
|
GetJsonAsync<MountedContainersResponseDto>("/libpod/containers/showmounted", "Get mounted containers", PodmanJsonContext.Default.MountedContainersResponseDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result<ContainerTopDto?>> TopContainerAsync(
|
public Task<Result<ContainerTopDto?>> TopContainerAsync(
|
||||||
string name,
|
string name,
|
||||||
@ -273,6 +278,7 @@ public partial class PodmanClient {
|
|||||||
GetJsonAsync<ContainerTopDto>(
|
GetJsonAsync<ContainerTopDto>(
|
||||||
$"{ContainerPath(name)}/top",
|
$"{ContainerPath(name)}/top",
|
||||||
"Top container",
|
"Top container",
|
||||||
|
PodmanJsonContext.Default.ContainerTopDto,
|
||||||
[
|
[
|
||||||
("ps_args", psArgs),
|
("ps_args", psArgs),
|
||||||
("stream", stream.ToString().ToLowerInvariant()),
|
("stream", stream.ToString().ToLowerInvariant()),
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
using System.Text;
|
using MaksIT.PodmanClientDotNet;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
using MaksIT.Core.Extensions;
|
|
||||||
using MaksIT.PodmanClientDotNet.Internal;
|
using MaksIT.PodmanClientDotNet.Internal;
|
||||||
using MaksIT.PodmanClientDotNet.Models;
|
using MaksIT.PodmanClientDotNet.Models;
|
||||||
using MaksIT.PodmanClientDotNet.Dtos.Exec;
|
using MaksIT.PodmanClientDotNet.Dtos.Exec;
|
||||||
@ -39,7 +39,9 @@ public partial class PodmanClient {
|
|||||||
return await PostJsonAsync<CreateExecRequest, CreateExecResponseDto>(
|
return await PostJsonAsync<CreateExecRequest, CreateExecResponseDto>(
|
||||||
$"/libpod/containers/{Uri.EscapeDataString(containerName)}/exec",
|
$"/libpod/containers/{Uri.EscapeDataString(containerName)}/exec",
|
||||||
"Create exec",
|
"Create exec",
|
||||||
execRequest
|
execRequest,
|
||||||
|
PodmanJsonContext.Default.CreateExecRequest,
|
||||||
|
PodmanJsonContext.Default.CreateExecResponseDto
|
||||||
).ConfigureAwait(false);
|
).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +62,8 @@ public partial class PodmanClient {
|
|||||||
var result = await PostJsonWithoutBodyAsync<StartExecRequest>(
|
var result = await PostJsonWithoutBodyAsync<StartExecRequest>(
|
||||||
$"/libpod/exec/{Uri.EscapeDataString(execId)}/start",
|
$"/libpod/exec/{Uri.EscapeDataString(execId)}/start",
|
||||||
"Start exec",
|
"Start exec",
|
||||||
startExecRequest
|
startExecRequest,
|
||||||
|
PodmanJsonContext.Default.StartExecRequest
|
||||||
).ConfigureAwait(false);
|
).ConfigureAwait(false);
|
||||||
|
|
||||||
if (result.IsSuccess)
|
if (result.IsSuccess)
|
||||||
@ -72,7 +75,8 @@ public partial class PodmanClient {
|
|||||||
public Task<Result<InspectExecResponseDto?>> InspectExecAsync(string execId) =>
|
public Task<Result<InspectExecResponseDto?>> InspectExecAsync(string execId) =>
|
||||||
GetJsonAsync<InspectExecResponseDto>(
|
GetJsonAsync<InspectExecResponseDto>(
|
||||||
$"/libpod/exec/{Uri.EscapeDataString(execId)}/json",
|
$"/libpod/exec/{Uri.EscapeDataString(execId)}/json",
|
||||||
"Inspect exec"
|
"Inspect exec",
|
||||||
|
PodmanJsonContext.Default.InspectExecResponseDto
|
||||||
);
|
);
|
||||||
|
|
||||||
public Task<Result> ResizeExecAsync(string execId, int height, int width, CancellationToken cancellationToken = default) =>
|
public Task<Result> ResizeExecAsync(string execId, int height, int width, CancellationToken cancellationToken = default) =>
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
using MaksIT.PodmanClientDotNet;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
|
|
||||||
using MaksIT.PodmanClientDotNet.Dtos.Generate;
|
using MaksIT.PodmanClientDotNet.Dtos.Generate;
|
||||||
@ -18,6 +19,7 @@ public partial class PodmanClient {
|
|||||||
GetJsonAsync<GenerateSystemdDto>(
|
GetJsonAsync<GenerateSystemdDto>(
|
||||||
$"/libpod/generate/{Uri.EscapeDataString(name)}/systemd",
|
$"/libpod/generate/{Uri.EscapeDataString(name)}/systemd",
|
||||||
"Generate systemd",
|
"Generate systemd",
|
||||||
|
PodmanJsonContext.Default.GenerateSystemdDto,
|
||||||
[
|
[
|
||||||
("useName", useName.ToString().ToLowerInvariant()),
|
("useName", useName.ToString().ToLowerInvariant()),
|
||||||
("new", createNew.ToString().ToLowerInvariant()),
|
("new", createNew.ToString().ToLowerInvariant()),
|
||||||
@ -62,6 +64,7 @@ public partial class PodmanClient {
|
|||||||
return PostLibpodAsync<PlayKubeReportDto>(
|
return PostLibpodAsync<PlayKubeReportDto>(
|
||||||
"/libpod/play/kube",
|
"/libpod/play/kube",
|
||||||
"Play kube",
|
"Play kube",
|
||||||
|
PodmanJsonContext.Default.PlayKubeReportDto,
|
||||||
content,
|
content,
|
||||||
[
|
[
|
||||||
("network", network),
|
("network", network),
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization.Metadata;
|
||||||
|
|
||||||
using MaksIT.Core.Extensions;
|
|
||||||
using MaksIT.PodmanClientDotNet.Internal;
|
using MaksIT.PodmanClientDotNet.Internal;
|
||||||
using MaksIT.Results;
|
using MaksIT.Results;
|
||||||
|
|
||||||
@ -55,13 +56,14 @@ public partial class PodmanClient {
|
|||||||
internal Task<Result<T?>> GetJsonAsync<T>(
|
internal Task<Result<T?>> GetJsonAsync<T>(
|
||||||
string libpodPath,
|
string libpodPath,
|
||||||
string operation,
|
string operation,
|
||||||
|
JsonTypeInfo<T> typeInfo,
|
||||||
IEnumerable<(string Key, string? Value)>? query = null,
|
IEnumerable<(string Key, string? Value)>? query = null,
|
||||||
CancellationToken cancellationToken = default
|
CancellationToken cancellationToken = default
|
||||||
) =>
|
) =>
|
||||||
SendAsync<T>(
|
SendAsync<T>(
|
||||||
() => _httpClient.GetAsync(LibpodPath(libpodPath) + BuildQuery(query ?? []), cancellationToken),
|
() => _httpClient.GetAsync(LibpodPath(libpodPath) + BuildQuery(query ?? []), cancellationToken),
|
||||||
operation,
|
operation,
|
||||||
body => body.ToObject<T>(),
|
body => JsonSerializer.Deserialize(body, typeInfo),
|
||||||
cancellationToken
|
cancellationToken
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -81,17 +83,19 @@ public partial class PodmanClient {
|
|||||||
string libpodPath,
|
string libpodPath,
|
||||||
string operation,
|
string operation,
|
||||||
TRequest? requestBody,
|
TRequest? requestBody,
|
||||||
|
JsonTypeInfo<TRequest> requestTypeInfo,
|
||||||
|
JsonTypeInfo<TResponse> responseTypeInfo,
|
||||||
IEnumerable<(string Key, string? Value)>? query = null,
|
IEnumerable<(string Key, string? Value)>? query = null,
|
||||||
CancellationToken cancellationToken = default
|
CancellationToken cancellationToken = default
|
||||||
) {
|
) {
|
||||||
var content = requestBody is null
|
var content = requestBody is null
|
||||||
? null
|
? null
|
||||||
: new StringContent(requestBody.ToJson(), Encoding.UTF8, "application/json");
|
: new StringContent(JsonSerializer.Serialize(requestBody, requestTypeInfo), Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
return SendAsync<TResponse>(
|
return SendAsync<TResponse>(
|
||||||
() => _httpClient.PostAsync(LibpodPath(libpodPath) + BuildQuery(query ?? []), content, cancellationToken),
|
() => _httpClient.PostAsync(LibpodPath(libpodPath) + BuildQuery(query ?? []), content, cancellationToken),
|
||||||
operation,
|
operation,
|
||||||
body => string.IsNullOrWhiteSpace(body) ? default : body.ToObject<TResponse>(),
|
body => string.IsNullOrWhiteSpace(body) ? default : JsonSerializer.Deserialize(body, responseTypeInfo),
|
||||||
cancellationToken
|
cancellationToken
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -100,12 +104,13 @@ public partial class PodmanClient {
|
|||||||
string libpodPath,
|
string libpodPath,
|
||||||
string operation,
|
string operation,
|
||||||
TRequest? requestBody,
|
TRequest? requestBody,
|
||||||
|
JsonTypeInfo<TRequest> requestTypeInfo,
|
||||||
IEnumerable<(string Key, string? Value)>? query = null,
|
IEnumerable<(string Key, string? Value)>? query = null,
|
||||||
CancellationToken cancellationToken = default
|
CancellationToken cancellationToken = default
|
||||||
) {
|
) {
|
||||||
var content = requestBody is null
|
var content = requestBody is null
|
||||||
? null
|
? null
|
||||||
: new StringContent(requestBody.ToJson(), Encoding.UTF8, "application/json");
|
: new StringContent(JsonSerializer.Serialize(requestBody, requestTypeInfo), Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
return SendWithoutBodyAsync(
|
return SendWithoutBodyAsync(
|
||||||
() => _httpClient.PostAsync(LibpodPath(libpodPath) + BuildQuery(query ?? []), content, cancellationToken),
|
() => _httpClient.PostAsync(LibpodPath(libpodPath) + BuildQuery(query ?? []), content, cancellationToken),
|
||||||
@ -155,6 +160,7 @@ public partial class PodmanClient {
|
|||||||
internal Task<Result<TResponse?>> PostLibpodAsync<TResponse>(
|
internal Task<Result<TResponse?>> PostLibpodAsync<TResponse>(
|
||||||
string libpodPath,
|
string libpodPath,
|
||||||
string operation,
|
string operation,
|
||||||
|
JsonTypeInfo<TResponse> responseTypeInfo,
|
||||||
HttpContent? content = null,
|
HttpContent? content = null,
|
||||||
IEnumerable<(string Key, string? Value)>? query = null,
|
IEnumerable<(string Key, string? Value)>? query = null,
|
||||||
CancellationToken cancellationToken = default
|
CancellationToken cancellationToken = default
|
||||||
@ -162,20 +168,21 @@ public partial class PodmanClient {
|
|||||||
SendAsync<TResponse>(
|
SendAsync<TResponse>(
|
||||||
() => _httpClient.PostAsync(LibpodPath(libpodPath) + BuildQuery(query ?? []), content, cancellationToken),
|
() => _httpClient.PostAsync(LibpodPath(libpodPath) + BuildQuery(query ?? []), content, cancellationToken),
|
||||||
operation,
|
operation,
|
||||||
body => string.IsNullOrWhiteSpace(body) ? default : body.ToObject<TResponse>(),
|
body => string.IsNullOrWhiteSpace(body) ? default : JsonSerializer.Deserialize(body, responseTypeInfo),
|
||||||
cancellationToken
|
cancellationToken
|
||||||
);
|
);
|
||||||
|
|
||||||
internal Task<Result<T?>> DeleteJsonAsync<T>(
|
internal Task<Result<T?>> DeleteJsonAsync<T>(
|
||||||
string libpodPath,
|
string libpodPath,
|
||||||
string operation,
|
string operation,
|
||||||
|
JsonTypeInfo<T> typeInfo,
|
||||||
IEnumerable<(string Key, string? Value)>? query = null,
|
IEnumerable<(string Key, string? Value)>? query = null,
|
||||||
CancellationToken cancellationToken = default
|
CancellationToken cancellationToken = default
|
||||||
) =>
|
) =>
|
||||||
SendAsync<T>(
|
SendAsync<T>(
|
||||||
() => _httpClient.DeleteAsync(LibpodPath(libpodPath) + BuildQuery(query ?? []), cancellationToken),
|
() => _httpClient.DeleteAsync(LibpodPath(libpodPath) + BuildQuery(query ?? []), cancellationToken),
|
||||||
operation,
|
operation,
|
||||||
body => string.IsNullOrWhiteSpace(body) ? default : body.ToObject<T>(),
|
body => string.IsNullOrWhiteSpace(body) ? default : JsonSerializer.Deserialize(body, typeInfo),
|
||||||
cancellationToken
|
cancellationToken
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
using MaksIT.PodmanClientDotNet;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
|
|
||||||
using MaksIT.PodmanClientDotNet.Dtos.Common;
|
using MaksIT.PodmanClientDotNet.Dtos.Common;
|
||||||
@ -16,6 +17,7 @@ public partial class PodmanClient {
|
|||||||
GetJsonAsync<List<ImageListEntryDto>>(
|
GetJsonAsync<List<ImageListEntryDto>>(
|
||||||
"/libpod/images/json",
|
"/libpod/images/json",
|
||||||
"List images",
|
"List images",
|
||||||
|
PodmanJsonContext.Default.ListImageListEntryDto,
|
||||||
[
|
[
|
||||||
("all", all.ToString().ToLowerInvariant()),
|
("all", all.ToString().ToLowerInvariant()),
|
||||||
("filters", filters),
|
("filters", filters),
|
||||||
@ -24,7 +26,7 @@ public partial class PodmanClient {
|
|||||||
);
|
);
|
||||||
|
|
||||||
public Task<Result<ImageInspectDto?>> InspectImageAsync(string name, CancellationToken cancellationToken = default) =>
|
public Task<Result<ImageInspectDto?>> InspectImageAsync(string name, CancellationToken cancellationToken = default) =>
|
||||||
GetJsonAsync<ImageInspectDto>($"{ImagePath(name)}/json", "Inspect image", cancellationToken: cancellationToken);
|
GetJsonAsync<ImageInspectDto>($"{ImagePath(name)}/json", "Inspect image", PodmanJsonContext.Default.ImageInspectDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result> ImageExistsAsync(string name, CancellationToken cancellationToken = default) =>
|
public Task<Result> ImageExistsAsync(string name, CancellationToken cancellationToken = default) =>
|
||||||
GetWithoutBodyAsync($"{ImagePath(name)}/exists", "Image exists", cancellationToken: cancellationToken);
|
GetWithoutBodyAsync($"{ImagePath(name)}/exists", "Image exists", cancellationToken: cancellationToken);
|
||||||
@ -33,6 +35,7 @@ public partial class PodmanClient {
|
|||||||
DeleteJsonAsync<ImageDeleteDto[]>(
|
DeleteJsonAsync<ImageDeleteDto[]>(
|
||||||
ImagePath(name),
|
ImagePath(name),
|
||||||
"Delete image",
|
"Delete image",
|
||||||
|
PodmanJsonContext.Default.ImageDeleteDtoArray,
|
||||||
[("force", force.ToString().ToLowerInvariant())],
|
[("force", force.ToString().ToLowerInvariant())],
|
||||||
cancellationToken
|
cancellationToken
|
||||||
);
|
);
|
||||||
@ -50,11 +53,11 @@ public partial class PodmanClient {
|
|||||||
foreach (var image in images)
|
foreach (var image in images)
|
||||||
query.Add(("images", image));
|
query.Add(("images", image));
|
||||||
|
|
||||||
return DeleteJsonAsync<ImageDeleteDto[]>("/libpod/images/remove", "Remove images", query, cancellationToken);
|
return DeleteJsonAsync<ImageDeleteDto[]>("/libpod/images/remove", "Remove images", PodmanJsonContext.Default.ImageDeleteDtoArray, query, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<Result<PruneReportDto?>> PruneImagesAsync(CancellationToken cancellationToken = default) =>
|
public Task<Result<PruneReportDto?>> PruneImagesAsync(CancellationToken cancellationToken = default) =>
|
||||||
PostLibpodAsync<PruneReportDto>("/libpod/images/prune", "Prune images", cancellationToken: cancellationToken);
|
PostLibpodAsync<PruneReportDto>("/libpod/images/prune", "Prune images", PodmanJsonContext.Default.PruneReportDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result<List<ImageSearchResultDto>?>> SearchImagesAsync(
|
public Task<Result<List<ImageSearchResultDto>?>> SearchImagesAsync(
|
||||||
string term,
|
string term,
|
||||||
@ -64,6 +67,7 @@ public partial class PodmanClient {
|
|||||||
GetJsonAsync<List<ImageSearchResultDto>>(
|
GetJsonAsync<List<ImageSearchResultDto>>(
|
||||||
"/libpod/images/search",
|
"/libpod/images/search",
|
||||||
"Search images",
|
"Search images",
|
||||||
|
PodmanJsonContext.Default.ListImageSearchResultDto,
|
||||||
[
|
[
|
||||||
("term", term),
|
("term", term),
|
||||||
("limit", limit?.ToString()),
|
("limit", limit?.ToString()),
|
||||||
@ -115,13 +119,13 @@ public partial class PodmanClient {
|
|||||||
);
|
);
|
||||||
|
|
||||||
public Task<Result<List<ImageHistoryEntryDto>?>> GetImageHistoryAsync(string name, CancellationToken cancellationToken = default) =>
|
public Task<Result<List<ImageHistoryEntryDto>?>> GetImageHistoryAsync(string name, CancellationToken cancellationToken = default) =>
|
||||||
GetJsonAsync<List<ImageHistoryEntryDto>>($"{ImagePath(name)}/history", "Get image history", cancellationToken: cancellationToken);
|
GetJsonAsync<List<ImageHistoryEntryDto>>($"{ImagePath(name)}/history", "Get image history", PodmanJsonContext.Default.ListImageHistoryEntryDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result<ImageTreeDto?>> GetImageTreeAsync(string name, CancellationToken cancellationToken = default) =>
|
public Task<Result<ImageTreeDto?>> GetImageTreeAsync(string name, CancellationToken cancellationToken = default) =>
|
||||||
GetJsonAsync<ImageTreeDto>($"{ImagePath(name)}/tree", "Get image tree", cancellationToken: cancellationToken);
|
GetJsonAsync<ImageTreeDto>($"{ImagePath(name)}/tree", "Get image tree", PodmanJsonContext.Default.ImageTreeDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result<ImageChangesDto?>> GetImageChangesAsync(string name, CancellationToken cancellationToken = default) =>
|
public Task<Result<ImageChangesDto?>> GetImageChangesAsync(string name, CancellationToken cancellationToken = default) =>
|
||||||
GetJsonAsync<ImageChangesDto>($"{ImagePath(name)}/changes", "Get image changes", cancellationToken: cancellationToken);
|
GetJsonAsync<ImageChangesDto>($"{ImagePath(name)}/changes", "Get image changes", PodmanJsonContext.Default.ImageChangesDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result<ImageImportDto?>> ImportImageAsync(
|
public Task<Result<ImageImportDto?>> ImportImageAsync(
|
||||||
Stream? tarball = null,
|
Stream? tarball = null,
|
||||||
@ -140,6 +144,7 @@ public partial class PodmanClient {
|
|||||||
return PostLibpodAsync<ImageImportDto>(
|
return PostLibpodAsync<ImageImportDto>(
|
||||||
"/libpod/images/import",
|
"/libpod/images/import",
|
||||||
"Import image",
|
"Import image",
|
||||||
|
PodmanJsonContext.Default.ImageImportDto,
|
||||||
content,
|
content,
|
||||||
[
|
[
|
||||||
("changes", changes),
|
("changes", changes),
|
||||||
@ -154,7 +159,7 @@ public partial class PodmanClient {
|
|||||||
public Task<Result<ImageLoadDto?>> LoadImageAsync(Stream tarball, CancellationToken cancellationToken = default) {
|
public Task<Result<ImageLoadDto?>> LoadImageAsync(Stream tarball, CancellationToken cancellationToken = default) {
|
||||||
var content = new StreamContent(tarball);
|
var content = new StreamContent(tarball);
|
||||||
content.Headers.ContentType = new MediaTypeHeaderValue("application/x-tar");
|
content.Headers.ContentType = new MediaTypeHeaderValue("application/x-tar");
|
||||||
return PostLibpodAsync<ImageLoadDto>("/libpod/images/load", "Load image", content, cancellationToken: cancellationToken);
|
return PostLibpodAsync<ImageLoadDto>("/libpod/images/load", "Load image", PodmanJsonContext.Default.ImageLoadDto, content, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<Result<Stream?>> ExportImagesAsync(
|
public Task<Result<Stream?>> ExportImagesAsync(
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
using MaksIT.PodmanClientDotNet;
|
||||||
using MaksIT.PodmanClientDotNet.Dtos.Manifest;
|
using MaksIT.PodmanClientDotNet.Dtos.Manifest;
|
||||||
using MaksIT.Results;
|
using MaksIT.Results;
|
||||||
|
|
||||||
@ -13,6 +14,7 @@ public partial class PodmanClient {
|
|||||||
PostLibpodAsync<ManifestCreateDto>(
|
PostLibpodAsync<ManifestCreateDto>(
|
||||||
"/libpod/manifests/create",
|
"/libpod/manifests/create",
|
||||||
"Create manifest",
|
"Create manifest",
|
||||||
|
PodmanJsonContext.Default.ManifestCreateDto,
|
||||||
query: [
|
query: [
|
||||||
("name", name),
|
("name", name),
|
||||||
("image", image),
|
("image", image),
|
||||||
@ -30,10 +32,10 @@ public partial class PodmanClient {
|
|||||||
);
|
);
|
||||||
|
|
||||||
public Task<Result<ManifestInspectDto?>> InspectManifestAsync(string name, CancellationToken cancellationToken = default) =>
|
public Task<Result<ManifestInspectDto?>> InspectManifestAsync(string name, CancellationToken cancellationToken = default) =>
|
||||||
GetJsonAsync<ManifestInspectDto>($"{ManifestPath(name)}/json", "Inspect manifest", cancellationToken: cancellationToken);
|
GetJsonAsync<ManifestInspectDto>($"{ManifestPath(name)}/json", "Inspect manifest", PodmanJsonContext.Default.ManifestInspectDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result> AddToManifestAsync(string name, ManifestAddRequestDto request, CancellationToken cancellationToken = default) =>
|
public Task<Result> AddToManifestAsync(string name, ManifestAddRequestDto request, CancellationToken cancellationToken = default) =>
|
||||||
PostJsonWithoutBodyAsync($"{ManifestPath(name)}/add", "Add to manifest", request, cancellationToken: cancellationToken);
|
PostJsonWithoutBodyAsync($"{ManifestPath(name)}/add", "Add to manifest", request, PodmanJsonContext.Default.ManifestAddRequestDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result> PushManifestAsync(
|
public Task<Result> PushManifestAsync(
|
||||||
string name,
|
string name,
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
using MaksIT.PodmanClientDotNet;
|
||||||
using MaksIT.PodmanClientDotNet.Dtos.Network;
|
using MaksIT.PodmanClientDotNet.Dtos.Network;
|
||||||
using MaksIT.PodmanClientDotNet.Models.Network;
|
using MaksIT.PodmanClientDotNet.Models.Network;
|
||||||
using MaksIT.Results;
|
using MaksIT.Results;
|
||||||
@ -11,14 +12,16 @@ public partial class PodmanClient {
|
|||||||
"/libpod/networks/create",
|
"/libpod/networks/create",
|
||||||
"Create network",
|
"Create network",
|
||||||
request,
|
request,
|
||||||
|
PodmanJsonContext.Default.NetworkCreateRequest,
|
||||||
|
PodmanJsonContext.Default.NetworkListEntryDto,
|
||||||
cancellationToken: cancellationToken
|
cancellationToken: cancellationToken
|
||||||
);
|
);
|
||||||
|
|
||||||
public Task<Result<List<NetworkListEntryDto>?>> ListNetworksAsync(CancellationToken cancellationToken = default) =>
|
public Task<Result<List<NetworkListEntryDto>?>> ListNetworksAsync(CancellationToken cancellationToken = default) =>
|
||||||
GetJsonAsync<List<NetworkListEntryDto>>("/libpod/networks/json", "List networks", cancellationToken: cancellationToken);
|
GetJsonAsync<List<NetworkListEntryDto>>("/libpod/networks/json", "List networks", PodmanJsonContext.Default.ListNetworkListEntryDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result<NetworkInspectDto?>> InspectNetworkAsync(string name, CancellationToken cancellationToken = default) =>
|
public Task<Result<NetworkInspectDto?>> InspectNetworkAsync(string name, CancellationToken cancellationToken = default) =>
|
||||||
GetJsonAsync<NetworkInspectDto>($"/libpod/networks/{Uri.EscapeDataString(name)}/json", "Inspect network", cancellationToken: cancellationToken);
|
GetJsonAsync<NetworkInspectDto>($"/libpod/networks/{Uri.EscapeDataString(name)}/json", "Inspect network", PodmanJsonContext.Default.NetworkInspectDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result> DeleteNetworkAsync(string name, CancellationToken cancellationToken = default) =>
|
public Task<Result> DeleteNetworkAsync(string name, CancellationToken cancellationToken = default) =>
|
||||||
DeleteWithoutBodyAsync($"/libpod/networks/{Uri.EscapeDataString(name)}", "Delete network", cancellationToken: cancellationToken);
|
DeleteWithoutBodyAsync($"/libpod/networks/{Uri.EscapeDataString(name)}", "Delete network", cancellationToken: cancellationToken);
|
||||||
@ -32,6 +35,7 @@ public partial class PodmanClient {
|
|||||||
$"/libpod/networks/{Uri.EscapeDataString(name)}/connect",
|
$"/libpod/networks/{Uri.EscapeDataString(name)}/connect",
|
||||||
"Connect network",
|
"Connect network",
|
||||||
request,
|
request,
|
||||||
|
PodmanJsonContext.Default.NetworkConnectRequest,
|
||||||
cancellationToken: cancellationToken
|
cancellationToken: cancellationToken
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -44,6 +48,7 @@ public partial class PodmanClient {
|
|||||||
$"/libpod/networks/{Uri.EscapeDataString(name)}/disconnect",
|
$"/libpod/networks/{Uri.EscapeDataString(name)}/disconnect",
|
||||||
"Disconnect network",
|
"Disconnect network",
|
||||||
request,
|
request,
|
||||||
|
PodmanJsonContext.Default.NetworkDisconnectRequest,
|
||||||
cancellationToken: cancellationToken
|
cancellationToken: cancellationToken
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
using MaksIT.PodmanClientDotNet;
|
||||||
using MaksIT.PodmanClientDotNet.Dtos.Common;
|
using MaksIT.PodmanClientDotNet.Dtos.Common;
|
||||||
using MaksIT.PodmanClientDotNet.Dtos.Pod;
|
using MaksIT.PodmanClientDotNet.Dtos.Pod;
|
||||||
using MaksIT.PodmanClientDotNet.Models.Pod;
|
using MaksIT.PodmanClientDotNet.Models.Pod;
|
||||||
@ -5,18 +6,19 @@ using MaksIT.Results;
|
|||||||
|
|
||||||
public partial class PodmanClient {
|
public partial class PodmanClient {
|
||||||
public Task<Result<PodListEntryDto?>> CreatePodAsync(PodCreateRequest request, CancellationToken cancellationToken = default) =>
|
public Task<Result<PodListEntryDto?>> CreatePodAsync(PodCreateRequest request, CancellationToken cancellationToken = default) =>
|
||||||
PostJsonAsync<PodCreateRequest, PodListEntryDto>("/libpod/pods/create", "Create pod", request, cancellationToken: cancellationToken);
|
PostJsonAsync<PodCreateRequest, PodListEntryDto>("/libpod/pods/create", "Create pod", request, PodmanJsonContext.Default.PodCreateRequest, PodmanJsonContext.Default.PodListEntryDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result<List<PodListEntryDto>?>> ListPodsAsync(bool all = false, CancellationToken cancellationToken = default) =>
|
public Task<Result<List<PodListEntryDto>?>> ListPodsAsync(bool all = false, CancellationToken cancellationToken = default) =>
|
||||||
GetJsonAsync<List<PodListEntryDto>>(
|
GetJsonAsync<List<PodListEntryDto>>(
|
||||||
"/libpod/pods/json",
|
"/libpod/pods/json",
|
||||||
"List pods",
|
"List pods",
|
||||||
|
PodmanJsonContext.Default.ListPodListEntryDto,
|
||||||
[("all", all.ToString().ToLowerInvariant())],
|
[("all", all.ToString().ToLowerInvariant())],
|
||||||
cancellationToken
|
cancellationToken
|
||||||
);
|
);
|
||||||
|
|
||||||
public Task<Result<PodInspectDto?>> InspectPodAsync(string name, CancellationToken cancellationToken = default) =>
|
public Task<Result<PodInspectDto?>> InspectPodAsync(string name, CancellationToken cancellationToken = default) =>
|
||||||
GetJsonAsync<PodInspectDto>($"/libpod/pods/{Uri.EscapeDataString(name)}/json", "Inspect pod", cancellationToken: cancellationToken);
|
GetJsonAsync<PodInspectDto>($"/libpod/pods/{Uri.EscapeDataString(name)}/json", "Inspect pod", PodmanJsonContext.Default.PodInspectDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result> PodExistsAsync(string name, CancellationToken cancellationToken = default) =>
|
public Task<Result> PodExistsAsync(string name, CancellationToken cancellationToken = default) =>
|
||||||
GetWithoutBodyAsync($"/libpod/pods/{Uri.EscapeDataString(name)}/exists", "Pod exists", cancellationToken: cancellationToken);
|
GetWithoutBodyAsync($"/libpod/pods/{Uri.EscapeDataString(name)}/exists", "Pod exists", cancellationToken: cancellationToken);
|
||||||
@ -63,11 +65,11 @@ public partial class PodmanClient {
|
|||||||
PostWithoutBodyAsync($"/libpod/pods/{Uri.EscapeDataString(name)}/unpause", "Unpause pod", cancellationToken: cancellationToken);
|
PostWithoutBodyAsync($"/libpod/pods/{Uri.EscapeDataString(name)}/unpause", "Unpause pod", cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result<PruneReportDto?>> PrunePodsAsync(CancellationToken cancellationToken = default) =>
|
public Task<Result<PruneReportDto?>> PrunePodsAsync(CancellationToken cancellationToken = default) =>
|
||||||
PostLibpodAsync<PruneReportDto>("/libpod/pods/prune", "Prune pods", cancellationToken: cancellationToken);
|
PostLibpodAsync<PruneReportDto>("/libpod/pods/prune", "Prune pods", PodmanJsonContext.Default.PruneReportDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result<PodTopDto?>> TopPodAsync(string name, CancellationToken cancellationToken = default) =>
|
public Task<Result<PodTopDto?>> TopPodAsync(string name, CancellationToken cancellationToken = default) =>
|
||||||
GetJsonAsync<PodTopDto>($"/libpod/pods/{Uri.EscapeDataString(name)}/top", "Top pod", cancellationToken: cancellationToken);
|
GetJsonAsync<PodTopDto>($"/libpod/pods/{Uri.EscapeDataString(name)}/top", "Top pod", PodmanJsonContext.Default.PodTopDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result<PodStatsResponseDto?>> GetPodsStatsAsync(CancellationToken cancellationToken = default) =>
|
public Task<Result<PodStatsResponseDto?>> GetPodsStatsAsync(CancellationToken cancellationToken = default) =>
|
||||||
GetJsonAsync<PodStatsResponseDto>("/libpod/pods/stats", "Get pods stats", cancellationToken: cancellationToken);
|
GetJsonAsync<PodStatsResponseDto>("/libpod/pods/stats", "Get pods stats", PodmanJsonContext.Default.PodStatsResponseDto, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
|
using MaksIT.PodmanClientDotNet;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
using MaksIT.Core.Extensions;
|
|
||||||
using MaksIT.PodmanClientDotNet.Dtos.Build;
|
using MaksIT.PodmanClientDotNet.Dtos.Build;
|
||||||
using MaksIT.PodmanClientDotNet.Dtos.Image;
|
using MaksIT.PodmanClientDotNet.Dtos.Image;
|
||||||
using MaksIT.PodmanClientDotNet.Internal;
|
using MaksIT.PodmanClientDotNet.Internal;
|
||||||
@ -65,7 +66,7 @@ public partial class PodmanClient {
|
|||||||
Height = height,
|
Height = height,
|
||||||
Width = width,
|
Width = width,
|
||||||
};
|
};
|
||||||
var body = Encoding.UTF8.GetBytes(startExecRequest.ToJson());
|
var body = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(startExecRequest, PodmanJsonContext.Default.StartExecRequest));
|
||||||
var query = BuildQuery([]);
|
var query = BuildQuery([]);
|
||||||
|
|
||||||
var hijack = await PodmanHijackConnection.ConnectAsync(
|
var hijack = await PodmanHijackConnection.ConnectAsync(
|
||||||
@ -122,7 +123,7 @@ public partial class PodmanClient {
|
|||||||
return streamResult.ToResultOfType<IPodmanProgressSession<PullImageResponseDto>>(null!);
|
return streamResult.ToResultOfType<IPodmanProgressSession<PullImageResponseDto>>(null!);
|
||||||
|
|
||||||
return Result<IPodmanProgressSession<PullImageResponseDto>?>.Ok(
|
return Result<IPodmanProgressSession<PullImageResponseDto>?>.Ok(
|
||||||
new PodmanProgressSession<PullImageResponseDto>(streamResult.Value!)
|
new PodmanProgressSession<PullImageResponseDto>(streamResult.Value!, PodmanJsonContext.Default.PullImageResponseDto)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,7 +170,7 @@ public partial class PodmanClient {
|
|||||||
return streamResult.ToResultOfType<IPodmanProgressSession<BuildProgressLineDto>>(null!);
|
return streamResult.ToResultOfType<IPodmanProgressSession<BuildProgressLineDto>>(null!);
|
||||||
|
|
||||||
return Result<IPodmanProgressSession<BuildProgressLineDto>?>.Ok(
|
return Result<IPodmanProgressSession<BuildProgressLineDto>?>.Ok(
|
||||||
new PodmanProgressSession<BuildProgressLineDto>(streamResult.Value!)
|
new PodmanProgressSession<BuildProgressLineDto>(streamResult.Value!, PodmanJsonContext.Default.BuildProgressLineDto)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,22 +1,23 @@
|
|||||||
|
using MaksIT.PodmanClientDotNet;
|
||||||
using MaksIT.PodmanClientDotNet.Dtos.Common;
|
using MaksIT.PodmanClientDotNet.Dtos.Common;
|
||||||
using MaksIT.PodmanClientDotNet.Dtos.System;
|
using MaksIT.PodmanClientDotNet.Dtos.System;
|
||||||
using MaksIT.Results;
|
using MaksIT.Results;
|
||||||
|
|
||||||
public partial class PodmanClient {
|
public partial class PodmanClient {
|
||||||
public Task<Result<LibpodPingDto?>> PingAsync(CancellationToken cancellationToken = default) =>
|
public Task<Result<LibpodPingDto?>> PingAsync(CancellationToken cancellationToken = default) =>
|
||||||
GetJsonAsync<LibpodPingDto>("/libpod/_ping", "Ping", cancellationToken: cancellationToken);
|
GetJsonAsync<LibpodPingDto>("/libpod/_ping", "Ping", PodmanJsonContext.Default.LibpodPingDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result<LibpodVersionDto?>> GetVersionAsync(CancellationToken cancellationToken = default) =>
|
public Task<Result<LibpodVersionDto?>> GetVersionAsync(CancellationToken cancellationToken = default) =>
|
||||||
GetJsonAsync<LibpodVersionDto>("/libpod/version", "Get version", cancellationToken: cancellationToken);
|
GetJsonAsync<LibpodVersionDto>("/libpod/version", "Get version", PodmanJsonContext.Default.LibpodVersionDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result<InfoDto?>> GetInfoAsync(CancellationToken cancellationToken = default) =>
|
public Task<Result<InfoDto?>> GetInfoAsync(CancellationToken cancellationToken = default) =>
|
||||||
GetJsonAsync<InfoDto>("/libpod/info", "Get info", cancellationToken: cancellationToken);
|
GetJsonAsync<InfoDto>("/libpod/info", "Get info", PodmanJsonContext.Default.InfoDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result<SystemDfDto?>> GetSystemDiskUsageAsync(CancellationToken cancellationToken = default) =>
|
public Task<Result<SystemDfDto?>> GetSystemDiskUsageAsync(CancellationToken cancellationToken = default) =>
|
||||||
GetJsonAsync<SystemDfDto>("/libpod/system/df", "Get system disk usage", cancellationToken: cancellationToken);
|
GetJsonAsync<SystemDfDto>("/libpod/system/df", "Get system disk usage", PodmanJsonContext.Default.SystemDfDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result<PruneReportDto?>> PruneSystemAsync(CancellationToken cancellationToken = default) =>
|
public Task<Result<PruneReportDto?>> PruneSystemAsync(CancellationToken cancellationToken = default) =>
|
||||||
PostLibpodAsync<PruneReportDto>("/libpod/system/prune", "Prune system", cancellationToken: cancellationToken);
|
PostLibpodAsync<PruneReportDto>("/libpod/system/prune", "Prune system", PodmanJsonContext.Default.PruneReportDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result<Stream?>> GetEventsAsync(CancellationToken cancellationToken = default) =>
|
public Task<Result<Stream?>> GetEventsAsync(CancellationToken cancellationToken = default) =>
|
||||||
GetStreamAsync("/libpod/events", "Get events", cancellationToken: cancellationToken);
|
GetStreamAsync("/libpod/events", "Get events", cancellationToken: cancellationToken);
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
using MaksIT.PodmanClientDotNet;
|
||||||
using MaksIT.PodmanClientDotNet.Dtos.Common;
|
using MaksIT.PodmanClientDotNet.Dtos.Common;
|
||||||
using MaksIT.PodmanClientDotNet.Dtos.Volume;
|
using MaksIT.PodmanClientDotNet.Dtos.Volume;
|
||||||
using MaksIT.PodmanClientDotNet.Models.Volume;
|
using MaksIT.PodmanClientDotNet.Models.Volume;
|
||||||
@ -12,14 +13,16 @@ public partial class PodmanClient {
|
|||||||
"/libpod/volumes/create",
|
"/libpod/volumes/create",
|
||||||
"Create volume",
|
"Create volume",
|
||||||
request,
|
request,
|
||||||
|
PodmanJsonContext.Default.CreateVolumeRequest,
|
||||||
|
PodmanJsonContext.Default.VolumeInspectResponseDto,
|
||||||
cancellationToken: cancellationToken
|
cancellationToken: cancellationToken
|
||||||
);
|
);
|
||||||
|
|
||||||
public Task<Result<List<VolumeListEntryDto>?>> ListVolumesAsync(CancellationToken cancellationToken = default) =>
|
public Task<Result<List<VolumeListEntryDto>?>> ListVolumesAsync(CancellationToken cancellationToken = default) =>
|
||||||
GetJsonAsync<List<VolumeListEntryDto>>("/libpod/volumes/json", "List volumes", cancellationToken: cancellationToken);
|
GetJsonAsync<List<VolumeListEntryDto>>("/libpod/volumes/json", "List volumes", PodmanJsonContext.Default.ListVolumeListEntryDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result<VolumeInspectResponseDto?>> InspectVolumeAsync(string name, CancellationToken cancellationToken = default) =>
|
public Task<Result<VolumeInspectResponseDto?>> InspectVolumeAsync(string name, CancellationToken cancellationToken = default) =>
|
||||||
GetJsonAsync<VolumeInspectResponseDto>($"/libpod/volumes/{Uri.EscapeDataString(name)}/json", "Inspect volume", cancellationToken: cancellationToken);
|
GetJsonAsync<VolumeInspectResponseDto>($"/libpod/volumes/{Uri.EscapeDataString(name)}/json", "Inspect volume", PodmanJsonContext.Default.VolumeInspectResponseDto, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
public Task<Result> DeleteVolumeAsync(string name, bool force = false, CancellationToken cancellationToken = default) =>
|
public Task<Result> DeleteVolumeAsync(string name, bool force = false, CancellationToken cancellationToken = default) =>
|
||||||
DeleteWithoutBodyAsync(
|
DeleteWithoutBodyAsync(
|
||||||
@ -30,5 +33,5 @@ public partial class PodmanClient {
|
|||||||
);
|
);
|
||||||
|
|
||||||
public Task<Result<PruneReportDto?>> PruneVolumesAsync(CancellationToken cancellationToken = default) =>
|
public Task<Result<PruneReportDto?>> PruneVolumesAsync(CancellationToken cancellationToken = default) =>
|
||||||
PostLibpodAsync<PruneReportDto>("/libpod/volumes/prune", "Prune volumes", cancellationToken: cancellationToken);
|
PostLibpodAsync<PruneReportDto>("/libpod/volumes/prune", "Prune volumes", PodmanJsonContext.Default.PruneReportDto, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,6 +39,9 @@
|
|||||||
<!-- Deterministic builds for reproducibility -->
|
<!-- Deterministic builds for reproducibility -->
|
||||||
<Deterministic>true</Deterministic>
|
<Deterministic>true</Deterministic>
|
||||||
<ContinuousIntegrationBuild Condition="'$(CI)' == 'true'">true</ContinuousIntegrationBuild>
|
<ContinuousIntegrationBuild Condition="'$(CI)' == 'true'">true</ContinuousIntegrationBuild>
|
||||||
|
|
||||||
|
<!-- AOT / trimming compatibility -->
|
||||||
|
<IsAotCompatible>true</IsAotCompatible>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -46,7 +49,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="MaksIT.Core" Version="1.6.8" />
|
|
||||||
<PackageReference Include="MaksIT.Results" Version="2.0.3" />
|
<PackageReference Include="MaksIT.Results" Version="2.0.3" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.9" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.9" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.9" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.9" />
|
||||||
|
|||||||
116
src/PodmanClient/PodmanJsonContext.cs
Normal file
116
src/PodmanClient/PodmanJsonContext.cs
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
using MaksIT.PodmanClientDotNet.Dtos.Build;
|
||||||
|
using MaksIT.PodmanClientDotNet.Dtos.Common;
|
||||||
|
using MaksIT.PodmanClientDotNet.Dtos.Container;
|
||||||
|
using MaksIT.PodmanClientDotNet.Dtos.Exec;
|
||||||
|
using MaksIT.PodmanClientDotNet.Dtos.Generate;
|
||||||
|
using MaksIT.PodmanClientDotNet.Dtos.Image;
|
||||||
|
using MaksIT.PodmanClientDotNet.Dtos.Manifest;
|
||||||
|
using MaksIT.PodmanClientDotNet.Dtos.Network;
|
||||||
|
using MaksIT.PodmanClientDotNet.Dtos.Pod;
|
||||||
|
using MaksIT.PodmanClientDotNet.Dtos.System;
|
||||||
|
using MaksIT.PodmanClientDotNet.Dtos.Volume;
|
||||||
|
using MaksIT.PodmanClientDotNet.Models.Container;
|
||||||
|
using MaksIT.PodmanClientDotNet.Models.Exec;
|
||||||
|
using MaksIT.PodmanClientDotNet.Models.Network;
|
||||||
|
using MaksIT.PodmanClientDotNet.Models.Pod;
|
||||||
|
using MaksIT.PodmanClientDotNet.Models.Volume;
|
||||||
|
|
||||||
|
namespace MaksIT.PodmanClientDotNet;
|
||||||
|
|
||||||
|
// ----- Response / DTO types -----
|
||||||
|
|
||||||
|
// Common
|
||||||
|
[JsonSerializable(typeof(ErrorResponseDto))]
|
||||||
|
[JsonSerializable(typeof(IdResponseDto))]
|
||||||
|
[JsonSerializable(typeof(PruneReportDto))]
|
||||||
|
[JsonSerializable(typeof(ReportDto))]
|
||||||
|
|
||||||
|
// Build
|
||||||
|
[JsonSerializable(typeof(BuildProgressLineDto))]
|
||||||
|
[JsonSerializable(typeof(BuildReportDto))]
|
||||||
|
|
||||||
|
// Container
|
||||||
|
[JsonSerializable(typeof(ContainerChangesDto))]
|
||||||
|
[JsonSerializable(typeof(ContainerCommitDto))]
|
||||||
|
[JsonSerializable(typeof(ContainerHealthCheckDto))]
|
||||||
|
[JsonSerializable(typeof(ContainerInspectDto))]
|
||||||
|
[JsonSerializable(typeof(ContainerListEntryDto))]
|
||||||
|
[JsonSerializable(typeof(List<ContainerListEntryDto>))]
|
||||||
|
[JsonSerializable(typeof(ContainerMountDto))]
|
||||||
|
[JsonSerializable(typeof(ContainerStatsDto))]
|
||||||
|
[JsonSerializable(typeof(Dictionary<string, ContainerStatsDto>))]
|
||||||
|
[JsonSerializable(typeof(ContainerTopDto))]
|
||||||
|
[JsonSerializable(typeof(ContainerWaitDto))]
|
||||||
|
[JsonSerializable(typeof(CreateContainerResponseDto))]
|
||||||
|
[JsonSerializable(typeof(DeleteContainerResponseDto))]
|
||||||
|
[JsonSerializable(typeof(DeleteContainerResponseDto[]))]
|
||||||
|
[JsonSerializable(typeof(MountedContainersResponseDto))]
|
||||||
|
|
||||||
|
// Exec
|
||||||
|
[JsonSerializable(typeof(CreateExecResponseDto))]
|
||||||
|
[JsonSerializable(typeof(InspectExecResponseDto))]
|
||||||
|
|
||||||
|
// Generate
|
||||||
|
[JsonSerializable(typeof(GenerateSystemdDto))]
|
||||||
|
[JsonSerializable(typeof(PlayKubeReportDto))]
|
||||||
|
|
||||||
|
// Image
|
||||||
|
[JsonSerializable(typeof(ImageChangesDto))]
|
||||||
|
[JsonSerializable(typeof(ImageDeleteDto))]
|
||||||
|
[JsonSerializable(typeof(ImageDeleteDto[]))]
|
||||||
|
[JsonSerializable(typeof(ImageHistoryEntryDto))]
|
||||||
|
[JsonSerializable(typeof(List<ImageHistoryEntryDto>))]
|
||||||
|
[JsonSerializable(typeof(ImageImportDto))]
|
||||||
|
[JsonSerializable(typeof(ImageInspectDto))]
|
||||||
|
[JsonSerializable(typeof(ImageListEntryDto))]
|
||||||
|
[JsonSerializable(typeof(List<ImageListEntryDto>))]
|
||||||
|
[JsonSerializable(typeof(ImageLoadDto))]
|
||||||
|
[JsonSerializable(typeof(ImageRemoveResponseDto))]
|
||||||
|
[JsonSerializable(typeof(ImageSearchResultDto))]
|
||||||
|
[JsonSerializable(typeof(List<ImageSearchResultDto>))]
|
||||||
|
[JsonSerializable(typeof(ImageTreeDto))]
|
||||||
|
[JsonSerializable(typeof(PullImageResponseDto))]
|
||||||
|
|
||||||
|
// Manifest
|
||||||
|
[JsonSerializable(typeof(ManifestCreateDto))]
|
||||||
|
[JsonSerializable(typeof(ManifestInspectDto))]
|
||||||
|
|
||||||
|
// Network
|
||||||
|
[JsonSerializable(typeof(NetworkInspectDto))]
|
||||||
|
[JsonSerializable(typeof(NetworkListEntryDto))]
|
||||||
|
[JsonSerializable(typeof(List<NetworkListEntryDto>))]
|
||||||
|
|
||||||
|
// Pod
|
||||||
|
[JsonSerializable(typeof(PodInspectDto))]
|
||||||
|
[JsonSerializable(typeof(PodListEntryDto))]
|
||||||
|
[JsonSerializable(typeof(List<PodListEntryDto>))]
|
||||||
|
[JsonSerializable(typeof(PodTopDto))]
|
||||||
|
[JsonSerializable(typeof(PodStatsResponseDto))]
|
||||||
|
|
||||||
|
// System
|
||||||
|
[JsonSerializable(typeof(InfoDto))]
|
||||||
|
[JsonSerializable(typeof(LibpodPingDto))]
|
||||||
|
[JsonSerializable(typeof(LibpodVersionDto))]
|
||||||
|
[JsonSerializable(typeof(SystemDfDto))]
|
||||||
|
|
||||||
|
// Volume
|
||||||
|
[JsonSerializable(typeof(VolumeInspectResponseDto))]
|
||||||
|
[JsonSerializable(typeof(VolumeListEntryDto))]
|
||||||
|
[JsonSerializable(typeof(List<VolumeListEntryDto>))]
|
||||||
|
|
||||||
|
// ----- Request / model types -----
|
||||||
|
[JsonSerializable(typeof(CreateContainerRequest))]
|
||||||
|
[JsonSerializable(typeof(CreateExecRequest))]
|
||||||
|
[JsonSerializable(typeof(StartExecRequest))]
|
||||||
|
[JsonSerializable(typeof(NetworkCreateRequest))]
|
||||||
|
[JsonSerializable(typeof(NetworkConnectRequest))]
|
||||||
|
[JsonSerializable(typeof(NetworkDisconnectRequest))]
|
||||||
|
[JsonSerializable(typeof(PodCreateRequest))]
|
||||||
|
[JsonSerializable(typeof(CreateVolumeRequest))]
|
||||||
|
[JsonSerializable(typeof(ManifestAddRequestDto))]
|
||||||
|
|
||||||
|
[JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.Unspecified, PropertyNameCaseInsensitive = true)]
|
||||||
|
internal sealed partial class PodmanJsonContext : JsonSerializerContext {
|
||||||
|
}
|
||||||
@ -1,15 +1,16 @@
|
|||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization.Metadata;
|
||||||
using MaksIT.Core.Extensions;
|
|
||||||
|
|
||||||
namespace MaksIT.PodmanClientDotNet.Streaming;
|
namespace MaksIT.PodmanClientDotNet.Streaming;
|
||||||
|
|
||||||
internal sealed class PodmanProgressSession<T> : IPodmanProgressSession<T> {
|
internal sealed class PodmanProgressSession<T> : IPodmanProgressSession<T> {
|
||||||
private readonly Stream _stream;
|
private readonly Stream _stream;
|
||||||
private readonly bool _ownsStream;
|
private readonly bool _ownsStream;
|
||||||
|
private readonly JsonTypeInfo<T> _typeInfo;
|
||||||
|
|
||||||
internal PodmanProgressSession(Stream stream, bool ownsStream = true) {
|
internal PodmanProgressSession(Stream stream, JsonTypeInfo<T> typeInfo, bool ownsStream = true) {
|
||||||
_stream = stream ?? throw new ArgumentNullException(nameof(stream));
|
_stream = stream ?? throw new ArgumentNullException(nameof(stream));
|
||||||
|
_typeInfo = typeInfo ?? throw new ArgumentNullException(nameof(typeInfo));
|
||||||
_ownsStream = ownsStream;
|
_ownsStream = ownsStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ internal sealed class PodmanProgressSession<T> : IPodmanProgressSession<T> {
|
|||||||
|
|
||||||
T? item;
|
T? item;
|
||||||
try {
|
try {
|
||||||
item = line.ToObject<T>();
|
item = JsonSerializer.Deserialize(line, _typeInfo);
|
||||||
}
|
}
|
||||||
catch (JsonException) {
|
catch (JsonException) {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@ -10,7 +10,7 @@ public class PodmanProgressSessionTests {
|
|||||||
public async Task ReadProgressAsync_ParsesNdjsonLines() {
|
public async Task ReadProgressAsync_ParsesNdjsonLines() {
|
||||||
var json = "{\"status\":\"Pulling fs layer\"}\n{\"id\":\"abc\"}\n";
|
var json = "{\"status\":\"Pulling fs layer\"}\n{\"id\":\"abc\"}\n";
|
||||||
using var stream = new MemoryStream(Encoding.UTF8.GetBytes(json));
|
using var stream = new MemoryStream(Encoding.UTF8.GetBytes(json));
|
||||||
await using var session = new PodmanProgressSession<PullImageResponseDto>(stream, ownsStream: false);
|
await using var session = new PodmanProgressSession<PullImageResponseDto>(stream, PodmanJsonContext.Default.PullImageResponseDto, ownsStream: false);
|
||||||
|
|
||||||
var items = new List<PullImageResponseDto>();
|
var items = new List<PullImageResponseDto>();
|
||||||
await foreach (var item in session.ReadProgressAsync(TestContext.Current.CancellationToken))
|
await foreach (var item in session.ReadProgressAsync(TestContext.Current.CancellationToken))
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user