package io.cattle.platform.process.instance; import io.cattle.platform.core.addon.LogConfig; import io.cattle.platform.core.addon.SecretReference; import io.cattle.platform.core.constants.AgentConstants; import io.cattle.platform.core.constants.InstanceConstants; import io.cattle.platform.core.constants.NetworkConstants; import io.cattle.platform.core.dao.StorageDriverDao; import io.cattle.platform.core.model.Instance; import io.cattle.platform.core.model.Network; import io.cattle.platform.core.model.StorageDriver; import io.cattle.platform.core.model.Volume; import io.cattle.platform.core.util.SystemLabels; import io.cattle.platform.docker.constants.DockerInstanceConstants; import io.cattle.platform.engine.handler.HandlerResult; import io.cattle.platform.engine.handler.ProcessPreListener; import io.cattle.platform.engine.process.ProcessInstance; import io.cattle.platform.engine.process.ProcessState; import io.cattle.platform.engine.process.impl.ProcessCancelException; import io.cattle.platform.json.JsonMapper; import io.cattle.platform.object.meta.ObjectMetaDataManager; import io.cattle.platform.object.util.DataAccessor; import io.cattle.platform.process.common.handler.AbstractObjectProcessLogic; import io.cattle.platform.token.TokenService; import io.cattle.platform.util.type.CollectionUtils; import io.cattle.platform.util.type.Priority; import java.util.Date; 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.ObjectUtils; import org.apache.commons.lang3.StringUtils; import com.google.common.base.Joiner; @Named public class InstancePreCreate extends AbstractObjectProcessLogic implements ProcessPreListener, Priority { @Inject JsonMapper jsonMapper; @Inject StorageDriverDao storageDriverDao; @Inject TokenService tokenService; @Override public String[] getProcessNames() { return new String[] { "instance.create" }; } @Override public HandlerResult handle(ProcessState state, ProcessInstance process) { Instance instance = (Instance)state.getResource(); if (!InstanceConstants.CONTAINER_LIKE.contains(instance.getKind())) { return null; } Map<String, Object> labels = DataAccessor.fieldMap(instance, InstanceConstants.FIELD_LABELS); Map<Object, Object> data = new HashMap<>(); setAgentVolumes(instance, labels, data); setName(instance, labels, data); setDns(instance, labels, data); setLogConfig(instance, data); setSecrets(instance, data); setSystemLabel(instance, labels); if (!data.isEmpty()) { return new HandlerResult(data); } return null; } protected String toString(Object obj) { return ObjectUtils.toString(obj, null); } protected void setName(Instance instance, Map<String, Object> labels, Map<Object, Object> data) { String name = toString(labels.get(SystemLabels.LABEL_DISPLAY_NAME)); if (StringUtils.isBlank(name)) { return; } data.put(ObjectMetaDataManager.NAME_FIELD, name.replaceFirst("/", "")); } protected void setAgentVolumes(Instance instance, Map<String, Object> labels, Map<Object, Object> data) { if (!"true".equals(labels.get(SystemLabels.LABEL_AGENT_CREATE))) { return; } List<String> dataVolumes = DataAccessor.appendToFieldStringList(instance, InstanceConstants.FIELD_DATA_VOLUMES, AgentConstants.AGENT_INSTANCE_BIND_MOUNT); data.put(InstanceConstants.FIELD_DATA_VOLUMES, dataVolumes); } protected void setSecrets(Instance instance, Map<Object, Object> data) { List<SecretReference> secrets = DataAccessor.fieldObjectList(instance, InstanceConstants.FIELD_SECRETS, SecretReference.class, jsonMapper); if (secrets == null || secrets.isEmpty()) { return; } StorageDriver driver = storageDriverDao.findSecretsDriver(instance.getAccountId()); if (driver == null) { return; } String token = tokenService.generateToken(CollectionUtils.asMap("uuid", instance.getUuid()), new Date(System.currentTimeMillis() + 31556926000L)); try { Volume vol = storageDriverDao.createSecretsVolume(instance, driver, token); create(vol, null); } catch (ProcessCancelException e) { // ignore } } protected void setLogConfig(Instance instance, Map<Object, Object> data) { LogConfig logConfig = DataAccessor.field(instance, InstanceConstants.FIELD_LOG_CONFIG, jsonMapper, LogConfig.class); if (logConfig != null && !StringUtils.isEmpty(logConfig.getDriver()) && logConfig.getConfig() == null) { logConfig.setConfig(new HashMap<String, String>()); data.put(InstanceConstants.FIELD_LOG_CONFIG, logConfig); } } protected void setDns(Instance instance, Map<String, Object> labels, Map<Object, Object> data) { if (!InstanceConstants.KIND_CONTAINER.equals(instance.getKind())) { return; } boolean addDns = DataAccessor.fromMap(labels).withKey(SystemLabels.LABEL_USE_RANCHER_DNS).withDefault(true).as(Boolean.class); if (!addDns) { return; } List<Long> networkIds = DataAccessor.fieldLongList(instance, InstanceConstants.FIELD_NETWORK_IDS); if (networkIds == null || networkIds.size() == 0) { return; } for (Long networkId : networkIds) { Network network = objectManager.loadResource(Network.class, networkId); for (String dns : DataAccessor.fieldStringList(network, NetworkConstants.FIELD_DNS)) { List<String> dnsList = DataAccessor.appendToFieldStringList(instance, DockerInstanceConstants.FIELD_DNS, dns); data.put(DockerInstanceConstants.FIELD_DNS, dnsList); data.put(InstanceConstants.FIELD_DNS_INTERNAL, Joiner.on(",").join(dnsList)); } for (String dnsSearch : DataAccessor.fieldStringList(network, NetworkConstants.FIELD_DNS_SEARCH)) { List<String> dnsSearchList = DataAccessor.appendToFieldStringList(instance, DockerInstanceConstants.FIELD_DNS_SEARCH, dnsSearch); data.put(DockerInstanceConstants.FIELD_DNS_SEARCH, dnsSearchList); data.put(InstanceConstants.FIELD_DNS_SEARCH_INTERNAL, Joiner.on(",").join(dnsSearchList)); } } } protected void setSystemLabel(Instance instance, Map<String, Object> labels) { if(Boolean.TRUE.equals(instance.getSystem()) && !labels.containsKey(SystemLabels.LABEL_CONTAINER_SYSTEM)) { labels.put(SystemLabels.LABEL_CONTAINER_SYSTEM, "true"); } } @Override public int getPriority() { return Priority.PRE; } }