Update docs. Better error message when openssl fails. Simplifying

`KubernetesClientConfiguration`
This commit is contained in:
Jason Poon
2017-08-09 16:49:45 -07:00
parent c6a769b39e
commit 0e1b6b7b7d
5 changed files with 101 additions and 96 deletions

View File

@@ -1,43 +1,58 @@
# csharp
Work In Progress
Currently only supported on Linux
[![Travis](https://img.shields.io/travis/kubernetes-client/csharp.svg)](https://travis-ci.org/kubernetes-client/csharp)
# Generating the client code
# Generating the Client Code
## Prerequisites
Check out the generator project into some other directory
(henceforth `$GEN_DIR`)
```
```bash
cd $GEN_DIR/..
git clone https://github.com/kubernetes-client/gen
```
Install the [`autorest` tool](https://github.com/azure/autorest):
```
```bash
npm install autorest
```
## Generating code
```
```bash
# Where REPO_DIR points to the root of the csharp repository
cd ${REPO_DIR}/csharp/src
${GEN_DIR}/openapi/csharp.sh generated csharp.settings
```
# Testing
# Usage
## Prerequisities
* [OpenSSL](https://www.openssl.org/)
* For Linux/Mac:
* LibCurl built with OpenSSL (Mac: `brew install curl --with-nghttp2`)
## Running the Examples
```bash
git clone git@github.com:kubernetes-client/csharp.git
cd csharp\examples\simple
dotnet run
```
## Testing
The project uses [XUnit](https://xunit.github.io) as unit testing framework.
To run the tests you need to:
To run the tests
```bash
cd tests
cd csharp\tests
dotnet restore
dotnet xunit
```

View File

@@ -71,10 +71,6 @@
!string.IsNullOrWhiteSpace(config.ClientKey)))
{
var pfxFilePath = await Utils.GeneratePfxAsync(config).ConfigureAwait(false);
if (string.IsNullOrWhiteSpace(pfxFilePath))
{
throw new KubernetesClientException("Failed to generate pfx file");
}
var cert = new X509Certificate2(pfxFilePath, string.Empty, X509KeyStorageFlags.PersistKeySet);
handler.ClientCertificates.Add(cert);

View File

@@ -16,17 +16,12 @@ namespace k8s
{
/// <summary>
/// Initializes a new instance of the <see cref="KubernetesClientConfiguration"/> class.
/// Initializes a new instance of the ClientConfiguration class
/// </summary>
/// <param name="kubeconfig">kubeconfig file info</param>
/// <param name="currentContext">Context to use from kube config</param>
public KubernetesClientConfiguration(FileInfo kubeconfig = null, string currentContext = null)
{
if (kubeconfig == null)
{
kubeconfig = new FileInfo(KubeConfigDefaultLocation);
}
var k8SConfig = this.LoadKubeConfig(kubeconfig);
var k8SConfig = this.LoadKubeConfig(kubeconfig ?? new FileInfo(KubeConfigDefaultLocation));
this.Initialize(k8SConfig, currentContext);
}
@@ -108,86 +103,73 @@ namespace k8s
/// <param name="currentContext">Current Context</param>
private void Initialize(K8SConfiguration k8SConfig, string currentContext = null)
{
Context activeContext;
if (k8SConfig.Contexts == null)
{
throw new KubeConfigException("No contexts found in kubeconfig");
}
// set the currentCOntext to passed context if not null
if (!string.IsNullOrWhiteSpace(currentContext))
{
activeContext = k8SConfig.Contexts.FirstOrDefault(c => c.Name.Equals(currentContext, StringComparison.OrdinalIgnoreCase));
if (activeContext != null)
{
this.CurrentContext = activeContext.Name;
}
else
{
throw new KubeConfigException($"CurrentContext: {0} not found in contexts in kubeconfig");
}
}
// otherwise set current context from kubeconfig
else
{
activeContext = k8SConfig.Contexts.FirstOrDefault(c => c.Name.Equals(k8SConfig.CurrentContext, StringComparison.OrdinalIgnoreCase));
if (activeContext == null)
{
throw new KubeConfigException($"CurrentContext: {currentContext} not found in contexts in kubeconfig");
}
this.CurrentContext = activeContext.Name;
}
if (k8SConfig.Clusters == null)
{
throw new KubeConfigException($"clusters not found for current-context :{activeContext} in kubeconfig");
throw new KubeConfigException($"No clusters found in kubeconfig");
}
var clusterDetails = k8SConfig.Clusters.FirstOrDefault(c => c.Name.Equals(activeContext.ContextDetails.Cluster, StringComparison.OrdinalIgnoreCase));
if (clusterDetails?.ClusterEndpoint != null)
if (k8SConfig.Users == null)
{
if (string.IsNullOrWhiteSpace(clusterDetails.ClusterEndpoint.Server))
{
throw new KubeConfigException($"server not found for current-context :{activeContext} in kubeconfig");
}
if (!clusterDetails.ClusterEndpoint.SkipTlsVerify &&
string.IsNullOrWhiteSpace(clusterDetails.ClusterEndpoint.CertificateAuthorityData) &&
string.IsNullOrWhiteSpace(clusterDetails.ClusterEndpoint.CertificateAuthority))
{
throw new KubeConfigException($"neither certificate-authority-data nor certificate-authority not found for current-context :{activeContext} in kubeconfig");
}
this.Host = clusterDetails.ClusterEndpoint.Server;
if (!string.IsNullOrEmpty(clusterDetails.ClusterEndpoint.CertificateAuthorityData)) {
string data = clusterDetails.ClusterEndpoint.CertificateAuthorityData;
this.SslCaCert = new X509Certificate2(System.Text.Encoding.UTF8.GetBytes(Utils.Base64Decode(data)));
}
else if (!string.IsNullOrEmpty(clusterDetails.ClusterEndpoint.CertificateAuthority)) {
this.SslCaCert = new X509Certificate2(clusterDetails.ClusterEndpoint.CertificateAuthority, null);
}
this.SkipTlsVerify = clusterDetails.ClusterEndpoint.SkipTlsVerify;
throw new KubeConfigException($"No users found in kubeconfig");
}
else
// current context
currentContext = currentContext ?? k8SConfig.CurrentContext;
Context activeContext = k8SConfig.Contexts.FirstOrDefault(c => c.Name.Equals(currentContext, StringComparison.OrdinalIgnoreCase));
if (activeContext == null)
{
throw new KubeConfigException($"Cluster details not found for current-context: {activeContext} in kubeconfig");
throw new KubeConfigException($"CurrentContext: {currentContext} not found in contexts in kubeconfig");
}
// set user details from kubeconfig
var userDetails = k8SConfig.Users.FirstOrDefault(c => c.Name.Equals(activeContext.ContextDetails.User, StringComparison.OrdinalIgnoreCase));
this.CurrentContext = activeContext.Name;
this.SetUserDetails(userDetails);
// cluster
var clusterDetails = k8SConfig.Clusters.FirstOrDefault(c => c.Name.Equals(activeContext.ContextDetails.Cluster, StringComparison.OrdinalIgnoreCase));
if (clusterDetails?.ClusterEndpoint == null)
{
throw new KubeConfigException($"Cluster not found for context {activeContext} in kubeconfig");
}
if (string.IsNullOrWhiteSpace(clusterDetails.ClusterEndpoint.Server))
{
throw new KubeConfigException($"Server not found for current-context {activeContext} in kubeconfig");
}
if (!clusterDetails.ClusterEndpoint.SkipTlsVerify &&
string.IsNullOrWhiteSpace(clusterDetails.ClusterEndpoint.CertificateAuthorityData) &&
string.IsNullOrWhiteSpace(clusterDetails.ClusterEndpoint.CertificateAuthority))
{
throw new KubeConfigException($"neither certificate-authority-data nor certificate-authority not found for current-context :{activeContext} in kubeconfig");
}
this.Host = clusterDetails.ClusterEndpoint.Server;
if (!string.IsNullOrEmpty(clusterDetails.ClusterEndpoint.CertificateAuthorityData))
{
string data = clusterDetails.ClusterEndpoint.CertificateAuthorityData;
this.SslCaCert = new X509Certificate2(System.Text.Encoding.UTF8.GetBytes(Utils.Base64Decode(data)));
}
else if (!string.IsNullOrEmpty(clusterDetails.ClusterEndpoint.CertificateAuthority))
{
this.SslCaCert = new X509Certificate2(clusterDetails.ClusterEndpoint.CertificateAuthority, null);
}
this.SkipTlsVerify = clusterDetails.ClusterEndpoint.SkipTlsVerify;
// user
this.SetUserDetails(k8SConfig, activeContext);
}
private void SetUserDetails(User userDetails)
private void SetUserDetails(K8SConfiguration k8SConfig, Context activeContext)
{
var userDetails = k8SConfig.Users.FirstOrDefault(c => c.Name.Equals(activeContext.ContextDetails.User, StringComparison.OrdinalIgnoreCase));
if (userDetails == null)
{
throw new KubeConfigException("User not found for the current context in kubeconfig");
throw new KubeConfigException("User not found for context {activeContext.Name} in kubeconfig");
}
if (userDetails.UserCredentials == null)
@@ -229,7 +211,7 @@ namespace k8s
if (!userCredentialsFound)
{
throw new KubeConfigException($"User: {userDetails.Name} does not have appropriate auth credentials in kube config");
throw new KubeConfigException($"User: {userDetails.Name} does not have appropriate auth credentials in kubeconfig");
}
}

View File

@@ -1,8 +1,9 @@
namespace k8s
{
using k8s.Exceptions;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
@@ -50,7 +51,8 @@
var filePrefix = config.CurrentContext;
var pfxFilePath = Path.Combine(certDirPath, filePrefix + "pfx");
if (!string.IsNullOrWhiteSpace(config.ClientCertificateKey)) {
if (!string.IsNullOrWhiteSpace(config.ClientCertificateKey))
{
keyFilePath = Path.Combine(certDirPath, filePrefix + "key");
using (FileStream fs = File.Create(keyFilePath))
{
@@ -58,24 +60,27 @@
await fs.WriteAsync(info, 0, info.Length).ConfigureAwait(false);
}
}
if (!string.IsNullOrWhiteSpace(config.ClientKey)) {
if (!string.IsNullOrWhiteSpace(config.ClientKey))
{
keyFilePath = config.ClientKey;
}
if (!string.IsNullOrWhiteSpace(config.ClientCertificateData)) {
if (!string.IsNullOrWhiteSpace(config.ClientCertificateData))
{
certFilePath = Path.Combine(certDirPath, filePrefix + "cert");
using (FileStream fs = File.Create(certFilePath))
{
byte[] info = Convert.FromBase64String(config.ClientCertificateData);
await fs.WriteAsync(info, 0, info.Length).ConfigureAwait(false);
}
}
if (!string.IsNullOrWhiteSpace(config.ClientCertificate)) {
if (!string.IsNullOrWhiteSpace(config.ClientCertificate))
{
certFilePath = config.ClientCertificate;
}
var process = new Process();
process.StartInfo = new ProcessStartInfo()
var processStartInfo = new ProcessStartInfo
{
FileName = @"openssl",
Arguments = $"pkcs12 -export -out {pfxFilePath} -inkey {keyFilePath} -in {certFilePath} -passout pass:",
@@ -84,14 +89,23 @@
RedirectStandardOutput = true
};
process.Start();
process.WaitForExit();
if (process.ExitCode == 0)
try
{
return pfxFilePath;
using (Process process = Process.Start(processStartInfo))
{
process.WaitForExit();
if (process.ExitCode != 0)
{
throw new KubernetesClientException($"Failed to generate pfx file with openssl. ExitCode = {process.ExitCode}.");
}
}
}
catch (Win32Exception e)
{
throw new KubernetesClientException("Failed to generate pfx file with openssl.", e);
}
return null;
return pfxFilePath;
}
}
}

View File

@@ -1,6 +1,4 @@
using System;
using Xunit;
using k8s;
using Xunit;
using System.IO;
namespace k8s.Tests