mirror of
https://github.com/MAKS-IT-COM/maksit-cluster-console.git
synced 2026-09-30 00:38:10 +02:00
(bugfix): sort resource table ip columns as addresses
This commit is contained in:
parent
1ed5962d21
commit
a741640858
@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.2.1] - 2026-08-20
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Resource table IP columns (**Cluster IP**, **External IP**) sort as addresses, not text (`10.1.1.2` before `10.1.1.10`).
|
||||||
|
|
||||||
## [0.2.0] - 2026-08-20
|
## [0.2.0] - 2026-08-20
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
# MaksIT.ClusterConsole
|
# MaksIT.ClusterConsole
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Version>0.2.0</Version>
|
<Version>0.2.1</Version>
|
||||||
<Product>MaksIT.ClusterConsole</Product>
|
<Product>MaksIT.ClusterConsole</Product>
|
||||||
<AssemblyTitle>MaksIT.ClusterConsole</AssemblyTitle>
|
<AssemblyTitle>MaksIT.ClusterConsole</AssemblyTitle>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
using System.Net;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using MaksIT.ClusterConsole.Client;
|
using MaksIT.ClusterConsole.Client;
|
||||||
@ -48,6 +49,7 @@ public static class ResourceColumnSort {
|
|||||||
"Memory" => KubeQuantity.ToBytes(left).CompareTo(KubeQuantity.ToBytes(right)),
|
"Memory" => KubeQuantity.ToBytes(left).CompareTo(KubeQuantity.ToBytes(right)),
|
||||||
"Replicas" or "Desired" or "Current" or "Min" or "Max" or "Port" =>
|
"Replicas" or "Desired" or "Current" or "Min" or "Max" or "Port" =>
|
||||||
ParseInt(left).CompareTo(ParseInt(right)),
|
ParseInt(left).CompareTo(ParseInt(right)),
|
||||||
|
_ when IsIpHeader(header) => CompareIpList(left, right),
|
||||||
_ => string.Compare(left, right, StringComparison.OrdinalIgnoreCase)
|
_ => string.Compare(left, right, StringComparison.OrdinalIgnoreCase)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -83,6 +85,67 @@ public static class ResourceColumnSort {
|
|||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsIpHeader(string header) =>
|
||||||
|
header.Equals("IP", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| header.EndsWith(" IP", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
private static int CompareIpList(string left, string right) {
|
||||||
|
var leftParts = SplitIpCell(left);
|
||||||
|
var rightParts = SplitIpCell(right);
|
||||||
|
var count = Math.Min(leftParts.Length, rightParts.Length);
|
||||||
|
for (var i = 0; i < count; i++) {
|
||||||
|
var cmp = CompareIpToken(leftParts[i], rightParts[i]);
|
||||||
|
if (cmp != 0)
|
||||||
|
return cmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return leftParts.Length.CompareTo(rightParts.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string[] SplitIpCell(string text) =>
|
||||||
|
text.Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
|
private static int CompareIpToken(string left, string right) {
|
||||||
|
var leftMissing = IsMissingIp(left);
|
||||||
|
var rightMissing = IsMissingIp(right);
|
||||||
|
if (leftMissing && rightMissing)
|
||||||
|
return 0;
|
||||||
|
if (leftMissing)
|
||||||
|
return -1;
|
||||||
|
if (rightMissing)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (IPAddress.TryParse(left, out var leftIp)) {
|
||||||
|
if (IPAddress.TryParse(right, out var rightIp))
|
||||||
|
return CompareAddress(leftIp, rightIp);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IPAddress.TryParse(right, out _))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return string.Compare(left, right, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsMissingIp(string text) =>
|
||||||
|
text.Equals("None", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| text.Equals("<none>", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
private static int CompareAddress(IPAddress left, IPAddress right) {
|
||||||
|
var family = left.AddressFamily.CompareTo(right.AddressFamily);
|
||||||
|
if (family != 0)
|
||||||
|
return family;
|
||||||
|
|
||||||
|
Span<byte> leftBytes = stackalloc byte[16];
|
||||||
|
Span<byte> rightBytes = stackalloc byte[16];
|
||||||
|
if (!left.TryWriteBytes(leftBytes, out var leftLength)
|
||||||
|
|| !right.TryWriteBytes(rightBytes, out var rightLength))
|
||||||
|
return string.CompareOrdinal(left.ToString(), right.ToString());
|
||||||
|
|
||||||
|
return leftBytes[..leftLength].SequenceCompareTo(rightBytes[..rightLength]);
|
||||||
|
}
|
||||||
|
|
||||||
private static int CompareReady(string left, string right) {
|
private static int CompareReady(string left, string right) {
|
||||||
ParseReady(left, out var leftReady, out var leftTotal);
|
ParseReady(left, out var leftReady, out var leftTotal);
|
||||||
ParseReady(right, out var rightReady, out var rightTotal);
|
ParseReady(right, out var rightReady, out var rightTotal);
|
||||||
|
|||||||
@ -29,6 +29,17 @@ public class ResourceTableTests {
|
|||||||
Assert.True(ResourceColumnSort.Compare("Age", "2d", "5h") > 0);
|
Assert.True(ResourceColumnSort.Compare("Age", "2d", "5h") > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Ip_columns_sort_as_addresses_not_text() {
|
||||||
|
Assert.True(ResourceColumnSort.Compare("Cluster IP", "10.1.1.2", "10.1.1.10") < 0);
|
||||||
|
Assert.True(ResourceColumnSort.Compare("Cluster IP", "10.1.1.10", "10.1.1.2") > 0);
|
||||||
|
Assert.Equal(0, ResourceColumnSort.Compare("External IP", "192.168.0.1", "192.168.0.1"));
|
||||||
|
Assert.True(ResourceColumnSort.Compare("Cluster IP", "None", "10.0.0.1") < 0);
|
||||||
|
Assert.True(ResourceColumnSort.Compare("External IP", "10.0.0.2,10.0.0.10", "10.0.0.2,10.0.0.3") > 0);
|
||||||
|
Assert.True(ResourceColumnSort.Compare("Cluster IP", "127.0.0.1", "::1") < 0);
|
||||||
|
Assert.True(ResourceColumnSort.Compare("Cluster IP", "2001:db8::1", "2001:db8::10") < 0);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Ready_and_restarts_sort_numerically() {
|
public void Ready_and_restarts_sort_numerically() {
|
||||||
Assert.True(ResourceColumnSort.Compare("Ready", "1/2", "2/2") < 0);
|
Assert.True(ResourceColumnSort.Compare("Ready", "1/2", "2/2") < 0);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user