Style fix1 (#512)

* fix SA1505 and SA1508

* fix SA1116

* fix SA1009

* fix SA1019

* fix SA1127

* fix SA1128

* fix SA1134

* fix indent

* allow CA2227

* fix CA1810

* using clean up

* fix naming

* fix CA1806

* fix await

* Revert "fix CA1806"

This reverts commit a3b465087fdaf26ec461272373ee9810a90de2cc.

* fix dotnet format

* allow SA1009
This commit is contained in:
Boshi Lian
2020-11-01 12:24:51 -08:00
committed by GitHub
parent 82c8ae059f
commit 16845bae1d
55 changed files with 212 additions and 179 deletions

View File

@@ -1,5 +1,4 @@
using System; using System;
using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using k8s; using k8s;
@@ -22,7 +21,8 @@ namespace logs
var pod = list.Items[0]; var pod = list.Items[0];
var response = await client.ReadNamespacedPodLogWithHttpMessagesAsync(pod.Metadata.Name, var response = await client.ReadNamespacedPodLogWithHttpMessagesAsync(
pod.Metadata.Name,
pod.Metadata.NamespaceProperty, follow: true).ConfigureAwait(false); pod.Metadata.NamespaceProperty, follow: true).ConfigureAwait(false);
var stream = response.Body; var stream = response.Body;
stream.CopyTo(Console.OpenStandardOutput()); stream.CopyTo(Console.OpenStandardOutput());

View File

@@ -106,7 +106,7 @@
<Rule Id="SA1314" Action="None" /> <Rule Id="SA1314" Action="None" />
<!-- A C# using directive is placed outside of a namespace element. https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1200.md --> <!-- A C# using directive is placed outside of a namespace element. https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1200.md -->
<Rule Id="SA1200" Action="Warning" /> <Rule Id="SA1200" Action="Error" />
<!-- An element within a C# code file is out of order in relation to the other elements in the code. https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1201.md --> <!-- An element within a C# code file is out of order in relation to the other elements in the code. https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1201.md -->
<Rule Id="SA1201" Action="None" /> <Rule Id="SA1201" Action="None" />
@@ -175,7 +175,7 @@
<Rule Id="SA1001" Action="Warning" /> <Rule Id="SA1001" Action="Warning" />
<!-- A closing parenthesis within a C# statement is not spaced correctly. https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1009.md --> <!-- A closing parenthesis within a C# statement is not spaced correctly. https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1009.md -->
<Rule Id="SA1009" Action="Warning" /> <Rule Id="SA1009" Action="None" />
<!-- An opening brace within a C# element is not spaced correctly. https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1012.md --> <!-- An opening brace within a C# element is not spaced correctly. https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1012.md -->
<Rule Id="SA1012" Action="Warning" /> <Rule Id="SA1012" Action="Warning" />
@@ -205,10 +205,10 @@
<Rule Id="CA2225" Action="None" /> <Rule Id="CA2225" Action="None" />
<!-- Collection properties should be read only https://docs.microsoft.com/en-us/visualstudio/code-quality/CA2227 --> <!-- Collection properties should be read only https://docs.microsoft.com/en-us/visualstudio/code-quality/CA2227 -->
<Rule Id="CA2227" Action="Warning" /> <Rule Id="CA2227" Action="None" />
<!-- Mark ISerializable types with SerializableAttribute https://docs.microsoft.com/en-us/visualstudio/code-quality/CA2237 --> <!-- Mark ISerializable types with SerializableAttribute https://docs.microsoft.com/en-us/visualstudio/code-quality/CA2237 -->
<Rule Id="CA2237" Action="Warning" /> <Rule Id="CA2237" Action="None" />
<!-- Do Not Disable Certificate Validation https://docs.microsoft.com/en-us/visualstudio/code-quality/CA5359 --> <!-- Do Not Disable Certificate Validation https://docs.microsoft.com/en-us/visualstudio/code-quality/CA5359 -->
<Rule Id="CA5359" Action="None" /> <Rule Id="CA5359" Action="None" />

View File

@@ -18,7 +18,7 @@ namespace k8s.Authentication
TokenFile = tokenFile; TokenFile = tokenFile;
} }
public async Task<AuthenticationHeaderValue> GetAuthenticationHeaderAsync(CancellationToken cancellationToken) public Task<AuthenticationHeaderValue> GetAuthenticationHeaderAsync(CancellationToken cancellationToken)
{ {
if (TokenExpiresAt < DateTime.UtcNow) if (TokenExpiresAt < DateTime.UtcNow)
{ {
@@ -32,7 +32,7 @@ namespace k8s.Authentication
TokenExpiresAt = DateTime.UtcNow.AddMinutes(1); TokenExpiresAt = DateTime.UtcNow.AddMinutes(1);
} }
return new AuthenticationHeaderValue("Bearer", token); return Task.FromResult(new AuthenticationHeaderValue("Bearer", token));
} }
} }
} }

View File

@@ -282,7 +282,8 @@ namespace k8s
Array.Copy(this.buffer, 0, newBuffer, 0, this.WriteWaterMark); Array.Copy(this.buffer, 0, newBuffer, 0, this.WriteWaterMark);
int trailingDataLength = this.buffer.Length - this.ReadWaterMark; int trailingDataLength = this.buffer.Length - this.ReadWaterMark;
Array.Copy(this.buffer, Array.Copy(
this.buffer,
sourceIndex: this.ReadWaterMark, sourceIndex: this.ReadWaterMark,
destinationArray: newBuffer, destinationArray: newBuffer,
destinationIndex: newBuffer.Length - trailingDataLength, destinationIndex: newBuffer.Length - trailingDataLength,

View File

@@ -5,10 +5,8 @@ using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security; using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509; using Org.BouncyCastle.X509;
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using System.Text.RegularExpressions;
namespace k8s namespace k8s
{ {

View File

@@ -1,7 +1,7 @@
using System;
namespace k8s.Exceptions namespace k8s.Exceptions
{ {
using System;
/// <summary> /// <summary>
/// The exception that is thrown when the kube config is invalid /// The exception that is thrown when the kube config is invalid
/// </summary> /// </summary>

View File

@@ -1,7 +1,7 @@
using System;
namespace k8s.Exceptions namespace k8s.Exceptions
{ {
using System;
/// <summary> /// <summary>
/// The exception that is thrown when there is a client exception /// The exception that is thrown when there is a client exception
/// </summary> /// </summary>

View File

@@ -1,22 +1,15 @@
using System; using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection; using System.Reflection;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks;
using k8s.Models; using k8s.Models;
using Microsoft.Rest;
using Microsoft.Rest.TransientFaultHandling;
using Newtonsoft.Json.Converters;
using VersionConverter = k8s.Versioning.VersionConverter;
namespace k8s namespace k8s
{ {
public static class Extensions public static class Extensions
{ {
public static KubernetesEntityAttribute GetKubernetesTypeMetadata<T>(this T obj) where T : IKubernetesObject => public static KubernetesEntityAttribute GetKubernetesTypeMetadata<T>(this T obj)
where T : IKubernetesObject
=>
obj.GetType().GetKubernetesTypeMetadata(); obj.GetType().GetKubernetesTypeMetadata();
public static KubernetesEntityAttribute GetKubernetesTypeMetadata(this Type currentType) public static KubernetesEntityAttribute GetKubernetesTypeMetadata(this Type currentType)
{ {
@@ -29,7 +22,8 @@ namespace k8s
return attr; return attr;
} }
public static T Initialize<T>(this T obj) where T : IKubernetesObject public static T Initialize<T>(this T obj)
where T : IKubernetesObject
{ {
var metadata = obj.GetKubernetesTypeMetadata(); var metadata = obj.GetKubernetesTypeMetadata();
obj.ApiVersion = !string.IsNullOrEmpty(metadata.Group) ? $"{metadata.Group}/{metadata.ApiVersion}" : metadata.ApiVersion; obj.ApiVersion = !string.IsNullOrEmpty(metadata.Group) ? $"{metadata.Group}/{metadata.ApiVersion}" : metadata.ApiVersion;

View File

@@ -1,7 +1,5 @@
using System; using System;
using Newtonsoft.Json; using Newtonsoft.Json;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.Tokens;
namespace k8s.Models namespace k8s.Models
{ {

View File

@@ -1,9 +1,8 @@
using System.Collections.Generic;
using YamlDotNet.Serialization;
namespace k8s.KubeConfigModels namespace k8s.KubeConfigModels
{ {
using System.Collections.Generic;
using YamlDotNet.RepresentationModel;
using YamlDotNet.Serialization;
/// <summary> /// <summary>
/// Contains information that describes identity information. This is use to tell the kubernetes cluster who you are. /// Contains information that describes identity information. This is use to tell the kubernetes cluster who you are.
/// </summary> /// </summary>

View File

@@ -1,7 +1,7 @@
using YamlDotNet.Serialization;
namespace k8s.KubeConfigModels namespace k8s.KubeConfigModels
{ {
using YamlDotNet.Serialization;
/// <summary> /// <summary>
/// Relates nicknames to cluster information. /// Relates nicknames to cluster information.
/// </summary> /// </summary>

View File

@@ -1,8 +1,8 @@
using System.Collections.Generic;
using YamlDotNet.Serialization;
namespace k8s.KubeConfigModels namespace k8s.KubeConfigModels
{ {
using System.Collections.Generic;
using YamlDotNet.Serialization;
/// <summary> /// <summary>
/// Contains information about how to communicate with a kubernetes cluster /// Contains information about how to communicate with a kubernetes cluster
/// </summary> /// </summary>

View File

@@ -1,8 +1,8 @@
using System;
using YamlDotNet.Serialization;
namespace k8s.KubeConfigModels namespace k8s.KubeConfigModels
{ {
using System;
using YamlDotNet.Serialization;
/// <summary> /// <summary>
/// Relates nicknames to context information. /// Relates nicknames to context information.
/// </summary> /// </summary>

View File

@@ -1,8 +1,8 @@
using System.Collections.Generic;
using YamlDotNet.Serialization;
namespace k8s.KubeConfigModels namespace k8s.KubeConfigModels
{ {
using System.Collections.Generic;
using YamlDotNet.Serialization;
/// <summary> /// <summary>
/// Represents a tuple of references to a cluster (how do I communicate with a kubernetes cluster), /// Represents a tuple of references to a cluster (how do I communicate with a kubernetes cluster),
/// a user (how do I identify myself), and a namespace (what subset of resources do I want to work with) /// a user (how do I identify myself), and a namespace (what subset of resources do I want to work with)

View File

@@ -5,8 +5,11 @@ namespace k8s.KubeConfigModels
{ {
public class ExecCredentialResponse public class ExecCredentialResponse
{ {
[JsonProperty("apiVersion")] public string ApiVersion { get; set; } [JsonProperty("apiVersion")]
[JsonProperty("kind")] public string Kind { get; set; } public string ApiVersion { get; set; }
[JsonProperty("status")] public IDictionary<string, string> Status { get; set; } [JsonProperty("kind")]
public string Kind { get; set; }
[JsonProperty("status")]
public IDictionary<string, string> Status { get; set; }
} }
} }

View File

@@ -5,7 +5,8 @@ namespace k8s.KubeConfigModels
{ {
public class ExternalExecution public class ExternalExecution
{ {
[YamlMember(Alias = "apiVersion")] public string ApiVersion { get; set; } [YamlMember(Alias = "apiVersion")]
public string ApiVersion { get; set; }
/// <summary> /// <summary>
/// The command to execute. Required. /// The command to execute. Required.

View File

@@ -1,8 +1,8 @@
using System.Collections.Generic;
using YamlDotNet.Serialization;
namespace k8s.KubeConfigModels namespace k8s.KubeConfigModels
{ {
using System.Collections.Generic;
using YamlDotNet.Serialization;
/// <summary> /// <summary>
/// kubeconfig configuration model. Holds the information needed to build connect to remote /// kubeconfig configuration model. Holds the information needed to build connect to remote
/// Kubernetes clusters as a given user. /// Kubernetes clusters as a given user.
@@ -19,9 +19,11 @@ namespace k8s.KubeConfigModels
[YamlMember(Alias = "preferences")] [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; } [YamlMember(Alias = "apiVersion")]
public string ApiVersion { get; set; }
[YamlMember(Alias = "kind")] public string Kind { get; set; } [YamlMember(Alias = "kind")]
public string Kind { get; set; }
/// <summary> /// <summary>
/// Gets or sets the name of the context that you would like to use by default. /// Gets or sets the name of the context that you would like to use by default.

View File

@@ -1,7 +1,7 @@
using YamlDotNet.Serialization;
namespace k8s.KubeConfigModels namespace k8s.KubeConfigModels
{ {
using YamlDotNet.Serialization;
/// <summary> /// <summary>
/// Relates nicknames to auth information. /// Relates nicknames to auth information.
/// </summary> /// </summary>

View File

@@ -1,9 +1,8 @@
using System.Collections.Generic;
using YamlDotNet.Serialization;
namespace k8s.KubeConfigModels namespace k8s.KubeConfigModels
{ {
using System.Collections.Generic;
using YamlDotNet.RepresentationModel;
using YamlDotNet.Serialization;
/// <summary> /// <summary>
/// Contains information that describes identity information. This is use to tell the kubernetes cluster who you are. /// Contains information that describes identity information. This is use to tell the kubernetes cluster who you are.
/// </summary> /// </summary>

View File

@@ -22,7 +22,8 @@ namespace k8s
/// <param name="httpClient"> /// <param name="httpClient">
/// The <see cref="HttpClient" /> to use for all requests. /// The <see cref="HttpClient" /> to use for all requests.
/// </param> /// </param>
public Kubernetes(KubernetesClientConfiguration config, HttpClient httpClient) : this(config, httpClient, false) public Kubernetes(KubernetesClientConfiguration config, HttpClient httpClient)
: this(config, httpClient, false)
{ {
} }
@@ -38,7 +39,8 @@ namespace k8s
/// <param name="disposeHttpClient"> /// <param name="disposeHttpClient">
/// Whether or not the <see cref="Kubernetes"/> object should own the lifetime of <paramref name="httpClient"/>. /// Whether or not the <see cref="Kubernetes"/> object should own the lifetime of <paramref name="httpClient"/>.
/// </param> /// </param>
public Kubernetes(KubernetesClientConfiguration config, HttpClient httpClient, bool disposeHttpClient) : this( public Kubernetes(KubernetesClientConfiguration config, HttpClient httpClient, bool disposeHttpClient)
: this(
httpClient, disposeHttpClient) httpClient, disposeHttpClient)
{ {
ValidateConfig(config); ValidateConfig(config);
@@ -179,12 +181,14 @@ namespace k8s
/// <summary>A <see cref="DelegatingHandler"/> that simply forwards a request with no further processing.</summary> /// <summary>A <see cref="DelegatingHandler"/> that simply forwards a request with no further processing.</summary>
private sealed class ForwardingHandler : DelegatingHandler private sealed class ForwardingHandler : DelegatingHandler
{ {
public ForwardingHandler(HttpMessageHandler handler) : base(handler) public ForwardingHandler(HttpMessageHandler handler)
: base(handler)
{ {
} }
} }
private void AppendDelegatingHandler<T>() where T : DelegatingHandler, new() private void AppendDelegatingHandler<T>()
where T : DelegatingHandler, new()
{ {
var cur = FirstMessageHandler as DelegatingHandler; var cur = FirstMessageHandler as DelegatingHandler;

View File

@@ -23,7 +23,8 @@ namespace k8s
try try
{ {
using (var muxedStream = await this.MuxedStreamNamespacedPodExecAsync(name: name, using (var muxedStream = await this.MuxedStreamNamespacedPodExecAsync(
name: name,
@namespace: @namespace, command: command, container: container, tty: tty, @namespace: @namespace, command: command, container: container, tty: tty,
cancellationToken: cancellationToken).ConfigureAwait(false)) cancellationToken: cancellationToken).ConfigureAwait(false))
using (Stream stdIn = muxedStream.GetStream(null, ChannelIndex.StdIn)) using (Stream stdIn = muxedStream.GetStream(null, ChannelIndex.StdIn))

View File

@@ -96,7 +96,8 @@ namespace k8s
uriBuilder.Query = uriBuilder.Query =
query.Length == 0 query.Length == 0
? "" ? ""
: query.ToString(1, : query.ToString(
1,
query.Length - 1); // UriBuilder.Query doesn't like leading '?' chars, so trim it query.Length - 1); // UriBuilder.Query doesn't like leading '?' chars, so trim it
// Create HTTP transport objects // Create HTTP transport objects
@@ -145,7 +146,8 @@ namespace k8s
{ {
string responseContent = string.Empty; string responseContent = string.Empty;
var ex = new HttpOperationException(string.Format("Operation returned an invalid status code '{0}'", var ex = new HttpOperationException(string.Format(
"Operation returned an invalid status code '{0}'",
httpResponse.StatusCode)); httpResponse.StatusCode));
if (httpResponse.Content != null) if (httpResponse.Content != null)
{ {
@@ -160,7 +162,8 @@ namespace k8s
throw ex; throw ex;
} }
return new Watcher<T>(async () => return new Watcher<T>(
async () =>
{ {
var stream = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false); var stream = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
StreamReader reader = new StreamReader(stream); StreamReader reader = new StreamReader(stream);

View File

@@ -37,7 +37,8 @@ namespace k8s
} }
/// <inheritdoc/> /// <inheritdoc/>
public virtual async Task<IStreamDemuxer> MuxedStreamNamespacedPodExecAsync(string name, public virtual async Task<IStreamDemuxer> MuxedStreamNamespacedPodExecAsync(
string name,
string @namespace = "default", IEnumerable<string> command = null, string container = null, string @namespace = "default", IEnumerable<string> command = null, string container = null,
bool stderr = true, bool stdin = true, bool stdout = true, bool tty = true, bool stderr = true, bool stdin = true, bool stdout = true, bool tty = true,
string webSocketSubProtol = WebSocketProtocol.V4BinaryWebsocketProtocol, string webSocketSubProtol = WebSocketProtocol.V4BinaryWebsocketProtocol,

View File

@@ -76,7 +76,8 @@ namespace k8s
/// <param name="masterUrl">kube api server endpoint</param> /// <param name="masterUrl">kube api server endpoint</param>
/// <param name="useRelativePaths">When <see langword="true"/>, the paths in the kubeconfig file will be considered to be relative to the directory in which the kubeconfig /// <param name="useRelativePaths">When <see langword="true"/>, the paths in the kubeconfig file will be considered to be relative to the directory in which the kubeconfig
/// file is located. When <see langword="false"/>, the paths will be considered to be relative to the current working directory.</param> /// file is located. When <see langword="false"/>, the paths will be considered to be relative to the current working directory.</param>
public static KubernetesClientConfiguration BuildConfigFromConfigFile(string kubeconfigPath = null, public static KubernetesClientConfiguration BuildConfigFromConfigFile(
string kubeconfigPath = null,
string currentContext = null, string masterUrl = null, bool useRelativePaths = true) string currentContext = null, string masterUrl = null, bool useRelativePaths = true)
{ {
return BuildConfigFromConfigFile(new FileInfo(kubeconfigPath ?? KubeConfigDefaultLocation), currentContext, return BuildConfigFromConfigFile(new FileInfo(kubeconfigPath ?? KubeConfigDefaultLocation), currentContext,
@@ -91,7 +92,8 @@ namespace k8s
/// <param name="masterUrl">override the kube api server endpoint, set null if do not want to override</param> /// <param name="masterUrl">override the kube api server endpoint, set null if do not want to override</param>
/// <param name="useRelativePaths">When <see langword="true"/>, the paths in the kubeconfig file will be considered to be relative to the directory in which the kubeconfig /// <param name="useRelativePaths">When <see langword="true"/>, the paths in the kubeconfig file will be considered to be relative to the directory in which the kubeconfig
/// file is located. When <see langword="false"/>, the paths will be considered to be relative to the current working directory.</param> /// file is located. When <see langword="false"/>, the paths will be considered to be relative to the current working directory.</param>
public static KubernetesClientConfiguration BuildConfigFromConfigFile(FileInfo kubeconfig, public static KubernetesClientConfiguration BuildConfigFromConfigFile(
FileInfo kubeconfig,
string currentContext = null, string masterUrl = null, bool useRelativePaths = true) string currentContext = null, string masterUrl = null, bool useRelativePaths = true)
{ {
return BuildConfigFromConfigFileAsync(kubeconfig, currentContext, masterUrl, useRelativePaths).GetAwaiter() return BuildConfigFromConfigFileAsync(kubeconfig, currentContext, masterUrl, useRelativePaths).GetAwaiter()
@@ -106,7 +108,8 @@ namespace k8s
/// <param name="masterUrl">override the kube api server endpoint, set null if do not want to override</param> /// <param name="masterUrl">override the kube api server endpoint, set null if do not want to override</param>
/// <param name="useRelativePaths">When <see langword="true"/>, the paths in the kubeconfig file will be considered to be relative to the directory in which the kubeconfig /// <param name="useRelativePaths">When <see langword="true"/>, the paths in the kubeconfig file will be considered to be relative to the directory in which the kubeconfig
/// file is located. When <see langword="false"/>, the paths will be considered to be relative to the current working directory.</param> /// file is located. When <see langword="false"/>, the paths will be considered to be relative to the current working directory.</param>
public static async Task<KubernetesClientConfiguration> BuildConfigFromConfigFileAsync(FileInfo kubeconfig, public static async Task<KubernetesClientConfiguration> BuildConfigFromConfigFileAsync(
FileInfo kubeconfig,
string currentContext = null, string masterUrl = null, bool useRelativePaths = true) string currentContext = null, string masterUrl = null, bool useRelativePaths = true)
{ {
if (kubeconfig == null) if (kubeconfig == null)
@@ -126,7 +129,8 @@ namespace k8s
/// <param name="kubeconfig">Stream of the kubeconfig, cannot be null</param> /// <param name="kubeconfig">Stream of the kubeconfig, cannot be null</param>
/// <param name="currentContext">Override the current context in config, set null if do not want to override</param> /// <param name="currentContext">Override the current context in config, set null if do not want to override</param>
/// <param name="masterUrl">Override the Kubernetes API server endpoint, set null if do not want to override</param> /// <param name="masterUrl">Override the Kubernetes API server endpoint, set null if do not want to override</param>
public static KubernetesClientConfiguration BuildConfigFromConfigFile(Stream kubeconfig, public static KubernetesClientConfiguration BuildConfigFromConfigFile(
Stream kubeconfig,
string currentContext = null, string masterUrl = null) string currentContext = null, string masterUrl = null)
{ {
return BuildConfigFromConfigFileAsync(kubeconfig, currentContext, masterUrl).GetAwaiter().GetResult(); return BuildConfigFromConfigFileAsync(kubeconfig, currentContext, masterUrl).GetAwaiter().GetResult();
@@ -138,7 +142,8 @@ namespace k8s
/// <param name="kubeconfig">Stream of the kubeconfig, cannot be null</param> /// <param name="kubeconfig">Stream of the kubeconfig, cannot be null</param>
/// <param name="currentContext">Override the current context in config, set null if do not want to override</param> /// <param name="currentContext">Override the current context in config, set null if do not want to override</param>
/// <param name="masterUrl">Override the Kubernetes API server endpoint, set null if do not want to override</param> /// <param name="masterUrl">Override the Kubernetes API server endpoint, set null if do not want to override</param>
public static async Task<KubernetesClientConfiguration> BuildConfigFromConfigFileAsync(Stream kubeconfig, public static async Task<KubernetesClientConfiguration> BuildConfigFromConfigFileAsync(
Stream kubeconfig,
string currentContext = null, string masterUrl = null) string currentContext = null, string masterUrl = null)
{ {
if (kubeconfig == null) if (kubeconfig == null)
@@ -165,11 +170,13 @@ namespace k8s
/// <param name="k8sConfig">A <see cref="K8SConfiguration"/>, for example loaded from <see cref="LoadKubeConfigAsync(string, bool)" /></param> /// <param name="k8sConfig">A <see cref="K8SConfiguration"/>, for example loaded from <see cref="LoadKubeConfigAsync(string, bool)" /></param>
/// <param name="currentContext">Override the current context in config, set null if do not want to override</param> /// <param name="currentContext">Override the current context in config, set null if do not want to override</param>
/// <param name="masterUrl">Override the Kubernetes API server endpoint, set null if do not want to override</param> /// <param name="masterUrl">Override the Kubernetes API server endpoint, set null if do not want to override</param>
public static KubernetesClientConfiguration BuildConfigFromConfigObject(K8SConfiguration k8SConfig, public static KubernetesClientConfiguration BuildConfigFromConfigObject(
K8SConfiguration k8SConfig,
string currentContext = null, string masterUrl = null) string currentContext = null, string masterUrl = null)
=> GetKubernetesClientConfiguration(currentContext, masterUrl, k8SConfig); => GetKubernetesClientConfiguration(currentContext, masterUrl, k8SConfig);
private static KubernetesClientConfiguration GetKubernetesClientConfiguration(string currentContext, private static KubernetesClientConfiguration GetKubernetesClientConfiguration(
string currentContext,
string masterUrl, K8SConfiguration k8SConfig) string masterUrl, K8SConfiguration k8SConfig)
{ {
var k8SConfiguration = new KubernetesClientConfiguration(); var k8SConfiguration = new KubernetesClientConfiguration();
@@ -232,7 +239,8 @@ namespace k8s
private void SetClusterDetails(K8SConfiguration k8SConfig, Context activeContext) private void SetClusterDetails(K8SConfiguration k8SConfig, Context activeContext)
{ {
var clusterDetails = var clusterDetails =
k8SConfig.Clusters.FirstOrDefault(c => c.Name.Equals(activeContext.ContextDetails.Cluster, k8SConfig.Clusters.FirstOrDefault(c => c.Name.Equals(
activeContext.ContextDetails.Cluster,
StringComparison.OrdinalIgnoreCase)); StringComparison.OrdinalIgnoreCase));
if (clusterDetails?.ClusterEndpoint == null) if (clusterDetails?.ClusterEndpoint == null)
@@ -262,7 +270,8 @@ namespace k8s
} }
else if (!string.IsNullOrEmpty(clusterDetails.ClusterEndpoint.CertificateAuthority)) else if (!string.IsNullOrEmpty(clusterDetails.ClusterEndpoint.CertificateAuthority))
{ {
SslCaCerts = new X509Certificate2Collection(new X509Certificate2(GetFullPath(k8SConfig, SslCaCerts = new X509Certificate2Collection(new X509Certificate2(GetFullPath(
k8SConfig,
clusterDetails.ClusterEndpoint.CertificateAuthority))); clusterDetails.ClusterEndpoint.CertificateAuthority)));
} }
} }
@@ -275,7 +284,8 @@ namespace k8s
return; return;
} }
var userDetails = k8SConfig.Users.FirstOrDefault(c => c.Name.Equals(activeContext.ContextDetails.User, var userDetails = k8SConfig.Users.FirstOrDefault(c => c.Name.Equals(
activeContext.ContextDetails.User,
StringComparison.OrdinalIgnoreCase)); StringComparison.OrdinalIgnoreCase));
if (userDetails == null) if (userDetails == null)
@@ -343,15 +353,17 @@ namespace k8s
expires = DateTimeOffset.FromUnixTimeSeconds(expiresOn); expires = DateTimeOffset.FromUnixTimeSeconds(expiresOn);
#endif #endif
if (DateTimeOffset.Compare(expires, if (DateTimeOffset.Compare(
DateTimeOffset.Now) expires,
DateTimeOffset.Now)
<= 0) <= 0)
{ {
var tenantId = config["tenant-id"]; var tenantId = config["tenant-id"];
var clientId = config["client-id"]; var clientId = config["client-id"];
var apiServerId = config["apiserver-id"]; var apiServerId = config["apiserver-id"];
var refresh = config["refresh-token"]; var refresh = config["refresh-token"];
var newToken = RenewAzureToken(tenantId, var newToken = RenewAzureToken(
tenantId,
clientId, clientId,
apiServerId, apiServerId,
refresh); refresh);
@@ -533,7 +545,8 @@ namespace k8s
/// <param name="useRelativePaths">When <see langword="true"/>, the paths in the kubeconfig file will be considered to be relative to the directory in which the kubeconfig /// <param name="useRelativePaths">When <see langword="true"/>, the paths in the kubeconfig file will be considered to be relative to the directory in which the kubeconfig
/// file is located. When <see langword="false"/>, the paths will be considered to be relative to the current working directory.</param> /// file is located. When <see langword="false"/>, the paths will be considered to be relative to the current working directory.</param>
/// <returns>Instance of the <see cref="K8SConfiguration"/> class</returns> /// <returns>Instance of the <see cref="K8SConfiguration"/> class</returns>
public static async Task<K8SConfiguration> LoadKubeConfigAsync(string kubeconfigPath = null, public static async Task<K8SConfiguration> LoadKubeConfigAsync(
string kubeconfigPath = null,
bool useRelativePaths = true) bool useRelativePaths = true)
{ {
var fileInfo = new FileInfo(kubeconfigPath ?? KubeConfigDefaultLocation); var fileInfo = new FileInfo(kubeconfigPath ?? KubeConfigDefaultLocation);
@@ -560,7 +573,8 @@ namespace k8s
/// <param name="useRelativePaths">When <see langword="true"/>, the paths in the kubeconfig file will be considered to be relative to the directory in which the kubeconfig /// <param name="useRelativePaths">When <see langword="true"/>, the paths in the kubeconfig file will be considered to be relative to the directory in which the kubeconfig
/// file is located. When <see langword="false"/>, the paths will be considered to be relative to the current working directory.</param> /// file is located. When <see langword="false"/>, the paths will be considered to be relative to the current working directory.</param>
/// <returns>Instance of the <see cref="K8SConfiguration"/> class</returns> /// <returns>Instance of the <see cref="K8SConfiguration"/> class</returns>
public static async Task<K8SConfiguration> LoadKubeConfigAsync(FileInfo kubeconfig, public static async Task<K8SConfiguration> LoadKubeConfigAsync(
FileInfo kubeconfig,
bool useRelativePaths = true) bool useRelativePaths = true)
{ {
if (!kubeconfig.Exists) if (!kubeconfig.Exists)
@@ -640,7 +654,8 @@ namespace k8s
/// The kube config files will be merges into a single <see cref="K8SConfiguration"/>, where first occurence wins. /// The kube config files will be merges into a single <see cref="K8SConfiguration"/>, where first occurence wins.
/// See https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/#merging-kubeconfig-files. /// See https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/#merging-kubeconfig-files.
/// </remarks> /// </remarks>
internal static async Task<K8SConfiguration> LoadKubeConfigAsync(FileInfo[] kubeConfigs, internal static async Task<K8SConfiguration> LoadKubeConfigAsync(
FileInfo[] kubeConfigs,
bool useRelativePaths = true) bool useRelativePaths = true)
{ {
var basek8SConfig = await LoadKubeConfigAsync(kubeConfigs[0], useRelativePaths).ConfigureAwait(false); var basek8SConfig = await LoadKubeConfigAsync(kubeConfigs[0], useRelativePaths).ConfigureAwait(false);

View File

@@ -1,12 +1,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using k8s.Models;
using Microsoft.Rest; using Microsoft.Rest;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace k8s.Models namespace k8s.Models
{ {
public class KubernetesList<T> : IMetadata<V1ListMeta>, IItems<T> where T : IKubernetesObject public class KubernetesList<T> : IMetadata<V1ListMeta>, IItems<T>
where T : IKubernetesObject
{ {
public KubernetesList(IList<T> items, string apiVersion = default(string), string kind = default(string), public KubernetesList(IList<T> items, string apiVersion = default(string), string kind = default(string),
V1ListMeta metadata = default(V1ListMeta)) V1ListMeta metadata = default(V1ListMeta))
@@ -27,7 +27,8 @@ namespace k8s.Models
[JsonProperty(PropertyName = "apiVersion")] [JsonProperty(PropertyName = "apiVersion")]
public string ApiVersion { get; set; } public string ApiVersion { get; set; }
[JsonProperty(PropertyName = "items")] public IList<T> Items { get; set; } [JsonProperty(PropertyName = "items")]
public IList<T> Items { get; set; }
/// <summary> /// <summary>
/// Gets or sets kind is a string value representing the REST resource /// Gets or sets kind is a string value representing the REST resource

View File

@@ -245,12 +245,14 @@ namespace k8s.Models
} }
/// <summary>Gets <see cref="V1OwnerReference"/> that matches the given object, or null if no matching reference exists.</summary> /// <summary>Gets <see cref="V1OwnerReference"/> that matches the given object, or null if no matching reference exists.</summary>
public static V1OwnerReference GetOwnerReference(this IMetadata<V1ObjectMeta> obj, public static V1OwnerReference GetOwnerReference(
this IMetadata<V1ObjectMeta> obj,
IKubernetesObject<V1ObjectMeta> owner) => IKubernetesObject<V1ObjectMeta> owner) =>
GetOwnerReference(obj, r => r.Matches(owner)); GetOwnerReference(obj, r => r.Matches(owner));
/// <summary>Gets the <see cref="V1OwnerReference"/> that matches the given predicate, or null if no matching reference exists.</summary> /// <summary>Gets the <see cref="V1OwnerReference"/> that matches the given predicate, or null if no matching reference exists.</summary>
public static V1OwnerReference GetOwnerReference(this IMetadata<V1ObjectMeta> obj, public static V1OwnerReference GetOwnerReference(
this IMetadata<V1ObjectMeta> obj,
Predicate<V1OwnerReference> predicate) Predicate<V1OwnerReference> predicate)
{ {
int index = FindOwnerReference(obj, predicate); int index = FindOwnerReference(obj, predicate);
@@ -310,7 +312,8 @@ namespace k8s.Models
/// <summary>Removes the first <see cref="V1OwnerReference"/> that matches the given object and returns it, or returns null if no /// <summary>Removes the first <see cref="V1OwnerReference"/> that matches the given object and returns it, or returns null if no
/// matching reference could be found. /// matching reference could be found.
/// </summary> /// </summary>
public static V1OwnerReference RemoveOwnerReference(this IMetadata<V1ObjectMeta> obj, public static V1OwnerReference RemoveOwnerReference(
this IMetadata<V1ObjectMeta> obj,
IKubernetesObject<V1ObjectMeta> owner) IKubernetesObject<V1ObjectMeta> owner)
{ {
int index = FindOwnerReference(obj, owner); int index = FindOwnerReference(obj, owner);
@@ -326,7 +329,8 @@ namespace k8s.Models
/// <summary>Removes all <see cref="V1OwnerReference">owner references</see> that match the given predicate, and returns true if /// <summary>Removes all <see cref="V1OwnerReference">owner references</see> that match the given predicate, and returns true if
/// any were removed. /// any were removed.
/// </summary> /// </summary>
public static bool RemoveOwnerReferences(this IMetadata<V1ObjectMeta> obj, public static bool RemoveOwnerReferences(
this IMetadata<V1ObjectMeta> obj,
Predicate<V1OwnerReference> predicate) Predicate<V1OwnerReference> predicate)
{ {
if (obj == null) if (obj == null)
@@ -359,7 +363,8 @@ namespace k8s.Models
/// <summary>Removes all <see cref="V1OwnerReference">owner references</see> that match the given object, and returns true if /// <summary>Removes all <see cref="V1OwnerReference">owner references</see> that match the given object, and returns true if
/// any were removed. /// any were removed.
/// </summary> /// </summary>
public static bool RemoveOwnerReferences(this IMetadata<V1ObjectMeta> obj, public static bool RemoveOwnerReferences(
this IMetadata<V1ObjectMeta> obj,
IKubernetesObject<V1ObjectMeta> owner) => IKubernetesObject<V1ObjectMeta> owner) =>
RemoveOwnerReferences(obj, r => r.Matches(owner)); RemoveOwnerReferences(obj, r => r.Matches(owner));

View File

@@ -1,5 +1,3 @@
using System;
namespace k8s namespace k8s
{ {
/// <summary> /// <summary>

View File

@@ -10,10 +10,11 @@ namespace k8s
public class StringQuotingEmitter : ChainedEventEmitter public class StringQuotingEmitter : ChainedEventEmitter
{ {
// Patterns from https://yaml.org/spec/1.2/spec.html#id2804356 // Patterns from https://yaml.org/spec/1.2/spec.html#id2804356
private static readonly Regex quotedRegex = private static readonly Regex QuotedRegex =
new Regex(@"^(\~|null|true|false|-?(0|[1-9][0-9]*)(\.[0-9]*)?([eE][-+]?[0-9]+)?)?$"); new Regex(@"^(\~|null|true|false|-?(0|[1-9][0-9]*)(\.[0-9]*)?([eE][-+]?[0-9]+)?)?$");
public StringQuotingEmitter(IEventEmitter next) : base(next) public StringQuotingEmitter(IEventEmitter next)
: base(next)
{ {
} }
@@ -34,7 +35,7 @@ namespace k8s
break; break;
case TypeCode.String: case TypeCode.String:
var val = eventInfo.Source.Value.ToString(); var val = eventInfo.Source.Value.ToString();
if (quotedRegex.IsMatch(val)) if (QuotedRegex.IsMatch(val))
{ {
eventInfo.Style = ScalarStyle.DoubleQuoted; eventInfo.Style = ScalarStyle.DoubleQuoted;
} }

View File

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

View File

@@ -6,14 +6,8 @@ namespace k8s.Versioning
{ {
public class KubernetesVersionComparer : IComparer<string> public class KubernetesVersionComparer : IComparer<string>
{ {
public static KubernetesVersionComparer Instance { get; private set; } public static KubernetesVersionComparer Instance { get; } = new KubernetesVersionComparer();
private static readonly Regex _kubernetesVersionRegex; private static readonly Regex KubernetesVersionRegex = new Regex(@"^v(?<major>[0-9]+)((?<stream>alpha|beta)(?<minor>[0-9]+))?$", RegexOptions.Compiled);
static KubernetesVersionComparer()
{
_kubernetesVersionRegex = new Regex(@"^v(?<major>[0-9]+)((?<stream>alpha|beta)(?<minor>[0-9]+))?$", RegexOptions.Compiled);
Instance = new KubernetesVersionComparer();
}
internal KubernetesVersionComparer() internal KubernetesVersionComparer()
{ {
@@ -26,13 +20,13 @@ namespace k8s.Versioning
return StringComparer.CurrentCulture.Compare(x, y); return StringComparer.CurrentCulture.Compare(x, y);
} }
var matchX = _kubernetesVersionRegex.Match(x); var matchX = KubernetesVersionRegex.Match(x);
if (!matchX.Success) if (!matchX.Success)
{ {
return StringComparer.CurrentCulture.Compare(x, y); return StringComparer.CurrentCulture.Compare(x, y);
} }
var matchY = _kubernetesVersionRegex.Match(y); var matchY = KubernetesVersionRegex.Match(y);
if (!matchY.Success) if (!matchY.Success)
{ {
return StringComparer.CurrentCulture.Compare(x, y); return StringComparer.CurrentCulture.Compare(x, y);

View File

@@ -59,7 +59,8 @@ namespace k8s.Versioning
.GroupBy(x => x.Kind) .GroupBy(x => x.Kind)
.ToDictionary(x => x.Key, kindGroup => kindGroup .ToDictionary(x => x.Key, kindGroup => kindGroup
.GroupBy(x => x.ApiVersion) .GroupBy(x => x.ApiVersion)
.ToDictionary(x => x.Key, .ToDictionary(
x => x.Key,
versionGroup => versionGroup.Select(x => x.Type).Distinct().Single())); // should only be one type for each Kind/Version combination versionGroup => versionGroup.Select(x => x.Type).Distinct().Single())); // should only be one type for each Kind/Version combination
} }
@@ -152,7 +153,7 @@ namespace k8s.Versioning
.ForMember(dest => dest.AverageValue, opt => opt.MapFrom(src => src.TargetAverageValue)) .ForMember(dest => dest.AverageValue, opt => opt.MapFrom(src => src.TargetAverageValue))
.ForMember(dest => dest.Value, opt => opt.Ignore()) .ForMember(dest => dest.Value, opt => opt.Ignore())
#if NET452 #if NET452
.ForMember(dest => dest.Type, opt => opt.ResolveUsing(src => src.TargetAverageValue != null ? "AverageValue" : "Utilization" )) .ForMember(dest => dest.Type, opt => opt.ResolveUsing(src => src.TargetAverageValue != null ? "AverageValue" : "Utilization"))
#else #else
.ForMember(dest => dest.Type, opt => opt.MapFrom((src, dest) => src.TargetAverageValue != null ? "AverageValue" : "Utilization")) .ForMember(dest => dest.Type, opt => opt.MapFrom((src, dest) => src.TargetAverageValue != null ? "AverageValue" : "Utilization"))
#endif #endif

View File

@@ -12,23 +12,28 @@ namespace k8s
public enum WatchEventType public enum WatchEventType
{ {
/// <summary>Emitted when an object is created, modified to match a watch's filter, or when a watch is first opened.</summary> /// <summary>Emitted when an object is created, modified to match a watch's filter, or when a watch is first opened.</summary>
[EnumMember(Value = "ADDED")] Added, [EnumMember(Value = "ADDED")]
Added,
/// <summary>Emitted when an object is modified.</summary> /// <summary>Emitted when an object is modified.</summary>
[EnumMember(Value = "MODIFIED")] Modified, [EnumMember(Value = "MODIFIED")]
Modified,
/// <summary>Emitted when an object is deleted or modified to no longer match a watch's filter.</summary> /// <summary>Emitted when an object is deleted or modified to no longer match a watch's filter.</summary>
[EnumMember(Value = "DELETED")] Deleted, [EnumMember(Value = "DELETED")]
Deleted,
/// <summary>Emitted when an error occurs while watching resources. Most commonly, the error is 410 Gone which indicates that /// <summary>Emitted when an error occurs while watching resources. Most commonly, the error is 410 Gone which indicates that
/// the watch resource version was outdated and events were probably lost. In that case, the watch should be restarted. /// the watch resource version was outdated and events were probably lost. In that case, the watch should be restarted.
/// </summary> /// </summary>
[EnumMember(Value = "ERROR")] Error, [EnumMember(Value = "ERROR")]
Error,
/// <summary>Bookmarks may be emitted periodically to update the resource version. The object will /// <summary>Bookmarks may be emitted periodically to update the resource version. The object will
/// contain only the resource version. /// contain only the resource version.
/// </summary> /// </summary>
[EnumMember(Value = "BOOKMARK")] Bookmark, [EnumMember(Value = "BOOKMARK")]
Bookmark,
} }
public class Watcher<T> : IDisposable public class Watcher<T> : IDisposable

View File

@@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Threading; using System.Threading;
@@ -15,7 +14,8 @@ namespace k8s
/// </summary> /// </summary>
internal class WatcherDelegatingHandler : DelegatingHandler internal class WatcherDelegatingHandler : DelegatingHandler
{ {
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
var originResponse = await base.SendAsync(request, cancellationToken).ConfigureAwait(false); var originResponse = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);

View File

@@ -19,12 +19,14 @@ namespace k8s
/// The action to invoke when the server closes the connection. /// The action to invoke when the server closes the connection.
/// </param> /// </param>
/// <returns>a watch object</returns> /// <returns>a watch object</returns>
public static Watcher<T> Watch<T, L>(this Task<HttpOperationResponse<L>> responseTask, public static Watcher<T> Watch<T, L>(
this Task<HttpOperationResponse<L>> responseTask,
Action<WatchEventType, T> onEvent, Action<WatchEventType, T> onEvent,
Action<Exception> onError = null, Action<Exception> onError = null,
Action onClosed = null) Action onClosed = null)
{ {
return new Watcher<T>(async () => return new Watcher<T>(
async () =>
{ {
var response = await responseTask.ConfigureAwait(false); var response = await responseTask.ConfigureAwait(false);
@@ -49,7 +51,8 @@ namespace k8s
/// The action to invoke when the server closes the connection. /// The action to invoke when the server closes the connection.
/// </param> /// </param>
/// <returns>a watch object</returns> /// <returns>a watch object</returns>
public static Watcher<T> Watch<T, L>(this HttpOperationResponse<L> response, public static Watcher<T> Watch<T, L>(
this HttpOperationResponse<L> response,
Action<WatchEventType, T> onEvent, Action<WatchEventType, T> onEvent,
Action<Exception> onError = null, Action<Exception> onError = null,
Action onClosed = null) Action onClosed = null)

View File

@@ -1,5 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Net.WebSockets; using System.Net.WebSockets;
#if (NET452 || NETSTANDARD2_0) #if (NET452 || NETSTANDARD2_0)
using System.Net.Security; using System.Net.Security;

View File

@@ -265,7 +265,8 @@ namespace k8s
set => _inner.ScalarStyle = value; set => _inner.ScalarStyle = value;
} }
public T GetCustomAttribute<T>() where T : Attribute public T GetCustomAttribute<T>()
where T : Attribute
{ {
return _inner.GetCustomAttribute<T>(); return _inner.GetCustomAttribute<T>();
} }

View File

@@ -3,8 +3,6 @@ using k8s.Models;
namespace k8s.Versioning namespace k8s.Versioning
{ {
public static partial class VersionConverter public static partial class VersionConverter
{ {
private static void AutoConfigurations(IMapperConfigurationExpression cfg) private static void AutoConfigurations(IMapperConfigurationExpression cfg)
@@ -160,6 +158,4 @@ namespace k8s.Versioning
cfg.CreateMap<V1beta1VolumeNodeResources, V1VolumeNodeResources>().ReverseMap(); cfg.CreateMap<V1beta1VolumeNodeResources, V1VolumeNodeResources>().ReverseMap();
} }
} }
} }

View File

@@ -18,7 +18,6 @@ using Microsoft.Rest;
using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Pkcs; using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security; using Org.BouncyCastle.Security;
using Remotion.Linq.Clauses;
using Xunit; using Xunit;
using Xunit.Abstractions; using Xunit.Abstractions;
@@ -89,8 +88,9 @@ namespace k8s.Tests
{ {
var header = cxt.Request.Headers["Authorization"].FirstOrDefault(); var header = cxt.Request.Headers["Authorization"].FirstOrDefault();
var expect = new AuthenticationHeaderValue("Basic", var expect = new AuthenticationHeaderValue(
Convert.ToBase64String(Encoding.UTF8.GetBytes($"{testName}:{testPassword}"))) "Basic",
Convert.ToBase64String(Encoding.UTF8.GetBytes($"{testName}:{testPassword}")))
.ToString(); .ToString();
if (header != expect) if (header != expect)

View File

@@ -1,7 +1,5 @@
using Nito.AsyncEx;
using System; using System;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Xunit; using Xunit;
@@ -262,7 +260,8 @@ namespace k8s.Tests
// Write data to the buffer // Write data to the buffer
buffer.Write(this.writeData, 0, 0x03); buffer.Write(this.writeData, 0, 0x03);
await TaskAssert.Completed(readTask, await TaskAssert.Completed(
readTask,
timeout: TimeSpan.FromMilliseconds(1000), timeout: TimeSpan.FromMilliseconds(1000),
message: "Timed out waiting for read task to complete.").ConfigureAwait(false); message: "Timed out waiting for read task to complete.").ConfigureAwait(false);

View File

@@ -1,9 +1,6 @@
using System; using System;
using Xunit; using Xunit;
using k8s;
using System.IO;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Linq; using System.Linq;
namespace k8s.Tests namespace k8s.Tests
@@ -42,7 +39,8 @@ namespace k8s.Tests
[Fact] [Fact]
public void LoadFromFilesRelativePath() public void LoadFromFilesRelativePath()
{ {
var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(KubeConfigWithRelativePathsFileName, var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(
KubeConfigWithRelativePathsFileName,
"federal-context"); "federal-context");
// Just validate that this doesn't throw and private key is non-null // Just validate that this doesn't throw and private key is non-null
@@ -70,7 +68,8 @@ namespace k8s.Tests
[Fact] [Fact]
public void LoadFromInlineDataRelativePath() public void LoadFromInlineDataRelativePath()
{ {
var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(KubeConfigWithRelativePathsFileName, var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(
KubeConfigWithRelativePathsFileName,
"victorian-context"); "victorian-context");
// Just validate that this doesn't throw and private key is non-null // Just validate that this doesn't throw and private key is non-null

View File

@@ -1,6 +1,3 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Security; using System.Net.Security;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using Xunit; using Xunit;

View File

@@ -4,7 +4,6 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using FluentAssertions; using FluentAssertions;
using k8s.Authentication; using k8s.Authentication;
using Xunit;
namespace k8s.Tests namespace k8s.Tests
{ {

View File

@@ -161,7 +161,8 @@ namespace k8s.Tests
public void CreatedFromPreLoadedConfig() public void CreatedFromPreLoadedConfig()
{ {
var k8sConfig = var k8sConfig =
KubernetesClientConfiguration.LoadKubeConfig(new FileInfo("assets/kubeconfig.yml"), KubernetesClientConfiguration.LoadKubeConfig(
new FileInfo("assets/kubeconfig.yml"),
useRelativePaths: false); useRelativePaths: false);
var cfg = KubernetesClientConfiguration.BuildConfigFromConfigObject(k8sConfig); var cfg = KubernetesClientConfiguration.BuildConfigFromConfigObject(k8sConfig);
Assert.NotNull(cfg.Host); Assert.NotNull(cfg.Host);
@@ -173,7 +174,8 @@ namespace k8s.Tests
[Fact] [Fact]
public void DefaultConfigurationLoaded() public void DefaultConfigurationLoaded()
{ {
var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(new FileInfo("assets/kubeconfig.yml"), var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(
new FileInfo("assets/kubeconfig.yml"),
useRelativePaths: false); useRelativePaths: false);
Assert.NotNull(cfg.Host); Assert.NotNull(cfg.Host);
} }
@@ -442,7 +444,8 @@ namespace k8s.Tests
var filePath = Path.GetFullPath("assets/kubeconfig.relative.yml"); var filePath = Path.GetFullPath("assets/kubeconfig.relative.yml");
var environmentVariable = "KUBECONFIG_LoadKubeConfigFromEnvironmentVariable_MultipleConfigs"; var environmentVariable = "KUBECONFIG_LoadKubeConfigFromEnvironmentVariable_MultipleConfigs";
Environment.SetEnvironmentVariable(environmentVariable, Environment.SetEnvironmentVariable(
environmentVariable,
string.Concat(filePath, RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ';' : ':', filePath)); string.Concat(filePath, RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ';' : ':', filePath));
KubernetesClientConfiguration.KubeConfigEnvironmentVariable = environmentVariable; KubernetesClientConfiguration.KubeConfigEnvironmentVariable = environmentVariable;
@@ -576,7 +579,8 @@ namespace k8s.Tests
{ {
Assert.Equal(expected.Name, actual.Name); Assert.Equal(expected.Name, actual.Name);
Assert.Equal(expected.ClusterEndpoint.CertificateAuthority, actual.ClusterEndpoint.CertificateAuthority); Assert.Equal(expected.ClusterEndpoint.CertificateAuthority, actual.ClusterEndpoint.CertificateAuthority);
Assert.Equal(expected.ClusterEndpoint.CertificateAuthorityData, Assert.Equal(
expected.ClusterEndpoint.CertificateAuthorityData,
actual.ClusterEndpoint.CertificateAuthorityData); actual.ClusterEndpoint.CertificateAuthorityData);
Assert.Equal(expected.ClusterEndpoint.Server, actual.ClusterEndpoint.Server); Assert.Equal(expected.ClusterEndpoint.Server, actual.ClusterEndpoint.Server);
Assert.Equal(expected.ClusterEndpoint.SkipTlsVerify, actual.ClusterEndpoint.SkipTlsVerify); Assert.Equal(expected.ClusterEndpoint.SkipTlsVerify, actual.ClusterEndpoint.SkipTlsVerify);

View File

@@ -83,7 +83,8 @@ namespace k8s.Tests.Logging
throw new ArgumentNullException(nameof(formatter)); throw new ArgumentNullException(nameof(formatter));
} }
TestOutput.WriteLine(string.Format("[{0}] {1}: {2}", TestOutput.WriteLine(string.Format(
"[{0}] {1}: {2}",
level, level,
LoggerCategory, LoggerCategory,
formatter(state, exception))); formatter(state, exception)));

View File

@@ -75,7 +75,8 @@ namespace k8s.Tests.Mock
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override async Task<WebSocketReceiveResult> ReceiveAsync(ArraySegment<byte> buffer, public override async Task<WebSocketReceiveResult> ReceiveAsync(
ArraySegment<byte> buffer,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
if (this.receiveBuffers.Count == 0) if (this.receiveBuffers.Count == 0)
@@ -113,7 +114,8 @@ namespace k8s.Tests.Mock
public override Task SendAsync(ArraySegment<byte> buffer, WebSocketMessageType messageType, bool endOfMessage, public override Task SendAsync(ArraySegment<byte> buffer, WebSocketMessageType messageType, bool endOfMessage,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
this.MessageSent?.Invoke(this, this.MessageSent?.Invoke(
this,
new MessageDataEventArgs() new MessageDataEventArgs()
{ {
Data = new MessageData() Data = new MessageData()

View File

@@ -1,7 +1,6 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System; using System;
using System.Net.WebSockets; using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace k8s.Tests.Mock.Server.Controllers namespace k8s.Tests.Mock.Server.Controllers

View File

@@ -2,7 +2,6 @@ using Microsoft.AspNetCore.Mvc;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net.WebSockets; using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace k8s.Tests.Mock.Server.Controllers namespace k8s.Tests.Mock.Server.Controllers

View File

@@ -67,9 +67,9 @@ namespace k8s.Tests
stdout: true, stdout: true,
webSocketSubProtol: WebSocketProtocol.ChannelWebSocketProtocol, webSocketSubProtol: WebSocketProtocol.ChannelWebSocketProtocol,
cancellationToken: TestCancellation).ConfigureAwait(false); cancellationToken: TestCancellation).ConfigureAwait(false);
Assert.Equal(WebSocketProtocol.ChannelWebSocketProtocol, Assert.Equal(
clientSocket WebSocketProtocol.ChannelWebSocketProtocol,
.SubProtocol); // For WebSockets, the Kubernetes API defaults to the binary channel (v1) protocol. clientSocket.SubProtocol); // For WebSockets, the Kubernetes API defaults to the binary channel (v1) protocol.
testOutput.WriteLine( testOutput.WriteLine(
$"Client socket connected (socket state is {clientSocket.State}). Waiting for server-side socket to become available..."); $"Client socket connected (socket state is {clientSocket.State}). Waiting for server-side socket to become available...");
@@ -200,8 +200,9 @@ namespace k8s.Tests
using (Kubernetes client = kubernetesMock.Object) using (Kubernetes client = kubernetesMock.Object)
{ {
await Assert.ThrowsAsync<ArgumentNullException>(() => client.NamespacedPodExecAsync("pod-name", await Assert.ThrowsAsync<ArgumentNullException>(() => client.NamespacedPodExecAsync(
"pod-namespace", "my-container", command, false, null, CancellationToken.None)) "pod-name",
"pod-namespace", "my-container", command, false, null, CancellationToken.None))
.ConfigureAwait(false); .ConfigureAwait(false);
} }
} }
@@ -223,8 +224,9 @@ namespace k8s.Tests
using (Kubernetes client = kubernetesMock.Object) using (Kubernetes client = kubernetesMock.Object)
{ {
var ex = await Assert.ThrowsAsync<KubernetesException>(() => client.NamespacedPodExecAsync("pod-name", var ex = await Assert.ThrowsAsync<KubernetesException>(() => client.NamespacedPodExecAsync(
"pod-namespace", "my-container", command, false, handler, CancellationToken.None)) "pod-name",
"pod-namespace", "my-container", command, false, handler, CancellationToken.None))
.ConfigureAwait(false); .ConfigureAwait(false);
Assert.Same(status, ex.Status); Assert.Same(status, ex.Status);
} }
@@ -269,8 +271,9 @@ namespace k8s.Tests
using (Kubernetes client = kubernetesMock.Object) using (Kubernetes client = kubernetesMock.Object)
{ {
var ex = await Assert.ThrowsAsync<Exception>(() => client.NamespacedPodExecAsync("pod-name", var ex = await Assert.ThrowsAsync<Exception>(() => client.NamespacedPodExecAsync(
"pod-namespace", "my-container", command, false, handler, CancellationToken.None)) "pod-name",
"pod-namespace", "my-container", command, false, handler, CancellationToken.None))
.ConfigureAwait(false); .ConfigureAwait(false);
Assert.Same(exception, ex); Assert.Same(exception, ex);
} }

View File

@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Net.WebSockets; using System.Net.WebSockets;
using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using k8s.Tests.Mock; using k8s.Tests.Mock;
@@ -37,7 +36,8 @@ namespace k8s.Tests
stream.Write(b, 0, b.Length); stream.Write(b, 0, b.Length);
// Send 100 bytes, expect 1 (channel index) + 100 (payload) = 101 bytes // Send 100 bytes, expect 1 (channel index) + 100 (payload) = 101 bytes
Assert.True(await WaitForAsync(() => sentBuffer.Count == 101).ConfigureAwait(false), Assert.True(
await WaitForAsync(() => sentBuffer.Count == 101).ConfigureAwait(false),
$"Demuxer error: expect to send 101 bytes, but actually send {sentBuffer.Count} bytes."); $"Demuxer error: expect to send 101 bytes, but actually send {sentBuffer.Count} bytes.");
Assert.True(sentBuffer[0] == channelIndex, "The first sent byte is not channel index!"); Assert.True(sentBuffer[0] == channelIndex, "The first sent byte is not channel index!");
Assert.True(sentBuffer[1] == 0xEF, "Incorrect payload!"); Assert.True(sentBuffer[1] == 0xEF, "Incorrect payload!");
@@ -63,7 +63,8 @@ namespace k8s.Tests
stream.Write(b, 0, b.Length); stream.Write(b, 0, b.Length);
// Send 300 bytes in 2 messages, expect 1 (channel index) * 2 + 300 (payload) = 302 bytes // Send 300 bytes in 2 messages, expect 1 (channel index) * 2 + 300 (payload) = 302 bytes
Assert.True(await WaitForAsync(() => sentBuffer.Count == 302).ConfigureAwait(false), Assert.True(
await WaitForAsync(() => sentBuffer.Count == 302).ConfigureAwait(false),
$"Demuxer error: expect to send 302 bytes, but actually send {sentBuffer.Count} bytes."); $"Demuxer error: expect to send 302 bytes, but actually send {sentBuffer.Count} bytes.");
Assert.True(sentBuffer[0] == channelIndex, "The first sent byte is not channel index!"); Assert.True(sentBuffer[0] == channelIndex, "The first sent byte is not channel index!");
Assert.True(sentBuffer[1] == 0xEF, "The first part of payload incorrect!"); Assert.True(sentBuffer[1] == 0xEF, "The first part of payload incorrect!");
@@ -119,7 +120,8 @@ namespace k8s.Tests
await t.ConfigureAwait(false); await t.ConfigureAwait(false);
Assert.True(receivedBuffer.Count == expectedCount, Assert.True(
receivedBuffer.Count == expectedCount,
$"Demuxer error: expect to receive {expectedCount} bytes, but actually got {receivedBuffer.Count} bytes."); $"Demuxer error: expect to receive {expectedCount} bytes, but actually got {receivedBuffer.Count} bytes.");
Assert.True(receivedBuffer[0] == 0xAA, "The first payload incorrect!"); Assert.True(receivedBuffer[0] == 0xAA, "The first payload incorrect!");
Assert.True(receivedBuffer[98] == 0xAA, "The first payload incorrect!"); Assert.True(receivedBuffer[98] == 0xAA, "The first payload incorrect!");
@@ -178,7 +180,8 @@ namespace k8s.Tests
await t.ConfigureAwait(false); await t.ConfigureAwait(false);
Assert.True(receivedBuffer.Count == expectedCount, Assert.True(
receivedBuffer.Count == expectedCount,
$"Demuxer error: expect to receive {expectedCount} bytes, but actually got {receivedBuffer.Count} bytes."); $"Demuxer error: expect to receive {expectedCount} bytes, but actually got {receivedBuffer.Count} bytes.");
Assert.True(receivedBuffer[0] == 0xB1, "The first payload incorrect!"); Assert.True(receivedBuffer[0] == 0xB1, "The first payload incorrect!");
Assert.True(receivedBuffer[96] == 0xB1, "The first payload incorrect!"); Assert.True(receivedBuffer[96] == 0xB1, "The first payload incorrect!");
@@ -237,7 +240,8 @@ namespace k8s.Tests
await t.ConfigureAwait(false); await t.ConfigureAwait(false);
Assert.True(receivedBuffer.Count == expectedCount, Assert.True(
receivedBuffer.Count == expectedCount,
$"Demuxer error: expect to receive {expectedCount} bytes, but actually got {receivedBuffer.Count} bytes."); $"Demuxer error: expect to receive {expectedCount} bytes, but actually got {receivedBuffer.Count} bytes.");
Assert.True(receivedBuffer[0] == 0xC2, "The first payload incorrect!"); Assert.True(receivedBuffer[0] == 0xC2, "The first payload incorrect!");
Assert.True(receivedBuffer[98] == 0xC2, "The first payload incorrect!"); Assert.True(receivedBuffer[98] == 0xC2, "The first payload incorrect!");
@@ -320,9 +324,11 @@ namespace k8s.Tests
}); });
await Task.WhenAll(t1, t2, t3).ConfigureAwait(false); await Task.WhenAll(t1, t2, t3).ConfigureAwait(false);
Assert.True(receivedBuffer1.Count == expectedCount1, Assert.True(
receivedBuffer1.Count == expectedCount1,
$"Demuxer error: expect to receive {expectedCount1} bytes, but actually got {receivedBuffer1.Count} bytes."); $"Demuxer error: expect to receive {expectedCount1} bytes, but actually got {receivedBuffer1.Count} bytes.");
Assert.True(receivedBuffer2.Count == expectedCount2, Assert.True(
receivedBuffer2.Count == expectedCount2,
$"Demuxer error: expect to receive {expectedCount2} bytes, but actually got {receivedBuffer2.Count} bytes."); $"Demuxer error: expect to receive {expectedCount2} bytes, but actually got {receivedBuffer2.Count} bytes.");
Assert.True(receivedBuffer1[0] == 0xD1, "The first payload incorrect!"); Assert.True(receivedBuffer1[0] == 0xD1, "The first payload incorrect!");
Assert.True(receivedBuffer1[98] == 0xD1, "The first payload incorrect!"); Assert.True(receivedBuffer1[98] == 0xD1, "The first payload incorrect!");
@@ -409,9 +415,11 @@ namespace k8s.Tests
}); });
await Task.WhenAll(t1, t2, t3).ConfigureAwait(false); await Task.WhenAll(t1, t2, t3).ConfigureAwait(false);
Assert.True(receivedBuffer1.Count == expectedCount1, Assert.True(
receivedBuffer1.Count == expectedCount1,
$"Demuxer error: expect to receive {expectedCount1} bytes, but actually got {receivedBuffer1.Count} bytes."); $"Demuxer error: expect to receive {expectedCount1} bytes, but actually got {receivedBuffer1.Count} bytes.");
Assert.True(receivedBuffer2.Count == expectedCount2, Assert.True(
receivedBuffer2.Count == expectedCount2,
$"Demuxer error: expect to receive {expectedCount2} bytes, but actually got {receivedBuffer2.Count} bytes."); $"Demuxer error: expect to receive {expectedCount2} bytes, but actually got {receivedBuffer2.Count} bytes.");
Assert.True(receivedBuffer1[0] == 0xE1, "The first payload incorrect!"); Assert.True(receivedBuffer1[0] == 0xE1, "The first payload incorrect!");
Assert.True(receivedBuffer1[96] == 0xE1, "The first payload incorrect!"); Assert.True(receivedBuffer1[96] == 0xE1, "The first payload incorrect!");

View File

@@ -1,5 +1,4 @@
using System; using System;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Xunit; using Xunit;

View File

@@ -3,7 +3,6 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using FluentAssertions; using FluentAssertions;
using k8s.Authentication; using k8s.Authentication;
using Xunit;
namespace k8s.Tests namespace k8s.Tests
{ {

View File

@@ -1,4 +1,3 @@
using System.Collections.Generic;
using k8s.Models; using k8s.Models;
using Xunit; using Xunit;
using FluentAssertions; using FluentAssertions;

View File

@@ -8,11 +8,9 @@ using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using k8s.Exceptions;
using k8s.Models; using k8s.Models;
using k8s.Tests.Mock; using k8s.Tests.Mock;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Converters; using Newtonsoft.Json.Converters;
using Nito.AsyncEx; using Nito.AsyncEx;
@@ -430,7 +428,8 @@ namespace k8s.Tests
{ {
internal bool Called { get; private set; } internal bool Called { get; private set; }
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
Called = true; Called = true;

View File

@@ -179,7 +179,8 @@ namespace k8s.Tests
{ {
if (received.IsFaulted) if (received.IsFaulted)
{ {
testOutput.WriteLine("Server socket operation to receive Close message failed: {0}", testOutput.WriteLine(
"Server socket operation to receive Close message failed: {0}",
received.Exception.Flatten().InnerExceptions[0]); received.Exception.Flatten().InnerExceptions[0]);
} }
else if (received.IsCanceled) else if (received.IsCanceled)

View File

@@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Text; using System.Text;
using k8s.Models; using k8s.Models;
using Xunit; using Xunit;
@@ -114,7 +113,8 @@ metadata:
var pod = new V1Pod() { ApiVersion = "v1", Kind = "Pod", Metadata = new V1ObjectMeta() { Name = "foo" } }; var pod = new V1Pod() { ApiVersion = "v1", Kind = "Pod", Metadata = new V1ObjectMeta() { Name = "foo" } };
var yaml = Yaml.SaveToString(pod); var yaml = Yaml.SaveToString(pod);
Assert.Equal(ToLines(@"apiVersion: v1 Assert.Equal(
ToLines(@"apiVersion: v1
kind: Pod kind: Pod
metadata: metadata:
name: foo"), ToLines(yaml)); name: foo"), ToLines(yaml));
@@ -131,7 +131,8 @@ metadata:
}; };
var yaml = Yaml.SaveToString(pod); var yaml = Yaml.SaveToString(pod);
Assert.Equal(ToLines(@"apiVersion: v1 Assert.Equal(
ToLines(@"apiVersion: v1
kind: Pod kind: Pod
metadata: metadata:
name: foo name: foo
@@ -170,7 +171,8 @@ metadata:
}; };
var yaml = Yaml.SaveToString(pod); var yaml = Yaml.SaveToString(pod);
Assert.Equal(ToLines(@"apiVersion: v1 Assert.Equal(
ToLines(@"apiVersion: v1
kind: Pod kind: Pod
metadata: metadata:
name: foo name: foo