Add in formatting pre-check. (#431)

This commit is contained in:
Brendan Burns
2020-04-22 12:15:45 -07:00
committed by GitHub
parent 56b7f76d6c
commit c1de779933
32 changed files with 125 additions and 81 deletions

View File

@@ -34,6 +34,12 @@ jobs:
if: matrix.os != 'windows-latest'
run: |
rsync --archive --ignore-existing ${DOTNET_ROOT/3.1.201/2.1.805}/ ${DOTNET_ROOT/3.1.201/2.1.202}/ $DOTNET_ROOT
- name: Setup Format
run: dotnet tool install -g dotnet-format
- name: Check Format
# don't check formatting on Windows b/c of CRLF issues.
if: matrix.os != 'windows-latest'
run: dotnet format --check --dry-run --exclude ./src/KubernetesClient/generated/
- name: Build
run: dotnet build --configuration Release
- name: Test

View File

@@ -21,7 +21,8 @@ namespace attach
await AttachToPod(client, pod);
}
private async static Task AttachToPod(IKubernetes client, V1Pod pod) {
private async static Task AttachToPod(IKubernetes client, V1Pod pod)
{
var webSocket = await client.WebSocketNamespacedPodAttachAsync(pod.Metadata.Name, "default", pod.Spec.Containers[0].Name);
var demux = new StreamDemuxer(webSocket);

View File

@@ -18,7 +18,8 @@ namespace exec
await ExecInPod(client, pod);
}
private async static Task ExecInPod(IKubernetes client, V1Pod pod) {
private async static Task ExecInPod(IKubernetes client, V1Pod pod)
{
var webSocket = await client.WebSocketNamespacedPodExecAsync(pod.Metadata.Name, "default", "ls", pod.Spec.Containers[0].Name);
var demux = new StreamDemuxer(webSocket);

View File

@@ -14,7 +14,8 @@ namespace logs
Console.WriteLine("Starting Request!");
var list = client.ListNamespacedPod("default");
if (list.Items.Count == 0) {
if (list.Items.Count == 0)
{
Console.WriteLine("No pods!");
return;
}

View File

@@ -8,34 +8,47 @@ namespace @namespace
{
class NamespaceExample
{
static void ListNamespaces(IKubernetes client) {
static void ListNamespaces(IKubernetes client)
{
var list = client.ListNamespace();
foreach (var item in list.Items) {
foreach (var item in list.Items)
{
Console.WriteLine(item.Metadata.Name);
}
if (list.Items.Count == 0) {
if (list.Items.Count == 0)
{
Console.WriteLine("Empty!");
}
}
static async Task DeleteAsync(IKubernetes client, string name, int delayMillis) {
while (true) {
static async Task DeleteAsync(IKubernetes client, string name, int delayMillis)
{
while (true)
{
await Task.Delay(delayMillis);
try
{
await client.ReadNamespaceAsync(name);
} catch (AggregateException ex) {
foreach (var innerEx in ex.InnerExceptions) {
if (innerEx is Microsoft.Rest.HttpOperationException) {
}
catch (AggregateException ex)
{
foreach (var innerEx in ex.InnerExceptions)
{
if (innerEx is Microsoft.Rest.HttpOperationException)
{
var code = ((Microsoft.Rest.HttpOperationException)innerEx).Response.StatusCode;
if (code == HttpStatusCode.NotFound) {
if (code == HttpStatusCode.NotFound)
{
return;
}
throw ex;
}
}
} catch (Microsoft.Rest.HttpOperationException ex) {
if (ex.Response.StatusCode == HttpStatusCode.NotFound) {
}
catch (Microsoft.Rest.HttpOperationException ex)
{
if (ex.Response.StatusCode == HttpStatusCode.NotFound)
{
return;
}
throw ex;
@@ -43,7 +56,8 @@ namespace @namespace
}
}
static void Delete(IKubernetes client, string name, int delayMillis) {
static void Delete(IKubernetes client, string name, int delayMillis)
{
DeleteAsync(client, name, delayMillis).Wait();
}

View File

@@ -51,9 +51,9 @@ namespace KubernetesWatchGenerator
_schemaDefinitionsInMultipleGroups = _schemaToNameMap.Values.Select(x =>
{
var parts = x.Split(".");
return new {FullName = x, Name = parts[parts.Length - 1], Version = parts[parts.Length - 2], Group = parts[parts.Length - 3]};
return new { FullName = x, Name = parts[parts.Length - 1], Version = parts[parts.Length - 2], Group = parts[parts.Length - 3] };
})
.GroupBy(x => new {x.Name, x.Version})
.GroupBy(x => new { x.Name, x.Version })
.Where(x => x.Count() > 1)
.SelectMany(x => x)
.Select(x => x.FullName)
@@ -61,7 +61,7 @@ namespace KubernetesWatchGenerator
_classNameToPluralMap = swagger.Operations
.Where(x => x.Operation.OperationId.StartsWith("list"))
.Select(x => { return new {PluralName = x.Path.Split("/").Last(), ClassName = GetClassNameForSchemaDefinition(x.Operation.Responses["200"].ActualResponseSchema)}; })
.Select(x => { return new { PluralName = x.Path.Split("/").Last(), ClassName = GetClassNameForSchemaDefinition(x.Operation.Responses["200"].ActualResponseSchema) }; })
.Distinct()
.ToDictionary(x => x.ClassName, x => x.PluralName);
@@ -69,7 +69,7 @@ namespace KubernetesWatchGenerator
_classNameToPluralMap = _classNameToPluralMap
.Where(x => x.Key.EndsWith("List"))
.Select(x =>
new {ClassName = x.Key.Remove(x.Key.Length - 4), PluralName = x.Value})
new { ClassName = x.Key.Remove(x.Key.Length - 4), PluralName = x.Value })
.ToDictionary(x => x.ClassName, x => x.PluralName)
.Union(_classNameToPluralMap)
.ToDictionary(x => x.Key, x => x.Value);
@@ -119,7 +119,7 @@ namespace KubernetesWatchGenerator
var modelsDir = Path.Combine(outputDirectory, "Models");
_classesWithValidation = Directory.EnumerateFiles(modelsDir)
.Select(x => new {Class = Path.GetFileNameWithoutExtension(x), Content = File.ReadAllText(x)})
.Select(x => new { Class = Path.GetFileNameWithoutExtension(x), Content = File.ReadAllText(x) })
.Where(x => x.Content.Contains("public virtual void Validate()"))
.Select(x => x.Class)
.ToHashSet();
@@ -244,7 +244,7 @@ namespace KubernetesWatchGenerator
interfaces.Add($"ISpec<{GetClassNameForSchemaDefinition(specProperty.Reference)}>");
}
if(_classesWithValidation.Contains(className))
if (_classesWithValidation.Contains(className))
interfaces.Add("IValidate");
var result = string.Join(", ", interfaces);
return result;
@@ -272,7 +272,7 @@ namespace KubernetesWatchGenerator
if (arguments != null && arguments.Count > 0 && arguments[0] != null && arguments[0] is JsonSchema4)
{
var plural = GetPlural(arguments[0] as JsonSchema4);
if(plural != null)
if (plural != null)
context.Write($"\"{plural}\"");
else
context.Write("null");

View File

@@ -21,7 +21,7 @@ namespace k8s
/// <returns>List of x509 instances.</returns>
public static X509Certificate2Collection LoadPemFileCert(string file)
{
var certs = new X509CertificateParser().ReadCertificates(File.OpenRead(file));
var certs = new X509CertificateParser().ReadCertificates(File.OpenRead(file));
var certCollection = new X509Certificate2Collection();
// Convert BouncyCastle X509Certificates to the .NET cryptography implementation and add
@@ -76,7 +76,8 @@ namespace k8s
var cert = new X509CertificateParser().ReadCertificate(new MemoryStream(certData));
// key usage is a bit string, zero-th bit is 'digitalSignature'
// See https://www.alvestrand.no/objectid/2.5.29.15.html for more details.
if (cert != null && cert.GetKeyUsage() != null && !cert.GetKeyUsage()[0]) {
if (cert != null && cert.GetKeyUsage() != null && !cert.GetKeyUsage()[0])
{
throw new Exception(
"Client certificates must be marked for digital signing. " +
"See https://github.com/kubernetes-client/csharp/issues/319");
@@ -93,10 +94,10 @@ namespace k8s
}
}
var keyParams = (AsymmetricKeyParameter) obj;
var keyParams = (AsymmetricKeyParameter)obj;
var store = new Pkcs12StoreBuilder().Build();
store.SetKeyEntry("K8SKEY", new AsymmetricKeyEntry(keyParams), new[] {new X509CertificateEntry(cert)});
store.SetKeyEntry("K8SKEY", new AsymmetricKeyEntry(keyParams), new[] { new X509CertificateEntry(cert) });
using (var pkcs = new MemoryStream())
{

View File

@@ -14,4 +14,4 @@ namespace k8s
/// </summary>
IList<T> Items { get; set; }
}
}
}

View File

@@ -15,4 +15,4 @@ namespace k8s
/// </summary>
T Metadata { get; set; }
}
}
}

View File

@@ -14,4 +14,4 @@ namespace k8s
/// </summary>
T Spec { get; set; }
}
}
}

View File

@@ -14,4 +14,4 @@ namespace k8s
/// </summary>
T Status { get; set; }
}
}
}

View File

@@ -11,4 +11,4 @@ namespace k8s
void Validate();
}
}
}

View File

@@ -7,7 +7,7 @@ using YamlDotNet.Serialization;
namespace k8s.Models
{
public class IntOrStringYamlConverter: IYamlTypeConverter
public class IntOrStringYamlConverter : IYamlTypeConverter
{
public bool Accepts(Type type)
{
@@ -18,13 +18,16 @@ namespace k8s.Models
{
if (parser.Current is YamlDotNet.Core.Events.Scalar scalar)
{
try {
try
{
if (string.IsNullOrEmpty(scalar.Value))
{
return null;
}
return new IntstrIntOrString(scalar.Value);
} finally {
}
finally
{
parser.MoveNext();
}
}
@@ -33,7 +36,7 @@ namespace k8s.Models
public void WriteYaml(IEmitter emitter, object value, Type type)
{
var obj = (IntstrIntOrString) value;
var obj = (IntstrIntOrString)value;
emitter.Emit(new YamlDotNet.Core.Events.Scalar(obj.Value));
}
}
@@ -56,7 +59,7 @@ namespace k8s.Models
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
return (IntstrIntOrString) serializer.Deserialize<string>(reader);
return (IntstrIntOrString)serializer.Deserialize<string>(reader);
}
public override bool CanConvert(Type objectType)
@@ -98,7 +101,7 @@ namespace k8s.Models
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((IntstrIntOrString) obj);
return Equals((IntstrIntOrString)obj);
}
public override int GetHashCode()

View File

@@ -7,7 +7,8 @@ namespace k8s.KubeConfigModels
/// <summary>
/// Contains information that describes identity information. This is use to tell the kubernetes cluster who you are.
/// </summary>
public class AuthProvider {
public class AuthProvider
{
/// <summary>
/// Gets or sets the nickname for this auth provider.
/// </summary>

View File

@@ -12,7 +12,7 @@ namespace k8s.KubeConfigModels
/// Gets or sets the path to a cert file for the certificate authority.
/// </summary>
[YamlMember(Alias = "certificate-authority", ApplyNamingConventions = false)]
public string CertificateAuthority {get; set; }
public string CertificateAuthority { get; set; }
/// <summary>
/// Gets or sets =PEM-encoded certificate authority certificates. Overrides <see cref="CertificateAuthority"/>.

View File

@@ -16,7 +16,7 @@ namespace k8s.KubeConfigModels
/// Gets or sets general information to be use for CLI interactions
/// </summary>
[YamlMember(Alias = "preferences")]
public IDictionary<string, object> Preferences{ get; set; }
public IDictionary<string, object> Preferences { get; set; }
[YamlMember(Alias = "apiVersion")]
public string ApiVersion { get; set; }

View File

@@ -43,7 +43,7 @@ namespace k8s
ValidateConfig(config);
CaCerts = config.SslCaCerts;
SkipTlsVerify = config.SkipTlsVerify;
SetCredentials(config);
SetCredentials(config);
}
/// <summary>

View File

@@ -24,7 +24,7 @@ namespace k8s
{
using (var muxedStream = await this.MuxedStreamNamespacedPodExecAsync(name: name, @namespace: @namespace, command: command, container: container, tty: tty, cancellationToken: cancellationToken).ConfigureAwait(false))
using (Stream stdIn = muxedStream.GetStream(null, ChannelIndex.StdIn))
using (Stream stdOut= muxedStream.GetStream(ChannelIndex.StdOut, null))
using (Stream stdOut = muxedStream.GetStream(ChannelIndex.StdOut, null))
using (Stream stdErr = muxedStream.GetStream(ChannelIndex.StdErr, null))
using (Stream error = muxedStream.GetStream(ChannelIndex.Error, null))
using (StreamReader errorReader = new StreamReader(error))

View File

@@ -47,7 +47,7 @@ namespace k8s
// Don't sent watch, because setting that value will cause the WatcherDelegatingHandler to kick in. That class
// "eats" the first line, which is something we don't want.
// query = QueryHelpers.AddQueryString(query, "watch", "true");
if(@continue != null)
if (@continue != null)
{
Utilities.AddQueryParameter(query, "continue", @continue);
}
@@ -87,7 +87,7 @@ namespace k8s
Utilities.AddQueryParameter(query, "resourceVersion", resourceVersion);
}
uriBuilder.Query = query.Length == 0 ? "" : query.ToString(1, query.Length-1); // UriBuilder.Query doesn't like leading '?' chars, so trim it
uriBuilder.Query = query.Length == 0 ? "" : query.ToString(1, query.Length - 1); // UriBuilder.Query doesn't like leading '?' chars, so trim it
// Create HTTP transport objects
var httpRequest = new HttpRequestMessage(HttpMethod.Get, uriBuilder.ToString());
@@ -147,7 +147,8 @@ namespace k8s
throw ex;
}
return new Watcher<T>(async () => {
return new Watcher<T>(async () =>
{
var stream = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
StreamReader reader = new StreamReader(stream);

View File

@@ -119,7 +119,7 @@ namespace k8s
query.Append("&stdin=").Append(stdin ? '1' : '0');
query.Append("&stdout=").Append(stdout ? '1' : '0');
query.Append("&tty=").Append(tty ? '1' : '0');
uriBuilder.Query = query.ToString(1, query.Length-1); // UriBuilder.Query doesn't like leading '?' chars, so trim it
uriBuilder.Query = query.ToString(1, query.Length - 1); // UriBuilder.Query doesn't like leading '?' chars, so trim it
return this.StreamConnectAsync(uriBuilder.Uri, _invocationId, webSocketSubProtol, customHeaders, cancellationToken);
}
@@ -228,7 +228,7 @@ namespace k8s
query.Append("&stdout=").Append(stdout ? '1' : '0');
query.Append("&tty=").Append(tty ? '1' : '0');
Utilities.AddQueryParameter(query, "container", container);
uriBuilder.Query = query.ToString(1, query.Length-1); // UriBuilder.Query doesn't like leading '?' chars, so trim it
uriBuilder.Query = query.ToString(1, query.Length - 1); // UriBuilder.Query doesn't like leading '?' chars, so trim it
return StreamConnectAsync(uriBuilder.Uri, _invocationId, webSocketSubProtol, customHeaders, cancellationToken);
}

View File

@@ -427,7 +427,7 @@ namespace k8s
process.StartInfo.Environment.Add("KUBERNETES_EXEC_INFO",
JsonConvert.SerializeObject(execInfo));
if (config.EnvironmentVariables != null)
foreach (var configEnvironmentVariableKey in config.EnvironmentVariables.Keys)
process.StartInfo.Environment.Add(key: configEnvironmentVariableKey,
@@ -474,7 +474,7 @@ namespace k8s
throw new KubeConfigException($"external exec failed due to uncaught exception: {ex}");
}
}
#endif

View File

@@ -3,16 +3,18 @@ using System.Net.Http;
namespace k8s
{
public partial class KubernetesClientConfiguration {
public HttpClientHandler CreateDefaultHttpClientHandler() {
public partial class KubernetesClientConfiguration
{
public HttpClientHandler CreateDefaultHttpClientHandler()
{
var httpClientHandler = new HttpClientHandler();
#if !NET452
var uriScheme = new Uri(this.Host).Scheme;
if(uriScheme == "https")
if (uriScheme == "https")
{
if(this.SkipTlsVerify)
if (this.SkipTlsVerify)
{
httpClientHandler.ServerCertificateCustomValidationCallback =
(sender, certificate, chain, sslPolicyErrors) => true;
@@ -32,7 +34,8 @@ namespace k8s
return httpClientHandler;
}
public void AddCertificates(HttpClientHandler handler) {
public void AddCertificates(HttpClientHandler handler)
{
if ((!string.IsNullOrWhiteSpace(this.ClientCertificateData) ||
!string.IsNullOrWhiteSpace(this.ClientCertificateFilePath)) &&
(!string.IsNullOrWhiteSpace(this.ClientCertificateKeyData) ||

View File

@@ -32,7 +32,8 @@ namespace k8s
public static KubernetesClientConfiguration InClusterConfig()
{
if (!IsInCluster()) {
if (!IsInCluster())
{
throw new KubeConfigException(
"unable to load in-cluster configuration, KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined");
}

View File

@@ -138,14 +138,14 @@ namespace k8s.Models
{
return false;
}
return Equals((ResourceQuantity) obj);
return Equals((ResourceQuantity)obj);
}
public override int GetHashCode()
{
unchecked
{
return ((int) Format * 397) ^ _unitlessValue.GetHashCode();
return ((int)Format * 397) ^ _unitlessValue.GetHashCode();
}
}
@@ -336,7 +336,7 @@ namespace k8s.Models
var minE = -9;
var lastv = Roundup(value * Fraction.Pow(10, -minE));
for (var exp = minE;; exp += 3)
for (var exp = minE; ; exp += 3)
{
var v = value * Fraction.Pow(10, -exp);
if (HasMantissa(v))
@@ -351,10 +351,10 @@ namespace k8s.Models
if (minE == 0)
{
return $"{(decimal) lastv}";
return $"{(decimal)lastv}";
}
return $"{(decimal) lastv}e{minE}";
return $"{(decimal)lastv}e{minE}";
}
case SuffixFormat.BinarySI:
@@ -384,7 +384,7 @@ namespace k8s.Models
lastv = v;
}
return $"{(decimal) lastv}{suffix}";
return $"{(decimal)lastv}{suffix}";
}
private static Fraction Roundup(Fraction lastv)

View File

@@ -37,7 +37,7 @@ namespace k8s.Models
public PathType Type { get; private set; }
public V1Patch(IJsonPatchDocument jsonPatch) : this((object) jsonPatch)
public V1Patch(IJsonPatchDocument jsonPatch) : this((object)jsonPatch)
{
}

View File

@@ -194,7 +194,8 @@ namespace k8s
Action<Exception> onError = null,
Action onClosed = null)
{
return new Watcher<T>(async () => {
return new Watcher<T>(async () =>
{
var response = await responseTask.ConfigureAwait(false);
if (!(response.Response.Content is WatcherDelegatingHandler.LineSeparatedHttpContent content))
@@ -203,7 +204,7 @@ namespace k8s
}
return content.StreamReader;
} , onEvent, onError, onClosed);
}, onEvent, onError, onClosed);
}
/// <summary>

View File

@@ -24,7 +24,7 @@ namespace k8s
{
string query = request.RequestUri.Query;
int index = query.IndexOf("watch=true");
if (index > 0 && (query[index-1] == '&' || query[index-1] == '?'))
if (index > 0 && (query[index - 1] == '&' || query[index - 1] == '?'))
{
originResponse.Content = new LineSeparatedHttpContent(originResponse.Content, cancellationToken);
}

View File

@@ -17,7 +17,8 @@ namespace k8s
/// This is a utility class that helps you load objects from YAML files.
/// </summary>
public class Yaml {
public class Yaml
{
/// <summary>
/// Load a collection of objects from a stream asynchronously
/// </summary>
@@ -27,7 +28,8 @@ namespace k8s
/// <param name="typeMap">
/// A map from <apiVersion>/<kind> to Type. For example "v1/Pod" -> typeof(V1Pod)
/// </param>
public static async Task<List<object>> LoadAllFromStreamAsync(Stream stream, Dictionary<String, Type> typeMap) {
public static async Task<List<object>> LoadAllFromStreamAsync(Stream stream, Dictionary<String, Type> typeMap)
{
var reader = new StreamReader(stream);
var content = await reader.ReadToEndAsync().ConfigureAwait(false);
return LoadAllFromString(content, typeMap);
@@ -59,7 +61,8 @@ namespace k8s
/// A map from <apiVersion>/<kind> to Type. For example "v1/Pod" -> typeof(V1Pod)
/// </param>
public static List<object> LoadAllFromString(String content, Dictionary<String, Type> typeMap) {
public static List<object> LoadAllFromString(String content, Dictionary<String, Type> typeMap)
{
var deserializer =
new DeserializerBuilder()
.WithNamingConvention(new CamelCaseNamingConvention())
@@ -70,7 +73,8 @@ namespace k8s
var types = new List<Type>();
var parser = new Parser(new StringReader(content));
parser.Expect<StreamStart>();
while (parser.Accept<DocumentStart>()) {
while (parser.Accept<DocumentStart>())
{
var obj = deserializer.Deserialize<KubernetesObject>(parser);
types.Add(typeMap[obj.ApiVersion + "/" + obj.Kind]);
}
@@ -85,7 +89,8 @@ namespace k8s
parser.Expect<StreamStart>();
var ix = 0;
var results = new List<object>();
while (parser.Accept<DocumentStart>()) {
while (parser.Accept<DocumentStart>())
{
var objType = types[ix++];
var obj = deserializer.Deserialize(parser, objType);
results.Add(obj);
@@ -93,19 +98,23 @@ namespace k8s
return results;
}
public static async Task<T> LoadFromStreamAsync<T>(Stream stream) {
public static async Task<T> LoadFromStreamAsync<T>(Stream stream)
{
var reader = new StreamReader(stream);
var content = await reader.ReadToEndAsync().ConfigureAwait(false);
return LoadFromString<T>(content);
}
public static async Task<T> LoadFromFileAsync<T> (string file) {
using (FileStream fs = File.OpenRead(file)) {
public static async Task<T> LoadFromFileAsync<T>(string file)
{
using (FileStream fs = File.OpenRead(file))
{
return await LoadFromStreamAsync<T>(fs).ConfigureAwait(false);
}
}
public static T LoadFromString<T>(string content) {
public static T LoadFromString<T>(string content)
{
var deserializer =
new DeserializerBuilder()
.WithNamingConvention(new CamelCaseNamingConvention())

View File

@@ -173,7 +173,8 @@ namespace k8s.Tests
[Fact]
public void Cert()
{
if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
// TODO: This test fails on OS X for some reason. Figure out why...
return;
}
@@ -442,7 +443,7 @@ namespace k8s.Tests
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
arguments = ($"/c echo {responseJson}").Split(" ");
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
arguments = new[] {responseJson};
arguments = new[] { responseJson };
var users = new List<User>
@@ -461,7 +462,7 @@ namespace k8s.Tests
}
}
};
var kubernetesConfig = new K8SConfiguration {Clusters = clusters, Users = users, Contexts = contexts};
var kubernetesConfig = new K8SConfiguration { Clusters = clusters, Users = users, Contexts = contexts };
return kubernetesConfig;
}
}

View File

@@ -7,7 +7,7 @@ namespace k8s.Tests
{
static class TaskAssert
{
public static void NotCompleted(Task task,string message = "Task should not be completed")
public static void NotCompleted(Task task, string message = "Task should not be completed")
{
Assert.False(task.IsCompleted, message);
}

View File

@@ -73,4 +73,4 @@ namespace k8s.Tests
}
}
}
}

View File

@@ -31,8 +31,8 @@ metadata:
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", ((V1Namespace) objs[1]).Metadata.Name);
Assert.Equal("foo", ((V1Pod)objs[0]).Metadata.Name);
Assert.Equal("ns", ((V1Namespace)objs[1]).Metadata.Name);
}
[Fact]