Skip to content

Commit

Permalink
feat(TypeScript): Initial cut at TypeScript support. (#174)
Browse files Browse the repository at this point in the history
  • Loading branch information
gisenberg committed Jan 18, 2018
1 parent 19eda08 commit d3ea455
Show file tree
Hide file tree
Showing 5 changed files with 305 additions and 2 deletions.
12 changes: 12 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
"version": "3.17.2",
"description": "Simplified Kubernetes API client.",
"main": "lib/index.js",
"types": "./typings/index.d.ts",
"scripts": {
"check-coverage": "istanbul check-coverage",
"coverage": "istanbul cover ./node_modules/.bin/_mocha && istanbul report cobertura",
"jsdoc": "jsdoc -d doc lib",
"lint": "eslint-godaddy lib/ test/",
"release": "standard-version --tag-prefix=''",
"test": "npm run lint && mocha",
"test": "npm run lint && mocha && npm run test-typings",
"test-typings": "tsc --project ./typings",
"test-integration": "TESTING=int mocha -t ${TIMEOUT:-30000} test"
},
"repository": "godaddy/kubernetes-client",
Expand All @@ -34,6 +36,7 @@
"util.promisify": "^1.0.0"
},
"devDependencies": {
"@types/node": "^8.0.50",
"assume": "^1.5.2",
"eslint": "^4.14.0",
"eslint-config-godaddy": "^2.1.0",
Expand All @@ -44,6 +47,7 @@
"mocha": "^4.1.0",
"nock": "^9.1.5",
"sinon": "4.1.3",
"standard-version": "^4.3.0"
"standard-version": "^4.3.0",
"typescript": "^2.6.1"
}
}
173 changes: 173 additions & 0 deletions typings/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
declare namespace KubernetesClient {
const ApiExtensions: ApiGroupStatic;
const Extensions: ApiGroupStatic;
const Core: ApiGroupStatic;
const Rbac: ApiGroupStatic;
const Batch: ApiGroupStatic;
const Apps: ApiGroupStatic;
const config: Configuration;

interface AuthorizationConfiguration {
bearer?: string;
user?: {
username: string;
password: string;
}
}

interface ClientConfiguration {
url: string;
ca?: string;
key?: string;
auth?: AuthorizationConfiguration;
namespace?: string;
insecureSkipTlsVerify: boolean;
}

interface ClusterConfiguration {
url: string;
ca: string;
key?: string;
auth: AuthorizationConfiguration;
namespace?: string;
insecureSkipTlsVerify?: boolean;
}

interface ApiGroupOptions {
version?: string;
promises?: boolean;
url?: string;
ca?: string;
key?: string;
auth?: AuthorizationConfiguration;
namespace?: string;
insecureSkipTlsVerify?: boolean;
}

interface ApiGroupStatic {
new(config?: ApiGroupOptions): ApiGroup;
}

interface ApiConstructorOptions extends ApiGroupOptions {
core?: ApiGroup;
apps?: ApiGroupOptions | ApiGroup;
batch?: ApiGroupOptions | ApiGroup;
rbac?: ApiGroupOptions | ApiGroup;
extensions?: ApiGroupOptions | ApiGroup;
apiExtensions?: ApiGroupOptions | ApiGroup;
}

interface Configuration {
fromKubeconfig(kubeconfig: any, currentContext?: string): ClientConfiguration;
loadKubeconfig(cfgPath?: string): any;
getInCluster() : ClusterConfiguration;
}

class Api {
constructor(options?: ApiConstructorOptions);
group(v: any | string): ApiGroup;
}

interface ResourceConstructor {
name: string;
Constructor: Function;
}

interface ApiRequestOptions {
[key: string]: any;
body?: any;
headers?: any;
path?: string;
qs?: any;
}

interface MatchExpression {
key: string;
operator: string;
values: Array<string>;
}

interface Resource extends ApiGroup {
(resourceName: string) : Resource;
}

interface NamespacesResource extends Resource {
kind(k: { kind: string } | string): ApiGroup;
}

interface ApiGroup {
addResource(options: string | ResourceConstructor);
get(callback: (error: any, value: any) => void): any;
get(options: ApiRequestOptions, callback: (error: any, value: any) => void): any;
delete(callback: (error: any, value: any) => void);
delete(options: ApiRequestOptions, callback: (error: any, value: any) => void);
patch(callback: (error: any, value: any) => void);
patch(options: ApiRequestOptions, callback: (error: any, value: any) => void);
post(callback: (error: any, value: any) => void);
post(options: ApiRequestOptions, callback: (error: any, value: any) => void);
put(callback: (error: any, value: any) => void);
put(options: ApiRequestOptions, callback: (error: any, value: any) => void);
match(expressions: Array<MatchExpression>): Resource;
matchLabels(labels: any): Resource;
getStream(options: ApiRequestOptions | string): NodeJS.ReadableStream;

// Resources
clusterroles?: Resource;
clusterrolebindings?: Resource;
componentstatuses?: Resource;
configmaps?: Resource;
cronjobs?: Resource;
customresourcedefinitions?: Resource;
daemonsets?: Resource;
deployments?: Resource;
events?: Resource;
endpoints?: Resource;
horizontalpodautoscalers?: Resource;
ingresses?: Resource;
jobs?: Resource;
limitranges?: Resource;
log?: Resource;
namespaces?: NamespacesResource;
nodes?: Resource;
persistentvolumes?: Resource;
persistentvolumeclaims?: Resource;
petsets?: Resource;
pods?: Resource;
replicationcontrollers?: Resource;
replicasets?: Resource;
resourcequotas?: Resource;
roles?: Resource;
rolebindings?: Resource;
scheduledjobs?: Resource;
secrets?: Resource;
serviceaccounts?: Resource;
services?: Resource;
statefulsets?: Resource;
thirdpartyresources?: Resource;

// Resource aliases
cs?: Resource;
crd?: Resource;
cm?: Resource;
ds?: Resource;
deploy?: Resource;
ev?: Resource;
ep?: Resource;
hpa?: Resource;
ing?: Resource;
limits?: Resource;
ns?: NamespacesResource;
no?: Resource;
pv?: Resource;
pvc?: Resource;
po?: Resource;
rc?: Resource;
rs?: Resource;
quota?: Resource;
svc?: Resource;
}
}

declare module "kubernetes-client" {
export = KubernetesClient;
}
104 changes: 104 additions & 0 deletions typings/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import * as Api from 'kubernetes-client';

const apiConfig = Api.config.fromKubeconfig(Api.config.loadKubeconfig('config'));
let core = new Api.Core(apiConfig);
let ext = new Api.Extensions(apiConfig);
let api = new Api.Api({
url: 'http://my-k8s-api-server.com',
namespace: 'my-project'
});

api = new Api.Api({
core: core
});

const manifest0 = {
kind: 'Deployment',
apiVersion: 'extensions/v1beta1'
};

const manifest1 = {
kind: 'ReplicationController',
apiVersion: 'v1'
};

function print(err, result) {
console.log(JSON.stringify(err || result, null, 2));
}

api.group(manifest0).ns.kind(manifest0).post({ body: manifest0 }, print);
api.group(manifest1).ns.kind(manifest1).post({ body: manifest1 }, print);

core = new Api.Core({
url: 'http://my-k8s-api-server.com',
version: 'v1',
promises: true,
namespace: 'my-project'
});

const rbac = new Api.Rbac();
const extensions = new Api.Extensions();
const batch = new Api.Batch();
const apps = new Api.Apps();
const apiExtensions = new Api.ApiExtensions();

ext = new Api.Extensions({
url: 'http://my-k8s-api-server.com',
version: 'v1beta1', // Defaults to 'v1beta1'
namespace: 'my-project' // Defaults to 'default'
});

core.ns.rc.match([{
key: 'service',
operator: 'In',
values: ['http']
}, {
key: 'deploy',
operator: 'NotIn',
values: ['production', 'staging']
}]).get(print);

const clusterConfig = Api.config.getInCluster();

ext.namespaces.deployments('http-deployment').get(print);

core.namespaces.replicationcontrollers('http-rc').get(print);
core.ns('custom-namespace').pods('pod-1').log.get((err, log) => {
if (err) {
throw err;
}
const logLines = log.split('\n');
for (const line of logLines) {
// ...
}
});

core.ns('custom-namespace').pods.matchLabels(['label-1', 'label-2']).get((err, matchedPods) => {
if (err) throw err;
console.log(matchedPods.length);
});

ext.ns('some-ns').deploy('deployment').get((err, deploy) => {
if (err) throw err;
console.log(`Find Pods with labels ${ JSON.stringify(deploy.spec.selector.matchLabels) }`);
});

core.pods.get((err, podsInfo) => {
console.log(podsInfo);
});

core.pods('foo').get((err, podsInfo) => {
console.log(podsInfo);
});

let stream = core.pods.matchLabels(['foo']).getStream({ qs: { watch: true }});
core.ns.rc('http-rc').get(print);
core.ns.rc.get({ qs: { labelSelector: 'service=http' } }, print);
core.ns.rc.matchLabels({ service: 'http' }).get(print);
core.ns.rc.delete({ name: 'http-rc', preservePods: true }, print);

stream = core.ns.po('http-123').log.getStream({ qs: { follow: true } });
stream.on('data', chunk => {
process.stdout.write(chunk.toString());
});

10 changes: 10 additions & 0 deletions typings/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"compilerOptions": {
"module": "es2015",
"noEmit": true,
"types": [ "node" ]
},
"include": [
"*.ts"
]
}

0 comments on commit d3ea455

Please sign in to comment.