protected Optional<Stack> getStack() { final List<Stack> stacks; try { stacks = cloudFormation.describeStacks(new DescribeStacksRequest().withStackName(stackName)).getStacks(); } catch (final AmazonCloudFormationException e) { if (e.getStatusCode() == 400) { return Optional.empty(); } throw e; } if (stacks.isEmpty()) { return Optional.empty(); } if (stacks.size() > 1) { throw new DeploymentException("Found more than one stack for name '" + stackName + "'"); } final Stack stack = stacks.get(0); return Optional.of(stack); }
/** * Since there doesn't appear to be a first class way through the SDK at this time to get a CF export. We can * iterate through the stacks for a given output key and return the value. * @param outputKey The exported CF variable to search and retrieve the value of. * @return The value for the export if found */ public Optional<String> searchStacksForOutput(String outputKey) { DescribeStacksResult describeStacksResult = null; do { DescribeStacksRequest request = new DescribeStacksRequest(); if (describeStacksResult != null && describeStacksResult.getNextToken() != null) { request.withNextToken(describeStacksResult.getNextToken()); } describeStacksResult = cloudFormationClient.describeStacks(); for (Stack stack : describeStacksResult.getStacks()) { for (Output output : stack.getOutputs()) { if (StringUtils.equals(output.getOutputKey(), outputKey)) { return Optional.of(output.getOutputValue()); } } } } while (describeStacksResult.getNextToken() != null); return Optional.empty(); }
@Test public void getObject_stackWithTagsDefined_createTagsMap() throws Exception { //Arrange AmazonCloudFormation cloudFormation = mock(AmazonCloudFormation.class); StackNameProvider stackNameProvider = mock(StackNameProvider.class); when(stackNameProvider.getStackName()).thenReturn("testStack"); when(cloudFormation.describeStacks(new DescribeStacksRequest().withStackName("testStack"))). thenReturn(new DescribeStacksResult().withStacks(new Stack().withTags( new Tag().withKey("key1").withValue("value1"), new Tag().withKey("key2").withValue("value2") ))); StackResourceUserTagsFactoryBean factoryBean = new StackResourceUserTagsFactoryBean(cloudFormation, stackNameProvider); //Act factoryBean.afterPropertiesSet(); Map<String, String> factoryBeanObject = factoryBean.getObject(); //Assert assertEquals("value1", factoryBeanObject.get("key1")); assertEquals("value2", factoryBeanObject.get("key2")); }
@Test public void parseInternal_stackConfigurationWithExternallyConfiguredCloudFormationClient_returnsConfiguredStackWithExternallyConfiguredClient() throws Exception { //Arrange DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory); reader.loadBeanDefinitions(new ClassPathResource(getClass().getSimpleName() + "-withCustomCloudFormationClient.xml", getClass())); AmazonCloudFormation amazonCloudFormationMock = beanFactory.getBean(AmazonCloudFormation.class); when(amazonCloudFormationMock.listStackResources(new ListStackResourcesRequest().withStackName("test"))). thenReturn(new ListStackResourcesResult().withStackResourceSummaries(new StackResourceSummary())); when(amazonCloudFormationMock.describeStacks(new DescribeStacksRequest().withStackName("test"))). thenReturn(new DescribeStacksResult().withStacks(new Stack())); //Act StackResourceRegistry stackResourceRegistry = beanFactory.getBean(StackResourceRegistry.class); //Assert assertNotNull(stackResourceRegistry); assertFalse(beanFactory.containsBeanDefinition(getBeanName(AmazonCloudFormationClient.class.getName()))); verify(amazonCloudFormationMock, times(1)).listStackResources(new ListStackResourcesRequest().withStackName("test")); beanFactory.getBean("customStackTags"); verify(amazonCloudFormationMock, times(1)).describeStacks(new DescribeStacksRequest().withStackName("test")); }
private List<Output> getOutputForRequest(String vpcStackName, AmazonCloudFormationClient client) { int tried = 0; while (tried < MAX_TRY) { LOGGER.info("checking vpc stack creation result, tried: " + tried + '/' + MAX_TRY); DescribeStacksRequest describeStacksRequest = new DescribeStacksRequest(); describeStacksRequest.withStackName(vpcStackName); Stack resultStack = client.describeStacks(describeStacksRequest).getStacks().get(0); StackStatus stackStatus = StackStatus.valueOf(resultStack.getStackStatus()); if (FAILED_STATUSES.contains(stackStatus)) { LOGGER.error("stack creation failed: ", stackStatus); throw new RuntimeException(); } else if (CREATE_COMPLETE.equals(stackStatus)) { return resultStack.getOutputs(); } try { Thread.sleep(10000); } catch (InterruptedException e) { LOGGER.error("thread sleep interrupted", e); } tried++; } throw new RuntimeException("vpc creation timed out"); }
private StackNameAndId updateStack(ProjectAndEnv projAndEnv, Collection<Parameter> userParameters, List<TemplateParameter> declaredParameters, String contents, ParameterFactory parameterFactory) throws CfnAssistException, IOException, InterruptedException { Collection<Parameter> parameters = parameterFactory.createRequiredParameters(projAndEnv, userParameters, declaredParameters, this); String stackName = findStackToUpdate(declaredParameters, projAndEnv); StackNameAndId id = cfnRepository.updateStack(contents, parameters, monitor, stackName); try { monitor.waitForUpdateFinished(id); } catch (WrongStackStatus stackFailedToUpdate) { logger.error("Failed to update stack",stackFailedToUpdate); cfnRepository.updateFail(id); throw stackFailedToUpdate; } Stack createdStack = cfnRepository.updateSuccess(id); createOutputTags(createdStack, projAndEnv); return id; }
protected StackNameAndId setUpdateExpectations(String stackName, String filename, List<TemplateParameter> templateParameters, Collection<Parameter> parameters) throws CfnAssistException, InterruptedException, IOException { String stackId = "stackId"; Stack stack = new Stack().withStackId(stackId); StackNameAndId stackNameAndId = new StackNameAndId(stackName, stackId); String contents = EnvironmentSetupForTests.loadFile(filename); EasyMock.expect(vpcRepository.getCopyOfVpc(projectAndEnv)).andReturn(new Vpc().withVpcId(VPC_ID)); EasyMock.expect(cfnRepository.validateStackTemplate(contents)).andReturn(templateParameters); EasyMock.expect(cfnRepository.updateStack(contents, parameters, monitor, stackName)).andReturn(stackNameAndId); EasyMock.expect(monitor.waitForUpdateFinished(stackNameAndId)).andReturn(StackStatus.UPDATE_COMPLETE.toString()); EasyMock.expect(cfnRepository.updateSuccess(stackNameAndId)).andReturn(stack); EasyMock.expect(cloudRepository.getZones()).andReturn(zones); return stackNameAndId; }
private StackNameAndId SetCreateExpectations(String stackName, String contents, List<TemplateParameter> templateParameters, Collection<Parameter> creationParameters, String comment, Collection<Output> outputs, Map<String, AvailabilityZone> zones) throws CfnAssistException, InterruptedException { StackNameAndId stackNameAndId = new StackNameAndId(stackName, "stackId"); Stack stack = new Stack().withStackId("stackId"); if (outputs.size()>0) { stack.setOutputs(outputs); } EasyMock.expect(vpcRepository.getCopyOfVpc(projectAndEnv)).andReturn(new Vpc().withVpcId(VPC_ID)); EasyMock.expect(cfnRepository.validateStackTemplate(contents)).andReturn(templateParameters); EasyMock.expect(cfnRepository.getStackStatus(stackName)).andReturn(""); Tagging tagging = new Tagging(); tagging.setCommentTag(comment); EasyMock.expect(cfnRepository.createStack(projectAndEnv, contents, stackName, creationParameters, monitor, tagging)). andReturn(stackNameAndId); EasyMock.expect(cloudRepository.getZones()).andReturn(zones); EasyMock.expect(monitor.waitForCreateFinished(stackNameAndId)).andReturn(CREATE_COMP_STATUS); EasyMock.expect(identityProvider.getUserId()).andReturn(user); CFNAssistNotification notification = new CFNAssistNotification(stackName, CREATE_COMP_STATUS, user); EasyMock.expect(notificationSender.sendNotification(notification)).andReturn("sendMessageID"); EasyMock.expect(cfnRepository.createSuccess(stackNameAndId)).andReturn(stack); return stackNameAndId; }
@Test public void shouldListStacks() throws MissingArgumentException, CfnAssistException, InterruptedException, IOException { String stackName = "theStackName"; String project = "theProject"; String stackId = "theStackId"; String env = "theEnv"; setFactoryExpectations(); List<StackEntry> stackEntries = new LinkedList<>(); Stack stack = new Stack().withStackName(stackName).withStackId(stackId).withStackStatus(StackStatus.CREATE_COMPLETE); stackEntries.add(new StackEntry(project, new EnvironmentTag(env), stack)); EasyMock.expect(facade.listStacks(projectAndEnv)).andReturn(stackEntries); String output = validate(CLIArgBuilder.listStacks()); CLIArgBuilder.checkForExpectedLine(stackName, project, env, output); }
@Override protected Map<String, String> createInstance() throws Exception { LinkedHashMap<String, String> userTags = new LinkedHashMap<>(); DescribeStacksResult stacksResult = this.amazonCloudFormation.describeStacks(new DescribeStacksRequest().withStackName(this.stackNameProvider.getStackName())); for (Stack stack : stacksResult.getStacks()) { for (Tag tag : stack.getTags()) { userTags.put(tag.getKey(), tag.getValue()); } } return userTags; }
private DescribeStackResourcesResult getStackResources(String stackName) throws InterruptedException, IOException { try { DescribeStacksResult describeStacksResult = this.amazonCloudFormationClient.describeStacks(new DescribeStacksRequest().withStackName(stackName)); for (Stack stack : describeStacksResult.getStacks()) { if (isAvailable(stack)) { return this.amazonCloudFormationClient.describeStackResources(new DescribeStackResourcesRequest().withStackName(stack.getStackName())); } if (isError(stack)) { if (this.stackCreatedByThisInstance) { throw new IllegalArgumentException("Could not create stack"); } this.amazonCloudFormationClient.deleteStack(new DeleteStackRequest().withStackName(stack.getStackName())); return getStackResources(stackName); } if (isInProgress(stack)) { //noinspection BusyWait Thread.sleep(5000L); return getStackResources(stackName); } } } catch (AmazonClientException e) { String templateBody = FileCopyUtils.copyToString(new InputStreamReader(new ClassPathResource(TEMPLATE_PATH).getInputStream())); this.amazonCloudFormationClient.createStack(new CreateStackRequest().withTemplateBody(templateBody).withOnFailure(OnFailure.DELETE). withStackName(stackName).withTags(new Tag().withKey("tag1").withValue("value1")). withParameters(new Parameter().withParameterKey("RdsPassword").withParameterValue(this.rdsPassword))); this.stackCreatedByThisInstance = true; } return getStackResources(stackName); }
private static Stack getStack(DescribeStacksResult describeStacksResult, String stackName) { for (Stack stack : describeStacksResult.getStacks()) { if (stack.getStackName().equals(stackName)) { return stack; } } throw new IllegalStateException("No stack found with name '" + stackName + "' (available stacks: " + allStackNames(describeStacksResult) + ")"); }
@Override public String getInstanceId() { DescribeStacksResult describeStacksResult = this.amazonCloudFormationClient.describeStacks(new DescribeStacksRequest()); Stack stack = getStack(describeStacksResult, this.stackName); return getOutputValue(stack, this.outputKey); }
private static String getOutputValue(Stack stack, String outputKey) { for (Output output : stack.getOutputs()) { if (output.getOutputKey().equals(outputKey)) { return output.getOutputValue(); } } throw new IllegalStateException("No output '" + outputKey + "' defined in stack '" + stack.getStackName() + "'"); }
@Override protected Boolean doCall() { LOGGER.info("Checking if AWS CloudFormation stack '{}' reached status '{}'", cloudFormationStackName, successStatus); try { com.amazonaws.services.cloudformation.model.Stack cfStack = cfClient.describeStacks(describeStacksRequest).getStacks().get(0); List<StackEvent> stackEvents = cfClient.describeStackEvents(stackEventsRequest).getStackEvents(); return doCheck(cfStack, stackEvents); } catch (AmazonServiceException e) { return handleError(e); } }
protected boolean isSuccess(Stack cfStack, List<StackEvent> stackEvents) { if (!stackEvents.isEmpty() && cfStack != null) { StackStatus cfStackStatus = StackStatus.valueOf(cfStack.getStackStatus()); if (stackErrorStatuses.contains(cfStackStatus)) { throw new CloudConnectorException(getErrorMessage(errorStatus.toString(), getErrorCauseStatusReason(stackEvents, errorStatus))); } else if (cfStackStatus.equals(successStatus)) { return true; } } return false; }
private StackNameAndId createStack(File file, ProjectAndEnv projAndEnv, Collection<Parameter> userParameters, List<TemplateParameter> declaredParameters, String contents, ParameterFactory parameterFactory, Tagging tagging) throws CfnAssistException, InterruptedException, IOException { String stackName = createStackName(file, projAndEnv); logger.info("Stackname is " + stackName); handlePossibleRollback(stackName); Collection<Parameter> parameters = parameterFactory.createRequiredParameters(projAndEnv, userParameters, declaredParameters, this); StackNameAndId id = cfnRepository.createStack(projAndEnv, contents, stackName, parameters, monitor, tagging); try { monitor.waitForCreateFinished(id); } catch (WrongStackStatus stackFailedToCreate) { logger.error("Failed to create stack",stackFailedToCreate); cfnRepository.createFail(id); throw stackFailedToCreate; } Stack createdStack = cfnRepository.createSuccess(id); createOutputTags(createdStack, projAndEnv); sendNotification(stackName, StackStatus.CREATE_COMPLETE.toString()); return id; }
private void createOutputTags(Stack createdStack, ProjectAndEnv projAndEnv) { List<Output> outputs = createdStack.getOutputs(); outputs.stream().filter(output -> shouldCreateTag(output.getDescription())).forEach(output -> { logger.info("Should create output tag for " + output.toString()); vpcRepository.setVpcTag(projAndEnv, output.getOutputKey(), output.getOutputValue()); }); }
private void getAllStacksForProject() { // TODO handle "next token"? if (theEntries.size() == 0) { logger.info("No cached stacks, loading all stacks"); List<Stack> stacks = formationClient.describeAllStacks(); populateEntriesIfProjectMatches(stacks); logger.info(String.format("Loaded %s stacks", theEntries.size())); } else { logger.info("Cache hit on stacks"); } }
private void populateEntriesIfProjectMatches(List<Stack> stacks) { logger.info(String.format("Populating stack entries for %s stacks", stacks.size())); for(Stack stack : stacks) { logger.info(String.format("Checking stack %s for tag", stack.getStackName())); List<Tag> tags = stack.getTags(); Map<String, String> keyValues = convertToMap(tags); int count = 3; String env = ""; String proj = ""; Integer build = null; for(Tag tag : tags) { String key = tag.getKey(); String value = tag.getValue(); if (key.equals(AwsFacade.ENVIRONMENT_TAG)) { env = value; count--; } else if (key.equals(AwsFacade.PROJECT_TAG)) { proj = value; count--; } else if (key.equals(AwsFacade.BUILD_TAG)) { build = Integer.parseInt(value); count--; } if (count==0) break; // small optimisation } //String index = keyValues.get(AwsFacade.INDEX_TAG); addEntryIfProjectAndEnvMatches(stack, env, proj, build, keyValues); } }
private void addEntryIfProjectAndEnvMatches(Stack stack, String env, String proj, Integer build, Map<String, String> keyValues) { String stackName = stack.getStackName(); if (!proj.equals(project) || (env.isEmpty())) { logger.warn(String.format("Could not match expected tags (%s and %s) for project '%s' and stackname %s", AwsFacade.ENVIRONMENT_TAG, AwsFacade.PROJECT_TAG, proj, stackName)); return; } logger.info(String.format("Stack %s matched %s and %s", stackName, env, proj)); EnvironmentTag envTag = new EnvironmentTag(env); StackEntry entry = new StackEntry(proj, envTag, stack); if (build!=null) { logger.info(String.format("Saving associated build number (%s) into stack %s", build, stackName)); entry.setBuildNumber(build); } if (keyValues.containsKey(AwsFacade.INDEX_TAG)) { addIndexTag(keyValues, stackName, entry); } if (keyValues.containsKey(AwsFacade.UPDATE_INDEX_TAG)) { addUpdateIndexTag(keyValues, entry); } if (theEntries.contains(entry)) { theEntries.remove(entry); logger.info("Replacing or Removing entry for stack " + stackName); } String stackStatus = stack.getStackStatus(); theEntries.add(entry); stackResources.removeResources(stackName); logger.info(String.format("Added stack %s matched, environment is %s, status was %s", stackName, envTag, stackStatus)); }
public Stack updateRepositoryFor(StackNameAndId id) throws WrongNumberOfStacksException { logger.info("Update stack repository for stack: " + id); Stack stack = formationClient.describeStack(id.getStackName()); populateEntriesIfProjectMatches(stack); return stack; }
@Test public void shouldHandleCreateWhenStackInRolledBackStatus() throws IOException, CfnAssistException, InterruptedException { String stackName = "CfnAssistTestsimpleStack"; String filename = FilesForTesting.SIMPLE_STACK; String contents = EnvironmentSetupForTests.loadFile(filename); String stackId = "stackId"; StackNameAndId stackNameAndId = new StackNameAndId(stackName, stackId); Collection<Parameter> creationParameters = new LinkedList<>(); List<TemplateParameter> templateParameters = new LinkedList<>(); Stack stack = new Stack().withStackId(stackId); EasyMock.expect(vpcRepository.getCopyOfVpc(projectAndEnv)).andReturn(new Vpc().withVpcId(VPC_ID)); EasyMock.expect(cfnRepository.validateStackTemplate(contents)).andReturn(templateParameters); // stack in rolled back status so delete it EasyMock.expect(cfnRepository.getStackStatus(stackName)).andReturn(StackStatus.ROLLBACK_COMPLETE.toString()); EasyMock.expect(cfnRepository.getStackNameAndId(stackName)).andReturn(stackNameAndId); cfnRepository.deleteStack(stackName); EasyMock.expectLastCall(); // now proceed with creation EasyMock.expect(cfnRepository.createStack(projectAndEnv, contents, stackName, creationParameters, monitor, new Tagging())). andReturn(stackNameAndId); Map<String, AvailabilityZone> zones = new HashMap<>(); EasyMock.expect(cloudRepository.getZones()).andReturn(zones); EasyMock.expect(monitor.waitForCreateFinished(stackNameAndId)).andReturn(CREATE_COMP_STATUS); EasyMock.expect(identityProvider.getUserId()).andReturn(user); CFNAssistNotification notification = new CFNAssistNotification(stackName, CREATE_COMP_STATUS, user); EasyMock.expect(notificationSender.sendNotification(notification)).andReturn("sendMessageId"); EasyMock.expect(cfnRepository.createSuccess(stackNameAndId)).andReturn(stack); replayAll(); StackNameAndId result = aws.applyTemplate(filename, projectAndEnv); assertEquals(stackNameAndId, result); verifyAll(); }
@Test public void shouldHandleCreateWhenStackRolledBackInProgressStatus() throws IOException, CfnAssistException, InterruptedException { String stackName = "CfnAssistTestsimpleStack"; String filename = FilesForTesting.SIMPLE_STACK; String contents = EnvironmentSetupForTests.loadFile(filename); String stackId = "stackId"; StackNameAndId stackNameAndId = new StackNameAndId(stackName, stackId); Collection<Parameter> creationParameters = new LinkedList<>(); List<TemplateParameter> templateParameters = new LinkedList<>(); Stack stack = new Stack().withStackId(stackId); EasyMock.expect(vpcRepository.getCopyOfVpc(projectAndEnv)).andReturn(new Vpc().withVpcId(VPC_ID)); EasyMock.expect(cfnRepository.validateStackTemplate(contents)).andReturn(templateParameters); // stack in rolled back status so delete it EasyMock.expect(cfnRepository.getStackStatus(stackName)).andReturn(StackStatus.ROLLBACK_IN_PROGRESS.toString()); EasyMock.expect(cfnRepository.getStackNameAndId(stackName)).andReturn(stackNameAndId); EasyMock.expect(monitor.waitForRollbackComplete(stackNameAndId)).andReturn(StackStatus.ROLLBACK_COMPLETE.toString()); cfnRepository.deleteStack(stackName); EasyMock.expectLastCall(); // now proceed with creation EasyMock.expect(cfnRepository.createStack(projectAndEnv, contents, stackName, creationParameters, monitor, new Tagging())). andReturn(stackNameAndId); Map<String, AvailabilityZone> zones = new HashMap<>(); EasyMock.expect(cloudRepository.getZones()).andReturn(zones); EasyMock.expect(monitor.waitForCreateFinished(stackNameAndId)).andReturn(CREATE_COMP_STATUS); EasyMock.expect(identityProvider.getUserId()).andReturn(user); CFNAssistNotification notification = new CFNAssistNotification(stackName, CREATE_COMP_STATUS, user); EasyMock.expect(notificationSender.sendNotification(notification)).andReturn("sendMessageId"); EasyMock.expect(cfnRepository.createSuccess(stackNameAndId)).andReturn(stack); replayAll(); StackNameAndId result = aws.applyTemplate(filename, projectAndEnv); assertEquals(stackNameAndId, result); verifyAll(); }
@Test public void shouldApplyAutoDiscoveryTemplateInputParameters() throws CfnAssistException, IOException, InterruptedException { String filename = FilesForTesting.SIMPLE_STACK; String stackName = "CfnAssistTestsimpleStack"; String contents = EnvironmentSetupForTests.loadFile(filename); List<TemplateParameter> templateParameters = new LinkedList<>(); templateParameters.add(new TemplateParameter().withParameterKey("keyName").withDescription("::logicalIdToFind")); Collection<Parameter> creationParameters = new LinkedList<>(); addParam(creationParameters, "keyName", "foundPhysicalId"); StackNameAndId stackNameAndId = new StackNameAndId(stackName, "stackId"); Stack stack = new Stack().withStackId("stackId"); EasyMock.expect(vpcRepository.getCopyOfVpc(projectAndEnv)).andReturn(new Vpc().withVpcId(VPC_ID)); EasyMock.expect(cfnRepository.validateStackTemplate(contents)).andReturn(templateParameters); EasyMock.expect(cfnRepository.getStackStatus(stackName)).andReturn(""); // search for the logical id, return the found id EasyMock.expect(cfnRepository.findPhysicalIdByLogicalId(projectAndEnv.getEnvTag(), "logicalIdToFind")).andReturn("foundPhysicalId"); EasyMock.expect(cfnRepository.createStack(projectAndEnv, contents, stackName, creationParameters, monitor, new Tagging())). andReturn(stackNameAndId); Map<String, AvailabilityZone> zones = new HashMap<>(); EasyMock.expect(cloudRepository.getZones()).andReturn(zones); EasyMock.expect(monitor.waitForCreateFinished(stackNameAndId)).andReturn(CREATE_COMP_STATUS); EasyMock.expect(identityProvider.getUserId()).andReturn(user); CFNAssistNotification notification = new CFNAssistNotification(stackName, CREATE_COMP_STATUS, user); EasyMock.expect(notificationSender.sendNotification(notification)).andReturn("sendMessageId"); EasyMock.expect(cfnRepository.createSuccess(stackNameAndId)).andReturn(stack); replayAll(); List<Parameter> userParams = new LinkedList<>(); StackNameAndId result = aws.applyTemplate(new File(filename), projectAndEnv, userParams); assertEquals(result, stackNameAndId); verifyAll(); }
@Test public void shouldApplyAutoDiscoveryVPCTagParameters() throws CfnAssistException, IOException, InterruptedException { String filename = FilesForTesting.SIMPLE_STACK; String stackName = "CfnAssistTestsimpleStack"; String contents = EnvironmentSetupForTests.loadFile(filename); List<TemplateParameter> templateParameters = new LinkedList<>(); templateParameters.add(new TemplateParameter().withParameterKey("vpcTagKey").withDescription("::CFN_TAG")); Collection<Parameter> creationParameters = new LinkedList<>(); addParam(creationParameters, "vpcTagKey", "foundVpcTagValue"); StackNameAndId stackNameAndId = new StackNameAndId(stackName, "stackId"); Stack stack = new Stack().withStackId("stackId"); EasyMock.expect(vpcRepository.getCopyOfVpc(projectAndEnv)).andReturn(new Vpc().withVpcId(VPC_ID)); EasyMock.expect(cfnRepository.validateStackTemplate(contents)).andReturn(templateParameters); EasyMock.expect(cfnRepository.getStackStatus(stackName)).andReturn(""); // get the tag from the VPC EasyMock.expect(vpcRepository.getVpcTag("vpcTagKey", projectAndEnv)).andReturn("foundVpcTagValue"); EasyMock.expect(cfnRepository.createStack(projectAndEnv, contents, stackName, creationParameters, monitor, new Tagging())). andReturn(stackNameAndId); Map<String, AvailabilityZone> zones = new HashMap<>(); EasyMock.expect(cloudRepository.getZones()).andReturn(zones); EasyMock.expect(monitor.waitForCreateFinished(stackNameAndId)).andReturn(CREATE_COMP_STATUS); EasyMock.expect(identityProvider.getUserId()).andReturn(user); CFNAssistNotification notification = new CFNAssistNotification(stackName, CREATE_COMP_STATUS, user); EasyMock.expect(notificationSender.sendNotification(notification)).andReturn("sendMessageId"); EasyMock.expect(cfnRepository.createSuccess(stackNameAndId)).andReturn(stack); replayAll(); List<Parameter> userParams = new LinkedList<>(); StackNameAndId result = aws.applyTemplate(new File(filename), projectAndEnv, userParams); assertEquals(result, stackNameAndId); verifyAll(); }
@Before public void beforeEachTestRuns() { Stack stack = new Stack(); entryA = new StackEntry("project", new EnvironmentTag("anEnv"), stack); entryB = new StackEntry("project", new EnvironmentTag("someOtherTag"), stack); entryC = new StackEntry("project", new EnvironmentTag("anEnv"), stack).setBuildNumber(42); entryD = new StackEntry("OtherProject", new EnvironmentTag("anEnv"), stack); entryE = new StackEntry("OtherProject", new EnvironmentTag("anEnv"), stack).setBuildNumber(42); entryF = new StackEntry("project", new EnvironmentTag("anEnv"), stack).setIndex(98); Set<Integer> updates= new HashSet<Integer>(asList(140)); entryG = new StackEntry("project", new EnvironmentTag("anEnv"), stack).setUpdateIndex(updates); criteria = new SearchCriteria(); }
@Test public void shouldListStacksEnvSupplied() { List<StackEntry> stacks = new LinkedList<>(); stacks.add(new StackEntry("proj", projectAndEnv.getEnvTag(), new Stack())); EasyMock.expect(cfnRepository.getStacks(projectAndEnv.getEnvTag())).andReturn(stacks); replayAll(); List<StackEntry> results = aws.listStacks(projectAndEnv); assertEquals(1, results.size()); verifyAll(); }
@Test public void shouldListStacksNoEnvSupplied() { List<StackEntry> stacks = new LinkedList<>(); stacks.add(new StackEntry("proj", projectAndEnv.getEnvTag(), new Stack())); EasyMock.expect(cfnRepository.getStacks()).andReturn(stacks); replayAll(); ProjectAndEnv pattern = new ProjectAndEnv("someProject", ""); List<StackEntry> results = aws.listStacks(pattern); assertEquals(1,results.size()); verifyAll(); }
@Test public void shouldExtractBasenameFromEntryWithNoBuildNumber() { Stack stack = new Stack().withStackName("ProjectEnvTheBaseName"); StackEntry entry = new StackEntry("Project", new EnvironmentTag("Env"), stack); assertEquals("TheBaseName", entry.getBaseName()); }
@Test public void shouldExtractBasenameFromEntryWithBuildNumber() { Stack stack = new Stack().withStackName("Project42EnvTheBaseName"); StackEntry entry = new StackEntry("Project", new EnvironmentTag("Env"), stack); entry.setBuildNumber(42); assertEquals("TheBaseName",entry.getBaseName()); }
@Test public void shouldHaveIndex() { StackEntry entry = new StackEntry("Project", new EnvironmentTag("Env"), new Stack().withStackName("theStackName")); entry.setIndex(56); assertTrue(entry.hasIndex()); assertEquals(new Integer(56), entry.getIndex()); }
@Test public void shouldHaveUpdateIndex() { StackEntry entry = new StackEntry("Project", new EnvironmentTag("Env"), new Stack().withStackName("theStackName")); Set<Integer> updates = new HashSet<>(Arrays.asList(42)); entry.setUpdateIndex(updates); assertTrue(entry.hasUpdateIndex()); assertEquals(new HashSet<>(Arrays.asList(42)), entry.getUpdateIndex()); }
@Test public void shouldHaveEquality() { StackEntry entryA = new StackEntry("project", new EnvironmentTag("Env1"), new Stack()); StackEntry entryB = new StackEntry("project", new EnvironmentTag("Env1"), new Stack()); StackEntry entryC = new StackEntry("project", new EnvironmentTag("Env2"), new Stack()); assertTrue(entryA.equals(entryB)); assertTrue(entryB.equals(entryA)); assertFalse(entryC.equals(entryA)); }
@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(); }
@Test public void shouldStepBackLastChangeOnAVpc() throws CfnAssistException { String stackB = "CfnAssistTest02createAcls"; StackNameAndId stackBNameAndId = new StackNameAndId(stackB, "id2"); SetDeltaIndexForProjectAndEnv setDeltaIndexForProjectAndEnv = new SetDeltaIndexForProjectAndEnv(projectAndEnv,vpcRepository); EasyMock.expect(vpcRepository.getVpcIndexTag(projectAndEnv)).andReturn("2"); StackEntry stackEntry = new StackEntry(projectAndEnv.getProject(), projectAndEnv.getEnvTag(), new Stack().withStackName(stackB)); EasyMock.expect(cfnRepository.getStacknameByIndex(projectAndEnv.getEnvTag(), 2)).andReturn(stackEntry); EasyMock.expect(cfnRepository.getStackNameAndId(stackB)).andReturn(stackBNameAndId); cfnRepository.deleteStack(stackB); EasyMock.expectLastCall(); EasyMock.expect(vpcRepository.getSetsDeltaIndexFor(projectAndEnv)).andReturn(setDeltaIndexForProjectAndEnv); DeletionsPending pending = new DeletionsPending(); pending.add(2, stackBNameAndId); List<String> deletedStacks = new LinkedList<>(); deletedStacks.add(stackB); EasyMock.expect(monitor.waitForDeleteFinished(pending, setDeltaIndexForProjectAndEnv)).andReturn(deletedStacks); replayAll(); List<String> result = aws.stepbackLastChange(projectAndEnv); verifyAll(); assertEquals(1, result.size()); assertTrue(result.contains(stackB)); }
private void setExpectationsForFile(Integer count, File file, List<TemplateParameter> templateParameters) throws IOException, CfnAssistException, InterruptedException { String templateContents = EnvironmentSetupForTests.loadFile(file.getAbsolutePath()); Collection<Parameter> creationParameters = new LinkedList<>(); String stackName = aws.createStackName(file, projectAndEnv); StackNameAndId stackNameAndId = new StackNameAndId(stackName, count.toString()); EasyMock.expect(vpcRepository.getCopyOfVpc(projectAndEnv)).andReturn(new Vpc()); EasyMock.expect(cfnRepository.validateStackTemplate(templateContents)).andReturn(templateParameters); EasyMock.expect(cfnRepository.getStackStatus(stackName)).andReturn(""); // tagging Tagging tagging = new Tagging(); tagging.setIndexTag(count); // create stack EasyMock.expect(cfnRepository.createStack(projectAndEnv, templateContents, stackName, creationParameters, monitor, tagging)) .andReturn(stackNameAndId); // monitor EasyMock.expect(monitor.waitForCreateFinished(stackNameAndId)).andReturn(StackStatus.CREATE_COMPLETE.toString()); // notification EasyMock.expect(identityProvider.getUserId()).andReturn(user); CFNAssistNotification notification = new CFNAssistNotification(stackName, StackStatus.CREATE_COMPLETE.toString(), user); EasyMock.expect(notificationSender.sendNotification(notification)).andReturn("sentMessageId"); // success EasyMock.expect(cfnRepository.createSuccess(stackNameAndId)).andReturn( new Stack().withStackId(count.toString()).withStackName(stackName)); // index update vpcRepository.setVpcIndexTag(projectAndEnv, count.toString()); }
@Test public void shouldGetStackEntry() { CloudFormationClient formationClient = createMock(CloudFormationClient.class); List<Stack> stacks = new LinkedList<>(); stacks.add(new Stack().withTags( createCfnStackTAG("CFN_ASSIST_PROJECT",EnvironmentSetupForTests.PROJECT), createCfnStackTAG("CFN_ASSIST_ENV", EnvironmentSetupForTests.ENV), createCfnStackTAG("CFN_ASSIST_BUILD_NUMBER", "42"), createCfnStackTAG("CFN_ASSIST_DELTA", "8"), createCfnStackTAG("CFN_ASSIST_UPDATE", "9,10,11"))); EasyMock.expect(formationClient.describeAllStacks()).andReturn(stacks); StackCache stackCache = new StackCache(formationClient, EnvironmentSetupForTests.PROJECT); replayAll(); List<StackEntry> result = stackCache.getEntries(); verifyAll(); assertEquals(1, result.size()); StackEntry stack = result.get(0); assertEquals(EnvironmentSetupForTests.PROJECT, stack.getProject()); assertEquals(EnvironmentSetupForTests.ENV, stack.getEnvTag().getEnv()); assertEquals(new Integer(42), stack.getBuildNumber()); assertEquals(new Integer(8), stack.getIndex()); Set<Integer> updateIndexs = stack.getUpdateIndex(); assertEquals(3,updateIndexs.size()); assertTrue(updateIndexs.contains(9)); assertTrue(updateIndexs.contains(10)); assertTrue(updateIndexs.contains(11)); }
private List<String> fetchCurrentStacks() { List<String> current = new LinkedList<>(); DescribeStacksResult result = cfnClient.describeStacks(); for(Stack stack : result.getStacks()) { current.add(stack.getStackName()); } return current; }