Skip to content

Commit 8888a16

Browse files
authored
add patch and replace to generic (#1040)
1 parent f1f35fa commit 8888a16

File tree

2 files changed

+89
-27
lines changed

2 files changed

+89
-27
lines changed

src/KubernetesClient/GenericClient.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using k8s.Models;
12
using System.Threading;
23
using System.Threading.Tasks;
34

@@ -86,6 +87,34 @@ public async Task<T> DeleteNamespacedAsync<T>(string ns, string name, Cancellati
8687
return KubernetesJson.Deserialize<T>(resp.Body.ToString());
8788
}
8889

90+
public async Task<T> PatchAsync<T>(V1Patch patch, string name, CancellationToken cancel = default)
91+
where T : IKubernetesObject
92+
{
93+
var resp = await kubernetes.CustomObjects.PatchClusterCustomObjectWithHttpMessagesAsync(patch, group, version, plural, name, cancellationToken: cancel).ConfigureAwait(false);
94+
return KubernetesJson.Deserialize<T>(resp.Body.ToString());
95+
}
96+
97+
public async Task<T> PatchNamespacedAsync<T>(V1Patch patch, string ns, string name, CancellationToken cancel = default)
98+
where T : IKubernetesObject
99+
{
100+
var resp = await kubernetes.CustomObjects.PatchNamespacedCustomObjectWithHttpMessagesAsync(patch, group, version, ns, plural, name, cancellationToken: cancel).ConfigureAwait(false);
101+
return KubernetesJson.Deserialize<T>(resp.Body.ToString());
102+
}
103+
104+
public async Task<T> ReplaceAsync<T>(T obj, string name, CancellationToken cancel = default)
105+
where T : IKubernetesObject
106+
{
107+
var resp = await kubernetes.CustomObjects.ReplaceClusterCustomObjectWithHttpMessagesAsync(obj, group, version, plural, name, cancellationToken: cancel).ConfigureAwait(false);
108+
return KubernetesJson.Deserialize<T>(resp.Body.ToString());
109+
}
110+
111+
public async Task<T> ReplaceNamespacedAsync<T>(T obj, string ns, string name, CancellationToken cancel = default)
112+
where T : IKubernetesObject
113+
{
114+
var resp = await kubernetes.CustomObjects.ReplaceNamespacedCustomObjectWithHttpMessagesAsync(obj, group, version, ns, plural, name, cancellationToken: cancel).ConfigureAwait(false);
115+
return KubernetesJson.Deserialize<T>(resp.Body.ToString());
116+
}
117+
89118
public void Dispose()
90119
{
91120
Dispose(true);

tests/E2E.Tests/MinikubeTests.cs

Lines changed: 60 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -504,45 +504,78 @@ void Cleanup()
504504
{
505505
Cleanup();
506506

507-
await genericPods.CreateNamespacedAsync(
508-
new V1Pod()
509-
{
510-
Metadata = new V1ObjectMeta { Name = podName, },
511-
Spec = new V1PodSpec
507+
// create + list
508+
{
509+
await genericPods.CreateNamespacedAsync(
510+
new V1Pod()
512511
{
513-
Containers = new[] { new V1Container() { Name = "k8scsharp-e2e", Image = "nginx", }, },
512+
Metadata = new V1ObjectMeta { Name = podName, Labels = new Dictionary<string, string> { { "place", "holder" }, }, },
513+
Spec = new V1PodSpec
514+
{
515+
Containers = new[] { new V1Container() { Name = "k8scsharp-e2e", Image = "nginx", }, },
516+
},
514517
},
515-
},
516-
namespaceParameter).ConfigureAwait(false);
518+
namespaceParameter).ConfigureAwait(false);
517519

518-
var pods = await genericPods.ListNamespacedAsync<V1PodList>(namespaceParameter).ConfigureAwait(false);
519-
Assert.Contains(pods.Items, p => p.Metadata.Name == podName);
520+
var pods = await genericPods.ListNamespacedAsync<V1PodList>(namespaceParameter).ConfigureAwait(false);
521+
Assert.Contains(pods.Items, p => p.Metadata.Name == podName);
522+
}
520523

521-
int retry = 5;
522-
while (retry-- > 0)
524+
// replace + get
523525
{
524-
try
525-
{
526-
await genericPods.DeleteNamespacedAsync<V1Pod>(namespaceParameter, podName).ConfigureAwait(false);
527-
}
528-
catch (HttpOperationException e)
526+
var pod = await genericPods.ReadNamespacedAsync<V1Pod>(namespaceParameter, podName).ConfigureAwait(false);
527+
var old = JsonSerializer.SerializeToDocument(pod);
528+
529+
var newlabels = new Dictionary<string, string>(pod.Metadata.Labels) { ["test"] = "generic-test-jsonpatch" };
530+
pod.Metadata.Labels = newlabels;
531+
532+
var expected = JsonSerializer.SerializeToDocument(pod);
533+
var patch = old.CreatePatch(expected);
534+
535+
await genericPods.PatchNamespacedAsync<V1Pod>(new V1Patch(patch, V1Patch.PatchType.JsonPatch), namespaceParameter, podName).ConfigureAwait(false);
536+
var pods = await genericPods.ListNamespacedAsync<V1PodList>(namespaceParameter).ConfigureAwait(false);
537+
Assert.Contains(pods.Items, p => p.Labels().Contains(new KeyValuePair<string, string>("test", "generic-test-jsonpatch")));
538+
}
539+
540+
// replace + get
541+
{
542+
var pod = await genericPods.ReadNamespacedAsync<V1Pod>(namespaceParameter, podName).ConfigureAwait(false);
543+
pod.Spec.Containers[0].Image = "httpd";
544+
await genericPods.ReplaceNamespacedAsync(pod, namespaceParameter, podName).ConfigureAwait(false);
545+
546+
pod = await genericPods.ReadNamespacedAsync<V1Pod>(namespaceParameter, podName).ConfigureAwait(false);
547+
Assert.Equal("httpd", pod.Spec.Containers[0].Image);
548+
}
549+
550+
// delete + list
551+
{
552+
V1PodList pods = new V1PodList();
553+
int retry = 5;
554+
while (retry-- > 0)
529555
{
530-
if (e.Response.StatusCode == System.Net.HttpStatusCode.NotFound)
556+
try
531557
{
532-
return;
558+
await genericPods.DeleteNamespacedAsync<V1Pod>(namespaceParameter, podName).ConfigureAwait(false);
559+
}
560+
catch (HttpOperationException e)
561+
{
562+
if (e.Response.StatusCode == System.Net.HttpStatusCode.NotFound)
563+
{
564+
return;
565+
}
533566
}
534-
}
535567

536-
pods = await genericPods.ListNamespacedAsync<V1PodList>(namespaceParameter).ConfigureAwait(false);
537-
if (!pods.Items.Any(p => p.Metadata.Name == podName))
538-
{
539-
break;
568+
pods = await genericPods.ListNamespacedAsync<V1PodList>(namespaceParameter).ConfigureAwait(false);
569+
if (!pods.Items.Any(p => p.Metadata.Name == podName))
570+
{
571+
break;
572+
}
573+
574+
await Task.Delay(TimeSpan.FromSeconds(2.5)).ConfigureAwait(false);
540575
}
541576

542-
await Task.Delay(TimeSpan.FromSeconds(2.5)).ConfigureAwait(false);
577+
Assert.DoesNotContain(pods.Items, p => p.Metadata.Name == podName);
543578
}
544-
545-
Assert.DoesNotContain(pods.Items, p => p.Metadata.Name == podName);
546579
}
547580
finally
548581
{

0 commit comments

Comments
 (0)