From 2d5c7c0317e03a623e6a88e3af0da534e5cbe1a3 Mon Sep 17 00:00:00 2001 From: Ludovic Alarcon <7009064+alarco-l@users.noreply.github.com> Date: Tue, 11 Aug 2020 00:51:59 +0200 Subject: [PATCH] Metrics optional property (#474) * fix: timespan can be optional * use one comment on properties --- src/KubernetesClient/NodeMetrics.cs | 2 +- src/KubernetesClient/PodMetrics.cs | 2 +- .../Kubernetes.Metrics.Tests.cs | 35 ++++++++++++++++--- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/KubernetesClient/NodeMetrics.cs b/src/KubernetesClient/NodeMetrics.cs index 15f0c68..ab641bd 100644 --- a/src/KubernetesClient/NodeMetrics.cs +++ b/src/KubernetesClient/NodeMetrics.cs @@ -19,7 +19,7 @@ namespace k8s.Models /// The timestamp when metrics were collected. /// [JsonProperty(PropertyName = "timestamp")] - public DateTime Timestamp { get; set; } + public DateTime? Timestamp { get; set; } /// /// The interval from which metrics were collected. diff --git a/src/KubernetesClient/PodMetrics.cs b/src/KubernetesClient/PodMetrics.cs index 8aaf4da..3e18831 100644 --- a/src/KubernetesClient/PodMetrics.cs +++ b/src/KubernetesClient/PodMetrics.cs @@ -19,7 +19,7 @@ namespace k8s.Models /// The timestamp when metrics were collected. /// [JsonProperty(PropertyName = "timestamp")] - public DateTime Timestamp { get; set; } + public DateTime? Timestamp { get; set; } /// /// The interval from which metrics were collected. diff --git a/tests/KubernetesClient.Tests/Kubernetes.Metrics.Tests.cs b/tests/KubernetesClient.Tests/Kubernetes.Metrics.Tests.cs index 16762d0..a616f26 100644 --- a/tests/KubernetesClient.Tests/Kubernetes.Metrics.Tests.cs +++ b/tests/KubernetesClient.Tests/Kubernetes.Metrics.Tests.cs @@ -10,13 +10,12 @@ namespace k8s.Tests { private readonly ITestOutputHelper testOutput; - // Copy / Paste from metrics server on minikube + // All payloads' response are Copy / Paste from metrics server on minikube public const string NodeMetricsResponse = "{\n \"kind\": \"NodeMetricsList\",\n \"apiVersion\": \"metrics.k8s.io/v1beta1\",\n \"metadata\": {\n \"selfLink\": \"/apis/metrics.k8s.io/v1beta1/nodes/\"\n },\n \"items\": [\n {\n \"metadata\": {\n \"name\": \"minikube\",\n \"selfLink\": \"/apis/metrics.k8s.io/v1beta1/nodes/minikube\",\n \"creationTimestamp\": \"2020-07-28T20:01:05Z\"\n },\n \"timestamp\": \"2020-07-28T20:01:00Z\",\n \"window\": \"1m0s\",\n \"usage\": {\n \"cpu\": \"394m\",\n \"memory\": \"1948140Ki\"\n }\n }\n ]\n}"; - // Copy / Paste from metrics server minikube + public const string OptionalPropertyNodeMetricsResponse = "{\n \"kind\": \"NodeMetricsList\",\n \"apiVersion\": \"metrics.k8s.io/v1beta1\",\n \"metadata\": {\n \"selfLink\": \"/apis/metrics.k8s.io/v1beta1/nodes/\"\n },\n \"items\": [\n {\n \"metadata\": {\n \"name\": \"minikube\",\n \"selfLink\": \"/apis/metrics.k8s.io/v1beta1/nodes/minikube\",\n \"creationTimestamp\": \"2020-07-28T20:01:05Z\"\n },\n \"timestamp\": null,\n \"window\": \"1m0s\",\n \"usage\": {\n \"cpu\": \"394m\",\n \"memory\": \"1948140Ki\"\n }\n }\n ]\n}"; public const string PodMetricsResponse = "{\n \"kind\": \"PodMetricsList\",\n \"apiVersion\": \"metrics.k8s.io/v1beta1\",\n \"metadata\": {\n \"selfLink\": \"/apis/metrics.k8s.io/v1beta1/namespaces/default/pods/\"\n },\n \"items\": [\n {\n \"metadata\": {\n \"name\": \"dotnet-test-d4894bfbd-2q2dw\",\n \"namespace\": \"default\",\n \"selfLink\": \"/apis/metrics.k8s.io/v1beta1/namespaces/default/pods/dotnet-test-d4894bfbd-2q2dw\",\n \"creationTimestamp\": \"2020-08-01T07:40:05Z\"\n },\n \"timestamp\": \"2020-08-01T07:40:00Z\",\n \"window\": \"1m0s\",\n \"containers\": [\n {\n \"name\": \"dotnet-test\",\n \"usage\": {\n \"cpu\": \"0\",\n \"memory\": \"14512Ki\"\n }\n }\n ]\n }\n ]\n}"; - // Copy / Paste from metrics server minikube + public const string OptionalPropertyPodMetricsResponse = "{\n \"kind\": \"PodMetricsList\",\n \"apiVersion\": \"metrics.k8s.io/v1beta1\",\n \"metadata\": {\n \"selfLink\": \"/apis/metrics.k8s.io/v1beta1/namespaces/default/pods/\"\n },\n \"items\": [\n {\n \"metadata\": {\n \"name\": \"dotnet-test-d4894bfbd-2q2dw\",\n \"namespace\": \"default\",\n \"selfLink\": \"/apis/metrics.k8s.io/v1beta1/namespaces/default/pods/dotnet-test-d4894bfbd-2q2dw\",\n \"creationTimestamp\": \"2020-08-01T07:40:05Z\"\n },\n \"timestamp\": null,\n \"window\": \"1m0s\",\n \"containers\": [\n {\n \"name\": \"dotnet-test\",\n \"usage\": {\n \"cpu\": \"0\",\n \"memory\": \"14512Ki\"\n }\n }\n ]\n }\n ]\n}"; // Copy / Paste from metrics server minikube public const string EmptyPodMetricsResponse = "{\n \"kind\": \"PodMetricsList\",\n \"apiVersion\": \"metrics.k8s.io/v1beta1\",\n \"metadata\": {\n \"selfLink\": \"/apis/metrics.k8s.io/v1beta1/namespaces/empty/pods/\"\n },\n \"items\": []\n}"; - // Copy / Paste from metrics server minikube public const string NonExistingNamespaceResponse = "{\n \"kind\": \"PodMetricsList\",\n \"apiVersion\": \"metrics.k8s.io/v1beta1\",\n \"metadata\": {\n \"selfLink\": \"/apis/metrics.k8s.io/v1beta1/namespaces/nonexisting/pods/\"\n },\n \"items\": []\n}"; public const string DefaultNodeName = "minikube"; @@ -49,6 +48,20 @@ namespace k8s.Tests } } + [Fact(DisplayName = "Node metrics optionnal property")] + public async Task NodesMetricsOptionalProperty() + { + using (var server = new MockKubeApiServer(testOutput, resp: OptionalPropertyNodeMetricsResponse)) + { + var client = new Kubernetes(new KubernetesClientConfiguration { Host = server.Uri.ToString() }); + + // Should not throw with timespan optional property + var exception = await Record.ExceptionAsync(async () => await client.GetKubernetesNodesMetricsAsync().ConfigureAwait(false)).ConfigureAwait(false); + + Assert.Null(exception); + } + } + [Fact(DisplayName = "Pod metrics")] public async Task PodsMetrics() { @@ -73,6 +86,20 @@ namespace k8s.Tests } } + [Fact(DisplayName = "Pod metrics optionnal property")] + public async Task PodsMetricsOptionalProperty() + { + using (var server = new MockKubeApiServer(testOutput, resp: OptionalPropertyPodMetricsResponse)) + { + var client = new Kubernetes(new KubernetesClientConfiguration { Host = server.Uri.ToString() }); + + // Should not throw with timespan optional property + var exception = await Record.ExceptionAsync(async () => await client.GetKubernetesPodsMetricsAsync().ConfigureAwait(false)).ConfigureAwait(false); + + Assert.Null(exception); + } + } + [Fact(DisplayName = "Pod metrics empty response")] public async Task PodsMetricsEmptyResponse() {