Support IgnoreUnmatchedProperties in YAML serialization (#574)
* Support IgnoreUnmatchedProperties in YAML serialization * Remove unnecessary null-conditional operator
This commit is contained in:
committed by
GitHub
parent
a4350d6c8f
commit
d48e93c1f6
@@ -3,6 +3,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using YamlDotNet.Core;
|
using YamlDotNet.Core;
|
||||||
@@ -18,6 +19,26 @@ namespace k8s
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class Yaml
|
public static class Yaml
|
||||||
{
|
{
|
||||||
|
private static readonly IDeserializer Deserializer =
|
||||||
|
new DeserializerBuilder()
|
||||||
|
.WithNamingConvention(CamelCaseNamingConvention.Instance)
|
||||||
|
.WithTypeConverter(new IntOrStringYamlConverter())
|
||||||
|
.WithTypeConverter(new ByteArrayStringYamlConverter())
|
||||||
|
.WithOverridesFromJsonPropertyAttributes()
|
||||||
|
.IgnoreUnmatchedProperties()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
private static readonly IValueSerializer Serializer =
|
||||||
|
new SerializerBuilder()
|
||||||
|
.DisableAliases()
|
||||||
|
.WithNamingConvention(CamelCaseNamingConvention.Instance)
|
||||||
|
.WithTypeConverter(new IntOrStringYamlConverter())
|
||||||
|
.WithTypeConverter(new ByteArrayStringYamlConverter())
|
||||||
|
.WithEventEmitter(e => new StringQuotingEmitter(e))
|
||||||
|
.ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitNull)
|
||||||
|
.WithOverridesFromJsonPropertyAttributes()
|
||||||
|
.BuildValueSerializer();
|
||||||
|
|
||||||
public class ByteArrayStringYamlConverter : IYamlTypeConverter
|
public class ByteArrayStringYamlConverter : IYamlTypeConverter
|
||||||
{
|
{
|
||||||
public bool Accepts(Type type)
|
public bool Accepts(Type type)
|
||||||
@@ -105,30 +126,15 @@ namespace k8s
|
|||||||
throw new ArgumentNullException(nameof(typeMap));
|
throw new ArgumentNullException(nameof(typeMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
var deserializer =
|
|
||||||
new DeserializerBuilder()
|
|
||||||
.WithNamingConvention(CamelCaseNamingConvention.Instance)
|
|
||||||
.WithTypeInspector(ti => new AutoRestTypeInspector(ti))
|
|
||||||
.WithTypeConverter(new IntOrStringYamlConverter())
|
|
||||||
.WithTypeConverter(new ByteArrayStringYamlConverter())
|
|
||||||
.IgnoreUnmatchedProperties()
|
|
||||||
.Build();
|
|
||||||
var types = new List<Type>();
|
var types = new List<Type>();
|
||||||
var parser = new Parser(new StringReader(content));
|
var parser = new Parser(new StringReader(content));
|
||||||
parser.Consume<StreamStart>();
|
parser.Consume<StreamStart>();
|
||||||
while (parser.Accept<DocumentStart>(out _))
|
while (parser.Accept<DocumentStart>(out _))
|
||||||
{
|
{
|
||||||
var obj = deserializer.Deserialize<KubernetesObject>(parser);
|
var obj = Deserializer.Deserialize<KubernetesObject>(parser);
|
||||||
types.Add(typeMap[obj.ApiVersion + "/" + obj.Kind]);
|
types.Add(typeMap[obj.ApiVersion + "/" + obj.Kind]);
|
||||||
}
|
}
|
||||||
|
|
||||||
deserializer =
|
|
||||||
new DeserializerBuilder()
|
|
||||||
.WithNamingConvention(CamelCaseNamingConvention.Instance)
|
|
||||||
.WithTypeInspector(ti => new AutoRestTypeInspector(ti))
|
|
||||||
.WithTypeConverter(new IntOrStringYamlConverter())
|
|
||||||
.WithTypeConverter(new ByteArrayStringYamlConverter())
|
|
||||||
.Build();
|
|
||||||
parser = new Parser(new StringReader(content));
|
parser = new Parser(new StringReader(content));
|
||||||
parser.Consume<StreamStart>();
|
parser.Consume<StreamStart>();
|
||||||
var ix = 0;
|
var ix = 0;
|
||||||
@@ -136,7 +142,7 @@ namespace k8s
|
|||||||
while (parser.Accept<DocumentStart>(out _))
|
while (parser.Accept<DocumentStart>(out _))
|
||||||
{
|
{
|
||||||
var objType = types[ix++];
|
var objType = types[ix++];
|
||||||
var obj = deserializer.Deserialize(parser, objType);
|
var obj = Deserializer.Deserialize(parser, objType);
|
||||||
results.Add(obj);
|
results.Add(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,14 +166,7 @@ namespace k8s
|
|||||||
|
|
||||||
public static T LoadFromString<T>(string content)
|
public static T LoadFromString<T>(string content)
|
||||||
{
|
{
|
||||||
var deserializer =
|
var obj = Deserializer.Deserialize<T>(content);
|
||||||
new DeserializerBuilder()
|
|
||||||
.WithNamingConvention(CamelCaseNamingConvention.Instance)
|
|
||||||
.WithTypeInspector(ti => new AutoRestTypeInspector(ti))
|
|
||||||
.WithTypeConverter(new IntOrStringYamlConverter())
|
|
||||||
.WithTypeConverter(new ByteArrayStringYamlConverter())
|
|
||||||
.Build();
|
|
||||||
var obj = deserializer.Deserialize<T>(content);
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,119 +176,44 @@ namespace k8s
|
|||||||
var writer = new StringWriter(stringBuilder);
|
var writer = new StringWriter(stringBuilder);
|
||||||
var emitter = new Emitter(writer);
|
var emitter = new Emitter(writer);
|
||||||
|
|
||||||
var serializer =
|
|
||||||
new SerializerBuilder()
|
|
||||||
.DisableAliases()
|
|
||||||
.WithNamingConvention(CamelCaseNamingConvention.Instance)
|
|
||||||
.WithTypeInspector(ti => new AutoRestTypeInspector(ti))
|
|
||||||
.WithTypeConverter(new IntOrStringYamlConverter())
|
|
||||||
.WithTypeConverter(new ByteArrayStringYamlConverter())
|
|
||||||
.WithEventEmitter(e => new StringQuotingEmitter(e))
|
|
||||||
.ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitNull)
|
|
||||||
.BuildValueSerializer();
|
|
||||||
emitter.Emit(new StreamStart());
|
emitter.Emit(new StreamStart());
|
||||||
emitter.Emit(new DocumentStart());
|
emitter.Emit(new DocumentStart());
|
||||||
serializer.SerializeValue(emitter, value, typeof(T));
|
Serializer.SerializeValue(emitter, value, typeof(T));
|
||||||
|
|
||||||
return stringBuilder.ToString();
|
return stringBuilder.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AutoRestTypeInspector : ITypeInspector
|
private static TBuilder WithOverridesFromJsonPropertyAttributes<TBuilder>(this TBuilder builder)
|
||||||
|
where TBuilder : BuilderSkeleton<TBuilder>
|
||||||
{
|
{
|
||||||
private readonly ITypeInspector _inner;
|
// Use VersionInfo from the model namespace as that should be stable.
|
||||||
|
// If this is not generated in the future we will get an obvious compiler error.
|
||||||
|
var targetNamespace = typeof(VersionInfo).Namespace;
|
||||||
|
|
||||||
public AutoRestTypeInspector(ITypeInspector inner)
|
// Get all the concrete model types from the code generated namespace.
|
||||||
{
|
var types = typeof(KubernetesEntityAttribute).Assembly
|
||||||
_inner = inner;
|
.ExportedTypes
|
||||||
}
|
.Where(type => type.Namespace == targetNamespace &&
|
||||||
|
!type.IsInterface &&
|
||||||
|
!type.IsAbstract);
|
||||||
|
|
||||||
public IEnumerable<IPropertyDescriptor> GetProperties(Type type, object container)
|
// Map any JsonPropertyAttribute instances to YamlMemberAttribute instances.
|
||||||
|
foreach (var type in types)
|
||||||
{
|
{
|
||||||
var pds = _inner.GetProperties(type, container);
|
foreach (var property in type.GetProperties())
|
||||||
return pds.Select(pd => TrimPropertySuffix(pd, type)).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IPropertyDescriptor GetProperty(Type type, object container, string name, bool ignoreUnmatched)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
return _inner.GetProperty(type, container, name, ignoreUnmatched);
|
var jsonAttribute = property.GetCustomAttribute<JsonPropertyAttribute>();
|
||||||
}
|
if (jsonAttribute == null)
|
||||||
catch (System.Runtime.Serialization.SerializationException)
|
{
|
||||||
{
|
continue;
|
||||||
return _inner.GetProperty(type, container, name + "Property", ignoreUnmatched);
|
}
|
||||||
|
|
||||||
|
var yamlAttribute = new YamlMemberAttribute { Alias = jsonAttribute.PropertyName };
|
||||||
|
builder.WithAttributeOverride(type, property.Name, yamlAttribute);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IPropertyDescriptor TrimPropertySuffix(IPropertyDescriptor pd, Type type)
|
return builder;
|
||||||
{
|
|
||||||
if (!pd.Name.EndsWith("Property", StringComparison.InvariantCulture))
|
|
||||||
{
|
|
||||||
return pd;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This might have been renamed by AutoRest. See if there is a
|
|
||||||
// JsonPropertyAttribute.PropertyName and use that instead if there is.
|
|
||||||
var jpa = pd.GetCustomAttribute<JsonPropertyAttribute>();
|
|
||||||
if (jpa == null || string.IsNullOrEmpty(jpa.PropertyName))
|
|
||||||
{
|
|
||||||
return pd;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new RenamedPropertyDescriptor(pd, jpa.PropertyName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class RenamedPropertyDescriptor : IPropertyDescriptor
|
|
||||||
{
|
|
||||||
private readonly IPropertyDescriptor _inner;
|
|
||||||
private readonly string _name;
|
|
||||||
|
|
||||||
public RenamedPropertyDescriptor(IPropertyDescriptor inner, string name)
|
|
||||||
{
|
|
||||||
_inner = inner;
|
|
||||||
_name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Name => _name;
|
|
||||||
|
|
||||||
public bool CanWrite => _inner.CanWrite;
|
|
||||||
|
|
||||||
public Type Type => _inner.Type;
|
|
||||||
|
|
||||||
public Type TypeOverride
|
|
||||||
{
|
|
||||||
get => _inner.TypeOverride;
|
|
||||||
set => _inner.TypeOverride = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Order
|
|
||||||
{
|
|
||||||
get => _inner.Order;
|
|
||||||
set => _inner.Order = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ScalarStyle ScalarStyle
|
|
||||||
{
|
|
||||||
get => _inner.ScalarStyle;
|
|
||||||
set => _inner.ScalarStyle = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T GetCustomAttribute<T>()
|
|
||||||
where T : Attribute
|
|
||||||
{
|
|
||||||
return _inner.GetCustomAttribute<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IObjectDescriptor Read(object target)
|
|
||||||
{
|
|
||||||
return _inner.Read(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write(object target, object value)
|
|
||||||
{
|
|
||||||
_inner.Write(target, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -503,6 +503,19 @@ namespace k8s.Tests
|
|||||||
AssertConfigEqual(expectedCfg, cfg);
|
AssertConfigEqual(expectedCfg, cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void LoadKubeConfigWithAdditionalProperties()
|
||||||
|
{
|
||||||
|
var txt = File.ReadAllText("assets/kubeconfig.additional-properties.yml");
|
||||||
|
var expectedCfg = Yaml.LoadFromString<K8SConfiguration>(txt);
|
||||||
|
|
||||||
|
var fileInfo = new FileInfo(Path.GetFullPath("assets/kubeconfig.additional-properties.yml"));
|
||||||
|
|
||||||
|
var cfg = KubernetesClientConfiguration.LoadKubeConfig(new FileInfo[] { fileInfo, fileInfo });
|
||||||
|
|
||||||
|
AssertConfigEqual(expectedCfg, cfg);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void MergeKubeConfigNoDuplicates()
|
public void MergeKubeConfigNoDuplicates()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -35,6 +35,35 @@ metadata:
|
|||||||
Assert.Equal("ns", ((V1Namespace)objs[1]).Metadata.Name);
|
Assert.Equal("ns", ((V1Namespace)objs[1]).Metadata.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void LoadAllFromStringWithAdditionalProperties()
|
||||||
|
{
|
||||||
|
var content = @"apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
namespace: ns
|
||||||
|
youDontKnow: Me
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: ns
|
||||||
|
youDontKnow: Me";
|
||||||
|
|
||||||
|
var types = new Dictionary<string, Type>();
|
||||||
|
types.Add("v1/Pod", typeof(V1Pod));
|
||||||
|
types.Add("v1/Namespace", typeof(V1Namespace));
|
||||||
|
|
||||||
|
var objs = Yaml.LoadAllFromString(content, types);
|
||||||
|
Assert.Equal(2, objs.Count);
|
||||||
|
Assert.IsType<V1Pod>(objs[0]);
|
||||||
|
Assert.IsType<V1Namespace>(objs[1]);
|
||||||
|
Assert.Equal("foo", ((V1Pod)objs[0]).Metadata.Name);
|
||||||
|
Assert.Equal("ns", ((V1Pod)objs[0]).Metadata.NamespaceProperty);
|
||||||
|
Assert.Equal("ns", ((V1Namespace)objs[1]).Metadata.Name);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task LoadAllFromFile()
|
public async Task LoadAllFromFile()
|
||||||
{
|
{
|
||||||
@@ -87,6 +116,21 @@ metadata:
|
|||||||
Assert.Equal("foo", obj.Metadata.Name);
|
Assert.Equal("foo", obj.Metadata.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void LoadFromStringWithAdditionalProperties()
|
||||||
|
{
|
||||||
|
var content = @"apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
youDontKnow: Me
|
||||||
|
";
|
||||||
|
|
||||||
|
var obj = Yaml.LoadFromString<V1Pod>(content);
|
||||||
|
|
||||||
|
Assert.Equal("foo", obj.Metadata.Name);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void LoadNamespacedFromString()
|
public void LoadNamespacedFromString()
|
||||||
{
|
{
|
||||||
@@ -172,6 +216,18 @@ metadata:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RoundtripTypeWithMismatchedPropertyName()
|
||||||
|
{
|
||||||
|
var content = @"namespace: foo";
|
||||||
|
|
||||||
|
var deserialized = Yaml.LoadFromString<V1ObjectMeta>(content);
|
||||||
|
Assert.Equal("foo", deserialized.NamespaceProperty);
|
||||||
|
|
||||||
|
var serialized = Yaml.SaveToString(deserialized);
|
||||||
|
Assert.Equal(content, serialized);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void WriteToString()
|
public void WriteToString()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
# Sample file based on https://kubernetes.io/docs/tasks/access-application-cluster/authenticate-across-clusters-kubeconfig/
|
||||||
|
# WARNING: File includes minor fixes
|
||||||
|
---
|
||||||
|
current-context: federal-context
|
||||||
|
apiVersion: v1
|
||||||
|
additionalProperty: foobar
|
||||||
|
clusters:
|
||||||
|
- cluster:
|
||||||
|
server: http://cow.org:8080
|
||||||
|
name: cow-cluster
|
||||||
|
farm: old-mac-donalds
|
||||||
|
- cluster:
|
||||||
|
certificate-authority: assets/ca.crt
|
||||||
|
server: https://horse.org:4443
|
||||||
|
name: horse-cluster
|
||||||
|
- cluster:
|
||||||
|
insecure-skip-tls-verify: true
|
||||||
|
server: https://pig.org:443
|
||||||
|
name: pig-cluster
|
||||||
|
- cluster:
|
||||||
|
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURERENDQWZTZ0F3SUJBZ0lSQUo5ZCtLeThkTDJVSzRjdXplMmo2WnN3RFFZSktvWklodmNOQVFFTEJRQXcKTHpFdE1Dc0dBMVVFQXhNa1lXRTBZVFV3T0RZdE0yVm1aaTAwWWpCa0xUbGxORGt0WmpNeVpXWXpabUpqWWpNNApNQjRYRFRFM01ESXlOakExTURRek5Gb1hEVEl5TURJeU5UQTFNRFF6TkZvd0x6RXRNQ3NHQTFVRUF4TWtZV0UwCllUVXdPRFl0TTJWbVppMDBZakJrTFRsbE5Ea3Raak15WldZelptSmpZak00TUlJQklqQU5CZ2txaGtpRzl3MEIKQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBM2dkandhdHNsdCsvQVpqV3hmbkNQeGZqMzNHUUxlOU00VU42VmEwRQpKd0FYL2R3L1ZVa0dvVjlDc3NKRUZMdEdTUnM2K2h0RTEvOUN3ak1USDh2WExKcURHTE9KdFQ5dW9sR2c2Q2k1ClBKNDNKelVLWmJlYVE4Z3hhZndzQjdQU05vTTJOYzROVm9lZzBVTUw0bndGeEhXeTNYWHlFZ0QxTWxTUnVrb3oKTTNoRUVxUjJNVFdrNm9KK3VJNFF4WVZWMnZuWXdXaEJwUDlDR3RWUTlyUW9MVFowcmFpOCtDYURBMVltTWRhbQpRYUVPdURlSFRqU2FYM2dyR0FBVVFWNWl6MC9qVVBuK3lJNm1iV0trbzFzNytPY1dZR2F1aDFaMzFYSjJsc0RTCnU4a3F0d215UEcyUVl2aUQ4YjNOWFAyY0dRK2EwZlpRZnBrbTF0U3IxQnhhaXdJREFRQUJveU13SVRBT0JnTlYKSFE4QkFmOEVCQU1DQWdRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQQpuVzFXVXlLbVJ0TlNzU1VzVFBSUnhFRzhhek9kdjdYeUhRL0R5VWNqWm9rUEJVVHY4VjdvNG96RHgyVHV6UEdYCmZ2YlMvT2g0VDd6ZlYxdjJadmU3dTBxelNiRTl5OGpsaDNxYXJEcEd5ZmlTamwycmhIOFBmay9sZGR0VFpVL04KSkVtYW5ReGl6R20xV2pCSklRSE5LZENneVIwN3A1c0MwNnR3K25YUytla1MxMlBUTG45WjBuRDBKVDdQSzRXQgpQc3ZXeDVXN0w5dnJIdVN5SGRSTkt5eEEvbWI1WHdXMDBkZUpmaHZub0p3ZWRYNDVKZVRiME5MczUzaURqVEU1CnRpdU03Z1RVSjlCcGZTL0gvYSt2SmovVWQ2bHM0QndrWmpUNHNhOTA1bnNzdnRqamlwZ1N5a0QzVkxCQ3VueTkKd1NnbE1vSnZNWmg0bC9FVFJPeFE3Zz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
|
||||||
|
server: https://llama.org:443
|
||||||
|
name: llama-cluster
|
||||||
|
contexts:
|
||||||
|
- context:
|
||||||
|
cluster: horse-cluster
|
||||||
|
namespace: chisel-ns
|
||||||
|
user: green-user
|
||||||
|
name: federal-context
|
||||||
|
- context:
|
||||||
|
cluster: pig-cluster
|
||||||
|
namespace: saw-ns
|
||||||
|
user: black-user
|
||||||
|
name: queen-anne-context
|
||||||
|
- context:
|
||||||
|
cluster: llama-cluster
|
||||||
|
namespace: saw-ns
|
||||||
|
user: red-user
|
||||||
|
name: victorian-context
|
||||||
|
- context:
|
||||||
|
cluster: llama-cluster
|
||||||
|
namespace: saw-ns
|
||||||
|
user: elliptic-user
|
||||||
|
name: elliptic-context
|
||||||
|
kind: Config
|
||||||
|
users:
|
||||||
|
- name: blue-user
|
||||||
|
user:
|
||||||
|
token: blue-token
|
||||||
|
- name: green-user
|
||||||
|
user:
|
||||||
|
client-certificate: assets/client.crt
|
||||||
|
client-key: assets/client.key
|
||||||
|
- name: black-user
|
||||||
|
user:
|
||||||
|
token: black-token
|
||||||
|
- name: red-user
|
||||||
|
user:
|
||||||
|
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURrVENDQW5tZ0F3SUJBZ0lVTzlVTkdpbHhmSHpMbVJXcWU2dVMyRVZ1NVhVd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1FURUxNQWtHQTFVRUJoTUNWVk14RURBT0JnTlZCQWdUQjFKbFpHMXZibVF4Q3pBSkJnTlZCQWNUQWxkQgpNUk13RVFZRFZRUURFd3ByZFdKbGNtNWxkR1Z6TUNBWERURTRNVEl3T0RBNU5URXdNRm9ZRHpJeE1UZ3hNVEUwCk1EazFNVEF3V2pCQk1Rc3dDUVlEVlFRR0V3SlZVekVRTUE0R0ExVUVDQk1IVW1Wa2JXOXVaREVMTUFrR0ExVUUKQnhNQ1YwRXhFekFSQmdOVkJBTVRDbXQxWW1WeWJtVjBaWE13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQgpEd0F3Z2dFS0FvSUJBUUM4WkVRS296SE8zOExmRzRpcHFYWnRLTzNxSENjL1Z1WjUxWnZSeWJuTnpCYU5iMk9oClM0cU1nNDF6cFdzL3dMQnk4ZndPclpoOHpHb28wbHllQXVCSlBPWFc5SmswMmhOc1Y3ZHBqYXBZWFMrSXJvN04KcUxhWDB5amQxWWllSWFlb3NtV2xib2ZpcDVzS3dzVUI3bGREeXJpQklBYTEwNlhhTng5ZG82UEh1TDNibStldwpiaWRoRTlNUFRHY2V5WW9rZ3pNbGppanordk0yUnN5Z05ncmR4VDhROC9GRER2ZndTRmZUaEZlYXIzckQvRkJGCmVYb0Y5MHp6cG1aZlphTDlyZ2NjQ0pzQ2JSZlpiellVVERRVHo2dStaUVhUdGlrbVMvQ3d2d0hXa0w3bGhQNXYKQU0yVFpETEJhQXQwOU14dGlORFNWaFFTWVR2QWpKRmU4SzJoQWdNQkFBR2pmekI5TUE0R0ExVWREd0VCL3dRRQpBd0lGb0RBZEJnTlZIU1VFRmpBVUJnZ3JCZ0VGQlFjREFRWUlLd1lCQlFVSEF3SXdEQVlEVlIwVEFRSC9CQUl3CkFEQWRCZ05WSFE0RUZnUVVuQmo0T3Y3MnFlWWJ5YjVYSHJma1pkazd6VUF3SHdZRFZSMGpCQmd3Rm9BVUxwemQKRlplYkR6N0RmZUNkZkJqNmNkUWJmNk13RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQU1CL1RDaElEbTNkeDA4SApJeXlFS2dYUHh1d3A1cTB5QkFoT0pUS1JOVXNpayt6ZVUyUGpibnV0M3B1WnBENkZoTGFKQUZPbTdsMHhkNU1ZCkFZOVloSy9wa1U3Rmw1TFg0MitxQzRqK05JdGhBbFM5clNtNkRvNlN1b3JRcjdNajErY0syTjFkZHBtRWZya3kKZXZnMm02aFB5YTFlV0hNanVCd250bkJmV2EzWHBWMWVGZVBvd21zY3R6UmRJYUh3WDM3Yit3c2JmbkppczRvTgo2bHk0THBQb2xtYld3ZTRnaEtPWXNuL3lMT3FrUGJMZVpLeU5yaWJpSGhSQTM0NUVHUGJleXNmSlNIWWFqMnBaCmE0VmRTRFhnT2JlM3Vtdk9keXVEaGl5RFJ3TFozbVJLWlpIR0lzZC9ORzRncWo3a0gzV2N2Wm5mSkVHMXY2cG0KQTZFYTJiRT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
|
||||||
|
client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBdkdSRUNxTXh6dC9DM3h1SXFhbDJiU2p0Nmh3blAxYm1lZFdiMGNtNXpjd1dqVzlqCm9VdUtqSU9OYzZWclA4Q3djdkg4RHEyWWZNeHFLTkpjbmdMZ1NUemwxdlNaTk5vVGJGZTNhWTJxV0YwdmlLNk8KemFpMmw5TW8zZFdJbmlHbnFMSmxwVzZINHFlYkNzTEZBZTVYUThxNGdTQUd0ZE9sMmpjZlhhT2p4N2k5MjV2bgpzRzRuWVJQVEQweG5Ic21LSklNekpZNG84L3J6TmtiTW9EWUszY1UvRVBQeFF3NzM4RWhYMDRSWG1xOTZ3L3hRClJYbDZCZmRNODZabVgyV2kvYTRISEFpYkFtMFgyVzgyRkV3MEU4K3J2bVVGMDdZcEprdndzTDhCMXBDKzVZVCsKYndETmsyUXl3V2dMZFBUTWJZalEwbFlVRW1FN3dJeVJYdkN0b1FJREFRQUJBb0lCQUNCYk9EUjdndnA5QkFNOQp2Mk1rYitxZnRQMFlpTVVnTDhXTklvNE5qNVFCRVg2Sk94dGcxaEw4SlRkUG1mUUJMRTBSc3JEeXI5WC9aZHhOCkJRcytnemNROW9qTXllT0I4UVFTckxXOFZ4MkdJN3ZkL3pqaldUa0tVMktHWWtpR2p6MHlKck1iSU11VTdkUVQKVDdMZE5LKzRDYWhqejhNNjdxbGova2NlNitwSlRLdHZKR2tNSDRYUXJyMFRmU3hLMmEwUUNmNkZwSXp2OFFEMApISE9HbFJaWlBYK1dXYVA2UFpFU3JSZG1vbmFKaTJlRG03b1Y1WU1DMExWTHJzMVprZS9FT01CODZYOVlraGJUCmJsRkxRZjlNR1hTdWtGeW1MSnFSd01DUjJxZytKSXpEU1BuYzkzbjNwcHl4Nys3UkhFeXZNMFVNOVhyeHQrNHcKUkd3ZVZlRUNnWUVBeElkaFRCdW4rRk52YkVhSHZUdlpzNkVCa1lJUXUyV0NDR3dWN1lPbTZzc0hzczJBaldrVgprQ0pMajhZMTFpMHd0Y21yOG9DcE1EN0FDRWxMSWFEK3RubW5CTzlkQ2NnTzJoNXFCSkY1UytJeFlGcVZ5ZVBsCnptQkE2VzFvdzB2Y1hsYmkrVUg4SWF3WnNLaFlMaklscmdmQ3YwaU9LNzBYaEF3YzZ6Vlk4TjhDZ1lFQTlXYUUKMklkNjJEaGxLWVRaNW5yY3g1aVN3WU1jaitMTE5FYTFZMlZFNEhZZktvbjFkRnNSa2NKV1YyRVpoRGlqcVIyaQpXZEdEVldiMVVaVEpiM3BZWW1NakJFQXhFbEJXTSt0SzhialRqMWhxbXJPQWhLU0ZYUjg4RkNEanVkcStSbmo4CklyZFlWanNCdDA5RkVkT2RqdVFseGgyRVdQWDNPdVFhRXd5WnNYOENnWUJzekNtZ0VadHVqUG9kTGZxTlZ5blIKR0t3ZW1xdWFvcnBXNFVkT1l0aXdHTS9kTzRrVVAvMlErbnRzVDZXVU9SWkRQUzgwbytlRjd1Y3VieXpwcEEvKwpndUJraWdLdW5KTWtTendUNVZrS0dtR05YdmlYZU5QSzZWeG1IWXltdVVONDhvN2F3SjNOSWxKaWl2K3VLMUxTCndqY2M0QlRjditUWjFEN2FNNEZXYndLQmdHY1MyNE96VEJiYmdTb3lRZS83OVJYazhPZFU4YjlCN0VZVjJRUloKdWRkcDVlZFJNUWJoWlh6S21zZHk0bXZWK25BRElYa0dkbHA5dDFhLzN1ZnpCSUsyenpOdTN1MnBUcnZaL1kyUQpLMVJQTjkrb3U3ZDYvd1ZCSkZQMENKSzgzU1R1bGtEaXI3andhZVViNTQvNFNYcUdPNU4rUEdPOVZFMnBGNGFlCnlVTnpBb0dCQUptMU1vcFQ4N0llelBmQ010ck51cXVqQjFpdStvb1lIYm9IbGJXZUNxS3RSRnNYMWhXOWpTY1UKQ0ZRanhSVCtPcENVWndjbDdkY2xsTUlxQTRWQ1NmUUFRMW9CMU41WENRWE8xVFlXOHU1K1BRTUdUcFEvQlVEawp6WmRJZzZqQkFXd3R6YkNzKzRjVkFoclN3cDRBSXFvcndTZU1qRmdsTmNoNzgxMEF6emNJCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
|
||||||
|
- name: elliptic-user
|
||||||
|
user:
|
||||||
|
client-certificate: assets/client.crt
|
||||||
|
client-key: assets/elliptic-client.key
|
||||||
Reference in New Issue
Block a user