package com.amazon.jenkins.ec2fleet; import com.amazonaws.services.ec2.AmazonEC2; import com.amazonaws.services.ec2.model.ActiveInstance; import com.amazonaws.services.ec2.model.DescribeInstancesRequest; import com.amazonaws.services.ec2.model.DescribeInstancesResult; import com.amazonaws.services.ec2.model.DescribeSpotFleetInstancesRequest; import com.amazonaws.services.ec2.model.DescribeSpotFleetInstancesResult; import com.amazonaws.services.ec2.model.DescribeSpotFleetRequestsRequest; import com.amazonaws.services.ec2.model.DescribeSpotFleetRequestsResult; import com.amazonaws.services.ec2.model.Instance; import com.amazonaws.services.ec2.model.InstanceState; import com.amazonaws.services.ec2.model.InstanceStateName; import com.amazonaws.services.ec2.model.Reservation; import com.amazonaws.services.ec2.model.SpotFleetRequestConfig; import com.amazonaws.services.ec2.model.SpotFleetRequestConfigData; import hudson.Functions; import hudson.model.FreeStyleProject; import hudson.model.Node; import hudson.model.ParametersAction; import hudson.model.ParametersDefinitionProperty; import hudson.model.Result; import hudson.model.StringParameterDefinition; import hudson.model.StringParameterValue; import hudson.model.labels.LabelAtom; import hudson.model.queue.QueueTaskFuture; import hudson.slaves.OfflineCause; import hudson.tasks.BatchFile; import hudson.tasks.Shell; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; @SuppressWarnings({"ArraysAsListWithZeroOrOneArgument", "deprecation"}) public class AutoResubmitIntegrationTest extends IntegrationTest { @Before public void before() { EC2Api ec2Api = spy(EC2Api.class); Registry.setEc2Api(ec2Api); AmazonEC2 amazonEC2 = mock(AmazonEC2.class); when(ec2Api.connect(anyString(), anyString(), Mockito.nullable(String.class))).thenReturn(amazonEC2); final Instance instance = new Instance() .withState(new InstanceState().withName(InstanceStateName.Running)) .withPublicIpAddress("public-io") .withInstanceId("i-1"); when(amazonEC2.describeInstances(any(DescribeInstancesRequest.class))).thenReturn( new DescribeInstancesResult().withReservations( new Reservation().withInstances( instance ))); when(amazonEC2.describeSpotFleetInstances(any(DescribeSpotFleetInstancesRequest.class))) .thenReturn(new DescribeSpotFleetInstancesResult() .withActiveInstances(new ActiveInstance().withInstanceId("i-1"))); DescribeSpotFleetRequestsResult describeSpotFleetRequestsResult = new DescribeSpotFleetRequestsResult(); describeSpotFleetRequestsResult.setSpotFleetRequestConfigs(Arrays.asList( new SpotFleetRequestConfig() .withSpotFleetRequestState("active") .withSpotFleetRequestConfig( new SpotFleetRequestConfigData().withTargetCapacity(1)))); when(amazonEC2.describeSpotFleetRequests(any(DescribeSpotFleetRequestsRequest.class))) .thenReturn(describeSpotFleetRequestsResult); } @Test public void should_successfully_resubmit_freestyle_task() throws Exception { EC2FleetCloud cloud = new EC2FleetCloud(null, null, "credId", null, "region", null, "fId", "momo", null, new LocalComputerConnector(j), false, false, 0, 0, 10, 1, false, false, false, 0, 0, false, 10, false); j.jenkins.clouds.add(cloud); List<QueueTaskFuture> rs = getQueueTaskFutures(1); System.out.println("check if zero nodes!"); Assert.assertEquals(0, j.jenkins.getNodes().size()); assertAtLeastOneNode(); final Node node = j.jenkins.getNodes().get(0); assertQueueIsEmpty(); System.out.println("disconnect node"); node.toComputer().disconnect(new OfflineCause.ChannelTermination(new UnsupportedOperationException("Test"))); // due to test nature job could be failed if started or aborted as we call disconnect // in prod code it's not matter assertLastBuildResult(Result.FAILURE, Result.ABORTED); node.toComputer().connect(true); assertNodeIsOnline(node); assertQueueAndNodesIdle(node); Assert.assertEquals(1, j.jenkins.getProjects().size()); Assert.assertEquals(Result.SUCCESS, j.jenkins.getProjects().get(0).getLastBuild().getResult()); Assert.assertEquals(2, j.jenkins.getProjects().get(0).getBuilds().size()); cancelTasks(rs); } @Test public void should_successfully_resubmit_parametrized_task() throws Exception { EC2FleetCloud cloud = new EC2FleetCloud(null, null, "credId", null, "region", null, "fId", "momo", null, new LocalComputerConnector(j), false, false, 0, 0, 10, 1, false, false, false, 0, 0, false, 10, false); j.jenkins.clouds.add(cloud); List<QueueTaskFuture> rs = new ArrayList<>(); final FreeStyleProject project = j.createFreeStyleProject(); project.setAssignedLabel(new LabelAtom("momo")); project.addProperty(new ParametersDefinitionProperty(new StringParameterDefinition("number", "opa"))); /* example of actions for project actions = {[email protected]} size = 2 0 = {[email protected]} safeParameters = {[email protected]} size = 0 parameters = {[email protected]} size = 1 0 = {[email protected]} "(StringParameterValue) number='1'" value = "1" name = "number" description = "" parameterDefinitionNames = {[email protected]} size = 1 0 = "number" build = null run = {[email protected]} "parameter #14" */ project.getBuildersList().add(Functions.isWindows() ? new BatchFile("Ping -n %number% 127.0.0.1 > nul") : new Shell("sleep ${number}")); rs.add(project.scheduleBuild2(0, new ParametersAction(new StringParameterValue("number", "30")))); System.out.println("check if zero nodes!"); Assert.assertEquals(0, j.jenkins.getNodes().size()); assertAtLeastOneNode(); final Node node = j.jenkins.getNodes().get(0); assertQueueIsEmpty(); System.out.println("disconnect node"); node.toComputer().disconnect(new OfflineCause.ChannelTermination(new UnsupportedOperationException("Test"))); assertLastBuildResult(Result.FAILURE, Result.ABORTED); node.toComputer().connect(true); assertNodeIsOnline(node); assertQueueAndNodesIdle(node); Assert.assertEquals(1, j.jenkins.getProjects().size()); Assert.assertEquals(Result.SUCCESS, j.jenkins.getProjects().get(0).getLastBuild().getResult()); Assert.assertEquals(2, j.jenkins.getProjects().get(0).getBuilds().size()); cancelTasks(rs); } @Test public void should_not_resubmit_if_disabled() throws Exception { EC2FleetCloud cloud = new EC2FleetCloud(null, null, "credId", null, "region", null, "fId", "momo", null, new LocalComputerConnector(j), false, false, 0, 0, 10, 1, false, false, true, 0, 0, false, 10, false); j.jenkins.clouds.add(cloud); List<QueueTaskFuture> rs = getQueueTaskFutures(1); System.out.println("check if zero nodes!"); Assert.assertEquals(0, j.jenkins.getNodes().size()); assertAtLeastOneNode(); final Node node = j.jenkins.getNodes().get(0); assertQueueIsEmpty(); System.out.println("disconnect node"); node.toComputer().disconnect(new OfflineCause.ChannelTermination(new UnsupportedOperationException("Test"))); assertLastBuildResult(Result.FAILURE, Result.ABORTED); node.toComputer().connect(true); assertNodeIsOnline(node); assertQueueAndNodesIdle(node); Assert.assertEquals(1, j.jenkins.getProjects().size()); Assert.assertEquals(Result.FAILURE, j.jenkins.getProjects().get(0).getLastBuild().getResult()); Assert.assertEquals(1, j.jenkins.getProjects().get(0).getBuilds().size()); cancelTasks(rs); } }