Allow multi patch http content type header (#521)

* header from obj

* update git version mod

* remove json patch test

* test for json patch
This commit is contained in:
Boshi Lian
2020-11-17 10:38:05 -08:00
committed by GitHub
parent e18ec35250
commit f59c13da0e
8 changed files with 673 additions and 539 deletions

View File

@@ -8,7 +8,7 @@ jobs:
os: [ubuntu-latest, windows-latest, macOS-latest]
name: Dotnet build
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Setup dotnet SDK 2.1
@@ -19,6 +19,10 @@ jobs:
uses: actions/setup-dotnet@v1
with:
dotnet-version: '3.1.x'
- name: Setup dotnet SDK 5
uses: actions/setup-dotnet@v1
with:
dotnet-version: '5.0.x'
- name: Setup Format
run: dotnet tool install -g dotnet-format
- name: Check Format
@@ -48,6 +52,10 @@ jobs:
uses: actions/setup-dotnet@v1
with:
dotnet-version: '3.1.x'
- name: Setup dotnet SDK 5
uses: actions/setup-dotnet@v1
with:
dotnet-version: '5.0.x'
- name: Minikube
run: minikube start
- name: Test

View File

@@ -0,0 +1,40 @@
using System;
using System.Net.Http.Headers;
using k8s.Models;
namespace k8s
{
public partial class Kubernetes
{
public virtual MediaTypeHeaderValue GetHeader(object body)
{
if (body == null)
{
throw new ArgumentNullException(nameof(body));
}
return MediaTypeHeaderValue.Parse("application/json; charset=utf-8");
}
public virtual MediaTypeHeaderValue GetHeader(V1Patch body)
{
if (body == null)
{
throw new ArgumentNullException(nameof(body));
}
switch (body.Type)
{
case V1Patch.PatchType.JsonPatch:
return MediaTypeHeaderValue.Parse("application/json-patch+json; charset=utf-8");
case V1Patch.PatchType.MergePatch:
return MediaTypeHeaderValue.Parse("application/merge-patch+json; charset=utf-8");
case V1Patch.PatchType.StrategicMergePatch:
return MediaTypeHeaderValue.Parse("application/strategic-merge-patch+json; charset=utf-8");
default:
throw new ArgumentOutOfRangeException(nameof(body.Type), "");
}
}
}
}

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Authors>The Kubernetes Project Authors</Authors>
<Copyright>2017 The Kubernetes Project Authors</Copyright>
@@ -30,18 +30,19 @@
<PackageReference Include="AutoMapper" Version="7.0.1" Condition="'$(TargetFramework)' == 'net452'" />
<PackageReference Include="AutoMapper" Version="9.0.0" Condition="'$(TargetFramework)' != 'net452'" />
<PackageReference Include="Fractions" Version="4.0.1" />
<PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="1.1.2" Condition="'$(TargetFramework)' != 'netstandard2.0' and '$(TargetFramework)' != 'netcoreapp2.1'" />
<PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="3.0.0" Condition="'$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'netcoreapp2.1'" />
<PackageReference Include="Nerdbank.GitVersioning" Version="3.0.50" PrivateAssets="all" />
<PackageReference Include="Nerdbank.GitVersioning" Version="3.3.37" PrivateAssets="all" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.1.3" />
<PackageReference Include="Microsoft.Rest.ClientRuntime" Version="2.3.10" />
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" Condition="'$(TargetFramework)' != 'netstandard2.0' and '$(TargetFramework)' != 'netcoreapp2.1'" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" Condition="'$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'netcoreapp2.1'" />
<PackageReference Include="System.Runtime.InteropServices.RuntimeInformation" Version="4.3.0" Condition="'$(TargetFramework)' == 'net452'" />
<PackageReference Include="YamlDotNet" Version="8.1.2" />
<PackageReference Include="System.Buffers" Version="4.5.1" Condition="'$(TargetFramework)' != 'netcoreapp2.1'" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net452'">
<Reference Include="System.Runtime.InteropServices" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.WebRequest" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
</ItemGroup>

View File

@@ -1,5 +1,4 @@
using System;
using Microsoft.AspNetCore.JsonPatch;
using Newtonsoft.Json;
namespace k8s.Models
@@ -9,6 +8,7 @@ namespace k8s.Models
{
public enum PatchType
{
Unknown,
JsonPatch,
MergePatch,
StrategicMergePatch,
@@ -16,31 +16,24 @@ namespace k8s.Models
public PatchType Type { get; private set; }
public V1Patch(IJsonPatchDocument jsonPatch)
: this((object)jsonPatch)
public V1Patch(object body, PatchType type)
{
}
public V1Patch(String body, PatchType type)
: this(body)
{
this.Type = type;
Content = body;
Type = type;
CustomInit();
}
partial void CustomInit()
{
if (Content is IJsonPatchDocument)
if (Content == null)
{
Type = PatchType.JsonPatch;
return;
throw new ArgumentNullException(nameof(Content), "object must be set");
}
if (Content is String)
if (Type == PatchType.Unknown)
{
return;
throw new ArgumentException("patch type must be set", nameof(Type));
}
throw new NotSupportedException();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -4,12 +4,14 @@
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\..\src\KubernetesClient\kubernetes-client.snk</AssemblyOriginatorKeyFile>
<RootNamespace>k8s.E2E</RootNamespace>
<TargetFrameworks>netcoreapp3.1</TargetFrameworks>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="5.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<PrivateAssets>all</PrivateAssets>

View File

@@ -1,6 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using k8s.Models;
using Microsoft.AspNetCore.JsonPatch;
using Microsoft.Rest;
using Xunit;
@@ -12,7 +15,7 @@ namespace k8s.E2E
public void SimpleTest()
{
var namespaceParameter = "default";
var podName = "k8s-e2e-pod";
var podName = "k8scsharp-e2e-pod";
var client = CreateClient();
@@ -35,7 +38,7 @@ namespace k8s.E2E
Metadata = new V1ObjectMeta { Name = podName, },
Spec = new V1PodSpec
{
Containers = new[] { new V1Container() { Name = "k8s-e2e", Image = "nginx", }, },
Containers = new[] { new V1Container() { Name = "k8scsharp-e2e", Image = "nginx", }, },
},
},
namespaceParameter);
@@ -49,6 +52,112 @@ namespace k8s.E2E
}
}
[MinikubeFact]
public void PatchTest()
{
var namespaceParameter = "default";
var podName = "k8scsharp-e2e-patch-pod";
var client = CreateClient();
void Cleanup()
{
var pods = client.ListNamespacedPod(namespaceParameter);
while (pods.Items.Any(p => p.Metadata.Name == podName))
{
try
{
client.DeleteNamespacedPod(podName, namespaceParameter);
}
catch (HttpOperationException e)
{
if (e.Response.StatusCode == System.Net.HttpStatusCode.NotFound)
{
return;
}
}
}
}
try
{
{
Cleanup();
client.CreateNamespacedPod(
new V1Pod()
{
Metadata = new V1ObjectMeta { Name = podName, Labels = new Dictionary<string, string> { { "place", "holder" }, }, },
Spec = new V1PodSpec
{
Containers = new[] { new V1Container() { Name = "k8scsharp-patch", Image = "nginx", }, },
},
},
namespaceParameter);
var pod = client.ListNamespacedPod(namespaceParameter).Items.First(p => p.Metadata.Name == podName);
var newlabels = new Dictionary<string, string>(pod.Metadata.Labels) { ["test"] = "test-jsonpatch" };
var patch = new JsonPatchDocument<V1Pod>();
patch.Replace(e => e.Metadata.Labels, newlabels);
client.PatchNamespacedPod(new V1Patch(patch, V1Patch.PatchType.JsonPatch), pod.Metadata.Name, "default");
Assert.False(pod.Labels().ContainsKey("test"));
// refresh
pod = client.ListNamespacedPod(namespaceParameter).Items.First(p => p.Metadata.Name == podName);
Assert.Equal("test-jsonpatch", pod.Labels()["test"]);
}
{
Cleanup();
}
{
client.CreateNamespacedPod(
new V1Pod()
{
Metadata = new V1ObjectMeta { Name = podName, Labels = new Dictionary<string, string> { { "place", "holder" }, }, },
Spec = new V1PodSpec
{
Containers = new[] { new V1Container() { Name = "k8scsharp-patch", Image = "nginx", }, },
},
},
namespaceParameter);
var pod = client.ListNamespacedPod(namespaceParameter).Items.First(p => p.Metadata.Name == podName);
var patchStr = @"
{
""metadata"": {
""labels"": {
""test"": ""test-mergepatch""
}
}
}";
client.PatchNamespacedPod(new V1Patch(patchStr, V1Patch.PatchType.MergePatch), pod.Metadata.Name, "default");
Assert.False(pod.Labels().ContainsKey("test"));
// refresh
pod = client.ListNamespacedPod(namespaceParameter).Items.First(p => p.Metadata.Name == podName);
Assert.Equal("test-mergepatch", pod.Labels()["test"]);
}
}
finally
{
Cleanup();
}
}
private static IKubernetes CreateClient()
{
return new Kubernetes(KubernetesClientConfiguration.BuildDefaultConfig());

View File

@@ -1,19 +0,0 @@
using System.Linq;
using k8s.Models;
using Microsoft.AspNetCore.JsonPatch;
using Xunit;
namespace k8s.Tests
{
public class JsonPatchTests
{
[Fact]
public void PathContainsUpperCase()
{
var patch = new JsonPatchDocument<V1HorizontalPodAutoscaler>();
patch.Replace(h => h.Spec.MinReplicas, 1);
Assert.Equal("/spec/minReplicas", patch.Operations.Single().path);
}
}
}