Skip to content

Commit

Permalink
fixes v2.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
raffis committed Feb 14, 2019
1 parent 1379bbe commit f02db50
Show file tree
Hide file tree
Showing 11 changed files with 506 additions and 66 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
## 1.1.0
## 2.0.0
**Maintainer**: Raffael Sahli <[email protected]>\
**Date**: Thur 14 Feb 2019 14:28:20 PM ET

* [FIX] Fixes "(node:25116) UnhandledPromiseRejectionWarning: TypeError: result is not iterable" due error response from icinga
* [FIX] Better error handling and catching various uncaught promises
Expand All @@ -15,6 +17,7 @@
* [FIX] kube workes are in no namespace, remove icinga groups
* [FIX] fixed Error: Invalid attribute specified: host_name\n for kube nodes
* [FIX] fixed duplicate ingress objects (different path, same ingress names in different namespaces, ...)
* [CHANGE] Added hostName setting, by default all resources (except nodes) get attached to single host object of their type (can be configured differently)


## 1.0.1
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:8.10.0-alpine
FROM node:10.15.1-alpine

RUN apk update && apk add git

Expand Down
122 changes: 82 additions & 40 deletions README.md

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"log": {
"level": "debug"
"level": "info"
},
"cleanup": true,
"icinga": {
Expand All @@ -17,6 +17,7 @@
},
"ingresses": {
"discover": true,
"hostName": "kubernetes-ingresses",
"serviceDefinition": {},
"hostDefinition": {},
"serviceTemplates": ["generic-service"],
Expand All @@ -26,6 +27,7 @@
},
"volumes": {
"discover": true,
"hostName": "kubernetes-volumes",
"hostDefinition": {},
"serviceTemplates": ["generic-service"],
"hostTemplates": ["generic-host"],
Expand All @@ -35,13 +37,15 @@
"services": {
"ClusterIP": {
"discover": false,
"hostName": "kubernetes-clusterip-services",
"hostDefinition": {},
"serviceTemplates": ["generic-service"],
"hostTemplates": ["generic-host"],
"applyServices": false
},
"NodePort": {
"discover": true,
"hostName": "kubernetes-nodeport-services",
"serviceDefinition": {},
"hostDefinition": {},
"serviceTemplates": ["generic-service"],
Expand All @@ -51,6 +55,7 @@
},
"LoadBalancer": {
"discover": true,
"hostName": "kubernetes-loadbalancer-services",
"serviceDefinition": {},
"hostDefinition": {},
"serviceTemplates": ["generic-service"],
Expand Down
37 changes: 34 additions & 3 deletions src/kube/ingress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Resource from './abstract.resource';

interface IngressOptions {
discover?: boolean;
hostName?: string;
applyServices?: boolean;
attachToNodes?: boolean;
hostDefinition?: object;
Expand All @@ -24,6 +25,7 @@ export default class Ingress extends Resource {
protected kubeNode: KubeNode;
protected options = {
applyServices: true,
hostName: "kubernetes-ingresses",
attachToNodes: false,
hostDefinition: {},
serviceDefinition: {},
Expand Down Expand Up @@ -79,9 +81,10 @@ export default class Ingress extends Resource {
* Preapre icinga object and apply
*/
public async prepareObject(definition: any): Promise<any> {
let hostname = this.escapeName(['ingress', definition.metadata.namespace, definition.metadata.name].join('-'));
let hostname = this.getHostname(definition);

if (!this.options.attachToNodes) {
await this.applyHost(hostname, definition.metadata.name, definition, this.options.hostTemplates);
await this.applyHost(hostname, hostname, definition, this.options.hostTemplates);
}

let service = this.prepareResource(definition);
Expand Down Expand Up @@ -123,23 +126,42 @@ export default class Ingress extends Resource {
}
}

/**
* Get hostname
*/
protected getHostname(definition: any): string {
if(definition.metadata.annotations['kube-icinga/host']) {
return definition.metadata.annotations['kube-icinga/host'];
} else if(this.options.hostName === null) {
return this.escapeName(['ingress', definition.metadata.namespace, definition.metadata.name].join('-'));
}

return this.options.hostName;
}

/**
* Start kube listener
*/
public async kubeListener(provider) {
console.log("Start listener before try");
try {
let stream = provider();
console.log("Start listener");
console.log(stream);
stream.pipe(this.jsonStream);
this.jsonStream.on('data', async (object) => {
console.log("data");
this.logger.debug('received kubernetes ingress resource', {object});

if (object.object.kind !== 'Ingress') {
this.logger.error('skip invalid ingress object', {object: object});
return;
}

let hostname = this.escapeName(['ingress', object.object.metadata.namespace, object.object.metadata.name].join('-'));
if (object.type == 'MODIFIED' || object.type == 'DELETED') {
await this.icinga.deleteHost(object.object.metadata.name);
let hostname = this.getHostname(object.object);
await this.icinga.deleteHost(hostname);
}

if (object.type == 'ADDED' || object.type == 'MODIFIED') {
Expand All @@ -150,6 +172,15 @@ export default class Ingress extends Resource {
});

this.jsonStream.on('finish', () => {
console.log("finish", this.kubeListener, provider);
this.kubeListener(provider);
});
this.jsonStream.on('error', () => {
console.log("error", this.kubeListener, provider);
this.kubeListener(provider);
});
this.jsonStream.on('end', () => {
console.log("end", this.kubeListener, provider);
this.kubeListener(provider);
});
} catch (err) {
Expand Down
30 changes: 26 additions & 4 deletions src/kube/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Resource from './abstract.resource';

interface ServiceTypeOptions {
discover?: boolean;
hostName?: string;
applyServices?: boolean;
hostDefinition?: any;
serviceDefinition?: any;
Expand All @@ -22,6 +23,7 @@ interface ServiceOptions {
const defaults: ServiceOptions = {
ClusterIP: {
discover: false,
hostName: "kubernetes-clusterip-services",
applyServices: true,
hostDefinition: {},
serviceDefinition: {},
Expand All @@ -30,6 +32,7 @@ const defaults: ServiceOptions = {
},
NodePort: {
discover: true,
hostName: "kubernetes-nodeport-services",
applyServices: true,
hostDefinition: {},
serviceDefinition: {},
Expand All @@ -38,6 +41,7 @@ const defaults: ServiceOptions = {
},
LoadBalancer: {
discover: true,
hostName: "kubernetes-loadbalancer-services",
applyServices: true,
hostDefinition: {},
serviceDefinition: {},
Expand Down Expand Up @@ -122,11 +126,13 @@ export default class Service extends Resource {
service['groups'] = [definition.metadata.namespace];
Object.assign(service, this.prepareResource(definition));

let hostname = this.escapeName(['service', definition.metadata.namespace, definition.metadata.name].join('-'));
let hostname = this.getHostname(definition);
let templates = options.serviceTemplates;
templates = templates.concat(this.prepareTemplates(definition));

if (serviceType !== Service.TYPE_NODEPORT) {
await this.applyHost(hostname, definition.spec.clusterIP, serviceType, definition, options.hostTemplates);
let address = options.hostName || definition.spec.clusterIP;
await this.applyHost(hostname, address, serviceType, definition, options.hostTemplates);
}

if (options.applyServices) {
Expand Down Expand Up @@ -155,14 +161,29 @@ export default class Service extends Resource {

port['vars._kubernetes'] = true;
port['vars.kubernetes'] = definition;
let name = this.escapeName([definition.metadata.name, portName].join('-'));
let name = this.escapeName([definition.metadata.namespace, definition.metadata.name, portName].join('-'));
port['display_name'] = name;

this.applyService(hostname, name, serviceType, port, templates);
}
}
}

/**
* Get hostname
*/
protected getHostname(definition: any): string {
let serviceType = definition.spec.type;

if(definition.metadata.annotations['kube-icinga/host']) {
return definition.metadata.annotations['kube-icinga/host'];
} else if(this.options[serviceType].hostName === null) {
return this.escapeName(['service', definition.metadata.namespace, definition.metadata.name].join('-'));
}

return this.options[serviceType].hostName;
}

/**
* Start kube listener
*/
Expand All @@ -184,7 +205,8 @@ export default class Service extends Resource {
}

if (object.type == 'MODIFIED' || object.type == 'DELETED') {
await this.icinga.deleteHost(object.object.metadata.name);
let hostname = this.getHostname(object.object);
await this.icinga.deleteHost(hostname);
}

if (object.type == 'ADDED' || object.type == 'MODIFIED') {
Expand Down
27 changes: 23 additions & 4 deletions src/kube/volume.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ interface VolumeOptions {
discover?: boolean;
applyServices?: boolean;
attachToNodes?: boolean;
hostName?: string;
hostDefinition?: object;
serviceDefinition?: object;
hostTemplates?: string[];
Expand All @@ -25,6 +26,7 @@ export default class Volume extends Resource {
protected options = {
applyServices: true,
attachToNodes: false,
hostName: "kubernetes-volumes",
hostDefinition: {},
serviceDefinition: {},
hostTemplates: [],
Expand Down Expand Up @@ -79,8 +81,11 @@ export default class Volume extends Resource {
* Preapre icinga object and apply
*/
public async prepareObject(definition: any): Promise<any> {
let hostname = this.escapeName(definition.metadata.annotations['pv.kubernetes.io/provisioned-by']);
await this.applyHost(hostname, hostname, definition, this.options.hostTemplates);
var hostname = this.getHostname(definition);

if (!this.options.attachToNodes) {
await this.applyHost(hostname, hostname, definition, this.options.hostTemplates);
}

if (this.options.applyServices) {
let groups = [];
Expand All @@ -93,7 +98,7 @@ export default class Volume extends Resource {
templates = templates.concat(this.prepareTemplates(definition));

let service = this.options.serviceDefinition;
let name = this.escapeName(['volume', definition.metadata.name].join('-'));
let name = this.escapeName(definition.metadata.name);
let addition = {
'check_command': 'dummy',
'display_name': `${definition.metadata.name}:volume`,
Expand All @@ -108,6 +113,19 @@ export default class Volume extends Resource {
}
}

/**
* Get hostname
*/
protected getHostname(definition: any): string {
if(definition.metadata.annotations['kube-icinga/host']) {
return definition.metadata.annotations['kube-icinga/host'];
} else if(this.options.hostName === null) {
return this.escapeName(['volume', definition.metadata.name].join('-'));
}

return this.options.hostName;
}

/**
* Start kube listener
*/
Expand All @@ -124,7 +142,8 @@ export default class Volume extends Resource {
}

if (object.type == 'MODIFIED' || object.type == 'DELETED') {
await this.icinga.deleteHost(object.object.metadata.name);
let hostname = this.getHostname(object.object);
await this.icinga.deleteHost(this.options.hostName);
}

if (object.type == 'ADDED' || object.type == 'MODIFIED') {
Expand Down
8 changes: 4 additions & 4 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,27 @@ async function main() {
}

if (config.kubernetes.nodes.discover) {
kubeNode.kubeListener(() => {
kubeNode.kubeListener(function() {
return kubeClient.apis.v1.watch.nodes.getStream();
});
}

if (config.kubernetes.ingresses.discover) {
kubeIngress.kubeListener(() => {
kubeIngress.kubeListener(function() {
return kubeClient.apis.extensions.v1beta1.watch.ingresses.getStream();
});
}

if (config.kubernetes.volumes.discover) {
kubeVolume.kubeListener(() => {
kubeVolume.kubeListener(function() {
return kubeClient.apis.v1.watch.persistentvolumes.getStream();
});
}

if (config.kubernetes.services.ClusterIP.discover
|| config.kubernetes.services.NodePort.discover
|| config.kubernetes.services.LoadBalancer.discover) {
kubeService.kubeListener(() => {
kubeService.kubeListener(function() {
return kubeClient.apis.v1.watch.services.getStream();
});
}
Expand Down
31 changes: 29 additions & 2 deletions tests/kube/ingress.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,19 @@ describe('kubernetes ingresses', () => {
Icinga.applyHost = jest.fn();
instance.prepareObject(fixture);
const call = Icinga.applyHost.mock.calls[0];
expect(call[0]).toBe('kubernetes-ingresses');
expect(call[1].display_name).toBe('kubernetes-ingresses');
expect(call[1].check_command).toBe('dummy');
});

it('create icinga host object with dynamic host', () => {
let instance = new Ingress(LoggerInstance, Node, Icinga, JSONStream, {
applyServices: false,
hostName: null
});
Icinga.applyHost = jest.fn();
instance.prepareObject(fixture);
const call = Icinga.applyHost.mock.calls[0];
expect(call[0]).toBe('ingress-foobar-foo');
expect(call[1].display_name).toBe('ingress-foobar-foo');
expect(call[1].check_command).toBe('dummy');
Expand Down Expand Up @@ -146,13 +159,27 @@ describe('kubernetes ingresses', () => {
await instance.prepareObject(fixture);
const calls = Icinga.applyService.mock.calls;
expect(Icinga.applyService.mock.instances.length).toBe(2);
expect(calls[0][0]).toBe('ingress-foobar-foo');
expect(calls[1][0]).toBe('ingress-foobar-foo');
expect(calls[0][0]).toBe('kubernetes-ingresses');
expect(calls[1][0]).toBe('kubernetes-ingresses');
expect(calls[0][1]).toBe('foobar.example.org-http--');
expect(calls[1][1]).toBe('barfoo.example.org-http--foo');
expect(calls[0][2]['vars.http_path']).toBe('/');
expect(calls[1][2]['vars.http_path']).toBe('/foo');
});

it('create all service objects with dynamic hosts', async () => {
let instance = new Ingress(LoggerInstance, Node, Icinga, JSONStream, {
hostName: null
});

Icinga.applyServiceGroup = jest.fn();
Icinga.applyService = jest.fn();
await instance.prepareObject(fixture);
const calls = Icinga.applyService.mock.calls;
expect(Icinga.applyService.mock.instances.length).toBe(2);
expect(calls[0][0]).toBe('ingress-foobar-foo');
expect(calls[1][0]).toBe('ingress-foobar-foo');
}

it('create all service objects with custom service definition', async () => {
let instance = new Ingress(LoggerInstance, Node, Icinga, JSONStream, {
Expand Down
Loading

0 comments on commit f02db50

Please sign in to comment.