/*
* Copyright 2013-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.aws.core.env.stack.config;
import com.amazonaws.services.cloudformation.AmazonCloudFormation;
import com.amazonaws.services.cloudformation.model.DescribeStackResourcesRequest;
import com.amazonaws.services.cloudformation.model.DescribeStackResourcesResult;
import com.amazonaws.services.ec2.AmazonEC2;
import com.amazonaws.services.ec2.model.DescribeTagsRequest;
import com.amazonaws.services.ec2.model.DescribeTagsResult;
import com.amazonaws.services.ec2.model.Filter;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.cloud.aws.core.env.ec2.AmazonEc2InstanceIdProvider;
import org.springframework.cloud.aws.core.env.ec2.InstanceIdProvider;
import org.springframework.util.Assert;
import java.util.Collections;
/**
* Represents a stack name provider that automatically detects the current stack name based on the amazon elastic cloud
* environment.
*
* @author Christian Stettler
* @author Agim Emruli
*/
public class AutoDetectingStackNameProvider implements StackNameProvider, InitializingBean {
private final AmazonCloudFormation amazonCloudFormationClient;
private final AmazonEC2 amazonEc2Client;
private final InstanceIdProvider instanceIdProvider;
private String stackName;
private AutoDetectingStackNameProvider(AmazonCloudFormation amazonCloudFormationClient, AmazonEC2 amazonEc2Client, InstanceIdProvider instanceIdProvider) {
this.amazonCloudFormationClient = amazonCloudFormationClient;
this.amazonEc2Client = amazonEc2Client;
this.instanceIdProvider = instanceIdProvider;
afterPropertiesSet();
}
public AutoDetectingStackNameProvider(AmazonCloudFormation amazonCloudFormationClient, AmazonEC2 amazonEc2Client) {
this(amazonCloudFormationClient, amazonEc2Client, new AmazonEc2InstanceIdProvider());
}
@Override
public void afterPropertiesSet() {
String instanceId = this.instanceIdProvider.getCurrentInstanceId();
this.stackName = autoDetectStackName(instanceId);
if (this.stackName == null) {
throw new IllegalStateException("No stack resources found in stack for EC2 instance '" + instanceId + "'");
}
}
@Override
public String getStackName() {
return this.stackName;
}
private String autoDetectStackName(String instanceId) {
Assert.notNull(instanceId, "No valid instance id defined");
DescribeStackResourcesResult describeStackResourcesResult = this.amazonCloudFormationClient.describeStackResources(new DescribeStackResourcesRequest().withPhysicalResourceId(instanceId));
if (describeStackResourcesResult != null && describeStackResourcesResult.getStackResources() != null &&
!describeStackResourcesResult.getStackResources().isEmpty()) {
return describeStackResourcesResult.getStackResources().get(0).getStackName();
}
if (this.amazonEc2Client != null) {
DescribeTagsResult describeTagsResult = this.amazonEc2Client.describeTags(new DescribeTagsRequest().withFilters(
new Filter("resource-id", Collections.singletonList(instanceId)),
new Filter("resource-type", Collections.singletonList("instance")),
new Filter("key", Collections.singletonList("aws:cloudformation:stack-name"))));
if (describeTagsResult != null && describeTagsResult.getTags() != null && !describeTagsResult.getTags().isEmpty()) {
return describeTagsResult.getTags().get(0).getValue();
}
}
return null;
}
}