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); }
/** * Returns the current status of the named stack. * * @param stackId Stack ID. * @return Stack status data. */ @Nullable public StackStatus getStackStatus(final String stackId) { final DescribeStacksRequest request = new DescribeStacksRequest().withStackName(stackId); try { final DescribeStacksResult result = cloudFormationClient.describeStacks(request); if (result.getStacks().size() > 0) { final String status = result.getStacks().get(0).getStackStatus(); if (StringUtils.isNotBlank(status)) { return StackStatus.fromValue(status); } } } catch (final AmazonServiceException ase) { // Stack doesn't exist, just return with no status if (ase.getStatusCode() != 400) { throw ase; } } return null; }
/** * 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"); }
/** * Returns the current status of the named stack. * * @param stackId Stack name. * @return Stack outputs data. */ public Map<String, String> getStackParameters(final String stackId) { final DescribeStacksRequest request = new DescribeStacksRequest().withStackName(stackId); final DescribeStacksResult result = cloudFormationClient.describeStacks(request); final Map<String, String> parameters = Maps.newHashMap(); if (result.getStacks().size() > 0) { parameters.putAll(result.getStacks().get(0).getParameters().stream().collect( Collectors.toMap(Parameter::getParameterKey, Parameter::getParameterValue))); } return parameters; }
/** * Returns the current status of the named stack. * * @param stackId Stack name. * @return Stack outputs data. */ public Map<String, String> getStackOutputs(final String stackId) { final DescribeStacksRequest request = new DescribeStacksRequest().withStackName(stackId); final DescribeStacksResult result = cloudFormationClient.describeStacks(request); final Map<String, String> outputs = Maps.newHashMap(); if (result.getStacks().size() > 0) { outputs.putAll(result.getStacks().get(0).getOutputs().stream().collect( Collectors.toMap(Output::getOutputKey, Output::getOutputValue))); } return outputs; }
@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); }
@Override public String getInstanceId() { DescribeStacksResult describeStacksResult = this.amazonCloudFormationClient.describeStacks(new DescribeStacksRequest()); Stack stack = getStack(describeStacksResult, this.stackName); return getOutputValue(stack, this.outputKey); }
public static boolean waitForCloudFormationStackToReachStatus( AmazonCloudFormationClient client, String stackName, String status) { int count = 0; while (true) { if (count++ == 100) { System.out .println(stackName + " never reached state " + status); return false; } try { Thread.sleep(1000 * 30); } catch (InterruptedException e) { System.out.println(e.getMessage()); return false; } String stackStatus = client .describeStacks( new DescribeStacksRequest() .withStackName(stackName)).getStacks() .get(0).getStackStatus(); if (stackStatus.equals(status)) { return true; } else if (stackStatus.contains(FAILED)) { System.out.println("The process failed with status " + stackStatus); return false; } System.out.println(stackName + " is in status " + stackStatus); } }
private Map<String, String> getOutputs(String cFStackName, AmazonCloudFormationClient client) { DescribeStacksRequest describeStacksRequest = new DescribeStacksRequest().withStackName(cFStackName); String outputNotFound = String.format("Couldn't get Cloudformation stack's('%s') output", cFStackName); List<Output> cfStackOutputs = client.describeStacks(describeStacksRequest).getStacks() .stream().findFirst().orElseThrow(getCloudConnectorExceptionSupplier(outputNotFound)).getOutputs(); return cfStackOutputs.stream().collect(Collectors.toMap(Output::getOutputKey, Output::getOutputValue)); }
@Override public void validate(AuthenticatedContext ac, CloudStack cloudStack) { AwsCredentialView credentialView = new AwsCredentialView(ac.getCloudCredential()); String regionName = ac.getCloudContext().getLocation().getRegion().value(); AmazonCloudFormationClient cfClient = awsClient.createCloudFormationClient(credentialView, regionName); String cFStackName = cfStackUtil.getCfStackName(ac); try { cfClient.describeStacks(new DescribeStacksRequest().withStackName(cFStackName)); throw new CloudConnectorException(String.format("Stack is already exists with the given name: %s", cFStackName)); } catch (AmazonServiceException ignored) { } }
AbstractAwsStackStatusCheckerTask(AuthenticatedContext authenticatedContext, AmazonCloudFormationClient cfClient, StackStatus successStatus, StackStatus errorStatus, List<StackStatus> stackErrorStatuses, String cloudFormationStackName, boolean cancellable) { super(authenticatedContext, cancellable); this.cfClient = cfClient; this.successStatus = successStatus; this.errorStatus = errorStatus; this.stackErrorStatuses = stackErrorStatuses; this.cloudFormationStackName = cloudFormationStackName; describeStacksRequest = new DescribeStacksRequest().withStackName(cloudFormationStackName); stackEventsRequest = new DescribeStackEventsRequest().withStackName(cloudFormationStackName); }
private List<Stack> describeStack(String stackName) { final DescribeStacksResult result = cloudFormation .describeStacks(new DescribeStacksRequest().withStackName(stackName)); return result.getStacks(); }
private void waitForCompletion() throws InterruptedException { DescribeStacksRequest wait = new DescribeStacksRequest(); wait.setStackName(this.stackName); Boolean completed = false; String stackStatus = "Unknown"; String stackReason = ""; while (!completed) { List<Stack> stacks = null; try { stacks = this.cloudFormation.describeStacks(wait).getStacks(); } catch (Exception e) { logger.error("cloudFormation.describeStacks() exception", e); } if (CollectionUtils.isEmpty(stacks)) { completed = true; stackStatus = StackStatus.DELETE_COMPLETE.toString(); stackReason = "Stack has been deleted"; } else { for (Stack stack : stacks) { if (stack.getStackStatus().equals(StackStatus.CREATE_COMPLETE.toString()) || stack.getStackStatus().equals(StackStatus.CREATE_FAILED.toString()) || stack.getStackStatus().equals(StackStatus.ROLLBACK_FAILED.toString()) || stack.getStackStatus().equals(StackStatus.DELETE_FAILED.toString())) { completed = true; stackStatus = stack.getStackStatus(); stackReason = stack.getStackStatusReason(); } } } // Not done yet so sleep for 2 seconds. if (!completed) { Thread.sleep(2000); } else { if (stackStatus.equals(StackStatus.CREATE_FAILED.toString())) { Assume.assumeTrue("The test AWS stack [" + this.stackName + "] cannot be created. Reason: " + stackReason, true); } } } }
@Override public List<CloudResourceStatus> launch(AuthenticatedContext ac, CloudStack stack, PersistenceNotifier resourceNotifier, AdjustmentType adjustmentType, Long threshold) throws Exception { createKeyPair(ac, stack); String cFStackName = cfStackUtil.getCfStackName(ac); AwsCredentialView credentialView = new AwsCredentialView(ac.getCloudCredential()); String regionName = ac.getCloudContext().getLocation().getRegion().value(); AmazonCloudFormationClient cfClient = awsClient.createCloudFormationClient(credentialView, regionName); AmazonEC2Client amazonEC2Client = awsClient.createAccess(credentialView, regionName); AwsNetworkView awsNetworkView = new AwsNetworkView(stack.getNetwork()); boolean existingVPC = awsNetworkView.isExistingVPC(); boolean existingSubnet = awsNetworkView.isExistingSubnet(); boolean mapPublicIpOnLaunch = isMapPublicOnLaunch(awsNetworkView, amazonEC2Client); try { cfClient.describeStacks(new DescribeStacksRequest().withStackName(cFStackName)); LOGGER.info("Stack already exists: {}", cFStackName); } catch (AmazonServiceException ignored) { CloudResource cloudFormationStack = new Builder().type(ResourceType.CLOUDFORMATION_STACK).name(cFStackName).build(); resourceNotifier.notifyAllocation(cloudFormationStack, ac.getCloudContext()); String cidr = stack.getNetwork().getSubnet().getCidr(); String subnet = isNoCIDRProvided(existingVPC, existingSubnet, cidr) ? findNonOverLappingCIDR(ac, stack) : cidr; AwsInstanceProfileView awsInstanceProfileView = new AwsInstanceProfileView(stack); ModelContext modelContext = new ModelContext() .withAuthenticatedContext(ac) .withStack(stack) .withExistingVpc(existingVPC) .withSnapshotId(getEbsSnapshotIdIfNeeded(ac, stack)) .withExistingIGW(awsNetworkView.isExistingIGW()) .withExistingSubnetCidr(existingSubnet ? getExistingSubnetCidr(ac, stack) : null) .withExistingSubnetIds(existingSubnet ? awsNetworkView.getSubnetList() : null) .mapPublicIpOnLaunch(mapPublicIpOnLaunch) .withEnableInstanceProfile(awsInstanceProfileView.isEnableInstanceProfileStrategy()) .withInstanceProfileAvailable(awsInstanceProfileView.isInstanceProfileAvailable()) .withTemplate(stack.getTemplate()) .withDefaultSubnet(subnet); String cfTemplate = cloudFormationTemplateBuilder.build(modelContext); LOGGER.debug("CloudFormationTemplate: {}", cfTemplate); cfClient.createStack(createCreateStackRequest(ac, stack, cFStackName, subnet, cfTemplate)); } LOGGER.info("CloudFormation stack creation request sent with stack name: '{}' for stack: '{}'", cFStackName, ac.getCloudContext().getId()); AmazonAutoScalingClient asClient = awsClient.createAutoScalingClient(credentialView, regionName); PollTask<Boolean> task = awsPollTaskFactory.newAwsCreateStackStatusCheckerTask(ac, cfClient, asClient, CREATE_COMPLETE, CREATE_FAILED, ERROR_STATUSES, cFStackName); try { Boolean statePollerResult = task.call(); if (!task.completed(statePollerResult)) { syncPollingScheduler.schedule(task); } } catch (RuntimeException e) { throw new CloudConnectorException(e.getMessage(), e); } AmazonAutoScalingClient amazonASClient = awsClient.createAutoScalingClient(credentialView, regionName); saveS3AccessRoleArn(ac, stack, cFStackName, cfClient, resourceNotifier); saveGeneratedSubnet(ac, stack, cFStackName, cfClient, resourceNotifier); List<CloudResource> cloudResources = getCloudResources(ac, stack, cFStackName, cfClient, amazonEC2Client, amazonASClient, mapPublicIpOnLaunch); return check(ac, cloudResources); }
public Stack findStack() throws Exception { final DescribeStacksRequest request = new DescribeStacksRequest(); final DescribeStacksResult result = amazonClient .describeStacks(request); for (final Stack stack : result.getStacks()) { if (name.equals(stack.getStackName())) { return stack; } } return null; }