package io.cattle.platform.servicediscovery.process; import static io.cattle.platform.core.model.tables.InstanceTable.*; import io.cattle.platform.core.addon.ServiceLink; import io.cattle.platform.core.constants.CommonStatesConstants; import io.cattle.platform.core.constants.ServiceConstants; import io.cattle.platform.core.model.Instance; import io.cattle.platform.core.model.Service; import io.cattle.platform.core.model.ServiceExposeMap; import io.cattle.platform.engine.handler.HandlerResult; import io.cattle.platform.engine.handler.ProcessPostListener; import io.cattle.platform.engine.process.ProcessInstance; import io.cattle.platform.engine.process.ProcessState; import io.cattle.platform.lock.LockCallbackNoReturn; import io.cattle.platform.lock.LockManager; import io.cattle.platform.object.process.StandardProcess; import io.cattle.platform.process.common.handler.AbstractObjectProcessLogic; import io.cattle.platform.servicediscovery.api.dao.ServiceConsumeMapDao; import io.cattle.platform.servicediscovery.api.dao.ServiceExposeMapDao; import io.cattle.platform.servicediscovery.deployment.impl.lock.ServiceInstanceLock; import io.cattle.platform.servicediscovery.service.ServiceDiscoveryService; import io.cattle.platform.util.type.Priority; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; import javax.inject.Named; import org.apache.commons.lang3.StringUtils; import com.google.common.base.Strings; @Named public class SelectorServiceCreatePostListener extends AbstractObjectProcessLogic implements ProcessPostListener, Priority { @Inject ServiceDiscoveryService sdService; @Inject ServiceExposeMapDao exposeMapDao; @Inject LockManager lockManager; @Inject ServiceConsumeMapDao consumeMapDao; @Override public String[] getProcessNames() { return new String[] { ServiceConstants.PROCESS_SERVICE_CREATE, ServiceConstants.PROCESS_SERVICE_UPDATE }; } @Override public HandlerResult handle(ProcessState state, ProcessInstance process) { Service service = (Service)state.getResource(); sdService.registerServiceLinks(service); registerInstances(service); if (process.getName().equalsIgnoreCase(ServiceConstants.PROCESS_SERVICE_UPDATE)) { cleanupOldSelectorLinks(state, service); } return null; } @SuppressWarnings("unchecked") protected void cleanupOldSelectorLinks(ProcessState state, Service service) { String selectorLink = service.getSelectorLink(); String oldSelectorLink = ""; Object oldObj = state.getData().get("old"); if (oldObj != null) { Map<String, Object> old = (Map<String, Object>) oldObj; Object obj = old.get(ServiceConstants.FIELD_SELECTOR_LINK); if (obj != null) { oldSelectorLink = obj.toString(); } } if (!StringUtils.isEmpty(oldSelectorLink) && !oldSelectorLink.equalsIgnoreCase(selectorLink)) { deregisterOldServiceLinks(service, oldSelectorLink); } } protected void deregisterOldServiceLinks(Service service, String selectorLink) { List<? extends Service> targetServices = consumeMapDao.findLinkedServices(service.getId()); for (Service targetService : targetServices) { if (sdService.isSelectorLinkMatch(selectorLink, targetService)) { removeServiceLink(service, targetService); } } } protected void removeServiceLink(Service service, Service targetService) { ServiceLink link = new ServiceLink(targetService.getId(), null); sdService.removeServiceLink(service, link); } protected void registerInstances(final Service service) { if (Strings.isNullOrEmpty(service.getSelectorContainer())) { return; } List<Instance> instances = objectManager.find(Instance.class, INSTANCE.ACCOUNT_ID, service.getAccountId(), INSTANCE.REMOVED, null); List<? extends ServiceExposeMap> current = exposeMapDao.getUnmanagedServiceInstanceMapsToRemove(service.getId()); final Map<Long, ServiceExposeMap> currentMappedInstances = new HashMap<>(); for (ServiceExposeMap map : current) { currentMappedInstances.put(map.getInstanceId(), map); } for (final Instance instance : instances) { boolean matched = sdService.isSelectorContainerMatch(service.getSelectorContainer(), instance); if (matched && !currentMappedInstances.containsKey(instance.getId())) { lockManager.lock(new ServiceInstanceLock(service, instance), new LockCallbackNoReturn() { @Override public void doWithLockNoResult() { ServiceExposeMap exposeMap = exposeMapDao.createServiceInstanceMap(service, instance, false); if (exposeMap.getState().equalsIgnoreCase(CommonStatesConstants.REQUESTED)) { objectProcessManager.scheduleStandardProcessAsync(StandardProcess.CREATE, exposeMap, null); } } }); } else if (!matched && currentMappedInstances.containsKey(instance.getId())) { lockManager.lock(new ServiceInstanceLock(service, instance), new LockCallbackNoReturn() { @Override public void doWithLockNoResult() { objectProcessManager.scheduleStandardProcessAsync(StandardProcess.REMOVE, currentMappedInstances.get(instance.getId()), null); } }); } } } @Override public int getPriority() { return Priority.DEFAULT; } }