Support relative paths in Kubernetes configuration files (#141)

* Support relative paths in Kubernetes configuration files

* Filename -> FileName

* Filename -> FileName

* KuberentesClientConfiguration: Allow the user to opt-out of the mechanism which resolves relative paths in the configuration file.

* Update unit tests

* Fix test
This commit is contained in:
Frederik Carlier
2018-04-27 06:13:48 +02:00
committed by Brendan Burns
parent eea4c88f8e
commit d90289a094
5 changed files with 182 additions and 40 deletions

View File

@@ -28,28 +28,32 @@ namespace k8s
/// Initializes a new instance of the <see cref="KubernetesClientConfiguration" /> from config file
/// </summary>
/// <param name="masterUrl">kube api server endpoint</param>
/// <param name="kubeconfigPath">Explicit file path to kubeconfig. Set to null to use the default file path</param>
/// <param name="kubeconfigPath">Explicit file path to kubeconfig. Set to null to use the default file path</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
/// 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,
string currentContext = null, string masterUrl = null)
string currentContext = null, string masterUrl = null, bool useRelativePaths = true)
{
return BuildConfigFromConfigFile(new FileInfo(kubeconfigPath ?? KubeConfigDefaultLocation), null,
masterUrl);
masterUrl, useRelativePaths);
}
/// <summary>
/// </summary>
/// <param name="kubeconfig">Fileinfo of the kubeconfig, cannot be null</param>
/// <param name="currentContext">override the context in config file, set null if do not want to override</param>
/// <param name="masterUrl">overrider 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
/// 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,
string currentContext = null, string masterUrl = null)
string currentContext = null, string masterUrl = null, bool useRelativePaths = true)
{
if (kubeconfig == null)
{
throw new NullReferenceException(nameof(kubeconfig));
}
var k8SConfig = LoadKubeConfig(kubeconfig);
var k8SConfig = LoadKubeConfig(kubeconfig, useRelativePaths);
var k8SConfiguration = GetKubernetesClientConfiguration(currentContext, masterUrl, k8SConfig);
return k8SConfiguration;
@@ -172,7 +176,7 @@ namespace k8s
}
else if (!string.IsNullOrEmpty(clusterDetails.ClusterEndpoint.CertificateAuthority))
{
SslCaCert = new X509Certificate2(clusterDetails.ClusterEndpoint.CertificateAuthority);
SslCaCert = new X509Certificate2(GetFullPath(k8SConfig, clusterDetails.ClusterEndpoint.CertificateAuthority));
}
}
}
@@ -230,8 +234,8 @@ namespace k8s
if (!string.IsNullOrWhiteSpace(userDetails.UserCredentials.ClientCertificate) &&
!string.IsNullOrWhiteSpace(userDetails.UserCredentials.ClientKey))
{
ClientCertificateFilePath = userDetails.UserCredentials.ClientCertificate;
ClientKeyFilePath = userDetails.UserCredentials.ClientKey;
ClientCertificateFilePath = GetFullPath(k8SConfig, userDetails.UserCredentials.ClientCertificate);
ClientKeyFilePath = GetFullPath(k8SConfig, userDetails.UserCredentials.ClientKey);
userCredentialsFound = true;
}
@@ -245,31 +249,37 @@ namespace k8s
/// <summary>
/// Loads entire Kube Config from default or explicit file path
/// </summary>
/// <param name="kubeconfigPath">Explicit file path to kubeconfig. Set to null to use the default file path</param>
/// <returns></returns>
public static async Task<K8SConfiguration> LoadKubeConfigAsync(string kubeconfigPath = null)
/// <param name="kubeconfigPath">Explicit file path to kubeconfig. Set to null to use the default file path</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
/// 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>
public static async Task<K8SConfiguration> LoadKubeConfigAsync(string kubeconfigPath = null, bool useRelativePaths = true)
{
var fileInfo = new FileInfo(kubeconfigPath ?? KubeConfigDefaultLocation);
return await LoadKubeConfigAsync(fileInfo);
return await LoadKubeConfigAsync(fileInfo, useRelativePaths);
}
/// <summary>
/// Loads entire Kube Config from default or explicit file path
/// </summary>
/// <param name="kubeconfigPath">Explicit file path to kubeconfig. Set to null to use the default file path</param>
/// <returns></returns>
public static K8SConfiguration LoadKubeConfig(string kubeconfigPath = null)
/// <param name="kubeconfigPath">Explicit file path to kubeconfig. Set to null to use the default file path</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
/// 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>
public static K8SConfiguration LoadKubeConfig(string kubeconfigPath = null, bool useRelativePaths = true)
{
return LoadKubeConfigAsync(kubeconfigPath).GetAwaiter().GetResult();
return LoadKubeConfigAsync(kubeconfigPath, useRelativePaths).GetAwaiter().GetResult();
}
// <summary>
/// Loads Kube Config
/// </summary>
/// <param name="kubeconfig">Kube config file contents</param>
/// <param name="kubeconfig">Kube config file contents</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
/// 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>
public static async Task<K8SConfiguration> LoadKubeConfigAsync(FileInfo kubeconfig)
public static async Task<K8SConfiguration> LoadKubeConfigAsync(FileInfo kubeconfig, bool useRelativePaths = true)
{
if (!kubeconfig.Exists)
{
@@ -278,18 +288,27 @@ namespace k8s
using (var stream = kubeconfig.OpenRead())
{
return await Yaml.LoadFromStreamAsync<K8SConfiguration>(stream);
var config = await Yaml.LoadFromStreamAsync<K8SConfiguration>(stream);
if (useRelativePaths)
{
config.FileName = kubeconfig.FullName;
}
return config;
}
}
/// <summary>
/// Loads Kube Config
/// </summary>
/// <param name="kubeconfig">Kube config file contents</param>
/// <param name="kubeconfig">Kube config file contents</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
/// 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>
public static K8SConfiguration LoadKubeConfig(FileInfo kubeconfig)
public static K8SConfiguration LoadKubeConfig(FileInfo kubeconfig, bool useRelativePaths = true)
{
return LoadKubeConfigAsync(kubeconfig).GetAwaiter().GetResult();
return LoadKubeConfigAsync(kubeconfig, useRelativePaths).GetAwaiter().GetResult();
}
// <summary>
@@ -311,5 +330,35 @@ namespace k8s
{
return LoadKubeConfigAsync(kubeconfigStream).GetAwaiter().GetResult();
}
/// <summary>
/// Tries to get the full path to a file referenced from the Kubernetes configuration.
/// </summary>
/// <param name="configuration">
/// The Kubernetes configuration.
/// </param>
/// <param name="path">
/// The path to resolve.
/// </param>
/// <returns>
/// When possible a fully qualified path to the file.
/// </returns>
/// <remarks>
/// For example, if the configuration file is at "C:\Users\me\kube.config" and path is "ca.crt",
/// this will return "C:\Users\me\ca.crt". Similarly, if path is "D:\ca.cart", this will return
/// "D:\ca.crt".
/// </remarks>
private static string GetFullPath(K8SConfiguration configuration, string path)
{
// If we don't have a file name,
if (string.IsNullOrWhiteSpace(configuration.FileName) || Path.IsPathRooted(path))
{
return path;
}
else
{
return Path.Combine(Path.GetDirectoryName(configuration.FileName), path);
}
}
}
}