package io.cattle.platform.process.host;
import io.cattle.iaas.labels.service.LabelsService;
import io.cattle.platform.core.constants.HostConstants;
import io.cattle.platform.core.dao.GenericMapDao;
import io.cattle.platform.core.dao.LabelsDao;
import io.cattle.platform.core.model.Host;
import io.cattle.platform.core.model.HostLabelMap;
import io.cattle.platform.core.model.Label;
import io.cattle.platform.engine.handler.HandlerResult;
import io.cattle.platform.engine.process.ProcessInstance;
import io.cattle.platform.engine.process.ProcessState;
import io.cattle.platform.object.util.DataAccessor;
import io.cattle.platform.process.common.handler.AbstractObjectProcessHandler;
import io.cattle.platform.util.type.Priority;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.inject.Inject;
import javax.inject.Named;
@Named
public class HostLabelReconcile extends AbstractObjectProcessHandler implements Priority {
@Inject
GenericMapDao mapDao;
@Inject
LabelsDao labelsDao;
@Inject
LabelsService labelsService;
@Override
public String[] getProcessNames() {
return new String[] { HostConstants.PROCESS_ACTIVATE, HostConstants.PROCESS_UPDATE };
}
@Override
@SuppressWarnings("unchecked")
public HandlerResult handle(ProcessState state, ProcessInstance process) {
final Host host = (Host) state.getResource();
Map<String, String> labelsField = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
labelsField.putAll(DataAccessor.fields(host).withKey(HostConstants.FIELD_LABELS)
.withDefault(Collections.EMPTY_MAP).as(Map.class));
List<Label> existing = labelsDao.getLabelsForHost(host.getId());
List<? extends HostLabelMap> existingInstanceMappings = mapDao.findNonRemoved(HostLabelMap.class, Host.class, host.getId());
// figure out potentially new labels to create and associate with host
Map<String, String> existingLabels = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
Map<Long, Label> existingLabelLookupById = new HashMap<Long, Label>();
for (Label existingLabel : existing) {
existingLabels.put(existingLabel.getKey(), existingLabel.getValue());
existingLabelLookupById.put(existingLabel.getId(), existingLabel);
}
for (Map.Entry<String, String> inputEntry : labelsField.entrySet()) {
String existingValue = existingLabels.get(inputEntry.getKey());
if (existingValue == null || !existingValue.equals(inputEntry.getValue())) {
labelsService.createHostLabel(
host.getAccountId(), host.getId(), inputEntry.getKey(), inputEntry.getValue());
}
}
// figure out which mappings to remove
for (HostLabelMap mapping : existingInstanceMappings) {
Long labelId = mapping.getLabelId();
Label existingLabel = existingLabelLookupById.get(labelId);
String newLabelValue = labelsField.get(existingLabel.getKey());
if (newLabelValue == null || !newLabelValue.equalsIgnoreCase(existingLabel.getValue())) {
objectProcessManager.scheduleProcessInstance("hostlabelmap.remove", mapping, null);
}
}
return null;
}
@Override
public int getPriority() {
return Priority.DEFAULT;
}
}