Skip to content

Commit e89ef57

Browse files
Merge pull request #6 from sesispla/master
Basic tests for configuration and credentials
2 parents 799a6bf + 2ff7b31 commit e89ef57

16 files changed

+512
-16
lines changed

src/KubeConfigModels/User.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
public class User
77
{
88
[YamlMember(Alias = "user")]
9-
public UserCrednetials UserCredentials { get; set; }
9+
public UserCredentials UserCredentials { get; set; }
1010

1111
[YamlMember(Alias = "name")]
1212
public string Name { get; set; }

src/KubeConfigModels/UserCrednetials.cs renamed to src/KubeConfigModels/UserCredentials.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
using YamlDotNet.RepresentationModel;
44
using YamlDotNet.Serialization;
55

6-
public class UserCrednetials
6+
public class UserCredentials
77
{
88
[YamlMember(Alias = "client-certificate-data")]
99
public string ClientCertificateData { get; set; }
@@ -14,7 +14,7 @@ public class UserCrednetials
1414
[YamlMember(Alias = "token")]
1515
public string Token { get; set; }
1616

17-
[YamlMember(Alias = "userName")]
17+
[YamlMember(Alias = "username")]
1818
public string UserName { get; set; }
1919

2020
[YamlMember(Alias = "password")]

src/KubernetesClient.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
<OutputType>Library</OutputType>
44
<TargetFramework>netcoreapp1.1</TargetFramework>
55
</PropertyGroup>
6-
<ItemGroup>
7-
<Compile Remove="GlobalSuppressions.cs" />
6+
<ItemGroup>
7+
<Compile Remove="GlobalSuppressions.cs" />
88
</ItemGroup>
99
<ItemGroup>
1010
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="1.1.0" />

src/KubernetesClientConfiguration.cs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,14 @@ private void Initialize(K8SConfiguration k8SConfig, string currentContext = null
9696
{
9797
Context activeContext;
9898

99+
if (k8SConfig.Contexts == null)
100+
{
101+
throw new KubeConfigException("No contexts found in kubeconfig");
102+
}
103+
99104
// set the currentCOntext to passed context if not null
100105
if (!string.IsNullOrWhiteSpace(currentContext))
101106
{
102-
if (k8SConfig.Contexts == null)
103-
{
104-
throw new KubeConfigException("No contexts found in kubeconfig");
105-
}
106107

107108
activeContext = k8SConfig.Contexts.FirstOrDefault(c => c.Name.Equals(currentContext, StringComparison.OrdinalIgnoreCase));
108109
if (activeContext != null)
@@ -127,6 +128,11 @@ private void Initialize(K8SConfiguration k8SConfig, string currentContext = null
127128
this.CurrentContext = activeContext.Name;
128129
}
129130

131+
if (k8SConfig.Clusters == null)
132+
{
133+
throw new KubeConfigException($"clusters not found for current-context :{activeContext} in kubeconfig");
134+
}
135+
130136
var clusterDetails = k8SConfig.Clusters.FirstOrDefault(c => c.Name.Equals(activeContext.ContextDetails.Cluster, StringComparison.OrdinalIgnoreCase));
131137
if (clusterDetails?.ClusterEndpoint != null)
132138
{
Lines changed: 216 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,68 @@
11
using System;
22
using Xunit;
33
using k8s;
4+
using System.IO;
45

56
namespace k8s.Tests
67
{
78
public class KubernetesClientConfigurationTests
89
{
10+
11+
/// <summary>
12+
/// This file contains a sample kubeconfig file
13+
/// </summary>
14+
private static readonly string kubeConfigFileName = "assets/kubeconfig.yml";
15+
16+
/// <summary>
17+
/// Invalid test file with no context on purpose
18+
/// </summary>
19+
private static readonly string kubeConfigNoContexts = "assets/kubeconfig-no-context.yml";
20+
21+
/// <summary>
22+
/// Sample configuration file with user/password authentication
23+
/// </summary>
24+
private static readonly string kubeConfigUserPassword = "assets/kubeconfig.user-pass.yml";
25+
26+
/// <summary>
27+
/// Sample configuration file with incorrect user credentials structures on purpose
28+
/// </summary>
29+
private static readonly string kubeConfigNoCredentials = "assets/kubeconfig.no-credentials.yml";
30+
31+
/// <summary>
32+
/// Sample configuration file with incorrect cluster/server structure on purpose
33+
/// </summary>
34+
private static readonly string kubeConfigNoServer = "assets/kubeconfig.no-server.yml";
35+
36+
/// <summary>
37+
/// Sample configuration file with incorrect cluster/server structure on purpose
38+
/// </summary>
39+
private static readonly string kubeConfigNoCluster = "assets/kubeconfig.no-cluster.yml";
40+
41+
/// <summary>
42+
/// Sample configuration file with incorrect match in cluster name
43+
/// </summary>
44+
private static readonly string kubeConfigClusterMissmatch = "assets/kubeconfig.cluster-missmatch.yml";
45+
46+
/// <summary>
47+
/// Sample configuration file with incorrect TLS configuration in cluster section
48+
/// </summary>
49+
private static readonly string kubeConfigTlsNoSkipError = "assets/kubeconfig.tls-no-skip-error.yml";
50+
51+
/// <summary>
52+
/// Sample configuration file with incorrect TLS configuration in cluster section
53+
/// </summary>
54+
private static readonly string kubeConfigTlsSkip = "assets/kubeconfig.tls-skip.yml";
55+
56+
/// <summary>
57+
/// The configuration file is not present. An KubeConfigException should be thrown
58+
/// </summary>
59+
[Fact]
60+
public void ConfigurationFileNotFound()
61+
{
62+
var fi = new FileInfo("/path/to/nowhere");
63+
Assert.Throws<k8s.Exceptions.KubeConfigException>(() => new KubernetesClientConfiguration(fi));
64+
}
65+
966
/// <summary>
1067
/// Checks Host is loaded from the default configuration file
1168
/// </summary>
@@ -15,18 +72,170 @@ public void DefaultConfigurationLoaded()
1572
var cfg = new KubernetesClientConfiguration();
1673
Assert.NotNull(cfg.Host);
1774
}
75+
76+
/// <summary>
77+
/// Check if host is properly loaded, per context
78+
/// </summary>
79+
[Theory]
80+
[InlineData("federal-context", "https://horse.org:4443")]
81+
[InlineData("queen-anne-context", "https://pig.org:443")]
82+
public void ContextHostTest(string context, string host)
83+
{
84+
var fi = new FileInfo(kubeConfigFileName);
85+
var cfg = new KubernetesClientConfiguration(fi, context);
86+
Assert.Equal(host, cfg.Host);
87+
}
88+
89+
/// <summary>
90+
/// Checks if user-based token is loaded properly from the config file, per context
91+
/// </summary>
92+
/// <param name="context"></param>
93+
/// <param name="username"></param>
94+
/// <param name="token"></param>
95+
[Theory]
96+
[InlineData("queen-anne-context", "black-token")]
97+
public void ContextUserTokenTest(string context, string token)
98+
{
99+
var fi = new FileInfo(kubeConfigFileName);
100+
var cfg = new KubernetesClientConfiguration(fi, context);
101+
Assert.Equal(context, cfg.CurrentContext);
102+
Assert.Null(cfg.Username);
103+
Assert.Equal(token, cfg.AccessToken);
104+
}
105+
106+
/// <summary>
107+
/// Checks if certificate-based authentication is loaded properly from the config file, per context
108+
/// </summary>
109+
/// <param name="context">Context to retreive the configuration</param>
110+
/// <param name="clientCertData">'client-certificate-data' node content</param>
111+
/// <param name="clientCertKey">'client-key-data' content</param>
112+
[Theory]
113+
[InlineData("federal-context", "path/to/my/client/cert" ,"path/to/my/client/key")]
114+
public void ContextCertificateTest(string context, string clientCertData, string clientCertKey)
115+
{
116+
var fi = new FileInfo(kubeConfigFileName);
117+
var cfg = new KubernetesClientConfiguration(fi, context);
118+
Assert.Equal(context, cfg.CurrentContext);
119+
Assert.Equal(cfg.ClientCertificateData, clientCertData);
120+
Assert.Equal(cfg.ClientCertificateKey, clientCertKey);
121+
}
122+
123+
/// <summary>
124+
/// Test that an Exception is thrown when initializating a KubernetClientConfiguration whose config file Context is not present
125+
/// </summary>
126+
[Fact]
127+
public void ContextNotFoundTest()
128+
{
129+
var fi = new FileInfo(kubeConfigFileName);
130+
Assert.Throws<k8s.Exceptions.KubeConfigException>(() => new KubernetesClientConfiguration(fi, "context-not-found"));
131+
}
18132

19133
/// <summary>
20-
/// Checks if the are pods
134+
/// Test if KubeConfigException is thrown when no Contexts and we use the default context name
21135
/// </summary>
22136
[Fact]
23-
public void ListDefaultNamespacedPod()
137+
public void NoContexts()
24138
{
25-
var k8sClientConfig = new KubernetesClientConfiguration();
26-
IKubernetes client = new Kubernetes(k8sClientConfig);
27-
var listTask = client.ListNamespacedPodWithHttpMessagesAsync("default").Result;
28-
var list = listTask.Body;
29-
Assert.NotEqual(0, list.Items.Count);
139+
var fi = new FileInfo(kubeConfigNoContexts);
140+
Assert.Throws<k8s.Exceptions.KubeConfigException>(() => new KubernetesClientConfiguration(fi));
141+
}
142+
143+
/// <summary>
144+
/// Test if KubeConfigException is thrown when no Contexts are set and we specify a concrete context name
145+
/// </summary>
146+
[Fact]
147+
public void NoContextsExplicit()
148+
{
149+
var fi = new FileInfo(kubeConfigNoContexts);
150+
Assert.Throws<k8s.Exceptions.KubeConfigException>(() => new KubernetesClientConfiguration(fi, "context"));
30151
}
152+
153+
/// <summary>
154+
/// Checks user/password authentication information is read properly
155+
/// </summary>
156+
[Fact]
157+
public void UserPasswordAuthentication()
158+
{
159+
var fi = new FileInfo(kubeConfigUserPassword);
160+
var cfg = new KubernetesClientConfiguration(fi);
161+
Assert.Equal("admin", cfg.Username);
162+
Assert.Equal("secret", cfg.Password);
163+
}
164+
165+
/// <summary>
166+
/// Checks that a KubeConfigException is thrown when incomplete user credentials
167+
/// </summary>
168+
[Fact]
169+
public void IncompleteUserCredentials()
170+
{
171+
var fi = new FileInfo(kubeConfigNoCredentials);
172+
Assert.Throws<k8s.Exceptions.KubeConfigException>(() => new KubernetesClientConfiguration(fi));
173+
}
174+
175+
/// <summary>
176+
/// Checks that a KubeConfigException is thrown when the server property is not set in cluster
177+
/// </summary>
178+
[Fact]
179+
public void ServerNotFound()
180+
{
181+
var fi = new FileInfo(kubeConfigNoServer);
182+
Assert.Throws<k8s.Exceptions.KubeConfigException>(() => new KubernetesClientConfiguration(fi));
183+
}
184+
185+
/// <summary>
186+
/// Checks that a KubeConfigException is thrown when the clusters section is missing
187+
/// </summary>
188+
[Fact]
189+
public void ClusterNotFound()
190+
{
191+
var fi = new FileInfo(kubeConfigNoCluster);
192+
Assert.Throws<k8s.Exceptions.KubeConfigException>(() => new KubernetesClientConfiguration(fi));
193+
}
194+
195+
/// <summary>
196+
/// Checks that a KubeConfigException is thrown when the cluster defined in clusters and contexts do not match
197+
/// </summary>
198+
[Fact]
199+
public void ClusterNameMissmatch()
200+
{
201+
var fi = new FileInfo(kubeConfigClusterMissmatch);
202+
Assert.Throws<k8s.Exceptions.KubeConfigException>(() => new KubernetesClientConfiguration(fi));
203+
}
204+
205+
/// <summary>
206+
/// Checks that a KubeConfigException is thrown when no certificate-authority-data is set and user do not require tls skip
207+
/// </summary>
208+
[Fact]
209+
public void CheckClusterTlsCorrectness()
210+
{
211+
var fi = new FileInfo(kubeConfigTlsNoSkipError);
212+
Assert.Throws<k8s.Exceptions.KubeConfigException>(() => new KubernetesClientConfiguration(fi));
213+
}
214+
215+
/// <summary>
216+
/// Checks that a KubeConfigException is thrown when no certificate-authority-data is set and user do not require tls skip
217+
/// </summary>
218+
[Fact]
219+
public void CheckClusterTlsSkipCorrectness()
220+
{
221+
var fi = new FileInfo(kubeConfigTlsSkip);
222+
var cfg = new KubernetesClientConfiguration(fi);
223+
Assert.NotNull(cfg.Host);
224+
Assert.Null(cfg.SslCaCert);
225+
Assert.True(cfg.SkipTlsVerify);
226+
}
227+
228+
// /// <summary>
229+
// /// Checks if the are pods
230+
// /// </summary>
231+
// [Fact]
232+
// public void ListDefaultNamespacedPod()
233+
// {
234+
// var k8sClientConfig = new KubernetesClientConfiguration();
235+
// IKubernetes client = new Kubernetes(k8sClientConfig);
236+
// var listTask = client.ListNamespacedPodWithHttpMessagesAsync("default").Result;
237+
// var list = listTask.Body;
238+
// Assert.NotEqual(0, list.Items.Count);
239+
// }
31240
}
32241
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using System;
2+
using Xunit;
3+
using k8s;
4+
using System.IO;
5+
6+
namespace k8s.Tests
7+
{
8+
public class KubernetesClientCredentialsTests
9+
{
10+
/// <summary>
11+
/// Checks that a ArgumentNullException is thrown when trying to create a KubernetesClientCredentials with null token
12+
/// </summary>
13+
[Fact]
14+
public void TokenNull()
15+
{
16+
Assert.Throws<ArgumentNullException>(() => new KubernetesClientCredentials(null));
17+
}
18+
19+
/// <summary>
20+
/// Checks that a ArgumentNullException is thrown when trying to create a KubernetesClientCredentials with null username
21+
/// </summary>
22+
[Fact]
23+
public void UsernameNull()
24+
{
25+
Assert.Throws<ArgumentNullException>(() => new KubernetesClientCredentials(null,"password"));
26+
}
27+
28+
/// <summary>
29+
/// Checks that a ArgumentNullException is thrown when trying to create a KubernetesClientCredentials with null password
30+
/// </summary>
31+
[Fact]
32+
public void PasswordNull()
33+
{
34+
Assert.Throws<ArgumentNullException>(() => new KubernetesClientCredentials("username", null));
35+
}
36+
37+
/// <summary>
38+
/// Checks that the Token is set with no exceptions
39+
/// </summary>
40+
[Fact]
41+
public void ValidTokenIsSet()
42+
{
43+
var token = "mytoken";
44+
var credentials = new KubernetesClientCredentials(token);
45+
Assert.NotNull(credentials);
46+
}
47+
48+
/// <summary>
49+
/// Checks that the Username and Password is set with no exceptions
50+
/// </summary>
51+
[Fact]
52+
public void ValidUserPasswordIsSet()
53+
{
54+
var username = "myuser";
55+
var password = "mypassword";
56+
var credentials = new KubernetesClientCredentials(username, password);
57+
Assert.NotNull(credentials);
58+
}
59+
}
60+
}

0 commit comments

Comments
 (0)