Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,9 @@ jobs:
exit 1

- name: Test (${{ matrix.docker.name }})
run: >-
dotnet test
--configuration Release
--framework ${{ matrix.dotnet.tfm }}
--no-restore
--no-build
--logger console
run: |
./test/Docker.DotNet.Tests/bin/Release/${{ matrix.dotnet.tfm }}/linux-x64/publish/Docker.DotNet.Tests
./test/Docker.DotNet.TestsV2/bin/Release/${{ matrix.dotnet.tfm }}/linux-x64/publish/Docker.DotNet.TestsV2
env:
DOCKER_HOST: ${{ matrix.docker.docker_host }}
DOCKER_TLS_VERIFY: ${{ matrix.docker.tls_verify }}
Expand Down
5 changes: 2 additions & 3 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
<PackageVersion Include="System.Text.Json" Version="8.0.5" />
<PackageVersion Include="BouncyCastle.Cryptography" Version="2.5.1" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.3" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
<PackageVersion Include="xunit" Version="2.9.2" />
<PackageVersion Include="xunit.v3.mtp-v2" Version="4.0.0-pre.33" />
<PackageVersion Include="xunit.v3.aot.mtp-v2" Version="4.0.0-pre.33" />
</ItemGroup>
</Project>
5 changes: 5 additions & 0 deletions global.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"test": {
"runner": "Microsoft.Testing.Platform"
}
}
1 change: 1 addition & 0 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

<PropertyGroup>
<Nullable>enable</Nullable>
<IsAotCompatible>true</IsAotCompatible>
</PropertyGroup>

<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">
Expand Down
6 changes: 3 additions & 3 deletions src/Docker.DotNet.NPipe/DockerHandlerFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ public ResolvedTransport CreateHandler(NPipeTransportOptions transportOptions, C

var dockerStream = new DockerPipeStream(clientStream);

#if NETSTANDARD
var namedPipeConnectTimeout = (int)transportOptions.ConnectTimeout.TotalMilliseconds;
#else
#if NET
var namedPipeConnectTimeout = transportOptions.ConnectTimeout;
#else
var namedPipeConnectTimeout = (int)transportOptions.ConnectTimeout.TotalMilliseconds;
#endif

await clientStream.ConnectAsync(namedPipeConnectTimeout, cancellationToken)
Expand Down
2 changes: 1 addition & 1 deletion src/Docker.DotNet.NativeHttp/DockerHandlerFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public ResolvedTransport CreateHandler(NativeHttpTransportOptions transportOptio
var scheme = clientOptions.AuthProvider.TlsEnabled ? Uri.UriSchemeHttps : Uri.UriSchemeHttp;
var uri = new UriBuilder(clientOptions.Endpoint) { Scheme = scheme }.Uri;

#if NET6_0_OR_GREATER
#if NET
var handler = new SocketsHttpHandler
{
MaxConnectionsPerServer = MaxConnectionsPerServer,
Expand Down
2 changes: 1 addition & 1 deletion src/Docker.DotNet.NativeHttp/NativeHttpTransportOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Docker.DotNet.NativeHttp;
/// </summary>
public sealed record NativeHttpTransportOptions
{
#if NET6_0_OR_GREATER
#if NET
/// <summary>
/// Gets a callback that configures the created <see cref="SocketsHttpHandler"/> instance.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Docker.DotNet.X509/CertificateCredentials.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public CertificateCredentials(X509Certificate2? certificate)

public HttpMessageHandler ConfigureHandler(HttpMessageHandler handler)
{
#if NET6_0_OR_GREATER
#if NET
if (handler is SocketsHttpHandler socketsHandler)
{
if (_certificate != null)
Expand Down
8 changes: 3 additions & 5 deletions src/Docker.DotNet.X509/DockerTlsCertificates.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public static X509Certificate2 LoadCertificateFromPemFiles(string certPemPath, s
}

return certificate;
#elif NET6_0_OR_GREATER
#elif NET
var certificate = X509Certificate2.CreateFromPemFile(certPemPath, keyPemPath);

if (OperatingSystem.IsWindows())
Expand All @@ -75,10 +75,8 @@ public static X509Certificate2 LoadCertificateFromPemFiles(string certPemPath, s
}

return certificate;
#elif NETSTANDARD
return Polyfills.X509Certificate2.CreateFromPemFile(certPemPath, keyPemPath);
#else
return X509Certificate2.CreateFromPemFile(certPemPath, keyPemPath);
return Polyfills.X509Certificate2.CreateFromPemFile(certPemPath, keyPemPath);
#endif
}

Expand Down Expand Up @@ -141,7 +139,7 @@ public static RemoteCertificateValidationCallback CreateCertificateAuthorityVali
using var chain = new X509Chain();
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;

#if NET5_0_OR_GREATER
#if NET
chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust;
chain.ChainPolicy.CustomTrustStore.Add(certificateAuthorityCertificate);
return chain.Build(serverCertificate2);
Expand Down
4 changes: 3 additions & 1 deletion src/Docker.DotNet/Docker.DotNet.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>Docker.DotNet</AssemblyName>
<PackageId>Docker.DotNet.Enhanced</PackageId>
Expand Down Expand Up @@ -29,6 +29,7 @@
<Using Include="System.Collections.Concurrent" />
<Using Include="System.Collections.Generic" />
<Using Include="System.Diagnostics" />
<Using Include="System.Diagnostics.CodeAnalysis" />
<Using Include="System.Globalization" />
<Using Include="System.IO" />
<Using Include="System.IO.Pipelines" />
Expand All @@ -49,6 +50,7 @@
<Using Include="System.Text" />
<Using Include="System.Text.Json" />
<Using Include="System.Text.Json.Serialization" />
<Using Include="System.Text.Json.Serialization.Metadata" />
<Using Include="System.Threading" />
<Using Include="System.Threading.Tasks" />
<Using Include="Docker.DotNet" />
Expand Down
4 changes: 1 addition & 3 deletions src/Docker.DotNet/DockerClient.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
namespace Docker.DotNet;

using System;

public sealed class DockerClient : IDockerClient
{
internal readonly IEnumerable<ApiResponseErrorHandlingDelegate> NoErrorHandlers = Enumerable.Empty<ApiResponseErrorHandlingDelegate>();
Expand Down Expand Up @@ -370,7 +368,7 @@ private async Task<HttpResponseMessage> PrivateMakeRequestAsync(

if (Timeout.InfiniteTimeSpan == timeout)
{
#if NET6_0_OR_GREATER
#if NET
return await _client.SendAsync(request, completionOption, cancellationToken)
.ConfigureAwait(false);
#else
Expand Down
2 changes: 1 addition & 1 deletion src/Docker.DotNet/Endpoints/ConfigsOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ internal ConfigOperations(DockerClient client)

public async Task<IList<SwarmConfig>> ListConfigsAsync(CancellationToken cancellationToken = default)
{
return await _client.MakeRequestAsync<IList<SwarmConfig>>(_client.NoErrorHandlers, HttpMethod.Get, "configs", cancellationToken)
return await _client.MakeRequestAsync<SwarmConfig[]>(_client.NoErrorHandlers, HttpMethod.Get, "configs", cancellationToken)
.ConfigureAwait(false);
}

Expand Down
4 changes: 2 additions & 2 deletions src/Docker.DotNet/Endpoints/ISwarmOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public interface ISwarmOperations
/// 500 - Server error.
/// 503 - Node is not part of a swarm.
/// </remarks>
Task<IEnumerable<SwarmService>> ListServicesAsync(ServiceListParameters? parameters = null, CancellationToken cancellationToken = default);
Task<IList<SwarmService>> ListServicesAsync(ServiceListParameters? parameters = null, CancellationToken cancellationToken = default);

/// <summary>
/// Update a service.
Expand Down Expand Up @@ -198,7 +198,7 @@ public interface ISwarmOperations
/// 503 - Node is not part of a swarm.
/// </remarks>
/// <returns></returns>
Task<IEnumerable<NodeListResponse>> ListNodesAsync(CancellationToken cancellationToken = default);
Task<IList<NodeListResponse>> ListNodesAsync(CancellationToken cancellationToken = default);

/// <summary>
/// Inspect a node.
Expand Down
4 changes: 2 additions & 2 deletions src/Docker.DotNet/Endpoints/SwarmOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ await _client.MakeRequestAsync([NotInSwarmResponseHandler], HttpMethod.Post, "sw
.ConfigureAwait(false);
}

public async Task<IEnumerable<SwarmService>> ListServicesAsync(ServiceListParameters? parameters = null, CancellationToken cancellationToken = default)
public async Task<IList<SwarmService>> ListServicesAsync(ServiceListParameters? parameters = null, CancellationToken cancellationToken = default)
{
var queryParameters = parameters == null ? null : new QueryString<ServiceListParameters>(parameters);

Expand Down Expand Up @@ -193,7 +193,7 @@ private static Dictionary<string, string> RegistryAuthHeaders(AuthConfig? authCo
};
}

public async Task<IEnumerable<NodeListResponse>> ListNodesAsync(CancellationToken cancellationToken = default)
public async Task<IList<NodeListResponse>> ListNodesAsync(CancellationToken cancellationToken = default)
{
return await _client.MakeRequestAsync<NodeListResponse[]>([NotInSwarmResponseHandler], HttpMethod.Get, "nodes", cancellationToken)
.ConfigureAwait(false);
Expand Down
6 changes: 0 additions & 6 deletions src/Docker.DotNet/IQueryStringConverterInstanceFactory.cs

This file was deleted.

51 changes: 45 additions & 6 deletions src/Docker.DotNet/JsonSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,16 @@ static JsonSerializer()

private JsonSerializer()
{
_options.TypeInfoResolver = JsonTypeInfoResolver.Combine(
DockerModelsJsonSerializerContext.Default,
DockerExtendedJsonSerializerContext.Default
);
_options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
_options.Converters.Add(new JsonEnumMemberConverter<RestartPolicyKind>());
_options.Converters.Add(new JsonEnumMemberConverter<TaskState>());
_options.Converters.Add(new JsonDateTimeConverter());
_options.Converters.Add(new JsonNullableDateTimeConverter());
_options.MakeReadOnly();
}

public static JsonSerializer Instance { get; }
Expand All @@ -38,22 +43,22 @@ public HttpContent GetHttpContent<T>(T value)

public string Serialize<T>(T value)
{
return System.Text.Json.JsonSerializer.Serialize(value, _options);
return System.Text.Json.JsonSerializer.Serialize(value, (JsonTypeInfo<T>)_options.GetTypeInfo(typeof(T)));
}

public byte[] SerializeToUtf8Bytes<T>(T value)
{
return System.Text.Json.JsonSerializer.SerializeToUtf8Bytes(value, _options);
return System.Text.Json.JsonSerializer.SerializeToUtf8Bytes(value, (JsonTypeInfo<T>)_options.GetTypeInfo(typeof(T)));
}

public T Deserialize<T>(byte[] json)
{
return System.Text.Json.JsonSerializer.Deserialize<T>(json, _options)!;
return System.Text.Json.JsonSerializer.Deserialize(json, (JsonTypeInfo<T>)_options.GetTypeInfo(typeof(T)))!;
}

public Task<T> DeserializeAsync<T>(HttpContent content, CancellationToken cancellationToken)
{
return content.ReadFromJsonAsync<T>(_options, cancellationToken)!;
return content.ReadFromJsonAsync((JsonTypeInfo<T>)_options.GetTypeInfo(typeof(T)), cancellationToken)!;
}

public async IAsyncEnumerable<T> DeserializeAsync<T>(Stream stream, [EnumeratorCancellation] CancellationToken cancellationToken)
Expand All @@ -69,7 +74,7 @@ public async IAsyncEnumerable<T> DeserializeAsync<T>(Stream stream, [EnumeratorC

while (!buffer.IsEmpty && TryParseJson(ref buffer, out var jsonDocument))
{
yield return jsonDocument!.Deserialize<T>(_options)!;
yield return jsonDocument!.Deserialize((JsonTypeInfo<T>)_options.GetTypeInfo(typeof(T)))!;
}

if (result.IsCompleted)
Expand All @@ -95,4 +100,38 @@ private static bool TryParseJson(ref ReadOnlySequence<byte> buffer, out JsonDocu

return false;
}
}
}

// extended types that are not generated by source generator
/// Filters
[JsonSerializable(typeof(IDictionary<string, IDictionary<string, bool>>))]

/// <see cref="ConfigOperations.ListConfigsAsync" />
[JsonSerializable(typeof(SwarmConfig[]))]
/// <see cref="ContainerOperations.ListContainersAsync" />
[JsonSerializable(typeof(ContainerListResponse[]))]
/// <see cref="ContainerOperations.InspectChangesAsync" />
[JsonSerializable(typeof(ContainerFileSystemChangeResponse[]))]

/// <see cref="ImageOperations.ListImagesAsync" />
[JsonSerializable(typeof(ImagesListResponse[]))]
/// <see cref="ImageOperations.GetImageHistoryAsync" />
[JsonSerializable(typeof(ImageHistoryResponse[]))]
/// <see cref="ImageOperations.DeleteImageAsync"/>
[JsonSerializable(typeof(Dictionary<string, string>[]))]
/// <see cref="ImageOperations.SearchImagesAsync" />
[JsonSerializable(typeof(ImageSearchResponse[]))]

/// <see cref="NetworkOperations.ListNetworksAsync" />
[JsonSerializable(typeof(NetworkResponse[]))]

/// <see cref="PluginOperations.ListPluginsAsync" />
[JsonSerializable(typeof(Plugin[]))]
/// <see cref="PluginOperations.GetPrivilegesAsync" />
[JsonSerializable(typeof(PluginPrivilege[]))]

/// <see cref="SwarmOperations.ListServicesAsync" />
[JsonSerializable(typeof(SwarmService[]))]
/// <see cref="SwarmOperations.ListNodesAsync" />
[JsonSerializable(typeof(NodeListResponse[]))]
internal sealed partial class DockerExtendedJsonSerializerContext : JsonSerializerContext { }
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ public CommitContainerChangesParameters(ContainerConfig Config)
[QueryStringParameter("author", false)]
public string? Author { get; set; }

[QueryStringParameter("changes", false, typeof(EnumerableQueryStringConverter))]
[QueryStringParameter<EnumerableQueryStringConverter>("changes", false)]
public IList<string>? Changes { get; set; }

[QueryStringParameter("pause", false, typeof(BoolQueryStringConverter))]
[QueryStringParameter<BoolQueryStringConverter>("pause", false)]
public bool? Pause { get; set; }

[JsonPropertyName("Hostname")]
Expand Down
10 changes: 5 additions & 5 deletions src/Docker.DotNet/Models/ContainerAttachParameters.Generated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@ namespace Docker.DotNet.Models
{
public class ContainerAttachParameters // (main.ContainerAttachParameters)
{
[QueryStringParameter("stream", false, typeof(BoolQueryStringConverter))]
[QueryStringParameter<BoolQueryStringConverter>("stream", false)]
public bool? Stream { get; set; }

[QueryStringParameter("stdin", false, typeof(BoolQueryStringConverter))]
[QueryStringParameter<BoolQueryStringConverter>("stdin", false)]
public bool? Stdin { get; set; }

[QueryStringParameter("stdout", false, typeof(BoolQueryStringConverter))]
[QueryStringParameter<BoolQueryStringConverter>("stdout", false)]
public bool? Stdout { get; set; }

[QueryStringParameter("stderr", false, typeof(BoolQueryStringConverter))]
[QueryStringParameter<BoolQueryStringConverter>("stderr", false)]
public bool? Stderr { get; set; }

[QueryStringParameter("detachKeys", false)]
public string? DetachKeys { get; set; }

[QueryStringParameter("logs", false, typeof(BoolQueryStringConverter))]
[QueryStringParameter<BoolQueryStringConverter>("logs", false)]
public bool? Logs { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class ContainerEventsParameters // (main.ContainerEventsParameters)
[QueryStringParameter("until", false)]
public string? Until { get; set; }

[QueryStringParameter("filters", false, typeof(MapQueryStringConverter))]
[QueryStringParameter<MapQueryStringConverter>("filters", false)]
public IDictionary<string, IDictionary<string, bool>>? Filters { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models
{
public class ContainerInspectParameters // (main.ContainerInspectParameters)
{
[QueryStringParameter("size", false, typeof(BoolQueryStringConverter))]
[QueryStringParameter<BoolQueryStringConverter>("size", false)]
public bool? IncludeSize { get; set; }
}
}
8 changes: 4 additions & 4 deletions src/Docker.DotNet/Models/ContainerLogsParameters.Generated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ namespace Docker.DotNet.Models
{
public class ContainerLogsParameters // (main.ContainerLogsParameters)
{
[QueryStringParameter("stdout", false, typeof(BoolQueryStringConverter))]
[QueryStringParameter<BoolQueryStringConverter>("stdout", false)]
public bool? ShowStdout { get; set; }

[QueryStringParameter("stderr", false, typeof(BoolQueryStringConverter))]
[QueryStringParameter<BoolQueryStringConverter>("stderr", false)]
public bool? ShowStderr { get; set; }

[QueryStringParameter("since", false)]
Expand All @@ -15,10 +15,10 @@ public class ContainerLogsParameters // (main.ContainerLogsParameters)
[QueryStringParameter("until", false)]
public string? Until { get; set; }

[QueryStringParameter("timestamps", false, typeof(BoolQueryStringConverter))]
[QueryStringParameter<BoolQueryStringConverter>("timestamps", false)]
public bool? Timestamps { get; set; }

[QueryStringParameter("follow", false, typeof(BoolQueryStringConverter))]
[QueryStringParameter<BoolQueryStringConverter>("follow", false)]
public bool? Follow { get; set; }

[QueryStringParameter("tail", false)]
Expand Down
Loading