diff --git a/lib/EventHandler.js b/lib/EventHandler.js index c0e8765..69b3946 100644 --- a/lib/EventHandler.js +++ b/lib/EventHandler.js @@ -1,18 +1,18 @@ /** -* Copyright 2019 IBM Corp. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ + * Copyright 2019 IBM Corp. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ const merge = require('deepmerge'); const touch = require('touch'); const watchman = require('./Watchman'); diff --git a/lib/Watchman.js b/lib/Watchman.js index 5e95b52..7a5bc3f 100644 --- a/lib/Watchman.js +++ b/lib/Watchman.js @@ -1,18 +1,18 @@ /** -* Copyright 2019 IBM Corp. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ + * Copyright 2019 IBM Corp. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ const request = require('request'); const validUrl = require('valid-url'); const JSONStream = require('JSONStream'); @@ -22,7 +22,7 @@ const merge = require('deepmerge'); module.exports = class Watchman { constructor(options, objectHandler) { if ((typeof objectHandler) !== 'function') { - throw 'objectHandler must be a function.'; + throw 'Watchman objectHandler must be a function.'; } this._objectHandler = objectHandler; this._requestOptions = merge({ @@ -35,15 +35,12 @@ module.exports = class Watchman { }, options.requestOptions || {}); this._requestOptions.uri = options.watchUri; - if ((typeof objectHandler) !== 'function') { - throw 'objectHandler must be a function.'; - } if ((options.logger) && ((typeof options.logger) !== 'object')) { throw 'options.logger must be an object.'; } this._logger = options.logger; - if (!validUrl.isUri(`${this._requestOptions.baseUrl}${this._requestOptions.uri}`)) { - throw `uri '${this._requestOptions.baseUrl}${this._requestOptions.uri}' not valid.`; + if (!validUrl.isUri(`${this._requestOptions.baseUrl}${this._requestOptions.uri}`) || !this._requestOptions.uri.includes('watch')) { + throw `uri '${this._requestOptions.baseUrl}${this._requestOptions.uri}' not valid watch uri.`; } this._rewatchOnTimeout = options.rewatchOnTimeout || true; @@ -71,7 +68,7 @@ module.exports = class Watchman { this._errors++; this.end(this._rewatchOnTimeout); delay(this._errors * 1000).then(() => { - if(this._rewatchOnTimeout) + if (this._rewatchOnTimeout) this.watch(); }); } diff --git a/lib/kubeClass.js b/lib/kubeClass.js index 57ae7ba..0c2c55d 100644 --- a/lib/kubeClass.js +++ b/lib/kubeClass.js @@ -119,6 +119,15 @@ module.exports = class KubeClass { } + injectSelfLink(object, resourceMeta) { + let resources = objectPath.get(object, 'items', []); + resources.forEach(r => { + let metadata = { name: objectPath.get(r, 'metadata.name'), namespace: objectPath.get(r, 'metadata.namespace') }; + objectPath.set(r, 'metadata.annotations.selfLink', resourceMeta.uri(metadata)); + }); + return object; + } + async getResource(resourceMeta, queryParams = {}) { let result; if (!resourceMeta) { @@ -132,7 +141,7 @@ module.exports = class KubeClass { result.statusCode = response.statusCode; switch (response.statusCode) { case 200: - result.object = response.body; + result.object = this.injectSelfLink(response.body, resourceMeta); break; default: // this.logger.error(`this.getResource ${uri} ${response.statusCode} ${status[response.statusCode]}.`, response.body); diff --git a/test/Watchman-test.js b/test/Watchman-test.js index 2af3391..e46dea4 100644 --- a/test/Watchman-test.js +++ b/test/Watchman-test.js @@ -1,27 +1,27 @@ /** -* Copyright 2019 IBM Corp. All Rights Reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ + * Copyright 2019 IBM Corp. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ const assert = require('chai').assert; const nock = require('nock'); const watchman = require('../lib/Watchman'); const log = require('../lib/bunyan-api').createLogger('Watchman-test'); -const dummyOptions = { rewatchOnTimeout: false, requestOptions: { baseUrl: 'https://localhost:32263' }, watchUri: '/api/v1/namespaces/default/services/kubernetes' }; +const dummyOptions = { rewatchOnTimeout: false, requestOptions: { baseUrl: 'https://localhost:32263' }, watchUri: '/api/v1/watch/namespaces/default/services/kubernetes' }; const data1 = { 'type': 'ADDED', 'object': { 'kind': 'Service', 'apiVersion': 'v1', 'metadata': { 'name': 'kubernetes', 'namespace': 'default', 'selfLink': '/api/v1/namespaces/default/services/kubernetes', 'uid': '7c75c135-fca7-11e8-9f10-3a7d3a0f8cf2', 'resourceVersion': '14840391', 'creationTimestamp': '2018-12-10T18:14:51Z', 'labels': { 'component': 'apiserver', 'provider': 'kubernetes', 'razee/watch-resource': 'lite' } }, 'spec': { 'ports': [{ 'name': 'https', 'protocol': 'TCP', 'port': 443, 'targetPort': 2040 }], 'clusterIP': '172.21.0.1', 'type': 'ClusterIP', 'sessionAffinity': 'None' }, 'status': { 'loadBalancer': {} } } }; -let mockObjectHandler = (data) => { }; // eslint-disable-line no-unused-vars +let mockObjectHandler = (data) => {}; // eslint-disable-line no-unused-vars describe('watchman', () => { @@ -43,7 +43,7 @@ describe('watchman', () => { var wm = new watchman(dummyOptions, ''); // eslint-disable-line no-unused-vars } catch (err) { errorsHappen = true; - assert.equal(err, 'objectHandler must be a function.'); + assert.equal(err, 'Watchman objectHandler must be a function.'); } finally { assert.isTrue(errorsHappen); } @@ -53,7 +53,7 @@ describe('watchman', () => { try { var wm = new watchman('', mockObjectHandler); // eslint-disable-line no-unused-vars } catch (err) { - assert.equal(err, 'uri \'undefinedundefined\' not valid.'); + assert.equal(err, 'uri \'undefinedundefined\' not valid watch uri.'); errorsHappen = true; } assert.isTrue(errorsHappen); @@ -83,7 +83,7 @@ describe('watchman', () => { errorsHappen = true; assert.equal(err, ''); } finally { - assert.equal(wm.selfLink, '/api/v1/namespaces/default/services/kubernetes'); + assert.equal(wm.selfLink, '/api/v1/watch/namespaces/default/services/kubernetes'); assert.isFalse(errorsHappen); } @@ -154,7 +154,7 @@ describe('watchman', () => { let myOptions = dummyOptions; myOptions.logger = dummyLogger; nock('https://localhost:32263') - .get('/api/v1/namespaces/default/services/kubernetes') + .get('/api/v1/watch/namespaces/default/services/kubernetes') .reply(200, data1); let errorsHappen = false; try { @@ -201,19 +201,19 @@ describe('watchman', () => { log.info('dummyLogger', msg); }, error: (msg) => { - assert.equal(msg, 'GET /api/v1/namespaces/default/services/kubernetes returned 201'); + assert.equal(msg, 'GET /api/v1/watch/namespaces/default/services/kubernetes returned 201'); wm.end(); } }; let myOptions = dummyOptions; myOptions.logger = dummyLogger; myOptions.requestOptions.baseUrl = 'https://localhost:666'; - myOptions.rewatchOnTimeout=false; + myOptions.rewatchOnTimeout = false; let xmockObjectHandler = (data) => { log.info('xmockObjectHandler', data); }; nock('https://localhost:666') - .get('/api/v1/namespaces/default/services/kubernetes') + .get('/api/v1/watch/namespaces/default/services/kubernetes') .reply(201); let errorsHappen = false; try { @@ -239,7 +239,7 @@ describe('watchman', () => { log.info('dummyLogger', msg); }, error: (msg) => { - assert.equal(msg, 'GET /api/v1/namespaces/default/services/kubernetes errored'); + assert.equal(msg, 'GET /api/v1/watch/namespaces/default/services/kubernetes errored'); wm.end(); done(); } @@ -247,12 +247,12 @@ describe('watchman', () => { let myOptions = dummyOptions; myOptions.logger = dummyLogger; myOptions.requestOptions.baseUrl = 'https://localhost:666'; - myOptions.rewatchOnTimeout=false; + myOptions.rewatchOnTimeout = false; let xmockObjectHandler = (data) => { log.info('xmockObjectHandler', data); }; nock('https://localhost:666') - .get('/api/v1/namespaces/default/services/kubernetes') + .get('/api/v1/watch/namespaces/default/services/kubernetes') .replyWithError('test errorstream error'); let errorsHappen = false; try {