Skip to content

Commit

Permalink
feat(config.loadKubeconfig): helper for loading an API config from ~/…
Browse files Browse the repository at this point in the history
….kube/config (#73)

* feat(config.loadKubeconfig): helper for loading an API config from ~/.kube/config

* Fix a bugo in the README.md

* Move `js-yaml` to dependencies
  • Loading branch information
silasbw authored and jcrugzz committed Feb 13, 2017
1 parent e285404 commit 3a9b609
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 3 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ const K8Api = require('kubernetes-client');
const k8 = new K8Api.Core(K8Api.config.getInCluster());
```

and a helper to get the current-context config from `~/.kube/config`:

```js
const K8Api = require('kubernetes-client');
const k8 = new K8Api.Core(K8Api.config.fromKubeconfig());
```

### Creating and updating

kubernetes-client objects expose `.post`, `.patch`, and `.put`
Expand Down
74 changes: 72 additions & 2 deletions lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
/* eslint no-process-env: 0 no-sync:0 */

const fs = require('fs');
const path = require('path');
const yaml = require('js-yaml');

const certPath = '/var/run/secrets/kubernetes.io/serviceaccount/ca.crt';
const tokenPath = '/var/run/secrets/kubernetes.io/serviceaccount/token';
Expand Down Expand Up @@ -37,6 +39,74 @@ function getInCluster () {
};
}

module.exports = {
getInCluster
module.exports.getInCluster = getInCluster;

/* eslint-disable complexity, max-statements */
function fromKubeconfig (kubeconfig) {
if (!kubeconfig) kubeconfig = loadKubeconfig();

const current = kubeconfig['current-context'];
const context = kubeconfig.contexts
.find(item => item.name === current).context;
const cluster = kubeconfig.clusters
.find(item => item.name === context.cluster).cluster;
const userConfig = kubeconfig.users
.find(user => user.name === context.user);
const user = userConfig ? userConfig.user : null;

let ca;
let insecureSkipTlsVerify = false;
if (cluster) {
if (cluster['certificate-authority']) {
ca = fs.readFileSync(path.normalize(cluster['certificate-authority']));
} else if (cluster['certificate-authority-data']) {
ca = Buffer.from(cluster['certificate-authority-data'], 'base64').toString();
}

if (cluster['insecure-skip-tls-verify']) {
insecureSkipTlsVerify = cluster['insecure-skip-tls-verify'];
}
}

let cert;
let key;
const auth = {};
if (user) {
if (user['client-certificate']) {
cert = fs.readFileSync(path.normalize(user['client-certificate']));
} else if (user && user['client-certificate-data']) {
cert = Buffer.from(user['client-certificate-data'], 'base64').toString();
}

if (user['client-key']) {
key = fs.readFileSync(path.normalize(user['client-key']));
} else if (user['client-key-data']) {
key = Buffer.from(user['client-key-data'], 'base64').toString();
}

if (user.username) auth.user = user.username;
if (user.password) auth.pass = user.password;
}

return {
url: cluster.server,
auth: Object.keys(auth).length ? auth : null,
ca: ca,
insecureSkipTlsVerify: insecureSkipTlsVerify,
key: key,
cert: cert
};
}
/* eslint-enable complexity, max-statements */

module.exports.fromKubeconfig = fromKubeconfig;

function loadKubeconfig (cfgPath) {
cfgPath = cfgPath || path.join(
process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME'],
'.kube',
'config');
return yaml.safeLoad(fs.readFileSync(cfgPath));
}

module.exports.loadKubeconfig = loadKubeconfig;
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@
],
"dependencies": {
"async": "^2.0.0-rc.6",
"js-yaml": "^3.7.0",
"request": "^2.72.0"
},
"devDependencies": {
"assume": "^1.4.1",
"godaddy-style": "^3.1.5",
"istanbul": "^0.4.3",
"js-yaml": "^3.7.0",
"jsdoc": "^3.4.0",
"mocha": "^2.5.3",
"nock": "^8.0.0",
Expand Down
80 changes: 80 additions & 0 deletions test/config.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,84 @@ describe('Config', () => {
});
});
});

describe('.fromKubeconfig', () => {
it('handles username and password', () => {
const kubeconfig = {
apiVersion: 'v1',
kind: 'Config',
preferences: {},
'current-context': 'foo-context',
contexts: [
{
name: 'foo-context',
context: {
cluster: 'foo-cluster',
user: 'foo-user'
}
}
],
clusters: [
{
name: 'foo-cluster',
cluster: {
server: 'https://192.168.42.121:8443'
}
}
],
users: [
{
name: 'foo-user',
user: {
password: 'foo-password',
username: 'foo-user'
}
}
]
};
const args = config.fromKubeconfig(kubeconfig);
assume(args.auth.user).equals('foo-user');
assume(args.auth.pass).equals('foo-password');
});

it('handles base64 encoded certs and keys', () => {
const kubeconfig = {
apiVersion: 'v1',
kind: 'Config',
preferences: {},
'current-context': 'foo-context',
contexts: [
{
name: 'foo-context',
context: {
cluster: 'foo-cluster',
user: 'foo-user'
}
}
],
clusters: [
{
name: 'foo-cluster',
cluster: {
'certificate-authority-data': new Buffer('certificate-authority-data').toString('base64'),
server: 'https://192.168.42.121:8443'
}
}
],
users: [
{
name: 'foo-user',
user: {
'client-certificate-data': new Buffer('client-certificate').toString('base64'),
'client-key-data': new Buffer('client-key').toString('base64')
}
}
]
};
const args = config.fromKubeconfig(kubeconfig);
assume(args.ca).equals('certificate-authority-data');
assume(args.key).equals('client-key');
assume(args.cert).equals('client-certificate');
});
});
});

0 comments on commit 3a9b609

Please sign in to comment.