Search in sources :

Example 6 with ECSTask

use of com.thoughtworks.gocd.elasticagent.ecs.ECSTask in project gocd-ecs-elastic-agent by gocd.

the class TaskHelper method create.

public Optional<ECSTask> create(CreateAgentRequest createAgentRequest, PluginSettings pluginSettings, ConsoleLogAppender consoleLogAppender) throws ContainerInstanceFailedToRegisterException, LimitExceededException, ContainerFailedToRegisterException {
    final String taskName = "GoCD" + UUID.randomUUID().toString().replaceAll("-", "");
    final ElasticAgentProfileProperties elasticAgentProfileProperties = createAgentRequest.elasticProfile();
    ContainerDefinition containerDefinition = new ContainerDefinitionBuilder().withName(taskName).pluginSettings(pluginSettings).createAgentRequest(createAgentRequest).withServerId(getServerId()).build();
    StopPolicy stopPolicy = elasticAgentProfileProperties.platform() == LINUX ? pluginSettings.getLinuxStopPolicy() : pluginSettings.getWindowsStopPolicy();
    Optional<ContainerInstance> containerInstance = instanceSelectionStrategyFactory.strategyFor(stopPolicy).instanceForScheduling(pluginSettings, elasticAgentProfileProperties, containerDefinition);
    if (!containerInstance.isPresent()) {
        consoleLogAppender.accept("No running instance(s) found to build the ECS Task to perform current job.");
        LOG.info(format("[create-agent] No running instances found to build container with profile {0}", createAgentRequest.elasticProfile().toJson()));
        if (elasticAgentProfileProperties.runAsSpotInstance()) {
            spotInstanceService.create(pluginSettings, elasticAgentProfileProperties, consoleLogAppender);
            return Optional.empty();
        } else {
            containerInstance = containerInstanceHelper.startOrCreateOneInstance(pluginSettings, elasticAgentProfileProperties, consoleLogAppender);
        }
    } else {
        consoleLogAppender.accept("Found existing running container instance platform matching ECS Task instance configuration. Not starting a new EC2 instance...");
    }
    final RegisterTaskDefinitionRequest registerTaskDefinitionRequest = registerTaskDefinitionRequestBuilder.build(pluginSettings, elasticAgentProfileProperties, containerDefinition).withFamily(taskName);
    consoleLogAppender.accept("Registering ECS Task definition with cluster...");
    LOG.debug(format("[create-agent] Registering task definition: {0} ", registerTaskDefinitionRequest.toString()));
    RegisterTaskDefinitionResult taskDefinitionResult = pluginSettings.ecsClient().registerTaskDefinition(registerTaskDefinitionRequest);
    consoleLogAppender.accept("Done registering ECS Task definition with cluster.");
    LOG.debug("[create-agent] Done registering task definition");
    TaskDefinition taskDefinitionFromNewTask = taskDefinitionResult.getTaskDefinition();
    StartTaskRequest startTaskRequest = new StartTaskRequest().withTaskDefinition(taskDefinitionFromNewTask.getTaskDefinitionArn()).withContainerInstances(containerInstance.get().getContainerInstanceArn()).withCluster(pluginSettings.getClusterName());
    consoleLogAppender.accept("Starting ECS Task to perform current job...");
    LOG.debug(format("[create-agent] Starting task : {0} ", startTaskRequest.toString()));
    StartTaskResult startTaskResult = pluginSettings.ecsClient().startTask(startTaskRequest);
    LOG.debug("[create-agent] Done executing start task request.");
    if (isStarted(startTaskResult)) {
        String message = elasticAgentProfileProperties.runAsSpotInstance() ? "[WARNING] The ECS task is scheduled on a Spot Instance. A spot instance termination would re-schedule the job." : String.format("ECS Task %s scheduled on container instance %s.", taskName, containerInstance.get().getEc2InstanceId());
        consoleLogAppender.accept(message);
        LOG.info(format("[create-agent] Task {0} scheduled on container instance {1}", taskName, containerInstance.get().getEc2InstanceId()));
        return Optional.of(new ECSTask(startTaskResult.getTasks().get(0), taskDefinitionFromNewTask, elasticAgentProfileProperties, createAgentRequest.getJobIdentifier(), createAgentRequest.environment(), containerInstance.get().getEc2InstanceId()));
    } else {
        deregisterTaskDefinition(pluginSettings, taskDefinitionFromNewTask.getTaskDefinitionArn());
        String errors = startTaskResult.getFailures().stream().map(failure -> "    " + failure.getArn() + " failed with reason :" + failure.getReason()).collect(Collectors.joining("\n"));
        throw new ContainerFailedToRegisterException("Fail to start task " + taskName + ":\n" + errors);
    }
}
Also used : Optional.empty(java.util.Optional.empty) com.amazonaws.services.ecs.model(com.amazonaws.services.ecs.model) LimitExceededException(com.thoughtworks.gocd.elasticagent.ecs.exceptions.LimitExceededException) java.util(java.util) ContainerInstanceFailedToRegisterException(com.thoughtworks.gocd.elasticagent.ecs.exceptions.ContainerInstanceFailedToRegisterException) InstanceSelectionStrategyFactory(com.thoughtworks.gocd.elasticagent.ecs.aws.strategy.InstanceSelectionStrategyFactory) Collectors(java.util.stream.Collectors) MessageFormat(java.text.MessageFormat) Constants(com.thoughtworks.gocd.elasticagent.ecs.Constants) ECSElasticPlugin.getServerId(com.thoughtworks.gocd.elasticagent.ecs.ECSElasticPlugin.getServerId) MessageFormat.format(java.text.MessageFormat.format) com.thoughtworks.gocd.elasticagent.ecs.domain(com.thoughtworks.gocd.elasticagent.ecs.domain) ContainerFailedToRegisterException(com.thoughtworks.gocd.elasticagent.ecs.exceptions.ContainerFailedToRegisterException) CreateAgentRequest(com.thoughtworks.gocd.elasticagent.ecs.requests.CreateAgentRequest) ECSTask(com.thoughtworks.gocd.elasticagent.ecs.ECSTask) LOG(com.thoughtworks.gocd.elasticagent.ecs.ECSElasticPlugin.LOG) AmazonECS(com.amazonaws.services.ecs.AmazonECS) StringUtils.equalsIgnoreCase(org.apache.commons.lang3.StringUtils.equalsIgnoreCase) LINUX(com.thoughtworks.gocd.elasticagent.ecs.domain.Platform.LINUX) ECSTask(com.thoughtworks.gocd.elasticagent.ecs.ECSTask) ContainerFailedToRegisterException(com.thoughtworks.gocd.elasticagent.ecs.exceptions.ContainerFailedToRegisterException)

Example 7 with ECSTask

use of com.thoughtworks.gocd.elasticagent.ecs.ECSTask in project gocd-ecs-elastic-agent by gocd.

the class TaskHelperTest method shouldCreateTaskForCreateAgentRequest.

@Test
void shouldCreateTaskForCreateAgentRequest() throws Exception {
    final InstanceSelectionStrategy instanceSelectionStrategy = mock(InstanceSelectionStrategy.class);
    final TaskDefinition taskDefinition = new TaskDefinition().withTaskDefinitionArn("task-definition-arn");
    final Task task = new Task().withTaskArn("task-arn").withTaskDefinitionArn(taskDefinition.getTaskDefinitionArn());
    final ContainerInstance containerInstance = new ContainerInstance().withContainerInstanceArn("container-instance-arn");
    final ArgumentCaptor<StartTaskRequest> startTaskRequestArgumentCaptor = ArgumentCaptor.forClass(StartTaskRequest.class);
    RegisterTaskDefinitionRequest registerTaskDefinitionRequest = new RegisterTaskDefinitionRequest();
    when(pluginSettings.efsDnsOrIP()).thenReturn("efs-dns-name");
    when(elasticAgentProfileProperties.isMountDockerSocket()).thenReturn(true);
    when(elasticAgentProfileProperties.getImage()).thenReturn("alpine");
    when(registerTaskDefinitionRequestBuilder.build(eq(pluginSettings), eq(elasticAgentProfileProperties), any(ContainerDefinition.class))).thenReturn(registerTaskDefinitionRequest);
    when(ecsClient.registerTaskDefinition(any())).thenReturn(new RegisterTaskDefinitionResult().withTaskDefinition(taskDefinition));
    when(ecsClient.startTask(startTaskRequestArgumentCaptor.capture())).thenReturn(new StartTaskResult().withTasks(task));
    when(instanceSelectionStrategyFactory.strategyFor(any())).thenReturn(instanceSelectionStrategy);
    when(instanceSelectionStrategy.instanceForScheduling(eq(pluginSettings), eq(elasticAgentProfileProperties), any(ContainerDefinition.class))).thenReturn(Optional.of(containerInstance));
    when(elasticAgentProfileProperties.runAsSpotInstance()).thenReturn(false);
    final Optional<ECSTask> ecsTask = taskHelper.create(createAgentRequest, pluginSettings, consoleLogAppender);
    assertThat(ecsTask.isPresent()).isTrue();
    assertThat(ecsTask.get().taskArn()).isEqualTo(task.getTaskArn());
    assertThat(ecsTask.get().taskDefinition()).isEqualTo(taskDefinition);
    final StartTaskRequest startTaskRequest = startTaskRequestArgumentCaptor.getValue();
    assertThat(startTaskRequest.getCluster()).isEqualTo(pluginSettings.getClusterName());
    assertThat(startTaskRequest.getTaskDefinition()).isEqualTo(taskDefinition.getTaskDefinitionArn());
    assertThat(startTaskRequest.getContainerInstances()).contains(containerInstance.getContainerInstanceArn());
    InOrder inOrder = inOrder(consoleLogAppender);
    inOrder.verify(consoleLogAppender, times(1)).accept("Found existing running container instance platform matching ECS Task instance configuration. Not starting a new EC2 instance...");
    inOrder.verify(consoleLogAppender, times(1)).accept("Registering ECS Task definition with cluster...");
    inOrder.verify(consoleLogAppender, times(1)).accept("Done registering ECS Task definition with cluster.");
    inOrder.verify(consoleLogAppender, times(1)).accept("Starting ECS Task to perform current job...");
    inOrder.verify(consoleLogAppender, times(1)).accept(String.format("ECS Task %s scheduled on container instance %s.", registerTaskDefinitionRequest.getFamily(), containerInstance.getEc2InstanceId()));
    verifyNoMoreInteractions(consoleLogAppender);
}
Also used : ECSTask(com.thoughtworks.gocd.elasticagent.ecs.ECSTask) ECSTask(com.thoughtworks.gocd.elasticagent.ecs.ECSTask) InOrder(org.mockito.InOrder) InstanceSelectionStrategy(com.thoughtworks.gocd.elasticagent.ecs.aws.strategy.InstanceSelectionStrategy) Test(org.junit.jupiter.api.Test)

Example 8 with ECSTask

use of com.thoughtworks.gocd.elasticagent.ecs.ECSTask in project gocd-ecs-elastic-agent by gocd.

the class TaskHelperTest method shouldCreateECSTaskFromTaskAndTaskDefinitionWhenContainerDefinitionIsNotTaggedWithServerId.

@Test
void shouldCreateECSTaskFromTaskAndTaskDefinitionWhenContainerDefinitionIsNotTaggedWithServerId() {
    final Task task = mock(Task.class);
    final TaskDefinition taskDefinition = mock(TaskDefinition.class);
    final ContainerDefinition containerDefinition = mock(ContainerDefinition.class);
    final Map<String, String> dockerLabels = new HashMap<String, String>() {

        {
            put(CONFIGURATION_LABEL_KEY, "{\"Image\":\"alpine\"}");
            put(CREATED_BY_LABEL_KEY, PLUGIN_ID);
            put(ENVIRONMENT_LABEL_KEY, "environment");
        }
    };
    when(task.getTaskArn()).thenReturn("task-arn");
    when(task.getContainerInstanceArn()).thenReturn("container-instance-arn");
    when(taskDefinition.getContainerDefinitions()).thenReturn(Collections.singletonList(containerDefinition));
    when(containerDefinition.getDockerLabels()).thenReturn(dockerLabels);
    final Optional<ECSTask> ecsTask = taskHelper.fromTaskInfo(task, taskDefinition, Collections.singletonMap("container-instance-arn", "i-12345ab"), "gocd-server-id");
    assertThat(ecsTask.isPresent()).isTrue();
    assertThat(ecsTask.get().elasticProfile().getImage()).isEqualTo("alpine");
    assertThat(ecsTask.get().environment()).isEqualTo("environment");
    assertThat(ecsTask.get().getEC2InstanceId()).isEqualTo("i-12345ab");
    assertThat(ecsTask.get().taskDefinition()).isEqualTo(taskDefinition);
    assertThat(ecsTask.get().taskArn()).isEqualTo("task-arn");
}
Also used : ECSTask(com.thoughtworks.gocd.elasticagent.ecs.ECSTask) ECSTask(com.thoughtworks.gocd.elasticagent.ecs.ECSTask) Test(org.junit.jupiter.api.Test)

Example 9 with ECSTask

use of com.thoughtworks.gocd.elasticagent.ecs.ECSTask in project gocd-ecs-elastic-agent by gocd.

the class TaskHelperTest method shouldStopAndDeregisterTask.

@Test
void shouldStopAndDeregisterTask() {
    final ECSTask ecsTask = mock(ECSTask.class);
    when(ecsTask.taskArn()).thenReturn("task-arn");
    when(ecsTask.taskDefinitionArn()).thenReturn("task-definition-arn");
    taskHelper.stopAndDeregisterTask(pluginSettings, ecsTask);
    final ArgumentCaptor<StopTaskRequest> stopTaskRequestArgumentCaptor = ArgumentCaptor.forClass(StopTaskRequest.class);
    verify(ecsClient).stopTask(stopTaskRequestArgumentCaptor.capture());
    final StopTaskRequest stopTaskRequest = stopTaskRequestArgumentCaptor.getValue();
    assertThat(stopTaskRequest).isNotNull();
    assertThat(stopTaskRequest.getCluster()).isEqualTo(pluginSettings.getClusterName());
    assertThat(stopTaskRequest.getReason()).isEqualTo("Stopped by GoCD server.");
    assertThat(stopTaskRequest.getTask()).isEqualTo("task-arn");
    final ArgumentCaptor<DeregisterTaskDefinitionRequest> deregisterTaskDefinitionRequestArgumentCaptor = ArgumentCaptor.forClass(DeregisterTaskDefinitionRequest.class);
    verify(ecsClient).deregisterTaskDefinition(deregisterTaskDefinitionRequestArgumentCaptor.capture());
    final DeregisterTaskDefinitionRequest deregisterTaskDefinitionRequest = deregisterTaskDefinitionRequestArgumentCaptor.getValue();
    assertThat(deregisterTaskDefinitionRequest).isNotNull();
    assertThat(deregisterTaskDefinitionRequest.getTaskDefinition()).isEqualTo("task-definition-arn");
}
Also used : ECSTask(com.thoughtworks.gocd.elasticagent.ecs.ECSTask) Test(org.junit.jupiter.api.Test)

Example 10 with ECSTask

use of com.thoughtworks.gocd.elasticagent.ecs.ECSTask in project gocd-ecs-elastic-agent by gocd.

the class ShouldAssignWorkRequestExecutor method execute.

@Override
public GoPluginApiResponse execute() {
    ECSTask instance = agentInstances.find(request.agent().elasticAgentId());
    if (instance == null) {
        return DefaultGoPluginApiResponse.success("false");
    }
    boolean sameJobIdentifiers = request.jobIdentifier().equals(instance.getJobIdentifier());
    if (sameJobIdentifiers) {
        LOG.info(format("[should-assign-work] Job[{0}] can be assigned to an agent {1}.", request.jobIdentifier().getRepresentation(), instance.name()));
        return DefaultGoPluginApiResponse.success("true");
    }
    LOG.info(format("[should-assign-work] Job[{0}] can not be assigned to an agent {1}.", request.jobIdentifier().getRepresentation(), instance.name()));
    return DefaultGoPluginApiResponse.success("false");
}
Also used : ECSTask(com.thoughtworks.gocd.elasticagent.ecs.ECSTask)

Aggregations

ECSTask (com.thoughtworks.gocd.elasticagent.ecs.ECSTask)10 Test (org.junit.jupiter.api.Test)7 InstanceSelectionStrategy (com.thoughtworks.gocd.elasticagent.ecs.aws.strategy.InstanceSelectionStrategy)3 InOrder (org.mockito.InOrder)3 AmazonECS (com.amazonaws.services.ecs.AmazonECS)1 com.amazonaws.services.ecs.model (com.amazonaws.services.ecs.model)1 Constants (com.thoughtworks.gocd.elasticagent.ecs.Constants)1 LOG (com.thoughtworks.gocd.elasticagent.ecs.ECSElasticPlugin.LOG)1 ECSElasticPlugin.getServerId (com.thoughtworks.gocd.elasticagent.ecs.ECSElasticPlugin.getServerId)1 InstanceSelectionStrategyFactory (com.thoughtworks.gocd.elasticagent.ecs.aws.strategy.InstanceSelectionStrategyFactory)1 com.thoughtworks.gocd.elasticagent.ecs.domain (com.thoughtworks.gocd.elasticagent.ecs.domain)1 LINUX (com.thoughtworks.gocd.elasticagent.ecs.domain.Platform.LINUX)1 ContainerFailedToRegisterException (com.thoughtworks.gocd.elasticagent.ecs.exceptions.ContainerFailedToRegisterException)1 ContainerInstanceFailedToRegisterException (com.thoughtworks.gocd.elasticagent.ecs.exceptions.ContainerInstanceFailedToRegisterException)1 LimitExceededException (com.thoughtworks.gocd.elasticagent.ecs.exceptions.LimitExceededException)1 CreateAgentRequest (com.thoughtworks.gocd.elasticagent.ecs.requests.CreateAgentRequest)1 MessageFormat (java.text.MessageFormat)1 MessageFormat.format (java.text.MessageFormat.format)1 java.util (java.util)1 Optional.empty (java.util.Optional.empty)1