package io.cattle.platform.iaas.api.change.impl; import static io.cattle.platform.core.model.tables.AgentTable.*; import io.cattle.platform.core.constants.AgentConstants; import io.cattle.platform.core.model.Account; import io.cattle.platform.core.model.Agent; import io.cattle.platform.eventing.EventService; import io.cattle.platform.eventing.model.Event; import io.cattle.platform.eventing.model.EventVO; import io.cattle.platform.iaas.api.change.ResourceChangeEventListener; import io.cattle.platform.iaas.event.IaasEvents; import io.cattle.platform.json.JsonMapper; import io.cattle.platform.lock.LockDelegator; import io.cattle.platform.object.ObjectManager; import io.cattle.platform.object.meta.ObjectMetaDataManager; import io.cattle.platform.object.util.DataAccessor; import io.cattle.platform.task.Task; import io.cattle.platform.task.TaskOptions; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javax.inject.Inject; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; public class ResourceChangeEventListenerImpl implements ResourceChangeEventListener, Task, TaskOptions { volatile Map<Pair<String, String>, Object> changed = new ConcurrentHashMap<Pair<String, String>, Object>(); LockDelegator lockDelegator; EventService eventService; @Inject ObjectManager objectManager; @Inject JsonMapper jsonMapper; @Override public void stateChange(Event event) { add(event); } @Override public void apiChange(Event event) { add(event); } @Override public void resourceProgress(Event event) { add(event); } @Override public void serviceEvent(Event event) { Account account = objectManager.loadResource(Account.class, event.getResourceId()); if (account == null) { return; } Agent agent = objectManager.findAny(Agent.class, AGENT.ACCOUNT_ID, new Long(event.getResourceId())); if (agent == null) { return; } Long resourceAccId = DataAccessor.fromDataFieldOf(agent) .withKey(AgentConstants.DATA_AGENT_RESOURCES_ACCOUNT_ID) .as(Long.class); if (resourceAccId == null) { return; } Event originalEvent = jsonMapper.convertValue(event.getData(), EventVO.class); EventVO<?> eventWithAccount = new EventVO<>(originalEvent, null); eventWithAccount.setName(IaasEvents.appendAccount(originalEvent.getName(), resourceAccId)); eventService.publish(originalEvent); eventService.publish(eventWithAccount); } protected void add(Event event) { String id = event.getResourceId(); String type = event.getResourceType(); @SuppressWarnings("unchecked") Map<String, Object> data = (Map<String, Object>) event.getData(); Object accountId = data == null ? null : data.get(ObjectMetaDataManager.ACCOUNT_FIELD); if (accountId == null) { accountId = Boolean.TRUE; } if (type != null && id != null) { changed.put(new ImmutablePair<String, String>(type, id), accountId); } } @Override public void run() { if (!lockDelegator.tryLock(new ResourceChangePublishLock())) { changed.clear(); return; } Map<Pair<String, String>, Object> changed = this.changed; this.changed = new ConcurrentHashMap<Pair<String, String>, Object>(); for (Map.Entry<Pair<String, String>, Object> entry : changed.entrySet()) { Pair<String, String> pair = entry.getKey(); Object accountId = entry.getValue(); eventService.publish(EventVO.newEvent(IaasEvents.RESOURCE_CHANGE).withResourceType(pair.getLeft()).withResourceId(pair.getRight())); if (accountId instanceof Number) { String event = IaasEvents.appendAccount(IaasEvents.RESOURCE_CHANGE, ((Number) accountId).longValue()); eventService.publish(EventVO.newEvent(event).withResourceType(pair.getLeft()).withResourceId(pair.getRight())); } } } @Override public String getName() { return "resource.change.publish"; } @Override public boolean isShouldRecord() { return false; } @Override public boolean isShouldLock() { return false; } public EventService getEventService() { return eventService; } @Inject public void setEventService(EventService eventService) { this.eventService = eventService; } public LockDelegator getLockDelegator() { return lockDelegator; } @Inject public void setLockDelegator(LockDelegator lockDelegator) { this.lockDelegator = lockDelegator; } }