Skip to content
Merged
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
66 changes: 66 additions & 0 deletions src/Docker.DotNet/ConsoleSizeConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
namespace Docker.DotNet;

internal sealed class ConsoleSizeConverter : JsonConverter<ConsoleSize?>
{
public override ConsoleSize? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null)
{
return null;
}

if (reader.TokenType != JsonTokenType.StartArray)
{
throw new JsonException("Expected a JSON array for ConsoleSize.");
}

var height = ReadArrayElement(ref reader, "height");

var width = ReadArrayElement(ref reader, "width");

if (!reader.Read())
{
throw new JsonException("Expected the ConsoleSize array to end after two numeric elements.");
}

if (reader.TokenType != JsonTokenType.EndArray)
{
throw new JsonException("Expected the ConsoleSize array to contain exactly two numeric elements.");
}

return new ConsoleSize
{
Height = height,
Width = width
};
}

private static ulong ReadArrayElement(ref Utf8JsonReader reader, string elementName)
{
if (!reader.Read())
{
throw new JsonException($"Expected a numeric '{elementName}' element in the ConsoleSize array.");
}

if (reader.TokenType != JsonTokenType.Number)
{
throw new JsonException($"Expected the ConsoleSize '{elementName}' element to be a number.");
}

return reader.GetUInt64();
}

public override void Write(Utf8JsonWriter writer, ConsoleSize? value, JsonSerializerOptions options)
{
if (value == null)
{
writer.WriteNullValue();
return;
}

writer.WriteStartArray();
writer.WriteNumberValue(value.Height);
writer.WriteNumberValue(value.Width);
writer.WriteEndArray();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Docker.DotNet;
namespace Docker.DotNet;

public class DockerSwarmNodeAlreadyParticipatingException : DockerApiException
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Docker.DotNet;
namespace Docker.DotNet;

public class DockerSwarmNodeNotParticipatingException : DockerApiException
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class ContainerExecCreateParameters // (main.ContainerExecCreateParameter
public bool TTY { get; set; }

[JsonPropertyName("ConsoleSize")]
[JsonConverter(typeof(ConsoleSizeConverter))]
public ConsoleSize ConsoleSize { get; set; }

[JsonPropertyName("AttachStdin")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public class ContainerExecStartParameters // (main.ContainerExecStartParameters)
public bool TTY { get; set; }

[JsonPropertyName("ConsoleSize")]
[JsonConverter(typeof(ConsoleSizeConverter))]
public ConsoleSize ConsoleSize { get; set; }
}
}
3 changes: 2 additions & 1 deletion src/Docker.DotNet/Models/HostConfig.Generated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ public HostConfig(Resources Resources)
public IList<string> VolumesFrom { get; set; }

[JsonPropertyName("ConsoleSize")]
public ulong[] ConsoleSize { get; set; }
[JsonConverter(typeof(ConsoleSizeConverter))]
public ConsoleSize ConsoleSize { get; set; }

[JsonPropertyName("Annotations")]
public IDictionary<string, string> Annotations { get; set; }
Expand Down
100 changes: 100 additions & 0 deletions test/Docker.DotNet.Tests/ConsoleSizeConverterTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
namespace Docker.DotNet.Tests;

public sealed class ConsoleSizeConverterTests
{
private const ulong Height = 24;

private const ulong Width = 80;

private const string ConsoleSizeArrayFragment = "\"ConsoleSize\":[24,80]";

private const string ConsoleSizeJson = "{\"ConsoleSize\":[24,80]}";

[Fact]
public void Serialize_StandaloneConsoleSize_ProducesJsonObject()
{
var consoleSize = new ConsoleSize { Height = Height, Width = Width };

var jsonString = JsonSerializer.Instance.Serialize(consoleSize);

Assert.Equal("{\"Height\":24,\"Width\":80}", jsonString);
}

[Fact]
public void Serialize_ContainerExecCreateParameters_WithConsoleSizeProperty_ProducesArrayFormat()
{
var parameters = new ContainerExecCreateParameters
{
ConsoleSize = new ConsoleSize { Height = Height, Width = Width },
};

var jsonString = JsonSerializer.Instance.Serialize(parameters);

Assert.Contains(ConsoleSizeArrayFragment, jsonString);
}

[Fact]
public void Deserialize_ContainerExecCreateParameters_WithArrayConsoleSize_Succeeds()
{
var parameters = JsonSerializer.Instance.Deserialize<ContainerExecCreateParameters>(Encoding.UTF8.GetBytes(ConsoleSizeJson));
Assert.NotNull(parameters);
Assert.NotNull(parameters.ConsoleSize);
Assert.Equal(Height, parameters.ConsoleSize.Height);
Assert.Equal(Width, parameters.ConsoleSize.Width);
}

[Fact]
public void Serialize_ContainerExecStartParameters_WithConsoleSizeProperty_ProducesArrayFormat()
{
var parameters = new ContainerExecStartParameters
{
ConsoleSize = new ConsoleSize { Height = Height, Width = Width }
};

var jsonString = JsonSerializer.Instance.Serialize(parameters);

Assert.Contains(ConsoleSizeArrayFragment, jsonString);
}

[Fact]
public void Deserialize_ContainerExecStartParameters_WithArrayConsoleSize_Succeeds()
{
var parameters = JsonSerializer.Instance.Deserialize<ContainerExecStartParameters>(Encoding.UTF8.GetBytes(ConsoleSizeJson));
Assert.NotNull(parameters);
Assert.NotNull(parameters.ConsoleSize);
Assert.Equal(Height, parameters.ConsoleSize.Height);
Assert.Equal(Width, parameters.ConsoleSize.Width);
}

[Fact]
public void Serialize_HostConfig_WithConsoleSizeProperty_ProducesArrayFormat()
{
var hostConfig = new HostConfig
{
ConsoleSize = new ConsoleSize { Height = Height, Width = Width }
};

var jsonString = JsonSerializer.Instance.Serialize(hostConfig);

Assert.Contains(ConsoleSizeArrayFragment, jsonString);
}

[Fact]
public void Deserialize_HostConfig_WithArrayConsoleSize_Succeeds()
{
var hostConfig = JsonSerializer.Instance.Deserialize<HostConfig>(Encoding.UTF8.GetBytes(ConsoleSizeJson));
Assert.NotNull(hostConfig);
Assert.NotNull(hostConfig.ConsoleSize);
Assert.Equal(Height, hostConfig.ConsoleSize.Height);
Assert.Equal(Width, hostConfig.ConsoleSize.Width);
}

[Theory]
[InlineData("{\"ConsoleSize\":[24]}")]
[InlineData("{\"ConsoleSize\":[24,80,1]}")]
[InlineData("{\"ConsoleSize\":[\"24\",80]}")]
public void Deserialize_ContainerExecCreateParameters_WithInvalidArrayConsoleSize_ThrowsJsonException(string jsonString)
{
Assert.Throws<JsonException>(() => JsonSerializer.Instance.Deserialize<ContainerExecCreateParameters>(Encoding.UTF8.GetBytes(jsonString)));
}
}
1 change: 1 addition & 0 deletions test/Docker.DotNet.Tests/Docker.DotNet.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<Using Include="System.Reflection" />
<Using Include="System.Security.Cryptography.X509Certificates" />
<Using Include="System.Text" />
<Using Include="System.Text.Json" />
<Using Include="System.Threading" />
<Using Include="System.Threading.Tasks" />
<Using Include="Docker.DotNet.Handler.Abstractions" />
Expand Down
27 changes: 27 additions & 0 deletions tools/specgen/specgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@ var typesToDisambiguate = map[string]*CSModelType{
},
},
},
typeToKey(reflect.TypeOf(container.HostConfig{})): {
Properties: []CSProperty{
{
Name: "ConsoleSize",
Type: CSType{"", "ConsoleSize", true},
Attributes: []CSAttribute{{Type: CSType{"System.Text.Json.Serialization", "JsonConverter", false}, Arguments: []CSArgument{{Value: "typeof(ConsoleSizeConverter)"}}}},
},
},
},
typeToKey(reflect.TypeOf(container.CreateResponse{})): {Name: "CreateContainerResponse"},
typeToKey(reflect.TypeOf(container.HealthConfig{})): {
Properties: []CSProperty{
Expand Down Expand Up @@ -101,6 +110,24 @@ var typesToDisambiguate = map[string]*CSModelType{
},
},
},
typeToKey(reflect.TypeOf(ContainerExecCreateParameters{})): {
Properties: []CSProperty{
{
Name: "ConsoleSize",
Type: CSType{"", "ConsoleSize", true},
Attributes: []CSAttribute{{Type: CSType{"System.Text.Json.Serialization", "JsonConverter", false}, Arguments: []CSArgument{{Value: "typeof(ConsoleSizeConverter)"}}}},
},
},
},
typeToKey(reflect.TypeOf(ContainerExecStartParameters{})): {
Properties: []CSProperty{
{
Name: "ConsoleSize",
Type: CSType{"", "ConsoleSize", true},
Attributes: []CSAttribute{{Type: CSType{"System.Text.Json.Serialization", "JsonConverter", false}, Arguments: []CSArgument{{Value: "typeof(ConsoleSizeConverter)"}}}},
},
},
},
typeToKey(reflect.TypeOf(volume.AccessMode{})): {Name: "VolumeAccessMode"},
typeToKey(reflect.TypeOf(volume.Info{})): {Name: "VolumeInfo"},
typeToKey(reflect.TypeOf(volume.Secret{})): {Name: "VolumeSecret"},
Expand Down