package io.cattle.platform.iaas.api.filter.agent; import io.cattle.platform.archaius.util.ArchaiusUtil; import io.cattle.platform.core.constants.AgentConstants; import io.cattle.platform.core.dao.AgentDao; import io.cattle.platform.core.model.Agent; import io.cattle.platform.iaas.api.filter.common.AbstractDefaultResourceManagerFilter; import io.cattle.platform.object.util.DataUtils; import io.github.ibuildthecloud.gdapi.request.ApiRequest; import io.github.ibuildthecloud.gdapi.request.resource.ResourceManager; import io.github.ibuildthecloud.gdapi.request.resource.ResourceManagerLocator; import io.github.ibuildthecloud.gdapi.validation.ValidationErrorCodes; import java.net.InetAddress; import java.net.UnknownHostException; import javax.inject.Inject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.netflix.config.DynamicBooleanProperty; import com.netflix.config.DynamicStringProperty; public class AgentFilter extends AbstractDefaultResourceManagerFilter { private static final Logger log = LoggerFactory.getLogger(AgentFilter.class); private static final DynamicBooleanProperty ASSIGN_AGENT_URI = ArchaiusUtil.getBoolean("agent.filter.assign.uri"); private static final DynamicBooleanProperty TRY_DNS = ArchaiusUtil.getBoolean("agent.filter.default.uri.reverse.dns"); private static final DynamicStringProperty URI_FORMAT = ArchaiusUtil.getString("agent.filter.default.uri"); private static final DynamicStringProperty USER = ArchaiusUtil.getString("agent.filter.default.user"); ResourceManagerLocator locator; AgentDao agentDao; @Override public Class<?>[] getTypeClasses() { return new Class<?>[] { Agent.class }; } @Override public Object create(String type, ApiRequest request, ResourceManager next) { String ip = request.getClientIp(); Agent agent = request.proxyRequestObject(Agent.class); /* * This ensures that the accountId is always set from the request and * never overwritten by the default accountId setting logic. In the * situation in which the client doesn't have access to the accountId * field, the result will be null, which is correct. You want it to be * null so that the AgentCreate logic will create an account for this * Agent */ agent.setAccountId(agent.getAccountId()); String uri = agent.getUri(); String user = DataUtils.getFieldFromRequest(request, AgentConstants.USER, String.class); if (uri == null) { uri = getUri(user, ip); if (uri != null) { isUnique(uri); agent.setUri(uri); } } return super.create(type, request, next); } protected void isUnique(String uri) { Agent existing = agentDao.findNonRemovedByUri(uri); if (existing != null) { ValidationErrorCodes.throwValidationError(ValidationErrorCodes.NOT_UNIQUE, "uri"); } } protected String getUri(String user, String ip) { if (ip == null) { return null; } if (user == null) { user = USER.get(); } if (!ASSIGN_AGENT_URI.get()) { return null; } if (TRY_DNS.get()) { try { InetAddress addr = InetAddress.getByName(ip); ip = addr.getCanonicalHostName(); } catch (UnknownHostException e) { log.warn("Failed to do a reverse DNS lookup on [{}], using raw IP for uri", ip); } } return String.format(URI_FORMAT.get(), user, ip); } public ResourceManagerLocator getLocator() { return locator; } @Inject public void setLocator(ResourceManagerLocator locator) { this.locator = locator; } public AgentDao getAgentDao() { return agentDao; } @Inject public void setAgentDao(AgentDao agentDao) { this.agentDao = agentDao; } }