package com.sequenceiq.cloudbreak.cloud.gcp.compute;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
import com.google.api.services.compute.Compute;
import com.google.api.services.compute.model.Instance;
import com.google.api.services.compute.model.Operation;
import com.google.common.collect.ImmutableMap;
import com.sequenceiq.cloudbreak.api.model.InstanceGroupType;
import com.sequenceiq.cloudbreak.cloud.context.AuthenticatedContext;
import com.sequenceiq.cloudbreak.cloud.context.CloudContext;
import com.sequenceiq.cloudbreak.cloud.gcp.context.GcpContext;
import com.sequenceiq.cloudbreak.cloud.gcp.service.GcpResourceNameService;
import com.sequenceiq.cloudbreak.cloud.gcp.util.GcpStackUtil;
import com.sequenceiq.cloudbreak.cloud.model.AvailabilityZone;
import com.sequenceiq.cloudbreak.cloud.model.CloudCredential;
import com.sequenceiq.cloudbreak.cloud.model.CloudInstance;
import com.sequenceiq.cloudbreak.cloud.model.CloudResource;
import com.sequenceiq.cloudbreak.cloud.model.Group;
import com.sequenceiq.cloudbreak.cloud.model.Image;
import com.sequenceiq.cloudbreak.cloud.model.InstanceStatus;
import com.sequenceiq.cloudbreak.cloud.model.InstanceTemplate;
import com.sequenceiq.cloudbreak.cloud.model.Location;
import com.sequenceiq.cloudbreak.cloud.model.PortDefinition;
import com.sequenceiq.cloudbreak.cloud.model.Region;
import com.sequenceiq.cloudbreak.cloud.model.Security;
import com.sequenceiq.cloudbreak.cloud.model.SecurityRule;
import com.sequenceiq.cloudbreak.cloud.model.Volume;
import com.sequenceiq.cloudbreak.common.type.ResourceType;
@RunWith(MockitoJUnitRunner.class)
public class GcpInstanceResourceBuilderTest {
private long privateId;
private String instanceId;
private String name;
private String flavor;
private List<Volume> volumes;
private Location location;
private Map<InstanceGroupType, String> userData;
private Image image;
private List<SecurityRule> rules;
private Security security;
private CloudContext cloudContext;
private CloudCredential cloudCredential;
private String projectId;
private AuthenticatedContext authenticatedContext;
private GcpResourceNameService resourceNameService;
private GcpContext context;
private CloudResource networkResource;
private List<CloudResource> networkResources;
private Operation operation;
@Mock
private Compute compute;
@Mock
private Compute.Instances instances;
@Mock
private Compute.Instances.Insert insert;
@Captor
private ArgumentCaptor<Instance> instanceArg;
@InjectMocks
private GcpInstanceResourceBuilder builder = new GcpInstanceResourceBuilder();
@Before
public void setUp() throws Exception {
privateId = 0L;
name = "master";
flavor = "m1.medium";
instanceId = "SOME_ID";
volumes = Arrays.asList(new Volume("/hadoop/fs1", "HDD", 1), new Volume("/hadoop/fs2", "HDD", 1));
rules = Collections.singletonList(new SecurityRule("0.0.0.0/0",
new PortDefinition[]{new PortDefinition("22", "22"), new PortDefinition("443", "443")}, "tcp"));
security = new Security(rules, null);
location = Location.location(Region.region("region"), AvailabilityZone.availabilityZone("az"));
userData = ImmutableMap.of(InstanceGroupType.CORE, "CORE", InstanceGroupType.GATEWAY, "GATEWAY");
image = new Image("cb-centos66-amb200-2015-05-25", userData);
cloudContext = new CloudContext(privateId, "testname", "GCP", "owner");
cloudCredential = new CloudCredential(privateId, "credentialname", "sshkey", "loginuser");
cloudCredential.putParameter("projectId", "projectId");
projectId = GcpStackUtil.getProjectId(cloudCredential);
authenticatedContext = new AuthenticatedContext(cloudContext, cloudCredential);
context = new GcpContext(cloudContext.getName(), location, projectId, compute, false, 30, false);
networkResources = Arrays.asList(new CloudResource.Builder().type(ResourceType.GCP_NETWORK).name("network-test").build());
context.addNetworkResources(networkResources);
operation = new Operation();
operation.setName("operation");
operation.setHttpErrorStatusCode(null);
resourceNameService = new GcpResourceNameService();
ReflectionTestUtils.setField(resourceNameService, "maxResourceNameLength", 50);
ReflectionTestUtils.setField(builder, "resourceNameService", resourceNameService);
}
@Test
public void isSchedulingPreemptibleTest() throws Exception {
// GIVEN
Group group = newGroupWithParams(ImmutableMap.of("preemptible", true));
List<CloudResource> buildableResources = builder.create(context, privateId, authenticatedContext, group, image);
context.addComputeResources(0, buildableResources);
// WHEN
when(compute.instances()).thenReturn(instances);
when(instances.insert(anyString(), anyString(), instanceArg.capture())).thenReturn(insert);
when(insert.setPrettyPrint(anyBoolean())).thenReturn(insert);
when(insert.execute()).thenReturn(operation);
List<CloudResource> resources = builder.build(context, privateId, authenticatedContext, group, image, buildableResources, Collections.emptyMap());
// THEN
verify(compute).instances();
verify(instances).insert(anyString(), anyString(), instanceArg.capture());
assertTrue(instanceArg.getValue().getScheduling().getPreemptible());
}
@Test
public void isSchedulingNotPreemptibleTest() throws Exception {
// GIVEN
Group group = newGroupWithParams(ImmutableMap.of("preemptible", false));
List<CloudResource> buildableResources = builder.create(context, privateId, authenticatedContext, group, image);
context.addComputeResources(0, buildableResources);
// WHEN
when(compute.instances()).thenReturn(instances);
when(instances.insert(anyString(), anyString(), instanceArg.capture())).thenReturn(insert);
when(insert.setPrettyPrint(anyBoolean())).thenReturn(insert);
when(insert.execute()).thenReturn(operation);
List<CloudResource> resources = builder.build(context, privateId, authenticatedContext, group, image, buildableResources, Collections.emptyMap());
// THEN
verify(compute).instances();
verify(instances).insert(anyString(), anyString(), instanceArg.capture());
assertFalse(instanceArg.getValue().getScheduling().getPreemptible());
}
@Test
public void preemptibleParameterNotSetTest() throws Exception {
// GIVEN
Group group = newGroupWithParams(ImmutableMap.of());
List<CloudResource> buildableResources = builder.create(context, privateId, authenticatedContext, group, image);
context.addComputeResources(0, buildableResources);
// WHEN
when(compute.instances()).thenReturn(instances);
when(instances.insert(anyString(), anyString(), instanceArg.capture())).thenReturn(insert);
when(insert.setPrettyPrint(anyBoolean())).thenReturn(insert);
when(insert.execute()).thenReturn(operation);
List<CloudResource> resources = builder.build(context, privateId, authenticatedContext, group, image, buildableResources, Collections.emptyMap());
// THEN
verify(compute).instances();
verify(instances).insert(anyString(), anyString(), instanceArg.capture());
assertFalse(instanceArg.getValue().getScheduling().getPreemptible());
}
public Group newGroupWithParams(Map<String, Object> params) {
InstanceTemplate instanceTemplate = new InstanceTemplate(flavor, name, privateId, volumes, InstanceStatus.CREATE_REQUESTED, params);
CloudInstance cloudInstance = new CloudInstance(instanceId, instanceTemplate);
return new Group(name, InstanceGroupType.CORE, Collections.singletonList(cloudInstance), security, null);
}
}