diff --git a/src/application-manager.coffee b/src/application-manager.coffee index 25f93b37..867f0e30 100644 --- a/src/application-manager.coffee +++ b/src/application-manager.coffee @@ -735,18 +735,23 @@ module.exports = class ApplicationManager extends EventEmitter @proxyvisor.setTargetInTransaction(dependent, trx) contractViolators = {} - Promise.props(contractsFulfilled).then (fulfilledContracts) -> + Promise.props(contractsFulfilled).then (fulfilledContracts) => filteredApps = _.cloneDeep(apps) - _.each fulfilledContracts, ({ valid, unmetServices, fulfilledServices }, appId) -> - if not valid - contractViolators[apps[appId].name] = unmetServices - delete filteredApps[appId] - else - # valid is true, but we could still be missing - # some optional containers, and need to filter - # these out of the target state - filteredApps[appId].services = _.pickBy filteredApps[appId].services, ({ serviceName }) -> - fulfilledServices.includes(serviceName) + _.each( + fulfilledContracts, + ({ valid, unmetServices, fulfilledServices, unmetAndOptional }, appId) => + if not valid + contractViolators[apps[appId].name] = unmetServices + delete filteredApps[appId] + else + # valid is true, but we could still be missing + # some optional containers, and need to filter + # these out of the target state + filteredApps[appId].services = _.pickBy filteredApps[appId].services, ({ serviceName }) -> + fulfilledServices.includes(serviceName) + if unmetAndOptional.length != 0 + @reportOptionalContainers(unmetAndOptional) + ) if trx? setInTransaction(filteredApps, trx) else @@ -1008,3 +1013,12 @@ module.exports = class ApplicationManager extends EventEmitter return volumes.map((v) -> { action: 'removeVolume', current: v }) localModeSwitchCompletion: => @localModeManager.switchCompletion() + + reportOptionalContainers: (serviceNames) => + # Print logs to the console and dashboard, letting the + # user know that we're not going to run certain services + # because of their contract + message = "Not running containers because of contract violations: #{serviceNames.join('. ')}" + log.info(message) + @logger.logSystemMessage(message, {}, 'optionalContainerViolation', true) + diff --git a/src/lib/contracts.ts b/src/lib/contracts.ts index 78220b28..f262b985 100644 --- a/src/lib/contracts.ts +++ b/src/lib/contracts.ts @@ -22,6 +22,7 @@ export async function containerContractsFulfilled( valid: boolean; unmetServices: string[]; fulfilledServices: string[]; + unmetAndOptional: string[]; }> { const containers = _(serviceContracts) .map('contract') @@ -76,6 +77,7 @@ export async function containerContractsFulfilled( valid: false, unmetServices: _.keys(serviceContracts), fulfilledServices: [], + unmetAndOptional: [], }; } @@ -90,6 +92,7 @@ export async function containerContractsFulfilled( valid: true, unmetServices: [], fulfilledServices: _.keys(serviceContracts), + unmetAndOptional: [], }; } else { // If we got here, it means that at least one of the @@ -112,15 +115,18 @@ export async function containerContractsFulfilled( }, ); - const valid = !_.some( + const [unmetAndRequired, unmetAndOptional] = _.partition( unfulfilledServices, - svcName => !serviceContracts[svcName].optional, + serviceName => { + return !serviceContracts[serviceName].optional; + }, ); return { - valid, + valid: unmetAndRequired.length === 0, unmetServices: unfulfilledServices, fulfilledServices, + unmetAndOptional, }; } }