diff --git a/src/KubernetesClientConfiguration.ConfigFile.cs b/src/KubernetesClientConfiguration.ConfigFile.cs
index 6ec531f..559d07a 100644
--- a/src/KubernetesClientConfiguration.ConfigFile.cs
+++ b/src/KubernetesClientConfiguration.ConfigFile.cs
@@ -51,12 +51,25 @@ namespace k8s
var k8SConfig = LoadKubeConfig(kubeconfig);
var k8SConfiguration = new KubernetesClientConfiguration();
- k8SConfiguration.Initialize(k8SConfig, currentContext);
+
+ currentContext = currentContext ?? k8SConfig.CurrentContext;
+
+ // only init context if context if set
+ if (currentContext != null)
+ {
+ k8SConfiguration.InitializeContext(k8SConfig, currentContext);
+ }
if (!string.IsNullOrWhiteSpace(masterUrl))
{
k8SConfiguration.Host = masterUrl;
}
+
+ if (string.IsNullOrWhiteSpace(k8SConfiguration.Host))
+ {
+ throw new KubeConfigException("Cannot infer server host url either from context or masterUrl");
+ }
+
return k8SConfiguration;
}
@@ -65,11 +78,9 @@ namespace k8s
///
/// Kubernetes Configuration
/// Current Context
- private void Initialize(K8SConfiguration k8SConfig, string currentContext = null)
+ private void InitializeContext(K8SConfiguration k8SConfig, string currentContext)
{
// current context
- currentContext = currentContext ?? k8SConfig.CurrentContext;
-
var activeContext =
k8SConfig.Contexts.FirstOrDefault(
c => c.Name.Equals(currentContext, StringComparison.OrdinalIgnoreCase));
diff --git a/tests/KubernetesClientConfigurationTests.cs b/tests/KubernetesClientConfigurationTests.cs
index 62d24e7..e996c05 100755
--- a/tests/KubernetesClientConfigurationTests.cs
+++ b/tests/KubernetesClientConfigurationTests.cs
@@ -1,97 +1,26 @@
-using Xunit;
using System.IO;
+using k8s.Exceptions;
+using Xunit;
namespace k8s.Tests
{
public class KubernetesClientConfigurationTests
{
-
- public static string readLine(string fileName)
- {
- StreamReader reader = new StreamReader(new FileStream(fileName, FileMode.Open, FileAccess.Read));
- return reader.ReadLine();
- }
-
///
- /// This file contains a sample kubeconfig file
- ///
- private static readonly string kubeConfigFileName = "assets/kubeconfig.yml";
-
- ///
- /// Invalid test file with no context on purpose
- ///
- private static readonly string kubeConfigNoContexts = "assets/kubeconfig-no-context.yml";
-
- ///
- /// Sample configuration file with user/password authentication
- ///
- private static readonly string kubeConfigUserPassword = "assets/kubeconfig.user-pass.yml";
-
- ///
- /// Sample configuration file with incorrect user credentials structures on purpose
- ///
- private static readonly string kubeConfigNoCredentials = "assets/kubeconfig.no-credentials.yml";
-
- ///
- /// Sample configuration file with incorrect cluster/server structure on purpose
- ///
- private static readonly string kubeConfigNoServer = "assets/kubeconfig.no-server.yml";
-
- ///
- /// Sample configuration file with incorrect cluster/server structure on purpose
- ///
- private static readonly string kubeConfigNoCluster = "assets/kubeconfig.no-cluster.yml";
-
- ///
- /// Sample configuration file with incorrect match in cluster name
- ///
- private static readonly string kubeConfigClusterMissmatch = "assets/kubeconfig.cluster-missmatch.yml";
-
- ///
- /// Sample configuration file with incorrect TLS configuration in cluster section
- ///
- private static readonly string kubeConfigTlsNoSkipError = "assets/kubeconfig.tls-no-skip-error.yml";
-
- ///
- /// Sample configuration file with incorrect TLS configuration in cluster section
- ///
- private static readonly string kubeConfigTlsSkip = "assets/kubeconfig.tls-skip.yml";
-
- ///
- /// The configuration file is not present. An KubeConfigException should be thrown
- ///
- [Fact]
- public void ConfigurationFileNotFound()
- {
- var fi = new FileInfo("/path/to/nowhere");
- Assert.Throws(() => KubernetesClientConfiguration.BuildConfigFromConfigFile(fi));
- }
-
- ///
- /// Checks Host is loaded from the default configuration file
- ///
- [Fact]
- public void DefaultConfigurationLoaded()
- {
- var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(new FileInfo(kubeConfigFileName));
- Assert.NotNull(cfg.Host);
- }
-
- ///
- /// Check if host is properly loaded, per context
+ /// Check if host is properly loaded, per context
///
[Theory]
[InlineData("federal-context", "https://horse.org:4443")]
[InlineData("queen-anne-context", "https://pig.org:443")]
public void ContextHost(string context, string host)
{
- var fi = new FileInfo(kubeConfigFileName);
+ var fi = new FileInfo("assets/kubeconfig.yml");
var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(fi, context);
Assert.Equal(host, cfg.Host);
}
///
- /// Checks if user-based token is loaded properly from the config file, per context
+ /// Checks if user-based token is loaded properly from the config file, per context
///
///
///
@@ -99,7 +28,7 @@ namespace k8s.Tests
[InlineData("queen-anne-context", "black-token")]
public void ContextUserToken(string context, string token)
{
- var fi = new FileInfo(kubeConfigFileName);
+ var fi = new FileInfo("assets/kubeconfig.yml");
var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(fi, context);
Assert.Equal(context, cfg.CurrentContext);
Assert.Null(cfg.Username);
@@ -107,16 +36,16 @@ namespace k8s.Tests
}
///
- /// Checks if certificate-based authentication is loaded properly from the config file, per context
+ /// Checks if certificate-based authentication is loaded properly from the config file, per context
///
/// Context to retreive the configuration
- /// 'client-certificate-data' node content
+ /// 'client-certificate-data' node content
/// 'client-key-data' content
[Theory]
[InlineData("federal-context", "assets/client.crt", "assets/client.key")]
- public void ContextCertificateTest(string context, string clientCert, string clientCertKey)
+ public void ContextCertificate(string context, string clientCert, string clientCertKey)
{
- var fi = new FileInfo(kubeConfigFileName);
+ var fi = new FileInfo("assets/kubeconfig.yml");
var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(fi, context);
Assert.Equal(context, cfg.CurrentContext);
Assert.Equal(cfg.ClientCertificateFilePath, clientCert);
@@ -124,138 +53,211 @@ namespace k8s.Tests
}
///
- /// Checks if certificate-based authentication is loaded properly from the config file, per context
+ /// Checks if certificate-based authentication is loaded properly from the config file, per context
///
/// Context to retreive the configuration
[Theory]
[InlineData("victorian-context")]
public void ClientData(string context)
{
- var fi = new FileInfo(kubeConfigFileName);
+ var fi = new FileInfo("assets/kubeconfig.yml");
var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(fi, context);
Assert.Equal(context, cfg.CurrentContext);
Assert.NotNull(cfg.SslCaCert);
- Assert.Equal(readLine("assets/client-certificate-data.txt"), cfg.ClientCertificateData);
- Assert.Equal(readLine("assets/client-key-data.txt"), cfg.ClientCertificateKeyData);
- }
-
-
- ///
- /// Test that an Exception is thrown when initializating a KubernetClientConfiguration whose config file Context is not present
- ///
- [Fact]
- public void ContextNotFound()
- {
- var fi = new FileInfo(kubeConfigFileName);
- Assert.Throws(() => KubernetesClientConfiguration.BuildConfigFromConfigFile(fi, "context-not-found"));
+ Assert.Equal(File.ReadAllText("assets/client-certificate-data.txt"), cfg.ClientCertificateData);
+ Assert.Equal(File.ReadAllText("assets/client-key-data.txt"), cfg.ClientCertificateKeyData);
}
///
- /// Test if KubeConfigException is thrown when no Contexts and we use the default context name
- ///
- [Fact]
- public void NoContexts()
- {
- var fi = new FileInfo(kubeConfigNoContexts);
- Assert.Throws(() => KubernetesClientConfiguration.BuildConfigFromConfigFile(fi));
- }
-
- ///
- /// Test if KubeConfigException is thrown when no Contexts are set and we specify a concrete context name
- ///
- [Fact]
- public void NoContextsExplicit()
- {
- var fi = new FileInfo(kubeConfigNoContexts);
- Assert.Throws(() => KubernetesClientConfiguration.BuildConfigFromConfigFile(fi, "context"));
- }
-
- ///
- /// Checks user/password authentication information is read properly
- ///
- [Fact]
- public void UserPasswordAuthentication()
- {
- var fi = new FileInfo(kubeConfigUserPassword);
- var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(fi);
- Assert.Equal("admin", cfg.Username);
- Assert.Equal("secret", cfg.Password);
- }
-
- ///
- /// Checks that a KubeConfigException is thrown when incomplete user credentials
- ///
- [Fact]
- public void IncompleteUserCredentials()
- {
- var fi = new FileInfo(kubeConfigNoCredentials);
- Assert.Throws(() => KubernetesClientConfiguration.BuildConfigFromConfigFile(fi));
- }
-
- ///
- /// Checks that a KubeConfigException is thrown when the server property is not set in cluster
- ///
- [Fact]
- public void ServerNotFound()
- {
- var fi = new FileInfo(kubeConfigNoServer);
- Assert.Throws(() => KubernetesClientConfiguration.BuildConfigFromConfigFile(fi));
- }
-
- ///
- /// Checks that a KubeConfigException is thrown when the clusters section is missing
- ///
- [Fact]
- public void ClusterNotFound()
- {
- var fi = new FileInfo(kubeConfigNoCluster);
- Assert.Throws(() => KubernetesClientConfiguration.BuildConfigFromConfigFile(fi));
- }
-
- ///
- /// Checks that a KubeConfigException is thrown when the cluster defined in clusters and contexts do not match
- ///
- [Fact]
- public void ClusterNameMissmatch()
- {
- var fi = new FileInfo(kubeConfigClusterMissmatch);
- Assert.Throws(() => KubernetesClientConfiguration.BuildConfigFromConfigFile(fi));
- }
-
- ///
- /// Checks that a KubeConfigException is thrown when no certificate-authority-data is set and user do not require tls skip
+ /// Checks that a KubeConfigException is thrown when no certificate-authority-data is set and user do not require tls
+ /// skip
///
[Fact]
public void CheckClusterTlsCorrectness()
{
- var fi = new FileInfo(kubeConfigTlsNoSkipError);
- Assert.Throws(() => KubernetesClientConfiguration.BuildConfigFromConfigFile(fi));
+ var fi = new FileInfo("assets/kubeconfig.tls-no-skip-error.yml");
+ Assert.Throws(() => KubernetesClientConfiguration.BuildConfigFromConfigFile(fi));
}
///
- /// Checks that a KubeConfigException is thrown when no certificate-authority-data is set and user do not require tls skip
+ /// Checks that a KubeConfigException is thrown when no certificate-authority-data is set and user do not require tls
+ /// skip
///
[Fact]
public void CheckClusterTlsSkipCorrectness()
{
- var fi = new FileInfo(kubeConfigTlsSkip);
+ var fi = new FileInfo("assets/kubeconfig.tls-skip.yml");
var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(fi);
Assert.NotNull(cfg.Host);
Assert.Null(cfg.SslCaCert);
Assert.True(cfg.SkipTlsVerify);
}
- // ///
- // /// Checks if the are pods
- // ///
- // [Fact]
- // public void ListDefaultNamespacedPod()
- // {
- // var k8sClientConfig = KubernetesClientConfiguration.BuildConfigFromConfigFile();
- // IKubernetes client = new Kubernetes(k8sClientConfig);
- // var listTask = client.ListNamespacedPodWithHttpMessagesAsync("default").Result;
- // var list = listTask.Body;
- // Assert.NotEqual(0, list.Items.Count);
- // }
+ ///
+ /// Checks that a KubeConfigException is thrown when the cluster defined in clusters and contexts do not match
+ ///
+ [Fact]
+ public void ClusterNameMissmatch()
+ {
+ var fi = new FileInfo("assets/kubeconfig.cluster-missmatch.yml");
+ Assert.Throws(() => KubernetesClientConfiguration.BuildConfigFromConfigFile(fi));
+ }
+
+ ///
+ /// Checks that a KubeConfigException is thrown when the clusters section is missing
+ ///
+ [Fact]
+ public void ClusterNotFound()
+ {
+ var fi = new FileInfo("assets/kubeconfig.no-cluster.yml");
+ Assert.Throws(() => KubernetesClientConfiguration.BuildConfigFromConfigFile(fi));
+ }
+
+ ///
+ /// The configuration file is not present. An KubeConfigException should be thrown
+ ///
+ [Fact]
+ public void ConfigurationFileNotFound()
+ {
+ var fi = new FileInfo("/path/to/nowhere");
+ Assert.Throws(() => KubernetesClientConfiguration.BuildConfigFromConfigFile(fi));
+ }
+
+
+ ///
+ /// Test that an Exception is thrown when initializating a KubernetClientConfiguration whose config file Context is not
+ /// present
+ ///
+ [Fact]
+ public void ContextNotFound()
+ {
+ var fi = new FileInfo("assets/kubeconfig.yml");
+ Assert.Throws(() =>
+ KubernetesClientConfiguration.BuildConfigFromConfigFile(fi, "context-not-found"));
+ }
+
+ ///
+ /// Checks Host is loaded from the default configuration file
+ ///
+ [Fact]
+ public void DefaultConfigurationLoaded()
+ {
+ var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(new FileInfo("assets/kubeconfig.yml"));
+ Assert.NotNull(cfg.Host);
+ }
+
+ ///
+ /// Checks that a KubeConfigException is thrown when incomplete user credentials
+ ///
+ [Fact]
+ public void IncompleteUserCredentials()
+ {
+ var fi = new FileInfo("assets/kubeconfig.no-credentials.yml");
+ Assert.Throws(() => KubernetesClientConfiguration.BuildConfigFromConfigFile(fi));
+ }
+
+ ///
+ /// Test if KubeConfigException is thrown when no Contexts and we use the default context name
+ ///
+ [Fact]
+ public void NoContexts()
+ {
+ var fi = new FileInfo("assets/kubeconfig.no-context.yml");
+ Assert.Throws(() => KubernetesClientConfiguration.BuildConfigFromConfigFile(fi));
+ }
+
+ ///
+ /// Test if KubeConfigException is thrown when no Contexts are set and we specify a concrete context name
+ ///
+ [Fact]
+ public void NoContextsExplicit()
+ {
+ var fi = new FileInfo("assets/kubeconfig-no-context.yml");
+ Assert.Throws(() =>
+ KubernetesClientConfiguration.BuildConfigFromConfigFile(fi, "context"));
+ }
+
+ ///
+ /// Checks that a KubeConfigException is thrown when the server property is not set in cluster
+ ///
+ [Fact]
+ public void ServerNotFound()
+ {
+ var fi = new FileInfo("assets/kubeconfig.no-server.yml");
+ Assert.Throws(() => KubernetesClientConfiguration.BuildConfigFromConfigFile(fi));
+ }
+
+ ///
+ /// Checks user/password authentication information is read properly
+ ///
+ [Fact]
+ public void UserPasswordAuthentication()
+ {
+ var fi = new FileInfo("assets/kubeconfig.user-pass.yml");
+ var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(fi);
+ Assert.Equal("admin", cfg.Username);
+ Assert.Equal("secret", cfg.Password);
+ }
+
+ ///
+ /// Checks that a KubeConfigException is thrown when user cannot be found in users
+ ///
+ [Fact]
+ public void UserNotFound()
+ {
+ var fi = new FileInfo("assets/kubeconfig.user-not-found.yml");
+ Assert.Throws(() => KubernetesClientConfiguration.BuildConfigFromConfigFile(fi));
+ }
+
+ ///
+ /// Make sure that user is not a necessary field. set #issue 24
+ ///
+ [Fact]
+ public void EmptyUserNotFound()
+ {
+ var fi = new FileInfo("assets/kubeconfig.no-user.yml");
+ var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(fi);
+
+ Assert.NotEmpty(cfg.Host);
+ }
+
+ ///
+ /// Make sure Host is replaced by masterUrl
+ ///
+ [Fact]
+ public void OverrideByMasterUrl()
+ {
+ var fi = new FileInfo("assets/kubeconfig.yml");
+ var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(fi, masterUrl: "http://test.server");
+ Assert.Equal("http://test.server", cfg.Host);
+ }
+
+ ///
+ /// Make sure that http urls are loaded even if insecure-skip-tls-verify === true
+ ///
+ [Fact]
+ public void SmartSkipTlsVerify()
+ {
+ var fi = new FileInfo("assets/kubeconfig.tls-skip-http.yml");
+ var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(fi);
+ Assert.False(cfg.SkipTlsVerify);
+ Assert.Equal("http://horse.org", cfg.Host);
+ }
+
+ ///
+ /// Checks config could work well when current-context is not set but masterUrl is set. #issue 24
+ ///
+ [Fact]
+ public void NoCurrentContext()
+ {
+ var fi = new FileInfo("assets/kubeconfig.no-current-context.yml");
+
+ // failed if cannot infer any server host
+ Assert.Throws(() => KubernetesClientConfiguration.BuildConfigFromConfigFile(fi));
+
+ // survive when masterUrl is set
+ var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(fi, masterUrl: "http://test.server");
+ Assert.Equal("http://test.server", cfg.Host);
+ }
}
}
diff --git a/tests/assets/kubeconfig-no-context.yml b/tests/assets/kubeconfig.no-context.yml
similarity index 100%
rename from tests/assets/kubeconfig-no-context.yml
rename to tests/assets/kubeconfig.no-context.yml
diff --git a/tests/assets/kubeconfig.no-current-context.yml b/tests/assets/kubeconfig.no-current-context.yml
new file mode 100644
index 0000000..2dd066f
--- /dev/null
+++ b/tests/assets/kubeconfig.no-current-context.yml
@@ -0,0 +1,19 @@
+---
+apiVersion: v1
+clusters:
+- cluster:
+ certificate-authority: assets/ca.crt
+ server: https://horse.org:4443
+ name: horse-cluster
+contexts:
+- context:
+ cluster: horse-cluster
+ namespace: chisel-ns
+ user: green-user
+ name: federal-context
+kind: Config
+users:
+- name: green-user
+ user:
+ password: secret
+ username: admin
\ No newline at end of file
diff --git a/tests/assets/kubeconfig.no-user.yml b/tests/assets/kubeconfig.no-user.yml
new file mode 100644
index 0000000..3fdbc2c
--- /dev/null
+++ b/tests/assets/kubeconfig.no-user.yml
@@ -0,0 +1,14 @@
+---
+current-context: federal-context
+apiVersion: v1
+clusters:
+- cluster:
+ certificate-authority: assets/ca.crt
+ server: https://horse.org:4443
+ name: horse-cluster
+contexts:
+- context:
+ cluster: horse-cluster
+ namespace: chisel-ns
+ name: federal-context
+kind: Config
\ No newline at end of file
diff --git a/tests/assets/kubeconfig.tls-skip-http.yml b/tests/assets/kubeconfig.tls-skip-http.yml
new file mode 100644
index 0000000..55fd56a
--- /dev/null
+++ b/tests/assets/kubeconfig.tls-skip-http.yml
@@ -0,0 +1,19 @@
+---
+current-context: federal-context
+apiVersion: v1
+clusters:
+- cluster:
+ server: http://horse.org
+ name: horse-cluster
+contexts:
+- context:
+ cluster: horse-cluster
+ namespace: chisel-ns
+ user: green-user
+ name: federal-context
+kind: Config
+users:
+- name: green-user
+ user:
+ password: secret
+ username: admin
\ No newline at end of file
diff --git a/tests/assets/kubeconfig.user-not-found.yml b/tests/assets/kubeconfig.user-not-found.yml
new file mode 100644
index 0000000..39b79f6
--- /dev/null
+++ b/tests/assets/kubeconfig.user-not-found.yml
@@ -0,0 +1,15 @@
+---
+current-context: federal-context
+apiVersion: v1
+clusters:
+- cluster:
+ certificate-authority: assets/ca.crt
+ server: https://horse.org:4443
+ name: horse-cluster
+contexts:
+- context:
+ cluster: horse-cluster
+ namespace: chisel-ns
+ user: green-user
+ name: federal-context
+kind: Config
\ No newline at end of file