diff --git a/lib/BaseController.js b/lib/BaseController.js index 59277c5..a668b35 100644 --- a/lib/BaseController.js +++ b/lib/BaseController.js @@ -598,8 +598,23 @@ module.exports = class BaseController { if (liveResource) { let currentParent = objectPath.get(liveResource, ['metadata', 'annotations', 'deploy.razee.io.parent']); if (currentParent && (currentParent != this.selfLink)) { - return { statusCode: 200, body: 'Multiple Parents' }; + // Check to see if the current parent still exists. If it doesnt, it can be taken over. + try { + await this.kubeResourceMeta.request({ uri: currentParent, json: true }); + // Current parent still exists, abort with `Multiple Parents` response + return { statusCode: 200, body: 'Multiple Parents' }; + } + catch( e ) { + if( e.statusCode === 404 ) { + // Current parent is gone, continue and assume parent role + this.log.info( `parent ${currentParent} no longer exists, asserting ownership for new parent ${this.selfLink}` ); + } + else { + throw e; + } + } } + let debug = objectPath.get(liveResource, ['metadata', 'labels', 'deploy.razee.io/debug'], 'false'); if (debug.toLowerCase() === 'true') { this.log.warn(`${uri}: Debug enabled on resource: skipping modifying resource - adding annotation deploy.razee.io/pending-configuration.`); diff --git a/lib/CompositeController.js b/lib/CompositeController.js index 3c694b7..110450d 100644 --- a/lib/CompositeController.js +++ b/lib/CompositeController.js @@ -37,21 +37,28 @@ module.exports = class CompositeController extends BaseController { // if cleanup fails, do not return successful response => Promise.reject(err) or throw Error(err) let children = objectPath.get(this.data, ['object', 'status', 'children'], {}); let res = await Promise.all(Object.entries(children).map(async ([selfLink, child]) => { - let reconcile = objectPath.get(child, ['deploy.razee.io/Reconcile'], this.reconcileDefault); - if (reconcile.toLowerCase() == 'true') { - try { + try { + let reconcile = objectPath.get(child, ['deploy.razee.io/Reconcile'], this.reconcileDefault); + if (reconcile.toLowerCase() == 'true') { + // If child is to be Reconciled, delete it + this.log.info(`finalizer: ${selfLink} no longer applied.. Reconcile ${reconcile.toLowerCase()}.. removing from cluster`); await this._deleteChild(selfLink); - let res = await this.patchSelf({ - status: { - children: { - [selfLink]: null - } - } - }, { status: true }); - objectPath.set(this.data, 'object', res); - } catch (e) { - return Promise.reject({ selfLink: selfLink, action: 'delete', state: 'fail', error: e.message || e }); } + else { + // If child is NOT to be Reconciled, remove the parent reference + this.log.info(`finalizer: ${selfLink} no longer applied.. Reconcile ${reconcile.toLowerCase()}.. leaving on cluster`); + await this._patchChild(selfLink); + } + let res = await this.patchSelf({ + status: { + children: { + [selfLink]: null + } + } + }, { status: true }); + objectPath.set(this.data, 'object', res); + } catch (e) { + return Promise.reject({ selfLink: selfLink, action: 'delete', state: 'fail', error: e.message || e }); } })); return res;