package tw.com.unit;
import com.amazonaws.services.cloudformation.model.Stack;
import com.amazonaws.services.cloudformation.model.StackStatus;
import com.amazonaws.services.elasticloadbalancing.model.Instance;
import com.amazonaws.services.identitymanagement.model.User;
import org.easymock.EasyMock;
import org.easymock.EasyMockRunner;
import org.easymock.EasyMockSupport;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import tw.com.AwsFacade;
import tw.com.EnvironmentSetupForTests;
import tw.com.FilesForTesting;
import tw.com.MonitorStackEvents;
import tw.com.entity.*;
import tw.com.exceptions.CfnAssistException;
import tw.com.providers.IdentityProvider;
import tw.com.providers.NotificationSender;
import tw.com.repository.CloudFormRepository;
import tw.com.repository.CloudRepository;
import tw.com.repository.ELBRepository;
import tw.com.repository.VpcRepository;
import java.io.File;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
@RunWith(EasyMockRunner.class)
public class TestAWSFacadeDeleteStacks extends EasyMockSupport {
private static final String DELETE_COMP_STATUS = StackStatus.DELETE_COMPLETE.toString();
private AwsFacade aws;
private ProjectAndEnv projectAndEnv = EnvironmentSetupForTests.getMainProjectAndEnv();
private CloudFormRepository cfnRepository;
private ELBRepository elbRepository;
private MonitorStackEvents monitor;
private String project = projectAndEnv.getProject();
private EnvironmentTag environmentTag = projectAndEnv.getEnvTag();
private NotificationSender notificationSender;
private IdentityProvider identityProvider;
private User user;
@Before
public void beforeEachTestRuns() {
monitor = createMock(MonitorStackEvents.class);
cfnRepository = createMock(CloudFormRepository.class);
VpcRepository vpcRepository = createMock(VpcRepository.class);
elbRepository = createMock(ELBRepository.class);
CloudRepository cloudRepository = createStrictMock(CloudRepository.class);
notificationSender = createStrictMock(NotificationSender.class);
identityProvider = createStrictMock(IdentityProvider.class);
user = new User("path", "userName", "userId", "arn", new Date());
String regionName = EnvironmentSetupForTests.getRegion().getName();
aws = new AwsFacade(monitor, cfnRepository, vpcRepository, elbRepository, cloudRepository, notificationSender, identityProvider,regionName);
}
@Test
public void shouldDeleteStack() throws InterruptedException, CfnAssistException {
String fullName = "CfnAssistTestsimpleStack";
String filename = FilesForTesting.SIMPLE_STACK;
File file = new File(filename);
String stackId = "stackId";
StackNameAndId stackNameAndId = new StackNameAndId(fullName, stackId);
setDeleteExpectations(fullName, stackNameAndId);
replayAll();
aws.deleteStackFrom(file, projectAndEnv);
verifyAll();
}
@Test
public void shouldDeleteByName() throws CfnAssistException, InterruptedException {
String fullName = "CfnAssistTestsimpleStack";
String stackId = "stackId";
StackNameAndId stackNameAndId = new StackNameAndId(fullName, stackId);
setDeleteExpectations(fullName, stackNameAndId);
replayAll();
aws.deleteStackByName("simpleStack", projectAndEnv);
verifyAll();
}
@Test
public void shouldDeleteStackWithBuildNumber() throws InterruptedException, CfnAssistException {
String fullName = "CfnAssist57TestsimpleStack";
String filename = FilesForTesting.SIMPLE_STACK;
File file = new File(filename);
String stackId = "stackId";
StackNameAndId stackNameAndId = new StackNameAndId(fullName, stackId);
projectAndEnv.addBuildNumber(57);
setDeleteExpectations(fullName, stackNameAndId);
replayAll();
aws.deleteStackFrom(file, projectAndEnv);
verifyAll();
}
@Test
public void shouldDeleteByNameWithBuildNumber() throws CfnAssistException, InterruptedException {
String fullName = "CfnAssist57TestsimpleStack";
String stackId = "stackId";
StackNameAndId stackNameAndId = new StackNameAndId(fullName, stackId);
projectAndEnv.addBuildNumber(57);
setDeleteExpectations(fullName, stackNameAndId);
replayAll();
aws.deleteStackByName("simpleStack", projectAndEnv);
verifyAll();
}
@Test
public void shouldDeleteNamedStacksNotAssociatedWithLB() throws InterruptedException, CfnAssistException {
String filename = FilesForTesting.SIMPLE_STACK;
File file = new File(filename);
Stack stackA = new Stack().withStackName("CfnAssist0057TestsimpleStack").withStackId("idA");
Stack stackB = new Stack().withStackName("CfnAssist0058TestsimpleStack").withStackId("idB");
Stack stackC = new Stack().withStackName("CfnAssist0059TestsimpleStack").withStackId("idC"); // only this one associated with LB
List<StackEntry> stacksForProj = new LinkedList<>();
stacksForProj.add(new StackEntry(project, environmentTag, stackA));
stacksForProj.add(new StackEntry(project, environmentTag, stackB));
stacksForProj.add(new StackEntry(project, environmentTag, stackC));
List<Instance> elbInstances = new LinkedList<>();
elbInstances.add(new Instance().withInstanceId("matchingInstanceId"));
EasyMock.expect(elbRepository.findInstancesAssociatedWithLB(projectAndEnv,"typeTag")).andReturn(elbInstances);
EasyMock.expect(cfnRepository.getStacksMatching(environmentTag,"simpleStack")).andReturn(stacksForProj);
EasyMock.expect(cfnRepository.getInstancesFor(stackA.getStackName())).andReturn(createInstancesFor("123"));
EasyMock.expect(cfnRepository.getInstancesFor(stackB.getStackName())).andReturn(createInstancesFor("567"));
EasyMock.expect(cfnRepository.getInstancesFor(stackC.getStackName())).andReturn(createInstancesFor("matchingInstanceId"));
setDeleteExpectations(stackA.getStackName(), createNameAndId(stackA));
setDeleteExpectations(stackB.getStackName(), createNameAndId(stackB));
replayAll();
aws.tidyNonLBAssocStacks(file, projectAndEnv,"typeTag");
verifyAll();
}
@Test
public void shouldDeleteNamedStacksNotAssociatedWithLBWhileIgnoringStacksWithNoInstances() throws InterruptedException, CfnAssistException {
String filename = FilesForTesting.SIMPLE_STACK;
File file = new File(filename);
Stack stackA = new Stack().withStackName("CfnAssist0057TestsimpleStack").withStackId("idA"); // this one has no instances
Stack stackB = new Stack().withStackName("CfnAssist0058TestsimpleStack").withStackId("idB");
Stack stackC = new Stack().withStackName("CfnAssist0059TestsimpleStack").withStackId("idC"); // only this one associated with LB
List<StackEntry> stacksForProj = new LinkedList<>();
stacksForProj.add(new StackEntry(project, environmentTag, stackA));
stacksForProj.add(new StackEntry(project, environmentTag, stackB));
stacksForProj.add(new StackEntry(project, environmentTag, stackC));
List<Instance> elbInstances = new LinkedList<>();
elbInstances.add(new Instance().withInstanceId("matchingInstanceId"));
EasyMock.expect(elbRepository.findInstancesAssociatedWithLB(projectAndEnv,"typeTag")).andReturn(elbInstances);
EasyMock.expect(cfnRepository.getStacksMatching(environmentTag,"simpleStack")).andReturn(stacksForProj);
EasyMock.expect(cfnRepository.getInstancesFor(stackA.getStackName())).andReturn(new LinkedList<>());
EasyMock.expect(cfnRepository.getInstancesFor(stackB.getStackName())).andReturn(createInstancesFor("567"));
EasyMock.expect(cfnRepository.getInstancesFor(stackC.getStackName())).andReturn(createInstancesFor("matchingInstanceId"));
setDeleteExpectations(stackB.getStackName(), createNameAndId(stackB));
replayAll();
aws.tidyNonLBAssocStacks(file, projectAndEnv,"typeTag");
verifyAll();
}
private void setDeleteExpectations(String stackName,
StackNameAndId stackNameAndId) throws InterruptedException, CfnAssistException {
EasyMock.expect(cfnRepository.getStackNameAndId(stackName)).andReturn(stackNameAndId);
cfnRepository.deleteStack(stackName);
EasyMock.expectLastCall();
EasyMock.expect(monitor.waitForDeleteFinished(stackNameAndId)).andReturn(DELETE_COMP_STATUS);
EasyMock.expect(identityProvider.getUserId()).andReturn(user);
CFNAssistNotification notification = new CFNAssistNotification(stackName, DELETE_COMP_STATUS, user);
EasyMock.expect(notificationSender.sendNotification(notification)).andReturn("ifOfSentMessage");
}
private List<String> createInstancesFor(String id) {
List<String> instances = new LinkedList<>();
instances.add(id);
return instances;
}
private StackNameAndId createNameAndId(Stack stack) {
return new StackNameAndId(stack.getStackName(), stack.getStackId());
}
}