package org.zalando.stups.fullstop.jobs.elb;
import com.amazonaws.regions.Region;
import com.amazonaws.services.elasticloadbalancing.AmazonElasticLoadBalancingClient;
import com.amazonaws.services.elasticloadbalancing.model.DescribeLoadBalancersRequest;
import com.amazonaws.services.elasticloadbalancing.model.DescribeLoadBalancersResult;
import com.amazonaws.services.elasticloadbalancing.model.Instance;
import com.amazonaws.services.elasticloadbalancing.model.Listener;
import com.amazonaws.services.elasticloadbalancing.model.ListenerDescription;
import com.amazonaws.services.elasticloadbalancing.model.LoadBalancerDescription;
import com.google.common.collect.ImmutableMap;
import org.apache.http.impl.client.CloseableHttpClient;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.zalando.stups.fullstop.aws.ClientProvider;
import org.zalando.stups.fullstop.jobs.common.AccountIdSupplier;
import org.zalando.stups.fullstop.jobs.common.AmiDetailsProvider;
import org.zalando.stups.fullstop.jobs.common.AwsApplications;
import org.zalando.stups.fullstop.jobs.common.EC2InstanceProvider;
import org.zalando.stups.fullstop.jobs.common.FetchTaupageYaml;
import org.zalando.stups.fullstop.jobs.common.PortsChecker;
import org.zalando.stups.fullstop.jobs.common.SecurityGroupsChecker;
import org.zalando.stups.fullstop.jobs.config.JobsProperties;
import org.zalando.stups.fullstop.violation.ViolationSink;
import org.zalando.stups.fullstop.violation.service.ViolationService;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import static com.amazonaws.regions.Region.getRegion;
import static com.amazonaws.regions.Regions.fromName;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Sets.newHashSet;
import static java.util.Arrays.asList;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.anyListOf;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
public class FetchElasticLoadBalancersJobTest {
public static final String ACCOUNT_ID = "1";
public static final String REGION1 = "eu-west-1";
private ViolationSink violationSinkMock;
private ClientProvider clientProviderMock;
private AccountIdSupplier accountIdSupplierMock;
private JobsProperties jobsPropertiesMock;
private AmazonElasticLoadBalancingClient mockAwsELBClient;
private DescribeLoadBalancersResult mockDescribeELBResult;
private PortsChecker portsChecker;
private SecurityGroupsChecker securityGroupsChecker;
private final List<String> regions = newArrayList();
private AwsApplications mockAwsApplications;
private ViolationService mockViolationService;
private FetchTaupageYaml fetchTaupageYamlMock;
private AmiDetailsProvider mockAmiDetailsProvider;
private EC2InstanceProvider mockEC2InstanceProvider;
@Before
public void setUp() throws Exception {
this.violationSinkMock = mock(ViolationSink.class);
this.clientProviderMock = mock(ClientProvider.class);
this.accountIdSupplierMock = mock(AccountIdSupplier.class);
this.jobsPropertiesMock = mock(JobsProperties.class);
this.portsChecker = mock(PortsChecker.class);
this.securityGroupsChecker = mock(SecurityGroupsChecker.class);
this.mockAwsELBClient = mock(AmazonElasticLoadBalancingClient.class);
this.mockAwsApplications = mock(AwsApplications.class);
this.mockViolationService = mock(ViolationService.class);
this.fetchTaupageYamlMock = mock(FetchTaupageYaml.class);
this.mockAmiDetailsProvider = mock(AmiDetailsProvider.class);
this.mockEC2InstanceProvider = mock(EC2InstanceProvider.class);
final Listener listener = new Listener("HTTPS", 80, 80);
final ListenerDescription listenerDescription = new ListenerDescription();
listenerDescription.setListener(listener);
final LoadBalancerDescription publicELB = new LoadBalancerDescription();
publicELB.setScheme("internet-facing");
publicELB.setListenerDescriptions(newArrayList(listenerDescription));
publicELB.setCanonicalHostedZoneName("test.com");
publicELB.setInstances(asList(new Instance("i1"), new Instance("i2")));
final LoadBalancerDescription privateELB = new LoadBalancerDescription();
privateELB.setScheme("internal");
privateELB.setCanonicalHostedZoneName("internal.org");
mockDescribeELBResult = new DescribeLoadBalancersResult();
mockDescribeELBResult.setLoadBalancerDescriptions(newArrayList(publicELB, privateELB));
regions.add(REGION1);
when(clientProviderMock.getClient(any(), any(String.class), any(Region.class))).thenReturn(mockAwsELBClient);
when(mockEC2InstanceProvider.getById(anyString(), any(Region.class), anyString()))
.thenReturn(Optional.of(new com.amazonaws.services.ec2.model.Instance().withInstanceId("foo").withImageId("bar")));
when(mockAmiDetailsProvider.getAmiDetails(anyString(), any(Region.class), anyString()))
.thenReturn(ImmutableMap.of("ami_id", "bar"));
}
@Test
public void testCheck() throws Exception {
when(accountIdSupplierMock.get()).thenReturn(newHashSet(ACCOUNT_ID));
when(jobsPropertiesMock.getWhitelistedRegions()).thenReturn(regions);
when(portsChecker.check(any(LoadBalancerDescription.class))).thenReturn(Collections.<Integer>emptyList());
when(securityGroupsChecker.check(any(), any(), any())).thenReturn(Collections.<String>emptySet());
when(mockAwsELBClient.describeLoadBalancers(any(DescribeLoadBalancersRequest.class))).thenReturn(mockDescribeELBResult);
when(mockAwsApplications.isPubliclyAccessible(anyString(), anyString(), anyListOf(String.class)))
.thenReturn(Optional.of(false));
final FetchElasticLoadBalancersJob fetchELBJob = new FetchElasticLoadBalancersJob(
violationSinkMock,
clientProviderMock,
accountIdSupplierMock,
jobsPropertiesMock,
securityGroupsChecker,
portsChecker,
mockAwsApplications,
mockViolationService,
fetchTaupageYamlMock,
mockAmiDetailsProvider,
mockEC2InstanceProvider,
mock(CloseableHttpClient.class));
fetchELBJob.run();
verify(accountIdSupplierMock).get();
verify(jobsPropertiesMock, atLeast(1)).getWhitelistedRegions();
verify(jobsPropertiesMock).getElbAllowedPorts();
verify(securityGroupsChecker, atLeast(1)).check(any(), any(), any());
verify(portsChecker, atLeast(1)).check(any());
verify(mockAwsELBClient).describeLoadBalancers(any(DescribeLoadBalancersRequest.class));
verify(clientProviderMock).getClient(any(), any(String.class), any(Region.class));
verify(mockAwsApplications).isPubliclyAccessible(eq(ACCOUNT_ID), eq(REGION1), eq(asList("i1", "i2")));
verify(mockEC2InstanceProvider).getById(eq(ACCOUNT_ID), eq(getRegion(fromName(REGION1))), eq("i1"));
verify(mockAmiDetailsProvider).getAmiDetails(eq(ACCOUNT_ID), eq(getRegion(fromName(REGION1))), eq("bar"));
}
@After
public void tearDown() throws Exception {
verifyNoMoreInteractions(violationSinkMock,
clientProviderMock,
accountIdSupplierMock,
jobsPropertiesMock,
securityGroupsChecker,
portsChecker,
mockAwsApplications);
}
}