diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0559e652..90d97e1b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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 }} diff --git a/Directory.Packages.props b/Directory.Packages.props index c8be7ea0..3bb23f85 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -11,8 +11,7 @@ - - - + + diff --git a/global.json b/global.json new file mode 100644 index 00000000..802ab217 --- /dev/null +++ b/global.json @@ -0,0 +1,5 @@ +{ + "test": { + "runner": "Microsoft.Testing.Platform" + } +} \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props index efc57594..a6367c51 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -20,6 +20,7 @@ enable + true diff --git a/src/Docker.DotNet.NPipe/DockerHandlerFactory.cs b/src/Docker.DotNet.NPipe/DockerHandlerFactory.cs index 40d003f4..1310e069 100644 --- a/src/Docker.DotNet.NPipe/DockerHandlerFactory.cs +++ b/src/Docker.DotNet.NPipe/DockerHandlerFactory.cs @@ -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) diff --git a/src/Docker.DotNet.NativeHttp/DockerHandlerFactory.cs b/src/Docker.DotNet.NativeHttp/DockerHandlerFactory.cs index 4ee2d2d1..a7c568f8 100644 --- a/src/Docker.DotNet.NativeHttp/DockerHandlerFactory.cs +++ b/src/Docker.DotNet.NativeHttp/DockerHandlerFactory.cs @@ -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, diff --git a/src/Docker.DotNet.NativeHttp/NativeHttpTransportOptions.cs b/src/Docker.DotNet.NativeHttp/NativeHttpTransportOptions.cs index 5bf408ce..45a295fa 100644 --- a/src/Docker.DotNet.NativeHttp/NativeHttpTransportOptions.cs +++ b/src/Docker.DotNet.NativeHttp/NativeHttpTransportOptions.cs @@ -5,7 +5,7 @@ namespace Docker.DotNet.NativeHttp; /// public sealed record NativeHttpTransportOptions { -#if NET6_0_OR_GREATER +#if NET /// /// Gets a callback that configures the created instance. /// diff --git a/src/Docker.DotNet.X509/CertificateCredentials.cs b/src/Docker.DotNet.X509/CertificateCredentials.cs index 1c732bbd..2b37fe04 100644 --- a/src/Docker.DotNet.X509/CertificateCredentials.cs +++ b/src/Docker.DotNet.X509/CertificateCredentials.cs @@ -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) diff --git a/src/Docker.DotNet.X509/DockerTlsCertificates.cs b/src/Docker.DotNet.X509/DockerTlsCertificates.cs index 193fb85c..bbf58750 100644 --- a/src/Docker.DotNet.X509/DockerTlsCertificates.cs +++ b/src/Docker.DotNet.X509/DockerTlsCertificates.cs @@ -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()) @@ -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 } @@ -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); diff --git a/src/Docker.DotNet/Docker.DotNet.csproj b/src/Docker.DotNet/Docker.DotNet.csproj index da5c71ad..1430a200 100644 --- a/src/Docker.DotNet/Docker.DotNet.csproj +++ b/src/Docker.DotNet/Docker.DotNet.csproj @@ -1,4 +1,4 @@ - + Docker.DotNet Docker.DotNet.Enhanced @@ -29,6 +29,7 @@ + @@ -49,6 +50,7 @@ + diff --git a/src/Docker.DotNet/DockerClient.cs b/src/Docker.DotNet/DockerClient.cs index 6754f9b6..6328e8f7 100644 --- a/src/Docker.DotNet/DockerClient.cs +++ b/src/Docker.DotNet/DockerClient.cs @@ -1,7 +1,5 @@ namespace Docker.DotNet; -using System; - public sealed class DockerClient : IDockerClient { internal readonly IEnumerable NoErrorHandlers = Enumerable.Empty(); @@ -370,7 +368,7 @@ private async Task PrivateMakeRequestAsync( if (Timeout.InfiniteTimeSpan == timeout) { -#if NET6_0_OR_GREATER +#if NET return await _client.SendAsync(request, completionOption, cancellationToken) .ConfigureAwait(false); #else diff --git a/src/Docker.DotNet/Endpoints/ConfigsOperations.cs b/src/Docker.DotNet/Endpoints/ConfigsOperations.cs index d3712136..744f1c8f 100644 --- a/src/Docker.DotNet/Endpoints/ConfigsOperations.cs +++ b/src/Docker.DotNet/Endpoints/ConfigsOperations.cs @@ -11,7 +11,7 @@ internal ConfigOperations(DockerClient client) public async Task> ListConfigsAsync(CancellationToken cancellationToken = default) { - return await _client.MakeRequestAsync>(_client.NoErrorHandlers, HttpMethod.Get, "configs", cancellationToken) + return await _client.MakeRequestAsync(_client.NoErrorHandlers, HttpMethod.Get, "configs", cancellationToken) .ConfigureAwait(false); } diff --git a/src/Docker.DotNet/Endpoints/ISwarmOperations.cs b/src/Docker.DotNet/Endpoints/ISwarmOperations.cs index 1648e5ee..e69c6dec 100644 --- a/src/Docker.DotNet/Endpoints/ISwarmOperations.cs +++ b/src/Docker.DotNet/Endpoints/ISwarmOperations.cs @@ -121,7 +121,7 @@ public interface ISwarmOperations /// 500 - Server error. /// 503 - Node is not part of a swarm. /// - Task> ListServicesAsync(ServiceListParameters? parameters = null, CancellationToken cancellationToken = default); + Task> ListServicesAsync(ServiceListParameters? parameters = null, CancellationToken cancellationToken = default); /// /// Update a service. @@ -198,7 +198,7 @@ public interface ISwarmOperations /// 503 - Node is not part of a swarm. /// /// - Task> ListNodesAsync(CancellationToken cancellationToken = default); + Task> ListNodesAsync(CancellationToken cancellationToken = default); /// /// Inspect a node. diff --git a/src/Docker.DotNet/Endpoints/SwarmOperations.cs b/src/Docker.DotNet/Endpoints/SwarmOperations.cs index 6ff57d85..fa9a77cc 100644 --- a/src/Docker.DotNet/Endpoints/SwarmOperations.cs +++ b/src/Docker.DotNet/Endpoints/SwarmOperations.cs @@ -82,7 +82,7 @@ await _client.MakeRequestAsync([NotInSwarmResponseHandler], HttpMethod.Post, "sw .ConfigureAwait(false); } - public async Task> ListServicesAsync(ServiceListParameters? parameters = null, CancellationToken cancellationToken = default) + public async Task> ListServicesAsync(ServiceListParameters? parameters = null, CancellationToken cancellationToken = default) { var queryParameters = parameters == null ? null : new QueryString(parameters); @@ -193,7 +193,7 @@ private static Dictionary RegistryAuthHeaders(AuthConfig? authCo }; } - public async Task> ListNodesAsync(CancellationToken cancellationToken = default) + public async Task> ListNodesAsync(CancellationToken cancellationToken = default) { return await _client.MakeRequestAsync([NotInSwarmResponseHandler], HttpMethod.Get, "nodes", cancellationToken) .ConfigureAwait(false); diff --git a/src/Docker.DotNet/IQueryStringConverterInstanceFactory.cs b/src/Docker.DotNet/IQueryStringConverterInstanceFactory.cs deleted file mode 100644 index cd81a9c5..00000000 --- a/src/Docker.DotNet/IQueryStringConverterInstanceFactory.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Docker.DotNet; - -internal interface IQueryStringConverterInstanceFactory -{ - IQueryStringConverter GetConverterInstance(Type t); -} \ No newline at end of file diff --git a/src/Docker.DotNet/JsonSerializer.cs b/src/Docker.DotNet/JsonSerializer.cs index 87e11f9b..711a9fff 100644 --- a/src/Docker.DotNet/JsonSerializer.cs +++ b/src/Docker.DotNet/JsonSerializer.cs @@ -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()); _options.Converters.Add(new JsonEnumMemberConverter()); _options.Converters.Add(new JsonDateTimeConverter()); _options.Converters.Add(new JsonNullableDateTimeConverter()); + _options.MakeReadOnly(); } public static JsonSerializer Instance { get; } @@ -38,22 +43,22 @@ public HttpContent GetHttpContent(T value) public string Serialize(T value) { - return System.Text.Json.JsonSerializer.Serialize(value, _options); + return System.Text.Json.JsonSerializer.Serialize(value, (JsonTypeInfo)_options.GetTypeInfo(typeof(T))); } public byte[] SerializeToUtf8Bytes(T value) { - return System.Text.Json.JsonSerializer.SerializeToUtf8Bytes(value, _options); + return System.Text.Json.JsonSerializer.SerializeToUtf8Bytes(value, (JsonTypeInfo)_options.GetTypeInfo(typeof(T))); } public T Deserialize(byte[] json) { - return System.Text.Json.JsonSerializer.Deserialize(json, _options)!; + return System.Text.Json.JsonSerializer.Deserialize(json, (JsonTypeInfo)_options.GetTypeInfo(typeof(T)))!; } public Task DeserializeAsync(HttpContent content, CancellationToken cancellationToken) { - return content.ReadFromJsonAsync(_options, cancellationToken)!; + return content.ReadFromJsonAsync((JsonTypeInfo)_options.GetTypeInfo(typeof(T)), cancellationToken)!; } public async IAsyncEnumerable DeserializeAsync(Stream stream, [EnumeratorCancellation] CancellationToken cancellationToken) @@ -69,7 +74,7 @@ public async IAsyncEnumerable DeserializeAsync(Stream stream, [EnumeratorC while (!buffer.IsEmpty && TryParseJson(ref buffer, out var jsonDocument)) { - yield return jsonDocument!.Deserialize(_options)!; + yield return jsonDocument!.Deserialize((JsonTypeInfo)_options.GetTypeInfo(typeof(T)))!; } if (result.IsCompleted) @@ -95,4 +100,38 @@ private static bool TryParseJson(ref ReadOnlySequence buffer, out JsonDocu return false; } -} \ No newline at end of file +} + +// extended types that are not generated by source generator +/// Filters +[JsonSerializable(typeof(IDictionary>))] + +/// +[JsonSerializable(typeof(SwarmConfig[]))] +/// +[JsonSerializable(typeof(ContainerListResponse[]))] +/// +[JsonSerializable(typeof(ContainerFileSystemChangeResponse[]))] + +/// +[JsonSerializable(typeof(ImagesListResponse[]))] +/// +[JsonSerializable(typeof(ImageHistoryResponse[]))] +/// +[JsonSerializable(typeof(Dictionary[]))] +/// +[JsonSerializable(typeof(ImageSearchResponse[]))] + +/// +[JsonSerializable(typeof(NetworkResponse[]))] + +/// +[JsonSerializable(typeof(Plugin[]))] +/// +[JsonSerializable(typeof(PluginPrivilege[]))] + +/// +[JsonSerializable(typeof(SwarmService[]))] +/// +[JsonSerializable(typeof(NodeListResponse[]))] +internal sealed partial class DockerExtendedJsonSerializerContext : JsonSerializerContext { } diff --git a/src/Docker.DotNet/Models/CommitContainerChangesParameters.Generated.cs b/src/Docker.DotNet/Models/CommitContainerChangesParameters.Generated.cs index de1e14dc..1eb3e160 100644 --- a/src/Docker.DotNet/Models/CommitContainerChangesParameters.Generated.cs +++ b/src/Docker.DotNet/Models/CommitContainerChangesParameters.Generated.cs @@ -53,10 +53,10 @@ public CommitContainerChangesParameters(ContainerConfig Config) [QueryStringParameter("author", false)] public string? Author { get; set; } - [QueryStringParameter("changes", false, typeof(EnumerableQueryStringConverter))] + [QueryStringParameter("changes", false)] public IList? Changes { get; set; } - [QueryStringParameter("pause", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("pause", false)] public bool? Pause { get; set; } [JsonPropertyName("Hostname")] diff --git a/src/Docker.DotNet/Models/ContainerAttachParameters.Generated.cs b/src/Docker.DotNet/Models/ContainerAttachParameters.Generated.cs index 536058c3..f277ffba 100644 --- a/src/Docker.DotNet/Models/ContainerAttachParameters.Generated.cs +++ b/src/Docker.DotNet/Models/ContainerAttachParameters.Generated.cs @@ -3,22 +3,22 @@ namespace Docker.DotNet.Models { public class ContainerAttachParameters // (main.ContainerAttachParameters) { - [QueryStringParameter("stream", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("stream", false)] public bool? Stream { get; set; } - [QueryStringParameter("stdin", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("stdin", false)] public bool? Stdin { get; set; } - [QueryStringParameter("stdout", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("stdout", false)] public bool? Stdout { get; set; } - [QueryStringParameter("stderr", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("stderr", false)] public bool? Stderr { get; set; } [QueryStringParameter("detachKeys", false)] public string? DetachKeys { get; set; } - [QueryStringParameter("logs", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("logs", false)] public bool? Logs { get; set; } } } diff --git a/src/Docker.DotNet/Models/ContainerEventsParameters.Generated.cs b/src/Docker.DotNet/Models/ContainerEventsParameters.Generated.cs index 7214bcc7..728f69ab 100644 --- a/src/Docker.DotNet/Models/ContainerEventsParameters.Generated.cs +++ b/src/Docker.DotNet/Models/ContainerEventsParameters.Generated.cs @@ -9,7 +9,7 @@ public class ContainerEventsParameters // (main.ContainerEventsParameters) [QueryStringParameter("until", false)] public string? Until { get; set; } - [QueryStringParameter("filters", false, typeof(MapQueryStringConverter))] + [QueryStringParameter("filters", false)] public IDictionary>? Filters { get; set; } } } diff --git a/src/Docker.DotNet/Models/ContainerInspectParameters.Generated.cs b/src/Docker.DotNet/Models/ContainerInspectParameters.Generated.cs index 9da5c347..35cd3880 100644 --- a/src/Docker.DotNet/Models/ContainerInspectParameters.Generated.cs +++ b/src/Docker.DotNet/Models/ContainerInspectParameters.Generated.cs @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models { public class ContainerInspectParameters // (main.ContainerInspectParameters) { - [QueryStringParameter("size", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("size", false)] public bool? IncludeSize { get; set; } } } diff --git a/src/Docker.DotNet/Models/ContainerLogsParameters.Generated.cs b/src/Docker.DotNet/Models/ContainerLogsParameters.Generated.cs index 32c8e832..653b9d82 100644 --- a/src/Docker.DotNet/Models/ContainerLogsParameters.Generated.cs +++ b/src/Docker.DotNet/Models/ContainerLogsParameters.Generated.cs @@ -3,10 +3,10 @@ namespace Docker.DotNet.Models { public class ContainerLogsParameters // (main.ContainerLogsParameters) { - [QueryStringParameter("stdout", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("stdout", false)] public bool? ShowStdout { get; set; } - [QueryStringParameter("stderr", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("stderr", false)] public bool? ShowStderr { get; set; } [QueryStringParameter("since", false)] @@ -15,10 +15,10 @@ public class ContainerLogsParameters // (main.ContainerLogsParameters) [QueryStringParameter("until", false)] public string? Until { get; set; } - [QueryStringParameter("timestamps", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("timestamps", false)] public bool? Timestamps { get; set; } - [QueryStringParameter("follow", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("follow", false)] public bool? Follow { get; set; } [QueryStringParameter("tail", false)] diff --git a/src/Docker.DotNet/Models/ContainerRemoveParameters.Generated.cs b/src/Docker.DotNet/Models/ContainerRemoveParameters.Generated.cs index 861ab467..ce982bcc 100644 --- a/src/Docker.DotNet/Models/ContainerRemoveParameters.Generated.cs +++ b/src/Docker.DotNet/Models/ContainerRemoveParameters.Generated.cs @@ -3,13 +3,13 @@ namespace Docker.DotNet.Models { public class ContainerRemoveParameters // (main.ContainerRemoveParameters) { - [QueryStringParameter("v", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("v", false)] public bool? RemoveVolumes { get; set; } - [QueryStringParameter("link", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("link", false)] public bool? RemoveLinks { get; set; } - [QueryStringParameter("force", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("force", false)] public bool? Force { get; set; } } } diff --git a/src/Docker.DotNet/Models/ContainerStatsParameters.Generated.cs b/src/Docker.DotNet/Models/ContainerStatsParameters.Generated.cs index 8c00b12d..fb01ca98 100644 --- a/src/Docker.DotNet/Models/ContainerStatsParameters.Generated.cs +++ b/src/Docker.DotNet/Models/ContainerStatsParameters.Generated.cs @@ -3,10 +3,10 @@ namespace Docker.DotNet.Models { public class ContainerStatsParameters // (main.ContainerStatsParameters) { - [QueryStringParameter("stream", true, typeof(BoolQueryStringConverter))] + [QueryStringParameter("stream", true)] public bool Stream { get; set; } = true; - [QueryStringParameter("one-shot", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("one-shot", false)] public bool? OneShot { get; set; } } } diff --git a/src/Docker.DotNet/Models/ContainersListParameters.Generated.cs b/src/Docker.DotNet/Models/ContainersListParameters.Generated.cs index f7573786..1781acc9 100644 --- a/src/Docker.DotNet/Models/ContainersListParameters.Generated.cs +++ b/src/Docker.DotNet/Models/ContainersListParameters.Generated.cs @@ -3,16 +3,16 @@ namespace Docker.DotNet.Models { public class ContainersListParameters // (main.ContainersListParameters) { - [QueryStringParameter("all", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("all", false)] public bool? All { get; set; } [QueryStringParameter("limit", false)] public long? Limit { get; set; } - [QueryStringParameter("size", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("size", false)] public bool? Size { get; set; } - [QueryStringParameter("filters", false, typeof(MapQueryStringConverter))] + [QueryStringParameter("filters", false)] public IDictionary>? Filters { get; set; } } } diff --git a/src/Docker.DotNet/Models/ContainersPruneParameters.Generated.cs b/src/Docker.DotNet/Models/ContainersPruneParameters.Generated.cs index e25de825..c619c2b6 100644 --- a/src/Docker.DotNet/Models/ContainersPruneParameters.Generated.cs +++ b/src/Docker.DotNet/Models/ContainersPruneParameters.Generated.cs @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models { public class ContainersPruneParameters // (main.ContainersPruneParameters) { - [QueryStringParameter("filters", false, typeof(MapQueryStringConverter))] + [QueryStringParameter("filters", false)] public IDictionary>? Filters { get; set; } } } diff --git a/src/Docker.DotNet/Models/CopyToContainerParameters.Generated.cs b/src/Docker.DotNet/Models/CopyToContainerParameters.Generated.cs index b3e0608c..af17cb52 100644 --- a/src/Docker.DotNet/Models/CopyToContainerParameters.Generated.cs +++ b/src/Docker.DotNet/Models/CopyToContainerParameters.Generated.cs @@ -6,10 +6,10 @@ public class CopyToContainerParameters // (main.CopyToContainerParameters) [QueryStringParameter("path", true)] public string Path { get; set; } = default!; - [QueryStringParameter("noOverwriteDirNonDir", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("noOverwriteDirNonDir", false)] public bool? AllowOverwriteDirWithFile { get; set; } - [QueryStringParameter("copyUIDGID", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("copyUIDGID", false)] public bool? CopyUIDGID { get; set; } } } diff --git a/src/Docker.DotNet/Models/DockerModelsJsonSerializerContext.Generated.cs b/src/Docker.DotNet/Models/DockerModelsJsonSerializerContext.Generated.cs new file mode 100644 index 00000000..6ec7dcda --- /dev/null +++ b/src/Docker.DotNet/Models/DockerModelsJsonSerializerContext.Generated.cs @@ -0,0 +1,253 @@ +namespace Docker.DotNet.Models +{ + [JsonSerializable(typeof(Actor))] + [JsonSerializable(typeof(Annotations))] + [JsonSerializable(typeof(AppArmorOpts))] + [JsonSerializable(typeof(AttestationProperties))] + [JsonSerializable(typeof(AuthConfig))] + [JsonSerializable(typeof(AuthResponse))] + [JsonSerializable(typeof(BindOptions))] + [JsonSerializable(typeof(BlkioStatEntry))] + [JsonSerializable(typeof(BlkioStats))] + [JsonSerializable(typeof(CAConfig))] + [JsonSerializable(typeof(CPUStats))] + [JsonSerializable(typeof(CPUUsage))] + [JsonSerializable(typeof(CapacityRange))] + [JsonSerializable(typeof(ClusterInfo))] + [JsonSerializable(typeof(ClusterVolume))] + [JsonSerializable(typeof(ClusterVolumeSpec))] + [JsonSerializable(typeof(Commit))] + [JsonSerializable(typeof(CommitContainerChangesResponse))] + [JsonSerializable(typeof(ComponentVersion))] + [JsonSerializable(typeof(ConfigReference))] + [JsonSerializable(typeof(ConfigReferenceFileTarget))] + [JsonSerializable(typeof(ConsoleSize))] + [JsonSerializable(typeof(ContainerConfig))] + [JsonSerializable(typeof(ContainerExecCreateParameters))] + [JsonSerializable(typeof(ContainerExecCreateResponse))] + [JsonSerializable(typeof(ContainerExecInspectResponse))] + [JsonSerializable(typeof(ContainerExecStartParameters))] + [JsonSerializable(typeof(ContainerFileSystemChangeResponse))] + [JsonSerializable(typeof(ContainerInspectResponse))] + [JsonSerializable(typeof(ContainerListResponse))] + [JsonSerializable(typeof(ContainerPathStatResponse))] + [JsonSerializable(typeof(ContainerProcessesResponse))] + [JsonSerializable(typeof(ContainerSpec))] + [JsonSerializable(typeof(ContainerStatsResponse))] + [JsonSerializable(typeof(ContainerStatus))] + [JsonSerializable(typeof(ContainerUpdateResponse))] + [JsonSerializable(typeof(ContainerWaitResponse))] + [JsonSerializable(typeof(ContainerdInfo))] + [JsonSerializable(typeof(ContainerdNamespaces))] + [JsonSerializable(typeof(ContainersPruneResponse))] + [JsonSerializable(typeof(CreateContainerParameters))] + [JsonSerializable(typeof(CreateContainerResponse))] + [JsonSerializable(typeof(CredentialSpec))] + [JsonSerializable(typeof(DNSConfig))] + [JsonSerializable(typeof(Descriptor))] + [JsonSerializable(typeof(DeviceInfo))] + [JsonSerializable(typeof(DeviceMapping))] + [JsonSerializable(typeof(DeviceRequest))] + [JsonSerializable(typeof(DiscreteGenericResource))] + [JsonSerializable(typeof(DispatcherConfig))] + [JsonSerializable(typeof(DockerOCIImageConfigExt))] + [JsonSerializable(typeof(Driver))] + [JsonSerializable(typeof(DriverData))] + [JsonSerializable(typeof(EncryptionConfig))] + [JsonSerializable(typeof(Endpoint))] + [JsonSerializable(typeof(EndpointIPAMConfig))] + [JsonSerializable(typeof(EndpointResource))] + [JsonSerializable(typeof(EndpointSettings))] + [JsonSerializable(typeof(EndpointSpec))] + [JsonSerializable(typeof(EndpointVirtualIP))] + [JsonSerializable(typeof(EngineDescription))] + [JsonSerializable(typeof(ExecProcessConfig))] + [JsonSerializable(typeof(ExternalCA))] + [JsonSerializable(typeof(FirewallInfo))] + [JsonSerializable(typeof(GenericResource))] + [JsonSerializable(typeof(Health))] + [JsonSerializable(typeof(HealthSummary))] + [JsonSerializable(typeof(HealthcheckConfig))] + [JsonSerializable(typeof(HealthcheckResult))] + [JsonSerializable(typeof(HostConfig))] + [JsonSerializable(typeof(IPAM))] + [JsonSerializable(typeof(IPAMConfig))] + [JsonSerializable(typeof(IPAMOptions))] + [JsonSerializable(typeof(IPAMStatus))] + [JsonSerializable(typeof(ImageBuildParameters))] + [JsonSerializable(typeof(ImageBuildResult))] + [JsonSerializable(typeof(ImageConfig))] + [JsonSerializable(typeof(ImageDeleteResponse))] + [JsonSerializable(typeof(ImageHistoryResponse))] + [JsonSerializable(typeof(ImageInspectResponse))] + [JsonSerializable(typeof(ImageOptions))] + [JsonSerializable(typeof(ImageProperties))] + [JsonSerializable(typeof(ImagePropertiesSize))] + [JsonSerializable(typeof(ImagePushParameters))] + [JsonSerializable(typeof(ImageSearchResponse))] + [JsonSerializable(typeof(ImagesCreateParameters))] + [JsonSerializable(typeof(ImagesListResponse))] + [JsonSerializable(typeof(ImagesPruneResponse))] + [JsonSerializable(typeof(IndexInfo))] + [JsonSerializable(typeof(Info))] + [JsonSerializable(typeof(JSONError))] + [JsonSerializable(typeof(JSONMessage))] + [JsonSerializable(typeof(JSONProgress))] + [JsonSerializable(typeof(JobStatus))] + [JsonSerializable(typeof(JoinTokens))] + [JsonSerializable(typeof(LogConfig))] + [JsonSerializable(typeof(ManagerStatus))] + [JsonSerializable(typeof(ManifestSummary))] + [JsonSerializable(typeof(ManifestSummarySize))] + [JsonSerializable(typeof(MemoryStats))] + [JsonSerializable(typeof(Message))] + [JsonSerializable(typeof(Meta))] + [JsonSerializable(typeof(Metadata))] + [JsonSerializable(typeof(Mount))] + [JsonSerializable(typeof(MountPoint))] + [JsonSerializable(typeof(NamedGenericResource))] + [JsonSerializable(typeof(Network))] + [JsonSerializable(typeof(NetworkAddressPool))] + [JsonSerializable(typeof(NetworkAttachment))] + [JsonSerializable(typeof(NetworkAttachmentConfig))] + [JsonSerializable(typeof(NetworkAttachmentSpec))] + [JsonSerializable(typeof(NetworkConnectParameters))] + [JsonSerializable(typeof(NetworkDisconnectParameters))] + [JsonSerializable(typeof(NetworkResponse))] + [JsonSerializable(typeof(NetworkSettings))] + [JsonSerializable(typeof(NetworkSettingsSummary))] + [JsonSerializable(typeof(NetworkSpec))] + [JsonSerializable(typeof(NetworkStats))] + [JsonSerializable(typeof(NetworkTask))] + [JsonSerializable(typeof(NetworkingConfig))] + [JsonSerializable(typeof(NetworksCreateParameters))] + [JsonSerializable(typeof(NetworksCreateResponse))] + [JsonSerializable(typeof(NetworksPruneResponse))] + [JsonSerializable(typeof(NodeCSIInfo))] + [JsonSerializable(typeof(NodeDescription))] + [JsonSerializable(typeof(NodeListResponse))] + [JsonSerializable(typeof(NodeStatus))] + [JsonSerializable(typeof(NodeUpdateParameters))] + [JsonSerializable(typeof(OrchestrationConfig))] + [JsonSerializable(typeof(Peer))] + [JsonSerializable(typeof(PeerInfo))] + [JsonSerializable(typeof(PidsStats))] + [JsonSerializable(typeof(Placement))] + [JsonSerializable(typeof(PlacementPreference))] + [JsonSerializable(typeof(Platform))] + [JsonSerializable(typeof(PlatformInfo))] + [JsonSerializable(typeof(Plugin))] + [JsonSerializable(typeof(PluginArgs))] + [JsonSerializable(typeof(PluginCapabilityID))] + [JsonSerializable(typeof(PluginConfig))] + [JsonSerializable(typeof(PluginConfigureParameters))] + [JsonSerializable(typeof(PluginDescription))] + [JsonSerializable(typeof(PluginDevice))] + [JsonSerializable(typeof(PluginEnv))] + [JsonSerializable(typeof(PluginInstallParameters))] + [JsonSerializable(typeof(PluginInterface))] + [JsonSerializable(typeof(PluginLinuxConfig))] + [JsonSerializable(typeof(PluginMount))] + [JsonSerializable(typeof(PluginNetworkConfig))] + [JsonSerializable(typeof(PluginPrivilege))] + [JsonSerializable(typeof(PluginRootFS))] + [JsonSerializable(typeof(PluginSettings))] + [JsonSerializable(typeof(PluginUpgradeParameters))] + [JsonSerializable(typeof(PluginUser))] + [JsonSerializable(typeof(PluginsInfo))] + [JsonSerializable(typeof(PortBinding))] + [JsonSerializable(typeof(PortConfig))] + [JsonSerializable(typeof(PortStatus))] + [JsonSerializable(typeof(PortSummary))] + [JsonSerializable(typeof(Privileges))] + [JsonSerializable(typeof(PublishStatus))] + [JsonSerializable(typeof(RaftConfig))] + [JsonSerializable(typeof(ReplicatedJob))] + [JsonSerializable(typeof(ReplicatedService))] + [JsonSerializable(typeof(ResourceRequirements))] + [JsonSerializable(typeof(Resources))] + [JsonSerializable(typeof(RestartPolicy))] + [JsonSerializable(typeof(RootFS))] + [JsonSerializable(typeof(RootFSStorage))] + [JsonSerializable(typeof(RootFSStorageSnapshot))] + [JsonSerializable(typeof(Runtime))] + [JsonSerializable(typeof(RuntimePrivilege))] + [JsonSerializable(typeof(RuntimeWithStatus))] + [JsonSerializable(typeof(SELinuxContext))] + [JsonSerializable(typeof(SeccompOpts))] + [JsonSerializable(typeof(Secret))] + [JsonSerializable(typeof(SecretCreateResponse))] + [JsonSerializable(typeof(SecretReference))] + [JsonSerializable(typeof(SecretReferenceFileTarget))] + [JsonSerializable(typeof(ServiceConfig))] + [JsonSerializable(typeof(ServiceCreateParameters))] + [JsonSerializable(typeof(ServiceCreateResponse))] + [JsonSerializable(typeof(ServiceInfo))] + [JsonSerializable(typeof(ServiceMode))] + [JsonSerializable(typeof(ServiceSpec))] + [JsonSerializable(typeof(ServiceStatus))] + [JsonSerializable(typeof(ServiceUpdateParameters))] + [JsonSerializable(typeof(ServiceUpdateResponse))] + [JsonSerializable(typeof(Spec))] + [JsonSerializable(typeof(SpreadOver))] + [JsonSerializable(typeof(State))] + [JsonSerializable(typeof(Status))] + [JsonSerializable(typeof(Storage))] + [JsonSerializable(typeof(StorageStats))] + [JsonSerializable(typeof(SubnetStatus))] + [JsonSerializable(typeof(SummaryHostConfig))] + [JsonSerializable(typeof(SwarmConfig))] + [JsonSerializable(typeof(SwarmConfigReference))] + [JsonSerializable(typeof(SwarmConfigSpec))] + [JsonSerializable(typeof(SwarmCreateConfigParameters))] + [JsonSerializable(typeof(SwarmCreateConfigResponse))] + [JsonSerializable(typeof(SwarmDriver))] + [JsonSerializable(typeof(SwarmIPAMConfig))] + [JsonSerializable(typeof(SwarmInitParameters))] + [JsonSerializable(typeof(SwarmInspectResponse))] + [JsonSerializable(typeof(SwarmJoinParameters))] + [JsonSerializable(typeof(SwarmLimit))] + [JsonSerializable(typeof(SwarmNetwork))] + [JsonSerializable(typeof(SwarmPlatform))] + [JsonSerializable(typeof(SwarmResources))] + [JsonSerializable(typeof(SwarmRestartPolicy))] + [JsonSerializable(typeof(SwarmRuntimeSpec))] + [JsonSerializable(typeof(SwarmSecretSpec))] + [JsonSerializable(typeof(SwarmService))] + [JsonSerializable(typeof(SwarmUnlockParameters))] + [JsonSerializable(typeof(SwarmUnlockResponse))] + [JsonSerializable(typeof(SwarmUpdateConfig))] + [JsonSerializable(typeof(SwarmUpdateConfigParameters))] + [JsonSerializable(typeof(SwarmUpdateParameters))] + [JsonSerializable(typeof(SystemInfoResponse))] + [JsonSerializable(typeof(TLSInfo))] + [JsonSerializable(typeof(TaskDefaults))] + [JsonSerializable(typeof(TaskResponse))] + [JsonSerializable(typeof(TaskSpec))] + [JsonSerializable(typeof(TaskStatus))] + [JsonSerializable(typeof(ThrottleDevice))] + [JsonSerializable(typeof(ThrottlingData))] + [JsonSerializable(typeof(TmpfsOptions))] + [JsonSerializable(typeof(Topology))] + [JsonSerializable(typeof(TopologyRequirement))] + [JsonSerializable(typeof(TypeMount))] + [JsonSerializable(typeof(Ulimit))] + [JsonSerializable(typeof(UpdateConfig))] + [JsonSerializable(typeof(UpdateStatus))] + [JsonSerializable(typeof(UsageData))] + [JsonSerializable(typeof(Version))] + [JsonSerializable(typeof(VersionResponse))] + [JsonSerializable(typeof(VolumeAccessMode))] + [JsonSerializable(typeof(VolumeAttachment))] + [JsonSerializable(typeof(VolumeInfo))] + [JsonSerializable(typeof(VolumeOptions))] + [JsonSerializable(typeof(VolumeResponse))] + [JsonSerializable(typeof(VolumeSecret))] + [JsonSerializable(typeof(VolumeTopology))] + [JsonSerializable(typeof(VolumesCreateParameters))] + [JsonSerializable(typeof(VolumesListResponse))] + [JsonSerializable(typeof(VolumesPruneResponse))] + [JsonSerializable(typeof(WaitExitError))] + [JsonSerializable(typeof(WeightDevice))] + internal sealed partial class DockerModelsJsonSerializerContext : JsonSerializerContext { } +} diff --git a/src/Docker.DotNet/Models/ImageBuildParameters.Generated.cs b/src/Docker.DotNet/Models/ImageBuildParameters.Generated.cs index 65d412bb..55f3fcf6 100644 --- a/src/Docker.DotNet/Models/ImageBuildParameters.Generated.cs +++ b/src/Docker.DotNet/Models/ImageBuildParameters.Generated.cs @@ -3,22 +3,22 @@ namespace Docker.DotNet.Models { public class ImageBuildParameters // (main.ImageBuildParameters) { - [QueryStringParameter("t", false, typeof(EnumerableQueryStringConverter))] + [QueryStringParameter("t", false)] public IList? Tags { get; set; } - [QueryStringParameter("q", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("q", false)] public bool? SuppressOutput { get; set; } [QueryStringParameter("remote", false)] public string? RemoteContext { get; set; } - [QueryStringParameter("nocache", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("nocache", false)] public bool? NoCache { get; set; } - [QueryStringParameter("rm", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("rm", false)] public bool? Remove { get; set; } - [QueryStringParameter("forcerm", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("forcerm", false)] public bool? ForceRemove { get; set; } [QueryStringParameter("pull", false)] @@ -51,19 +51,19 @@ public class ImageBuildParameters // (main.ImageBuildParameters) [QueryStringParameter("dockerfile", false)] public string? Dockerfile { get; set; } - [QueryStringParameter("buildargs", false, typeof(MapQueryStringConverter))] + [QueryStringParameter("buildargs", false)] public IDictionary? BuildArgs { get; set; } - [QueryStringParameter("labels", false, typeof(MapQueryStringConverter))] + [QueryStringParameter("labels", false)] public IDictionary? Labels { get; set; } - [QueryStringParameter("squash", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("squash", false)] public bool? Squash { get; set; } - [QueryStringParameter("cachefrom", false, typeof(EnumerableQueryStringConverter))] + [QueryStringParameter("cachefrom", false)] public IList? CacheFrom { get; set; } - [QueryStringParameter("extrahosts", false, typeof(EnumerableQueryStringConverter))] + [QueryStringParameter("extrahosts", false)] public IList? ExtraHosts { get; set; } [QueryStringParameter("target", false)] diff --git a/src/Docker.DotNet/Models/ImageDeleteParameters.Generated.cs b/src/Docker.DotNet/Models/ImageDeleteParameters.Generated.cs index fae052ba..09f3813c 100644 --- a/src/Docker.DotNet/Models/ImageDeleteParameters.Generated.cs +++ b/src/Docker.DotNet/Models/ImageDeleteParameters.Generated.cs @@ -3,10 +3,10 @@ namespace Docker.DotNet.Models { public class ImageDeleteParameters // (main.ImageDeleteParameters) { - [QueryStringParameter("force", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("force", false)] public bool? Force { get; set; } - [QueryStringParameter("noprune", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("noprune", false)] public bool? NoPrune { get; set; } } } diff --git a/src/Docker.DotNet/Models/ImageLoadParameters.Generated.cs b/src/Docker.DotNet/Models/ImageLoadParameters.Generated.cs index 4b13705a..f0106403 100644 --- a/src/Docker.DotNet/Models/ImageLoadParameters.Generated.cs +++ b/src/Docker.DotNet/Models/ImageLoadParameters.Generated.cs @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models { public class ImageLoadParameters // (main.ImageLoadParameters) { - [QueryStringParameter("quiet", true, typeof(BoolQueryStringConverter))] + [QueryStringParameter("quiet", true)] public bool Quiet { get; set; } = default!; } } diff --git a/src/Docker.DotNet/Models/ImagesCreateParameters.Generated.cs b/src/Docker.DotNet/Models/ImagesCreateParameters.Generated.cs index 03931b53..36ccc26d 100644 --- a/src/Docker.DotNet/Models/ImagesCreateParameters.Generated.cs +++ b/src/Docker.DotNet/Models/ImagesCreateParameters.Generated.cs @@ -18,7 +18,7 @@ public class ImagesCreateParameters // (main.ImagesCreateParameters) [QueryStringParameter("message", false)] public string? Message { get; set; } - [QueryStringParameter("changes", false, typeof(EnumerableQueryStringConverter))] + [QueryStringParameter("changes", false)] public IList? Changes { get; set; } [QueryStringParameter("platform", false)] diff --git a/src/Docker.DotNet/Models/ImagesListParameters.Generated.cs b/src/Docker.DotNet/Models/ImagesListParameters.Generated.cs index c1e26dec..2efce66a 100644 --- a/src/Docker.DotNet/Models/ImagesListParameters.Generated.cs +++ b/src/Docker.DotNet/Models/ImagesListParameters.Generated.cs @@ -3,19 +3,19 @@ namespace Docker.DotNet.Models { public class ImagesListParameters // (main.ImagesListParameters) { - [QueryStringParameter("all", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("all", false)] public bool? All { get; set; } - [QueryStringParameter("filters", false, typeof(MapQueryStringConverter))] + [QueryStringParameter("filters", false)] public IDictionary>? Filters { get; set; } - [QueryStringParameter("shared-size", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("shared-size", false)] public bool? SharedSize { get; set; } - [QueryStringParameter("digests", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("digests", false)] public bool? Digests { get; set; } - [QueryStringParameter("manifests", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("manifests", false)] public bool? Manifests { get; set; } } } diff --git a/src/Docker.DotNet/Models/ImagesPruneParameters.Generated.cs b/src/Docker.DotNet/Models/ImagesPruneParameters.Generated.cs index e457204b..7d6968db 100644 --- a/src/Docker.DotNet/Models/ImagesPruneParameters.Generated.cs +++ b/src/Docker.DotNet/Models/ImagesPruneParameters.Generated.cs @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models { public class ImagesPruneParameters // (main.ImagesPruneParameters) { - [QueryStringParameter("filters", false, typeof(MapQueryStringConverter))] + [QueryStringParameter("filters", false)] public IDictionary>? Filters { get; set; } } } diff --git a/src/Docker.DotNet/Models/ImagesSearchParameters.Generated.cs b/src/Docker.DotNet/Models/ImagesSearchParameters.Generated.cs index 4c6ff82b..680afda8 100644 --- a/src/Docker.DotNet/Models/ImagesSearchParameters.Generated.cs +++ b/src/Docker.DotNet/Models/ImagesSearchParameters.Generated.cs @@ -9,7 +9,7 @@ public class ImagesSearchParameters // (main.ImagesSearchParameters) [QueryStringParameter("limit", false)] public long? Limit { get; set; } - [QueryStringParameter("filters", false, typeof(MapQueryStringConverter))] + [QueryStringParameter("filters", false)] public IDictionary>? Filters { get; set; } } } diff --git a/src/Docker.DotNet/Models/NetworksDeleteUnusedParameters.Generated.cs b/src/Docker.DotNet/Models/NetworksDeleteUnusedParameters.Generated.cs index 1788f844..6d004995 100644 --- a/src/Docker.DotNet/Models/NetworksDeleteUnusedParameters.Generated.cs +++ b/src/Docker.DotNet/Models/NetworksDeleteUnusedParameters.Generated.cs @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models { public class NetworksDeleteUnusedParameters // (main.NetworksDeleteUnusedParameters) { - [QueryStringParameter("filters", false, typeof(MapQueryStringConverter))] + [QueryStringParameter("filters", false)] public IDictionary>? Filters { get; set; } } } diff --git a/src/Docker.DotNet/Models/NetworksListParameters.Generated.cs b/src/Docker.DotNet/Models/NetworksListParameters.Generated.cs index 10e2deb0..748bf325 100644 --- a/src/Docker.DotNet/Models/NetworksListParameters.Generated.cs +++ b/src/Docker.DotNet/Models/NetworksListParameters.Generated.cs @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models { public class NetworksListParameters // (main.NetworksListParameters) { - [QueryStringParameter("filters", false, typeof(MapQueryStringConverter))] + [QueryStringParameter("filters", false)] public IDictionary>? Filters { get; set; } } } diff --git a/src/Docker.DotNet/Models/NodeRemoveParameters.Generated.cs b/src/Docker.DotNet/Models/NodeRemoveParameters.Generated.cs index 305699ef..301c7f66 100644 --- a/src/Docker.DotNet/Models/NodeRemoveParameters.Generated.cs +++ b/src/Docker.DotNet/Models/NodeRemoveParameters.Generated.cs @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models { public class NodeRemoveParameters // (main.NodeRemoveParameters) { - [QueryStringParameter("force", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("force", false)] public bool? Force { get; set; } } } diff --git a/src/Docker.DotNet/Models/PluginDisableParameters.Generated.cs b/src/Docker.DotNet/Models/PluginDisableParameters.Generated.cs index ba4deaee..53effdbb 100644 --- a/src/Docker.DotNet/Models/PluginDisableParameters.Generated.cs +++ b/src/Docker.DotNet/Models/PluginDisableParameters.Generated.cs @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models { public class PluginDisableParameters // (main.PluginDisableParameters) { - [QueryStringParameter("force", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("force", false)] public bool? Force { get; set; } } } diff --git a/src/Docker.DotNet/Models/PluginListParameters.Generated.cs b/src/Docker.DotNet/Models/PluginListParameters.Generated.cs index 89dab338..f67b5704 100644 --- a/src/Docker.DotNet/Models/PluginListParameters.Generated.cs +++ b/src/Docker.DotNet/Models/PluginListParameters.Generated.cs @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models { public class PluginListParameters // (main.PluginListParameters) { - [QueryStringParameter("filters", false, typeof(MapQueryStringConverter))] + [QueryStringParameter("filters", false)] public IDictionary>? Filters { get; set; } } } diff --git a/src/Docker.DotNet/Models/PluginRemoveParameters.Generated.cs b/src/Docker.DotNet/Models/PluginRemoveParameters.Generated.cs index 3076aff2..e3c28174 100644 --- a/src/Docker.DotNet/Models/PluginRemoveParameters.Generated.cs +++ b/src/Docker.DotNet/Models/PluginRemoveParameters.Generated.cs @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models { public class PluginRemoveParameters // (main.PluginRemoveParameters) { - [QueryStringParameter("force", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("force", false)] public bool? Force { get; set; } } } diff --git a/src/Docker.DotNet/Models/ServiceListParameters.Generated.cs b/src/Docker.DotNet/Models/ServiceListParameters.Generated.cs index 593b0abb..0d26404e 100644 --- a/src/Docker.DotNet/Models/ServiceListParameters.Generated.cs +++ b/src/Docker.DotNet/Models/ServiceListParameters.Generated.cs @@ -3,10 +3,10 @@ namespace Docker.DotNet.Models { public class ServiceListParameters // (main.ServiceListParameters) { - [QueryStringParameter("filters", false, typeof(MapQueryStringConverter))] + [QueryStringParameter("filters", false)] public IDictionary>? Filters { get; set; } - [QueryStringParameter("status", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("status", false)] public bool? Status { get; set; } } } diff --git a/src/Docker.DotNet/Models/ServiceLogsParameters.Generated.cs b/src/Docker.DotNet/Models/ServiceLogsParameters.Generated.cs index 67e9fadc..01a5650b 100644 --- a/src/Docker.DotNet/Models/ServiceLogsParameters.Generated.cs +++ b/src/Docker.DotNet/Models/ServiceLogsParameters.Generated.cs @@ -3,25 +3,25 @@ namespace Docker.DotNet.Models { public class ServiceLogsParameters // (main.ServiceLogsParameters) { - [QueryStringParameter("stdout", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("stdout", false)] public bool? ShowStdout { get; set; } - [QueryStringParameter("stderr", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("stderr", false)] public bool? ShowStderr { get; set; } [QueryStringParameter("since", false)] public string? Since { get; set; } - [QueryStringParameter("timestamps", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("timestamps", false)] public bool? Timestamps { get; set; } - [QueryStringParameter("follow", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("follow", false)] public bool? Follow { get; set; } [QueryStringParameter("tail", false)] public string? Tail { get; set; } - [QueryStringParameter("details", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("details", false)] public bool? Details { get; set; } } } diff --git a/src/Docker.DotNet/Models/SwarmLeaveParameters.Generated.cs b/src/Docker.DotNet/Models/SwarmLeaveParameters.Generated.cs index a3109483..48a40697 100644 --- a/src/Docker.DotNet/Models/SwarmLeaveParameters.Generated.cs +++ b/src/Docker.DotNet/Models/SwarmLeaveParameters.Generated.cs @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models { public class SwarmLeaveParameters // (main.SwarmLeaveParameters) { - [QueryStringParameter("force", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("force", false)] public bool? Force { get; set; } } } diff --git a/src/Docker.DotNet/Models/SwarmUpdateParameters.Generated.cs b/src/Docker.DotNet/Models/SwarmUpdateParameters.Generated.cs index 0d1c6b93..03969603 100644 --- a/src/Docker.DotNet/Models/SwarmUpdateParameters.Generated.cs +++ b/src/Docker.DotNet/Models/SwarmUpdateParameters.Generated.cs @@ -9,13 +9,13 @@ public class SwarmUpdateParameters // (main.SwarmUpdateParameters) [QueryStringParameter("version", true)] public long Version { get; set; } = default!; - [QueryStringParameter("rotateworkertoken", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("rotateworkertoken", false)] public bool? RotateWorkerToken { get; set; } - [QueryStringParameter("rotatemanagertoken", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("rotatemanagertoken", false)] public bool? RotateManagerToken { get; set; } - [QueryStringParameter("rotatemanagerunlockkey", false, typeof(BoolQueryStringConverter))] + [QueryStringParameter("rotatemanagerunlockkey", false)] public bool? RotateManagerUnlockKey { get; set; } } } diff --git a/src/Docker.DotNet/Models/TasksListParameters.Generated.cs b/src/Docker.DotNet/Models/TasksListParameters.Generated.cs index d7d781d0..908fc2f0 100644 --- a/src/Docker.DotNet/Models/TasksListParameters.Generated.cs +++ b/src/Docker.DotNet/Models/TasksListParameters.Generated.cs @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models { public class TasksListParameters // (main.TasksListParameters) { - [QueryStringParameter("filters", false, typeof(MapQueryStringConverter))] + [QueryStringParameter("filters", false)] public IDictionary>? Filters { get; set; } } } diff --git a/src/Docker.DotNet/Models/VolumesListParameters.Generated.cs b/src/Docker.DotNet/Models/VolumesListParameters.Generated.cs index 49f1c909..34d8ef79 100644 --- a/src/Docker.DotNet/Models/VolumesListParameters.Generated.cs +++ b/src/Docker.DotNet/Models/VolumesListParameters.Generated.cs @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models { public class VolumesListParameters // (main.VolumesListParameters) { - [QueryStringParameter("filters", false, typeof(MapQueryStringConverter))] + [QueryStringParameter("filters", false)] public IDictionary>? Filters { get; set; } } } diff --git a/src/Docker.DotNet/Models/VolumesPruneParameters.Generated.cs b/src/Docker.DotNet/Models/VolumesPruneParameters.Generated.cs index 6904b653..44881eb2 100644 --- a/src/Docker.DotNet/Models/VolumesPruneParameters.Generated.cs +++ b/src/Docker.DotNet/Models/VolumesPruneParameters.Generated.cs @@ -3,7 +3,7 @@ namespace Docker.DotNet.Models { public class VolumesPruneParameters // (main.VolumesPruneParameters) { - [QueryStringParameter("filters", false, typeof(MapQueryStringConverter))] + [QueryStringParameter("filters", false)] public IDictionary>? Filters { get; set; } } } diff --git a/src/Docker.DotNet/QueryString.cs b/src/Docker.DotNet/QueryString.cs index e12869e5..fa61471a 100644 --- a/src/Docker.DotNet/QueryString.cs +++ b/src/Docker.DotNet/QueryString.cs @@ -1,13 +1,15 @@ namespace Docker.DotNet; -internal class QueryString : IQueryString where T : class +internal class QueryString< +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] +#endif +T> : IQueryString where T : class, new() { private T Object { get; } private Dictionary AttributedPublicProperties { get; } - private IQueryStringConverterInstanceFactory QueryStringConverterInstanceFactory { get; } - public QueryString(T value) { if (EqualityComparer.Default.Equals(value)) @@ -16,7 +18,6 @@ public QueryString(T value) } Object = value; - QueryStringConverterInstanceFactory = new QueryStringConverterInstanceFactory(); AttributedPublicProperties = FindAttributedPublicProperties(); } @@ -41,20 +42,19 @@ public IDictionary GetKeyValuePairs() { var keyStr = attribute.Name; string[] valueStr; - if (attribute.ConverterType == null) - { - valueStr = [value!.ToString()!]; - } - else + if (attribute.GetConverter() is IQueryStringConverter converter) { - var converter = QueryStringConverterInstanceFactory.GetConverterInstance(attribute.ConverterType); valueStr = ConvertValue(converter, value!); if (valueStr == null) { - throw new InvalidOperationException($"Got null from value converter '{attribute.ConverterType.FullName}'"); + throw new InvalidOperationException($"Got null from value converter '{converter.GetType().FullName}'"); } } + else + { + valueStr = [value!.ToString()!]; + } queryParameters[keyStr] = valueStr; } @@ -86,7 +86,11 @@ private static string[] ConvertValue(IQueryStringConverter converter, object val return converter.Convert(value); } - private static Dictionary FindAttributedPublicProperties() where TAttribType : Attribute + private static Dictionary FindAttributedPublicProperties< +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] +#endif + TValue, TAttribType>() where TAttribType : Attribute { Dictionary? attributedPublicProperties = null; @@ -113,6 +117,9 @@ private static Dictionary FindAttributedPublicPropert return attributedPublicProperties; } +#if NET + [UnconditionalSuppressMessage("Trimming", "IL2072", Justification = "Activator.CreateInstance is only used for value types here; safe for runtime usage.")] +#endif private static bool IsDefaultOfType(object? o) { if (o is ValueType) diff --git a/src/Docker.DotNet/QueryStringConverterInstanceFactory.cs b/src/Docker.DotNet/QueryStringConverterInstanceFactory.cs deleted file mode 100644 index 1450f50e..00000000 --- a/src/Docker.DotNet/QueryStringConverterInstanceFactory.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace Docker.DotNet; - -internal class QueryStringConverterInstanceFactory : IQueryStringConverterInstanceFactory -{ - private static readonly ConcurrentDictionary ConverterInstanceRegistry = new ConcurrentDictionary(); - - public IQueryStringConverter GetConverterInstance(Type t) - { - return ConverterInstanceRegistry.GetOrAdd( - t, - InitializeConverter); - } - - private IQueryStringConverter InitializeConverter(Type t) - { - var instance = Activator.CreateInstance(t) as IQueryStringConverter; - if (instance == null) - { - throw new InvalidOperationException($"Could not get instance of {t.FullName}"); - } - return instance; - } -} \ No newline at end of file diff --git a/src/Docker.DotNet/QueryStringParameterAttribute.cs b/src/Docker.DotNet/QueryStringParameterAttribute.cs index 6b08d259..754dd4ed 100644 --- a/src/Docker.DotNet/QueryStringParameterAttribute.cs +++ b/src/Docker.DotNet/QueryStringParameterAttribute.cs @@ -1,28 +1,29 @@ namespace Docker.DotNet; [AttributeUsage(AttributeTargets.Property)] -internal sealed class QueryStringParameterAttribute : Attribute +internal class QueryStringParameterAttribute : Attribute { public string Name { get; private set; } public bool IsRequired { get; private set; } - public Type? ConverterType { get; private set; } + public virtual IQueryStringConverter? GetConverter() => null; - public QueryStringParameterAttribute(string name, bool required, Type? converterType = null) + public QueryStringParameterAttribute(string name, bool required) { if (string.IsNullOrEmpty(name)) { throw new ArgumentNullException(nameof(name)); } - if (converterType != null && !converterType.GetInterfaces().Contains(typeof (IQueryStringConverter))) - { - throw new ArgumentException($"Provided query string converter type is not '{typeof(IQueryStringConverter).FullName}'.", nameof(converterType)); - } - Name = name; IsRequired = required; - ConverterType = converterType; } +} + +internal sealed class QueryStringParameterAttribute(string name, bool required) : QueryStringParameterAttribute(name, required) where TConverter : IQueryStringConverter, new() +{ + private static readonly TConverter ConverterInstance = new TConverter(); + + public override IQueryStringConverter GetConverter() => ConverterInstance; } \ No newline at end of file diff --git a/src/Microsoft.Net.Http.Client/HttpConnection.cs b/src/Microsoft.Net.Http.Client/HttpConnection.cs index fb8c1ab2..7cf88c49 100644 --- a/src/Microsoft.Net.Http.Client/HttpConnection.cs +++ b/src/Microsoft.Net.Http.Client/HttpConnection.cs @@ -26,7 +26,7 @@ await Transport.WriteAsync(requestBytes, 0, requestBytes.Length, cancellationTok { if (request.Content.Headers.ContentLength.HasValue) { -#if NET6_0_OR_GREATER +#if NET await request.Content.CopyToAsync(Transport, cancellationToken) .ConfigureAwait(false); #else @@ -39,7 +39,7 @@ await request.Content.CopyToAsync(Transport) // The length of the data is unknown. Send it in chunked mode. using (var chunkedStream = new ChunkedWriteStream(Transport)) { -#if NET6_0_OR_GREATER +#if NET await request.Content.CopyToAsync(chunkedStream, cancellationToken) .ConfigureAwait(false); #else diff --git a/src/Microsoft.Net.Http.Client/HttpConnectionResponseContent.cs b/src/Microsoft.Net.Http.Client/HttpConnectionResponseContent.cs index 4fbaefc2..5bed410a 100644 --- a/src/Microsoft.Net.Http.Client/HttpConnectionResponseContent.cs +++ b/src/Microsoft.Net.Http.Client/HttpConnectionResponseContent.cs @@ -45,7 +45,7 @@ protected override Task SerializeToStreamAsync(Stream stream, TransportContext? return _responseStream!.CopyToAsync(stream); } -#if NET6_0_OR_GREATER +#if NET protected override Task SerializeToStreamAsync(Stream stream, TransportContext? context, CancellationToken cancellationToken) { return _responseStream!.CopyToAsync(stream, cancellationToken); diff --git a/src/Microsoft.Net.Http.Client/RequestExtensions.cs b/src/Microsoft.Net.Http.Client/RequestExtensions.cs index c7872e17..e2be5054 100644 --- a/src/Microsoft.Net.Http.Client/RequestExtensions.cs +++ b/src/Microsoft.Net.Http.Client/RequestExtensions.cs @@ -84,7 +84,7 @@ public static void SetAddressLineProperty(this HttpRequestMessage request, strin public static T? GetProperty(this HttpRequestMessage request, string key) { -#if NET6_0_OR_GREATER +#if NET return request.Options.TryGetValue(new HttpRequestOptionsKey(key), out var obj) ? obj : default; #else return request.Properties.TryGetValue(key, out var obj) ? (T)obj : default; @@ -93,7 +93,7 @@ public static void SetAddressLineProperty(this HttpRequestMessage request, strin public static void SetProperty(this HttpRequestMessage request, string key, T value) { -#if NET6_0_OR_GREATER +#if NET request.Options.Set(new HttpRequestOptionsKey(key), value); #else request.Properties[key] = value; diff --git a/test/Docker.DotNet.Tests/Docker.DotNet.Tests.csproj b/test/Docker.DotNet.Tests/Docker.DotNet.Tests.csproj index 2d80e0e5..190d1748 100644 --- a/test/Docker.DotNet.Tests/Docker.DotNet.Tests.csproj +++ b/test/Docker.DotNet.Tests/Docker.DotNet.Tests.csproj @@ -1,13 +1,21 @@ - + net8.0;net9.0;net10.0 + linux-arm64 + linux-x64 + osx-arm64 + osx-x64 + win-arm64 + win-x64 + Exe false - false + true + true + true - - - + + @@ -24,7 +32,6 @@ - @@ -40,7 +47,10 @@ - + + + + diff --git a/test/Docker.DotNet.Tests/IConfigOperationsTests.cs b/test/Docker.DotNet.Tests/IConfigOperationsTests.cs index 533d5d25..96bb49ac 100644 --- a/test/Docker.DotNet.Tests/IConfigOperationsTests.cs +++ b/test/Docker.DotNet.Tests/IConfigOperationsTests.cs @@ -15,7 +15,7 @@ public IConfigOperationsTests(TestFixture testFixture, ITestOutputHelper testOut [Fact] public async Task SwarmConfig_CanCreateAndRead() { - var currentConfigs = await _testFixture.DockerClient.Configs.ListConfigsAsync(); + var currentConfigs = await _testFixture.DockerClient.Configs.ListConfigsAsync(TestContext.Current.CancellationToken); _testOutputHelper.WriteLine($"Current Configs: {currentConfigs.Count}"); @@ -31,15 +31,15 @@ public async Task SwarmConfig_CanCreateAndRead() Config = testConfigSpec }; - var createdConfig = await _testFixture.DockerClient.Configs.CreateConfigAsync(configParameters); + var createdConfig = await _testFixture.DockerClient.Configs.CreateConfigAsync(configParameters, TestContext.Current.CancellationToken); Assert.NotNull(createdConfig.ID); _testOutputHelper.WriteLine($"Config created: {createdConfig.ID}"); - var configs = await _testFixture.DockerClient.Configs.ListConfigsAsync(); + var configs = await _testFixture.DockerClient.Configs.ListConfigsAsync(TestContext.Current.CancellationToken); Assert.Contains(configs, c => c.ID == createdConfig.ID); _testOutputHelper.WriteLine($"Current Configs: {configs.Count}"); - var configResponse = await _testFixture.DockerClient.Configs.InspectConfigAsync(createdConfig.ID); + var configResponse = await _testFixture.DockerClient.Configs.InspectConfigAsync(createdConfig.ID, TestContext.Current.CancellationToken); Assert.NotNull(configResponse); @@ -51,8 +51,8 @@ public async Task SwarmConfig_CanCreateAndRead() _testOutputHelper.WriteLine("Config created is the same."); - await _testFixture.DockerClient.Configs.RemoveConfigAsync(createdConfig.ID); + await _testFixture.DockerClient.Configs.RemoveConfigAsync(createdConfig.ID, TestContext.Current.CancellationToken); - await Assert.ThrowsAsync(() => _testFixture.DockerClient.Configs.InspectConfigAsync(createdConfig.ID)); + await Assert.ThrowsAsync(() => _testFixture.DockerClient.Configs.InspectConfigAsync(createdConfig.ID, TestContext.Current.CancellationToken)); } } \ No newline at end of file diff --git a/test/Docker.DotNet.Tests/IContainerOperationsTests.cs b/test/Docker.DotNet.Tests/IContainerOperationsTests.cs index ff3ebab9..c2e36892 100644 --- a/test/Docker.DotNet.Tests/IContainerOperationsTests.cs +++ b/test/Docker.DotNet.Tests/IContainerOperationsTests.cs @@ -94,7 +94,7 @@ await _testFixture.DockerClient.Containers.StartContainerAsync( _testFixture.Cts.Token ); - await Task.Delay(TimeSpan.FromSeconds(5)); + await Task.Delay(TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken); await _testFixture.DockerClient.Containers.GetContainerLogsAsync( createContainerResponse.ID, @@ -141,7 +141,7 @@ await _testFixture.DockerClient.Containers.StartContainerAsync( _testFixture.Cts.Token ); - await Task.Delay(TimeSpan.FromSeconds(5)); + await Task.Delay(TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken); await _testFixture.DockerClient.Containers.GetContainerLogsAsync( createContainerResponse.ID, @@ -280,7 +280,7 @@ await _testFixture.DockerClient.Containers.StartContainerAsync( containerLogsCts.Token ); - await Task.Delay(TimeSpan.FromSeconds(5)); + await Task.Delay(TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken); await _testFixture.DockerClient.Containers.StopContainerAsync( createContainerResponse.ID, @@ -328,7 +328,7 @@ await _testFixture.DockerClient.Containers.GetContainerStatsAsync( tcs.Token ); - await Task.Delay(TimeSpan.FromSeconds(10)); + await Task.Delay(TimeSpan.FromSeconds(10), TestContext.Current.CancellationToken); Assert.NotEmpty(containerStatsList); Assert.Single(containerStatsList); @@ -341,9 +341,7 @@ public async Task GetContainerStatsAsync_Tty_False_StreamStats() using var tcs = CancellationTokenSource.CreateLinkedTokenSource(_testFixture.Cts.Token); using (tcs.Token.Register(() => throw new TimeoutException("GetContainerStatsAsync_Tty_False_StreamStats"))) { - var method = MethodBase.GetCurrentMethod(); - - _testOutputHelper.WriteLine($"Running test '{method!.Module}' -> '{method!.Name}'"); + _testOutputHelper.WriteLine($"Running test GetContainerStatsAsync_Tty_False_StreamStats"); var createContainerResponse = await _testFixture.DockerClient.Containers.CreateContainerAsync( new CreateContainerParameters @@ -421,7 +419,7 @@ await _testFixture.DockerClient.Containers.GetContainerStatsAsync( tcs.Token ); - await Task.Delay(TimeSpan.FromSeconds(10)); + await Task.Delay(TimeSpan.FromSeconds(10), TestContext.Current.CancellationToken); Assert.NotEmpty(containerStatsList); Assert.Single(containerStatsList); @@ -475,7 +473,7 @@ await _testFixture.DockerClient.Containers.GetContainerStatsAsync( // This is expected to happen on task cancellation. } - await Task.Delay(TimeSpan.FromSeconds(1)); + await Task.Delay(TimeSpan.FromSeconds(1), TestContext.Current.CancellationToken); _testOutputHelper.WriteLine($"Container stats count: {containerStatsList.Count}"); Assert.NotEmpty(containerStatsList); } @@ -727,10 +725,10 @@ public async Task WriteAsync_OnMultiplexedStream_ForwardsInputToPid1Stdin_Comple containerAttachParameters.Stream = true; // When - var createContainerResponse = await _testFixture.DockerClient.Containers.CreateContainerAsync(createContainerParameters); - _ = await _testFixture.DockerClient.Containers.StartContainerAsync(createContainerResponse.ID, new ContainerStartParameters()); + var createContainerResponse = await _testFixture.DockerClient.Containers.CreateContainerAsync(createContainerParameters, TestContext.Current.CancellationToken); + _ = await _testFixture.DockerClient.Containers.StartContainerAsync(createContainerResponse.ID, new ContainerStartParameters(), TestContext.Current.CancellationToken); - using var stream = await _testFixture.DockerClient.Containers.AttachContainerAsync(createContainerResponse.ID, containerAttachParameters); + using var stream = await _testFixture.DockerClient.Containers.AttachContainerAsync(createContainerResponse.ID, containerAttachParameters, TestContext.Current.CancellationToken); await stream.WriteAsync(linefeedByte, 0, linefeedByte.Length, _testFixture.Cts.Token); @@ -762,12 +760,12 @@ public async Task WriteAsync_OnMultiplexedStream_ForwardsInputToExecStdin_Comple var containerExecStartParameters = new ContainerExecStartParameters(); - var createContainerResponse = await _testFixture.DockerClient.Containers.CreateContainerAsync(createContainerParameters); - _ = await _testFixture.DockerClient.Containers.StartContainerAsync(createContainerResponse.ID, new ContainerStartParameters()); + var createContainerResponse = await _testFixture.DockerClient.Containers.CreateContainerAsync(createContainerParameters, TestContext.Current.CancellationToken); + _ = await _testFixture.DockerClient.Containers.StartContainerAsync(createContainerResponse.ID, new ContainerStartParameters(), TestContext.Current.CancellationToken); // When - var containerExecCreateResponse = await _testFixture.DockerClient.Exec.CreateContainerExecAsync(createContainerResponse.ID, containerExecCreateParameters); - using var stream = await _testFixture.DockerClient.Exec.StartContainerExecAsync(containerExecCreateResponse.ID, containerExecStartParameters); + var containerExecCreateResponse = await _testFixture.DockerClient.Exec.CreateContainerExecAsync(createContainerResponse.ID, containerExecCreateParameters, TestContext.Current.CancellationToken); + using var stream = await _testFixture.DockerClient.Exec.StartContainerExecAsync(containerExecCreateResponse.ID, containerExecStartParameters, TestContext.Current.CancellationToken); await stream.WriteAsync(linefeedByte, 0, linefeedByte.Length, _testFixture.Cts.Token); diff --git a/test/Docker.DotNet.Tests/IImageOperationsTests.cs b/test/Docker.DotNet.Tests/IImageOperationsTests.cs index 50d522f7..9eed7749 100644 --- a/test/Docker.DotNet.Tests/IImageOperationsTests.cs +++ b/test/Docker.DotNet.Tests/IImageOperationsTests.cs @@ -50,12 +50,11 @@ await _testFixture.DockerClient.Images.TagImageAsync( [Fact] public Task CreateImageAsync_ErrorResponse_ThrowsDockerApiException() { - return Assert.ThrowsAsync(() => _testFixture.DockerClient.Images.CreateImageAsync( - new ImagesCreateParameters + return Assert.ThrowsAsync(() => _testFixture.DockerClient.Images.CreateImageAsync(new ImagesCreateParameters { FromImage = "1.2.3.Apparently&this$is+not-a_valid%repository//name", Tag = "ancient-one" - }, null, null)); + }, null, null, TestContext.Current.CancellationToken)); } [Fact] diff --git a/test/Docker.DotNet.Tests/ISwarmOperationsTests.cs b/test/Docker.DotNet.Tests/ISwarmOperationsTests.cs index e620446c..9e86e2ed 100644 --- a/test/Docker.DotNet.Tests/ISwarmOperationsTests.cs +++ b/test/Docker.DotNet.Tests/ISwarmOperationsTests.cs @@ -24,7 +24,7 @@ public async Task GetFilteredServicesByName_Succeeds() Name = serviceName, TaskTemplate = new TaskSpec { ContainerSpec = new ContainerSpec { Image = _testFixture.Image.ID } } } - })).ID; + }, TestContext.Current.CancellationToken)).ID; var secondServiceId = (await _testFixture.DockerClient.Swarm.CreateServiceAsync(new ServiceCreateParameters { @@ -33,7 +33,7 @@ public async Task GetFilteredServicesByName_Succeeds() Name = $"service2-{Guid.NewGuid().ToString().Substring(1, 10)}", TaskTemplate = new TaskSpec { ContainerSpec = new ContainerSpec { Image = _testFixture.Image.ID } } } - })).ID; + }, TestContext.Current.CancellationToken)).ID; var thirdServiceId = (await _testFixture.DockerClient.Swarm.CreateServiceAsync(new ServiceCreateParameters { @@ -42,7 +42,7 @@ public async Task GetFilteredServicesByName_Succeeds() Name = $"service3-{Guid.NewGuid().ToString().Substring(1, 10)}", TaskTemplate = new TaskSpec { ContainerSpec = new ContainerSpec { Image = _testFixture.Image.ID } } } - })).ID; + }, TestContext.Current.CancellationToken)).ID; var services = await _testFixture.DockerClient.Swarm.ListServicesAsync(new ServiceListParameters { @@ -57,9 +57,9 @@ public async Task GetFilteredServicesByName_Succeeds() Assert.Single(services); - await _testFixture.DockerClient.Swarm.RemoveServiceAsync(firstServiceId); - await _testFixture.DockerClient.Swarm.RemoveServiceAsync(secondServiceId); - await _testFixture.DockerClient.Swarm.RemoveServiceAsync(thirdServiceId); + await _testFixture.DockerClient.Swarm.RemoveServiceAsync(firstServiceId, TestContext.Current.CancellationToken); + await _testFixture.DockerClient.Swarm.RemoveServiceAsync(secondServiceId, TestContext.Current.CancellationToken); + await _testFixture.DockerClient.Swarm.RemoveServiceAsync(thirdServiceId, TestContext.Current.CancellationToken); } [Fact] @@ -72,7 +72,7 @@ public async Task GetFilteredServicesById_Succeeds() Name = $"service1-{Guid.NewGuid().ToString().Substring(1, 10)}", TaskTemplate = new TaskSpec { ContainerSpec = new ContainerSpec { Image = _testFixture.Image.ID } } } - })).ID; + }, TestContext.Current.CancellationToken)).ID; var secondServiceId = (await _testFixture.DockerClient.Swarm.CreateServiceAsync(new ServiceCreateParameters { @@ -81,7 +81,7 @@ public async Task GetFilteredServicesById_Succeeds() Name = $"service2-{Guid.NewGuid().ToString().Substring(1, 10)}", TaskTemplate = new TaskSpec { ContainerSpec = new ContainerSpec { Image = _testFixture.Image.ID } } } - })).ID; + }, TestContext.Current.CancellationToken)).ID; var thirdServiceId = (await _testFixture.DockerClient.Swarm.CreateServiceAsync(new ServiceCreateParameters { @@ -90,7 +90,7 @@ public async Task GetFilteredServicesById_Succeeds() Name = $"service3-{Guid.NewGuid().ToString().Substring(1, 10)}", TaskTemplate = new TaskSpec { ContainerSpec = new ContainerSpec { Image = _testFixture.Image.ID } } } - })).ID; + }, TestContext.Current.CancellationToken)).ID; var services = await _testFixture.DockerClient.Swarm.ListServicesAsync(new ServiceListParameters { @@ -105,9 +105,9 @@ public async Task GetFilteredServicesById_Succeeds() Assert.Single(services); - await _testFixture.DockerClient.Swarm.RemoveServiceAsync(firstServiceId); - await _testFixture.DockerClient.Swarm.RemoveServiceAsync(secondServiceId); - await _testFixture.DockerClient.Swarm.RemoveServiceAsync(thirdServiceId); + await _testFixture.DockerClient.Swarm.RemoveServiceAsync(firstServiceId, TestContext.Current.CancellationToken); + await _testFixture.DockerClient.Swarm.RemoveServiceAsync(secondServiceId, TestContext.Current.CancellationToken); + await _testFixture.DockerClient.Swarm.RemoveServiceAsync(thirdServiceId, TestContext.Current.CancellationToken); } [Fact] @@ -122,7 +122,7 @@ public async Task GetServices_Succeeds() Name = $"service1-{Guid.NewGuid().ToString().Substring(1, 10)}", TaskTemplate = new TaskSpec { ContainerSpec = new ContainerSpec { Image = _testFixture.Image.ID } } } - })).ID; + }, TestContext.Current.CancellationToken)).ID; var secondServiceId = (await _testFixture.DockerClient.Swarm.CreateServiceAsync(new ServiceCreateParameters { @@ -131,7 +131,7 @@ public async Task GetServices_Succeeds() Name = $"service2-{Guid.NewGuid().ToString().Substring(1, 10)}", TaskTemplate = new TaskSpec { ContainerSpec = new ContainerSpec { Image = _testFixture.Image.ID } } } - })).ID; + }, TestContext.Current.CancellationToken)).ID; var thirdServiceId = (await _testFixture.DockerClient.Swarm.CreateServiceAsync(new ServiceCreateParameters { @@ -140,15 +140,15 @@ public async Task GetServices_Succeeds() Name = $"service3-{Guid.NewGuid().ToString().Substring(1, 10)}", TaskTemplate = new TaskSpec { ContainerSpec = new ContainerSpec { Image = _testFixture.Image.ID } } } - })).ID; + }, TestContext.Current.CancellationToken)).ID; var services = await _testFixture.DockerClient.Swarm.ListServicesAsync(cancellationToken: CancellationToken.None); Assert.True(services.Count() > initialServiceCount); - await _testFixture.DockerClient.Swarm.RemoveServiceAsync(firstServiceId); - await _testFixture.DockerClient.Swarm.RemoveServiceAsync(secondServiceId); - await _testFixture.DockerClient.Swarm.RemoveServiceAsync(thirdServiceId); + await _testFixture.DockerClient.Swarm.RemoveServiceAsync(firstServiceId, TestContext.Current.CancellationToken); + await _testFixture.DockerClient.Swarm.RemoveServiceAsync(secondServiceId, TestContext.Current.CancellationToken); + await _testFixture.DockerClient.Swarm.RemoveServiceAsync(thirdServiceId, TestContext.Current.CancellationToken); } [Fact] @@ -165,14 +165,14 @@ public async Task GetServiceLogs_Succeeds() Name = serviceName, TaskTemplate = new TaskSpec { ContainerSpec = new ContainerSpec { Image = _testFixture.Image.ID, Command = CommonCommands.EchoToStdoutAndStderr } } } - })).ID; + }, TestContext.Current.CancellationToken)).ID; using var stream = await _testFixture.DockerClient.Swarm.GetServiceLogsAsync(serviceName, false, new ServiceLogsParameters { Follow = true, ShowStdout = true, ShowStderr = true - }); + }, TestContext.Current.CancellationToken); var maxRetries = 3; var currentRetry = 0; @@ -238,7 +238,7 @@ public async Task GetServiceLogs_Succeeds() currentRetry++; if (currentRetry < maxRetries) { - await Task.Delay(delayBetweenRetries); + await Task.Delay(delayBetweenRetries, TestContext.Current.CancellationToken); } } } @@ -246,6 +246,6 @@ public async Task GetServiceLogs_Succeeds() Assert.NotNull(logLines); Assert.NotEmpty(logLines); - await _testFixture.DockerClient.Swarm.RemoveServiceAsync(serviceId); + await _testFixture.DockerClient.Swarm.RemoveServiceAsync(serviceId, TestContext.Current.CancellationToken); } } \ No newline at end of file diff --git a/test/Docker.DotNet.Tests/ISystemOperations.Tests.cs b/test/Docker.DotNet.Tests/ISystemOperations.Tests.cs index b94faa24..d1064779 100644 --- a/test/Docker.DotNet.Tests/ISystemOperations.Tests.cs +++ b/test/Docker.DotNet.Tests/ISystemOperations.Tests.cs @@ -22,14 +22,14 @@ public void Docker_IsRunning() [Fact] public async Task GetSystemInfoAsync_Succeeds() { - var info = await _testFixture.DockerClient.System.GetSystemInfoAsync(); + var info = await _testFixture.DockerClient.System.GetSystemInfoAsync(TestContext.Current.CancellationToken); Assert.NotNull(info.Architecture); } [Fact] public async Task GetVersionAsync_Succeeds() { - var version = await _testFixture.DockerClient.System.GetVersionAsync(); + var version = await _testFixture.DockerClient.System.GetVersionAsync(TestContext.Current.CancellationToken); Assert.NotNull(version.APIVersion); } @@ -40,7 +40,7 @@ public async Task MonitorEventsAsync_EmptyContainersList_CanBeCancelled() using var cts = new CancellationTokenSource(); await cts.CancelAsync(); - await Task.Delay(1); + await Task.Delay(1, TestContext.Current.CancellationToken); await Assert.ThrowsAsync(() => _testFixture.DockerClient.System.MonitorEventsAsync(new ContainerEventsParameters(), progress, cts.Token)); @@ -49,13 +49,13 @@ public async Task MonitorEventsAsync_EmptyContainersList_CanBeCancelled() [Fact] public async Task MonitorEventsAsync_NullParameters_Throws() { - await Assert.ThrowsAsync(() => _testFixture.DockerClient.System.MonitorEventsAsync(null, null)); + await Assert.ThrowsAsync(() => _testFixture.DockerClient.System.MonitorEventsAsync(null, null, TestContext.Current.CancellationToken)); } [Fact] public async Task MonitorEventsAsync_NullProgress_Throws() { - await Assert.ThrowsAsync(() => _testFixture.DockerClient.System.MonitorEventsAsync(new ContainerEventsParameters(), null)); + await Assert.ThrowsAsync(() => _testFixture.DockerClient.System.MonitorEventsAsync(new ContainerEventsParameters(), null, TestContext.Current.CancellationToken)); } [Fact] @@ -90,7 +90,7 @@ await _testFixture.DockerClient.Images.DeleteImageAsync( _testFixture.Cts.Token); // Give it some time for output operation to complete before cancelling task - await Task.Delay(TimeSpan.FromSeconds(1)); + await Task.Delay(TimeSpan.FromSeconds(1), TestContext.Current.CancellationToken); await cts.CancelAsync(); @@ -223,19 +223,19 @@ await _testFixture.DockerClient.Images.TagImageAsync( }); using var cts = CancellationTokenSource.CreateLinkedTokenSource(_testFixture.Cts.Token); - var task = Task.Run(() => _testFixture.DockerClient.System.MonitorEventsAsync(eventsParams, progress, cts.Token)); + var task = Task.Run(() => _testFixture.DockerClient.System.MonitorEventsAsync(eventsParams, progress, cts.Token), TestContext.Current.CancellationToken); // Wait briefly to ensure the monitoring task is fully established before triggering Docker events. // Ideally, the API would return (or signal) once monitoring is active. - await Task.Delay(TimeSpan.FromSeconds(1)); + await Task.Delay(TimeSpan.FromSeconds(1), TestContext.Current.CancellationToken); - await _testFixture.DockerClient.Images.TagImageAsync($"{_testFixture.Repository}:{_testFixture.Tag}", new ImageTagParameters { RepositoryName = _testFixture.Repository, Tag = newTag }); - await _testFixture.DockerClient.Images.DeleteImageAsync($"{_testFixture.Repository}:{newTag}", new ImageDeleteParameters()); + await _testFixture.DockerClient.Images.TagImageAsync($"{_testFixture.Repository}:{_testFixture.Tag}", new ImageTagParameters { RepositoryName = _testFixture.Repository, Tag = newTag }, TestContext.Current.CancellationToken); + await _testFixture.DockerClient.Images.DeleteImageAsync($"{_testFixture.Repository}:{newTag}", new ImageDeleteParameters(), TestContext.Current.CancellationToken); - var createContainerResponse = await _testFixture.DockerClient.Containers.CreateContainerAsync(new CreateContainerParameters { Image = $"{_testFixture.Repository}:{_testFixture.Tag}", Entrypoint = CommonCommands.SleepInfinity }); + var createContainerResponse = await _testFixture.DockerClient.Containers.CreateContainerAsync(new CreateContainerParameters { Image = $"{_testFixture.Repository}:{_testFixture.Tag}", Entrypoint = CommonCommands.SleepInfinity }, TestContext.Current.CancellationToken); await _testFixture.DockerClient.Containers.RemoveContainerAsync(createContainerResponse.ID, new ContainerRemoveParameters(), cts.Token); - await Task.Delay(TimeSpan.FromSeconds(1)); + await Task.Delay(TimeSpan.FromSeconds(1), TestContext.Current.CancellationToken); await cts.CancelAsync(); await Assert.ThrowsAnyAsync(() => task); @@ -247,6 +247,6 @@ await _testFixture.DockerClient.Images.TagImageAsync( [Fact] public async Task PingAsync_Succeeds() { - await _testFixture.DockerClient.System.PingAsync(); + await _testFixture.DockerClient.System.PingAsync(TestContext.Current.CancellationToken); } } \ No newline at end of file diff --git a/test/Docker.DotNet.Tests/JsonEnumMemberConverterTest.cs b/test/Docker.DotNet.Tests/JsonEnumMemberConverterTest.cs index ad26d82b..7a16d9d3 100644 --- a/test/Docker.DotNet.Tests/JsonEnumMemberConverterTest.cs +++ b/test/Docker.DotNet.Tests/JsonEnumMemberConverterTest.cs @@ -26,7 +26,7 @@ public void JsonSerialization_ShouldSerializeAndDeserializeCorrectly(RestartPoli Assert.Equal(restartPolicyKind, deserializedParameters.HostConfig.RestartPolicy.Name); } - private sealed class RestartPolicyKindTestData : TheoryData + public sealed class RestartPolicyKindTestData : TheoryData { public RestartPolicyKindTestData() { diff --git a/test/Docker.DotNet.Tests/JsonRequestContentTests.cs b/test/Docker.DotNet.Tests/JsonRequestContentTests.cs index 7731f612..ef61bb41 100644 --- a/test/Docker.DotNet.Tests/JsonRequestContentTests.cs +++ b/test/Docker.DotNet.Tests/JsonRequestContentTests.cs @@ -17,10 +17,10 @@ public void Constructor_ThrowsArgumentNullException_WhenSerializerIsNull() [Fact] public async Task GetContent_Succeeds_WhenValueAndSerializerAreValid() { - var content = new JsonRequestContent(new[] { 1 }, JsonSerializer.Instance); + var content = new JsonRequestContent[]>([new Dictionary() { { "key", "value" } }], JsonSerializer.Instance); using var httpContent = content.GetContent(); Assert.Equal("application/json; charset=utf-8", httpContent.Headers.ContentType.ToString()); - var jsonString = await httpContent.ReadAsStringAsync(); - Assert.Equal("[1]", jsonString); + var jsonString = await httpContent.ReadAsStringAsync(TestContext.Current.CancellationToken); + Assert.Equal("""[{"key":"value"}]""", jsonString); } } \ No newline at end of file diff --git a/test/Docker.DotNet.Tests/TestFixture.cs b/test/Docker.DotNet.Tests/TestFixture.cs index 9f3c7280..2c5c5205 100644 --- a/test/Docker.DotNet.Tests/TestFixture.cs +++ b/test/Docker.DotNet.Tests/TestFixture.cs @@ -54,7 +54,7 @@ public TestFixture(IMessageSink messageSink) public ImagesListResponse Image { get; private set; } /// - public async Task InitializeAsync() + public async ValueTask InitializeAsync() { const string repository = "alpine"; @@ -102,7 +102,7 @@ await DockerClient.Images.CreateImageAsync(new ImagesCreateParameters { FromImag } /// - public async Task DisposeAsync() + public async ValueTask DisposeAsync() { if (_hasInitializedSwarm) { diff --git a/test/Docker.DotNet.TestsV2/Docker.DotNet.TestsV2.csproj b/test/Docker.DotNet.TestsV2/Docker.DotNet.TestsV2.csproj index 6f9298b7..388cc7cd 100644 --- a/test/Docker.DotNet.TestsV2/Docker.DotNet.TestsV2.csproj +++ b/test/Docker.DotNet.TestsV2/Docker.DotNet.TestsV2.csproj @@ -1,13 +1,21 @@ - + net8.0;net9.0;net10.0 + linux-arm64 + linux-x64 + osx-arm64 + osx-x64 + win-arm64 + win-x64 + Exe false - false + true + true + true - - - + + @@ -18,7 +26,6 @@ - @@ -29,7 +36,8 @@ - - + + + diff --git a/tools/specgen/csharptype.go b/tools/specgen/csharptype.go index e58935c6..485a2d78 100644 --- a/tools/specgen/csharptype.go +++ b/tools/specgen/csharptype.go @@ -190,7 +190,8 @@ type CSModelType struct { // yet. it is possible that given the recursive nature that it not be // completed but as long as this is true we will not attempt to generate the // type more than once. - IsStarted bool + IsStarted bool + HasJsonSerializableProperties bool } // NewModel creates a new model type with valid slices diff --git a/tools/specgen/specgen.go b/tools/specgen/specgen.go index 0672cda9..5fe8ac4c 100644 --- a/tools/specgen/specgen.go +++ b/tools/specgen/specgen.go @@ -743,7 +743,18 @@ func reflectTypeMembers(t reflect.Type, m *CSModelType) { restTag.Name = strings.ToLower(f.Name) } - a := CSAttribute{Type: CSType{"", "QueryStringParameter"}} + queryStringParameter := "QueryStringParameter" + + switch f.Type.Kind() { + case reflect.Bool: + queryStringParameter += "" + case reflect.Slice, reflect.Array: + queryStringParameter += "" + case reflect.Map: + queryStringParameter += "" + } + + a := CSAttribute{Type: CSType{"", queryStringParameter}} a.Arguments = append( a.Arguments, CSArgument{ @@ -752,15 +763,6 @@ func reflectTypeMembers(t reflect.Type, m *CSModelType) { CSArgument{strconv.FormatBool(restTag.Required), CSInboxTypesMap[reflect.Bool]}) - switch f.Type.Kind() { - case reflect.Bool: - a.Arguments = append(a.Arguments, CSArgument{Value: "typeof(BoolQueryStringConverter)"}) - case reflect.Slice, reflect.Array: - a.Arguments = append(a.Arguments, CSArgument{Value: "typeof(EnumerableQueryStringConverter)"}) - case reflect.Map: - a.Arguments = append(a.Arguments, CSArgument{Value: "typeof(MapQueryStringConverter)"}) - } - csProp.IsOpt = omitEmpty || !restTag.Required csProp.Attributes = append(csProp.Attributes, a) csProp.DefaultValue = restTag.Default @@ -769,6 +771,8 @@ func reflectTypeMembers(t reflect.Type, m *CSModelType) { a.Arguments = append(a.Arguments, CSArgument{jsonName, CSInboxTypesMap[reflect.String]}) csProp.IsOpt = omitEmpty || f.Type.Kind() == reflect.Ptr csProp.Attributes = append(csProp.Attributes, a) + + m.HasJsonSerializableProperties = true } if hasTypeCustomizations { @@ -855,6 +859,8 @@ func main() { reflectType(t) } + jsonSerializableNames := make([]string, 0, len(reflectedTypes)) + for k, v := range reflectedTypes { if _, e := os.Stat(path.Join(sourcePath, v.Name+".Generated.cs")); e == nil { panic(fmt.Sprintf("File: (%s.Generated.cs) already exists. Failed to write key same name for key: (%s) type: (%s).", v.Name, k, v.SourceName)) @@ -877,5 +883,36 @@ func main() { f.Close() os.Rename(f.Name(), path.Join(sourcePath, v.Name+".Generated.cs")) + + if v.HasJsonSerializableProperties { + jsonSerializableNames = append(jsonSerializableNames, v.Name) + } + } + + slices.Sort(jsonSerializableNames) + + jscf, err := os.Create(path.Join(sourcePath, "DockerModelsJsonSerializerContext.Generated.cs")) + if err != nil { + panic(err) + } + + defer jscf.Close() + + jscb := bufio.NewWriter(jscf) + + fmt.Fprintln(jscb, "namespace Docker.DotNet.Models") + fmt.Fprintln(jscb, "{") + for _, name := range jsonSerializableNames { + fmt.Fprintf(jscb, " [JsonSerializable(typeof(%s))]\n", name) } + fmt.Fprintln(jscb, " internal sealed partial class DockerModelsJsonSerializerContext : JsonSerializerContext { }") + fmt.Fprintln(jscb, "}") + + err = jscb.Flush() + if err != nil { + os.Remove(jscf.Name()) + panic(err) + } + + jscf.Close() }