Skip to content

Commit 67be97e

Browse files
brendandburnsk8s-ci-robot
authored andcommitted
Add a loadAll to load multiple objects from a single YAML. (and tests) (#344)
1 parent 3a30033 commit 67be97e

File tree

4 files changed

+140
-1
lines changed

4 files changed

+140
-1
lines changed

examples/yaml/Program.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Threading.Tasks;
5+
using k8s;
6+
using k8s.Models;
7+
8+
namespace yaml
9+
{
10+
internal class Program
11+
{
12+
private async static Task Main(string[] args)
13+
{
14+
var typeMap = new Dictionary<String, Type>();
15+
typeMap.Add("v1/Pod", typeof(V1Pod));
16+
typeMap.Add("v1/Service", typeof(V1Service));
17+
typeMap.Add("apps/v1beta1/Deployment", typeof(Appsv1beta1Deployment));
18+
19+
var objects = await Yaml.LoadAllFromFileAsync(args[0], typeMap);
20+
21+
foreach (var obj in objects) {
22+
Console.WriteLine(obj);
23+
}
24+
}
25+
}
26+
}

examples/yaml/yaml.csproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<ItemGroup>
4+
<ProjectReference Include="..\..\src\KubernetesClient\KubernetesClient.csproj" />
5+
</ItemGroup>
6+
7+
<PropertyGroup>
8+
<OutputType>Exe</OutputType>
9+
<TargetFramework>netcoreapp2.0</TargetFramework>
10+
</PropertyGroup>
11+
12+
</Project>

src/KubernetesClient/Yaml.cs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,81 @@ namespace k8s
1818
/// </summary>
1919

2020
public class Yaml {
21+
/// <summary>
22+
/// Load a collection of objects from a stream asynchronously
23+
/// </summary>
24+
/// <param name="stream">
25+
/// The stream to load the objects from.
26+
/// </param>
27+
/// <param name="typeMap">
28+
/// A map from <apiVersion>/<kind> to Type. For example "v1/Pod" -> typeof(V1Pod)
29+
/// </param>
30+
public static async Task<List<object>> LoadAllFromStreamAsync(Stream stream, Dictionary<String, Type> typeMap) {
31+
var reader = new StreamReader(stream);
32+
var content = await reader.ReadToEndAsync();
33+
return LoadAllFromString(content, typeMap);
34+
}
35+
36+
/// <summary>
37+
/// Load a collection of objects from a file asynchronously
38+
/// </summary>
39+
/// <param name="fileName">
40+
/// The name of the file to load from.
41+
/// </param>
42+
/// <param name="typeMap">
43+
/// A map from <apiVersion>/<kind> to Type. For example "v1/Pod" -> typeof(V1Pod)
44+
/// </param>
45+
46+
public static Task<List<object>> LoadAllFromFileAsync(String fileName, Dictionary<String, Type> typeMap)
47+
{
48+
var reader = File.Open(fileName, FileMode.Open);
49+
return LoadAllFromStreamAsync(reader, typeMap);
50+
}
51+
52+
/// <summary>
53+
/// Load a collection of objects from a string
54+
/// </summary>
55+
/// <param name="content">
56+
/// The string to load the objects from.
57+
/// </param>
58+
/// <param name="typeMap">
59+
/// A map from <apiVersion>/<kind> to Type. For example "v1/Pod" -> typeof(V1Pod)
60+
/// </param>
61+
62+
public static List<object> LoadAllFromString(String content, Dictionary<String, Type> typeMap) {
63+
var deserializer =
64+
new DeserializerBuilder()
65+
.WithNamingConvention(new CamelCaseNamingConvention())
66+
.WithTypeInspector(ti => new AutoRestTypeInspector(ti))
67+
.WithTypeConverter(new IntOrStringYamlConverter())
68+
.IgnoreUnmatchedProperties()
69+
.Build();
70+
var types = new List<Type>();
71+
var parser = new Parser(new StringReader(content));
72+
parser.Expect<StreamStart>();
73+
while (parser.Accept<DocumentStart>()) {
74+
var obj = deserializer.Deserialize<KubernetesObject>(parser);
75+
types.Add(typeMap[obj.ApiVersion + "/" + obj.Kind]);
76+
}
77+
78+
deserializer =
79+
new DeserializerBuilder()
80+
.WithNamingConvention(new CamelCaseNamingConvention())
81+
.WithTypeInspector(ti => new AutoRestTypeInspector(ti))
82+
.WithTypeConverter(new IntOrStringYamlConverter())
83+
.Build();
84+
parser = new Parser(new StringReader(content));
85+
parser.Expect<StreamStart>();
86+
var ix = 0;
87+
var results = new List<object>();
88+
while (parser.Accept<DocumentStart>()) {
89+
var objType = types[ix++];
90+
var obj = deserializer.Deserialize(parser, objType);
91+
results.Add(obj);
92+
}
93+
return results;
94+
}
95+
2196
public static async Task<T> LoadFromStreamAsync<T>(Stream stream) {
2297
var reader = new StreamReader(stream);
2398
var content = await reader.ReadToEndAsync();

tests/KubernetesClient.Tests/YamlTests.cs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,39 @@
22
using System.Collections.Generic;
33
using System.IO;
44
using System.Linq;
5+
using k8s;
56
using k8s.Models;
67
using Xunit;
78

89
namespace k8s.Tests
910
{
1011
public class YamlTests
1112
{
13+
[Fact]
14+
public void LoadAllFromString()
15+
{
16+
var content = @"apiVersion: v1
17+
kind: Pod
18+
metadata:
19+
name: foo
20+
---
21+
apiVersion: v1
22+
kind: Namespace
23+
metadata:
24+
name: ns";
25+
26+
var types = new Dictionary<String, Type>();
27+
types.Add("v1/Pod", typeof(V1Pod));
28+
types.Add("v1/Namespace", typeof(V1Namespace));
29+
30+
var objs = Yaml.LoadAllFromString(content, types);
31+
Assert.Equal(objs.Count, 2);
32+
Assert.IsType<V1Pod>(objs[0]);
33+
Assert.IsType<V1Namespace>(objs[1]);
34+
Assert.Equal(((V1Pod) objs[0]).Metadata.Name, "foo");
35+
Assert.Equal(((V1Namespace) objs[1]).Metadata.Name, "ns");
36+
}
37+
1238
[Fact]
1339
public void LoadFromString()
1440
{
@@ -292,7 +318,7 @@ public void SerializeIntOrString()
292318
};
293319

294320
var output = Yaml.SaveToString<V1Service>(obj);
295-
Assert.True(ToLines(output).SequenceEqual(ToLines(content)));
321+
Assert.True(ToLines(output).SequenceEqual(ToLines(content)));
296322
}
297323
}
298324
}

0 commit comments

Comments
 (0)