<commit_before>package io.cattle.platform.agent.instance.factory.impl;

import static io.cattle.platform.core.model.tables.AgentTable.*;
import static io.cattle.platform.core.model.tables.InstanceTable.*;

import io.cattle.platform.agent.AgentLocator;
import io.cattle.platform.agent.instance.dao.AgentInstanceDao;
import io.cattle.platform.agent.instance.factory.AgentInstanceFactory;
import io.cattle.platform.agent.instance.factory.lock.AgentInstanceAgentCreateLock;
import io.cattle.platform.archaius.util.ArchaiusUtil;
import io.cattle.platform.core.constants.AgentConstants;
import io.cattle.platform.core.constants.CommonStatesConstants;
import io.cattle.platform.core.constants.InstanceConstants;
import io.cattle.platform.core.constants.ServiceConstants;
import io.cattle.platform.core.dao.AccountDao;
import io.cattle.platform.core.dao.GenericResourceDao;
import io.cattle.platform.core.dao.InstanceDao;
import io.cattle.platform.core.model.Agent;
import io.cattle.platform.core.model.Instance;
import io.cattle.platform.core.model.Service;
import io.cattle.platform.core.model.Stack;
import io.cattle.platform.core.util.SystemLabels;
import io.cattle.platform.deferred.util.DeferredUtils;
import io.cattle.platform.engine.process.impl.ProcessCancelException;
import io.cattle.platform.lock.LockCallback;
import io.cattle.platform.lock.LockManager;
import io.cattle.platform.object.ObjectManager;
import io.cattle.platform.object.process.ObjectProcessManager;
import io.cattle.platform.object.process.StandardProcess;
import io.cattle.platform.object.resource.ResourceMonitor;
import io.cattle.platform.object.resource.ResourcePredicate;
import io.cattle.platform.object.util.DataAccessor;
import io.cattle.platform.process.common.util.ProcessUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;

import javax.inject.Inject;

import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.ObjectUtils;

import com.netflix.config.DynamicStringProperty;

public class AgentInstanceFactoryImpl implements AgentInstanceFactory {
    private static final DynamicStringProperty LB_IMAGE_UUID = ArchaiusUtil.getString("lb.instance.image.uuid");

    @Inject
    AccountDao accountDao;
    @Inject
    ObjectManager objectManager;
    @Inject
    AgentInstanceDao factoryDao;
    @Inject
    LockManager lockManager;
    @Inject
    GenericResourceDao resourceDao;
    @Inject
    AgentLocator agentLocator;
    @Inject
    ResourceMonitor resourceMonitor;
    @Inject
    ObjectProcessManager processManager;
    @Inject
    InstanceDao instanceDao;

    protected Instance build(AgentInstanceBuilderImpl builder) {
        Agent agent = getAgent(builder);

        return getInstance(agent, builder);
    }

    private Instance getInstance(Agent agent, AgentInstanceBuilderImpl builder) {
        Instance instance = factoryDao.getInstanceByAgent(agent);

        if (instance != null) {
            return instance;
        }

        Map<String, Object> properties = getInstanceProperties(agent, builder);

        return createInstance(agent, properties, builder);
    }

    private Map<String, Object> getInstanceProperties(Agent agent, AgentInstanceBuilderImpl builder) {
        Map<Object, Object> properties = new HashMap<Object, Object>();

        properties.put(INSTANCE.ACCOUNT_ID, getAccountId(builder));
        properties.put(INSTANCE.AGENT_ID, agent.getId());
        properties.put(InstanceConstants.FIELD_IMAGE_UUID, builder.getImageUuid());
        properties.put(INSTANCE.NAME, builder.getName());
        properties.put(INSTANCE.ZONE_ID, agent.getZoneId());
        properties.put(INSTANCE.KIND, builder.getInstanceKind());
        properties.put(InstanceConstants.FIELD_PRIVILEGED, builder.isPrivileged());
        properties.put(InstanceConstants.FIELD_NETWORK_IDS, getNetworkIds(agent, builder));
        properties.putAll(builder.getParams());
        addAdditionalProperties(properties, agent, builder);

        return objectManager.convertToPropertiesFor(Instance.class, properties);
    }

    protected void addAdditionalProperties(Map<Object, Object> properties, Agent agent, AgentInstanceBuilderImpl builder) {
    }

    @Override
    public Agent createAgent(Instance instance) {
        if (shouldCreateAgent(instance)) {
            Map<String, Object> labels = DataAccessor.fieldMap(instance, InstanceConstants.FIELD_LABELS);
            Set<String> filteredRoles = new HashSet<>();

            String rolesVal = labels.get(SystemLabels.LABEL_AGENT_ROLE) != null ? labels.get(SystemLabels.LABEL_AGENT_ROLE).toString() : null;
            if (rolesVal != null) {
                String[] roles = rolesVal.split(",");
                for (String r : roles) {
                    if ("environment".equals(r) || "agent".equals(r)) {
                        filteredRoles.add(r);
                    } else if ("environmentAdmin".equals(r) && isSystem(instance)) {
                        filteredRoles.add(r);
                    }
                }
            }

            return getAgent(new AgentInstanceBuilderImpl(this, instance, filteredRoles));
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    protected boolean isLBSystemService(Service service) {
        Map<String, Object> data = DataAccessor.fields(service)
                .withKey("launchConfig").withDefault(Collections.EMPTY_MAP)
                .as(Map.class);

        Object imageObj = data.get(InstanceConstants.FIELD_IMAGE_UUID);
        if (imageObj == null) {
            return false;
        }

        // remove the tag from the default image (assuming that it is always tagged)
        String defaultImageUuid = LB_IMAGE_UUID.get().toLowerCase();
        String[] splitted = defaultImageUuid.split(":");
        String formattedDefault = String.format("%s:%s", splitted[0], splitted[1]);

        return imageObj.toString().startsWith(formattedDefault);
    }

    private boolean isSystem(Instance instance) {
        List<? extends Service> services = instanceDao.findServicesNonRemovedLinksOnly(instance);
        for (Service service : services) {
            Stack stack = objectManager.loadResource(Stack.class, service.getStackId());
            if (ServiceConstants.isSystem(stack)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void deleteAgent(Instance instance) {
        if (!shouldCreateAgent(instance) || instance.getAgentId() == null) {
            return;
        }

        Agent agent = objectManager.loadResource(Agent.class, instance.getAgentId());
        if (agent == null) {
            return;
        }

        if (CommonStatesConstants.DEACTIVATING.equals(agent.getState())) {<commit_msg>lb with default image can act as environment admin account<commit_after>package io.cattle.platform.agent.instance.factory.impl;

import static io.cattle.platform.core.model.tables.AgentTable.*;
import static io.cattle.platform.core.model.tables.InstanceTable.*;

import io.cattle.platform.agent.AgentLocator;
import io.cattle.platform.agent.instance.dao.AgentInstanceDao;
import io.cattle.platform.agent.instance.factory.AgentInstanceFactory;
import io.cattle.platform.agent.instance.factory.lock.AgentInstanceAgentCreateLock;
import io.cattle.platform.archaius.util.ArchaiusUtil;
import io.cattle.platform.core.constants.AgentConstants;
import io.cattle.platform.core.constants.CommonStatesConstants;
import io.cattle.platform.core.constants.InstanceConstants;
import io.cattle.platform.core.constants.ServiceConstants;
import io.cattle.platform.core.dao.AccountDao;
import io.cattle.platform.core.dao.GenericResourceDao;
import io.cattle.platform.core.dao.InstanceDao;
import io.cattle.platform.core.model.Agent;
import io.cattle.platform.core.model.Instance;
import io.cattle.platform.core.model.Service;
import io.cattle.platform.core.model.Stack;
import io.cattle.platform.core.util.SystemLabels;
import io.cattle.platform.deferred.util.DeferredUtils;
import io.cattle.platform.engine.process.impl.ProcessCancelException;
import io.cattle.platform.lock.LockCallback;
import io.cattle.platform.lock.LockManager;
import io.cattle.platform.object.ObjectManager;
import io.cattle.platform.object.process.ObjectProcessManager;
import io.cattle.platform.object.process.StandardProcess;
import io.cattle.platform.object.resource.ResourceMonitor;
import io.cattle.platform.object.resource.ResourcePredicate;
import io.cattle.platform.object.util.DataAccessor;
import io.cattle.platform.process.common.util.ProcessUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;

import javax.inject.Inject;

import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.ObjectUtils;

import com.netflix.config.DynamicStringProperty;

public class AgentInstanceFactoryImpl implements AgentInstanceFactory {
    private static final DynamicStringProperty LB_IMAGE_UUID = ArchaiusUtil.getString("lb.instance.image.uuid");

    @Inject
    AccountDao accountDao;
    @Inject
    ObjectManager objectManager;
    @Inject
    AgentInstanceDao factoryDao;
    @Inject
    LockManager lockManager;
    @Inject
    GenericResourceDao resourceDao;
    @Inject
    AgentLocator agentLocator;
    @Inject
    ResourceMonitor resourceMonitor;
    @Inject
    ObjectProcessManager processManager;
    @Inject
    InstanceDao instanceDao;

    protected Instance build(AgentInstanceBuilderImpl builder) {
        Agent agent = getAgent(builder);

        return getInstance(agent, builder);
    }

    private Instance getInstance(Agent agent, AgentInstanceBuilderImpl builder) {
        Instance instance = factoryDao.getInstanceByAgent(agent);

        if (instance != null) {
            return instance;
        }

        Map<String, Object> properties = getInstanceProperties(agent, builder);

        return createInstance(agent, properties, builder);
    }

    private Map<String, Object> getInstanceProperties(Agent agent, AgentInstanceBuilderImpl builder) {
        Map<Object, Object> properties = new HashMap<Object, Object>();

        properties.put(INSTANCE.ACCOUNT_ID, getAccountId(builder));
        properties.put(INSTANCE.AGENT_ID, agent.getId());
        properties.put(InstanceConstants.FIELD_IMAGE_UUID, builder.getImageUuid());
        properties.put(INSTANCE.NAME, builder.getName());
        properties.put(INSTANCE.ZONE_ID, agent.getZoneId());
        properties.put(INSTANCE.KIND, builder.getInstanceKind());
        properties.put(InstanceConstants.FIELD_PRIVILEGED, builder.isPrivileged());
        properties.put(InstanceConstants.FIELD_NETWORK_IDS, getNetworkIds(agent, builder));
        properties.putAll(builder.getParams());
        addAdditionalProperties(properties, agent, builder);

        return objectManager.convertToPropertiesFor(Instance.class, properties);
    }

    protected void addAdditionalProperties(Map<Object, Object> properties, Agent agent, AgentInstanceBuilderImpl builder) {
    }

    @Override
    public Agent createAgent(Instance instance) {
        if (shouldCreateAgent(instance)) {
            Map<String, Object> labels = DataAccessor.fieldMap(instance, InstanceConstants.FIELD_LABELS);
            Set<String> filteredRoles = new HashSet<>();

            String rolesVal = labels.get(SystemLabels.LABEL_AGENT_ROLE) != null ? labels.get(SystemLabels.LABEL_AGENT_ROLE).toString() : null;
            if (rolesVal != null) {
                String[] roles = rolesVal.split(",");
                for (String r : roles) {
                    if ("environment".equals(r) || "agent".equals(r)) {
                        filteredRoles.add(r);
                    } else if ("environmentAdmin".equals(r) && isSystem(instance)) {
                        filteredRoles.add(r);
                    }
                }
            }

            return getAgent(new AgentInstanceBuilderImpl(this, instance, filteredRoles));
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    protected boolean isLBSystemService(Service service) {
        Map<String, Object> data = DataAccessor.fields(service)
                .withKey("launchConfig").withDefault(Collections.EMPTY_MAP)
                .as(Map.class);

        Object imageObj = data.get(InstanceConstants.FIELD_IMAGE_UUID);
        if (imageObj == null) {
            return false;
        }

        // remove the tag from the default image (assuming that it is always tagged)
        String defaultImageUuid = LB_IMAGE_UUID.get().toLowerCase();
        String[] splitted = defaultImageUuid.split(":");
        String formattedDefault = String.format("%s:%s", splitted[0], splitted[1]);

        return imageObj.toString().startsWith(formattedDefault);
    }

    private boolean isSystem(Instance instance) {
        List<? extends Service> services = instanceDao.findServicesNonRemovedLinksOnly(instance);
        for (Service service : services) {
            Stack stack = objectManager.loadResource(Stack.class, service.getStackId());
            if (ServiceConstants.isSystem(stack) || isLBSystemService(service)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void deleteAgent(Instance instance) {
        if (!shouldCreateAgent(instance) || instance.getAgentId() == null) {
            return;
        }

        Agent agent = objectManager.loadResource(Agent.class, instance.getAgentId());
        if (agent == null) {
            return;
        }

        if (CommonStatesConstants.DEACTIVATING.equals(agent.getState())) {
{'fraction_non_alphanumeric': 0.10232424264229689, 'fraction_numerical': 0.0005756638123335972, 'mean_word_length': 3.4977346278317154, 'pattern_counts': {'":': 2, '<': 23, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3027124', 'n_tokens_mistral': 3739, 'n_tokens_neox': 3766, 'n_words': 692}