/*
 * 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 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;

/**
 * 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
 */
class AutoDetectingStackNameProvider implements StackNameProvider, InitializingBean {

	private final AmazonCloudFormation amazonCloudFormationClient;
	private final InstanceIdProvider instanceIdProvider;

	private String stackName;

	AutoDetectingStackNameProvider(AmazonCloudFormation amazonCloudFormationClient, InstanceIdProvider instanceIdProvider) {
		this.amazonCloudFormationClient = amazonCloudFormationClient;
		this.instanceIdProvider = instanceIdProvider;
		afterPropertiesSet();
	}

	AutoDetectingStackNameProvider(AmazonCloudFormation amazonCloudFormationClient) {
		this(amazonCloudFormationClient, new AmazonEc2InstanceIdProvider());
	}

	@Override
	public void afterPropertiesSet() {
		this.stackName = autoDetectStackName(this.amazonCloudFormationClient, this.instanceIdProvider.getCurrentInstanceId());
	}

	@Override
	public String getStackName() {
		return this.stackName;
	}

	private static String autoDetectStackName(AmazonCloudFormation amazonCloudFormationClient, String instanceId) {
		Assert.notNull(instanceId, "No valid instance id defined");
		DescribeStackResourcesResult describeStackResourcesResult = amazonCloudFormationClient.describeStackResources(new DescribeStackResourcesRequest().withPhysicalResourceId(instanceId));

		if (describeStackResourcesResult.getStackResources().isEmpty()) {
			throw new IllegalStateException("No stack resources found in stack for EC2 instance '" + instanceId + "'");
		}

		return describeStackResourcesResult.getStackResources().get(0).getStackName();
	}

}

/*
 * 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 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;

/**
 * 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
 */
class AutoDetectingStackNameProvider implements StackNameProvider, InitializingBean {

	private final AmazonCloudFormation amazonCloudFormationClient;
	private final InstanceIdProvider instanceIdProvider;

	private String stackName;

	AutoDetectingStackNameProvider(AmazonCloudFormation amazonCloudFormationClient, InstanceIdProvider instanceIdProvider) {
		this.amazonCloudFormationClient = amazonCloudFormationClient;
		this.instanceIdProvider = instanceIdProvider;
		afterPropertiesSet();
	}

	AutoDetectingStackNameProvider(AmazonCloudFormation amazonCloudFormationClient) {
		this(amazonCloudFormationClient, new AmazonEc2InstanceIdProvider());
	}

	@Override
	public void afterPropertiesSet() {
		this.stackName = autoDetectStackName(this.amazonCloudFormationClient, this.instanceIdProvider.getCurrentInstanceId());
	}

	@Override
	public String getStackName() {
		return this.stackName;
	}

	private static String autoDetectStackName(AmazonCloudFormation amazonCloudFormationClient, String instanceId) {
		Assert.notNull(instanceId, "No valid instance id defined");
		DescribeStackResourcesResult describeStackResourcesResult = amazonCloudFormationClient.describeStackResources(new DescribeStackResourcesRequest().withPhysicalResourceId(instanceId));

		if (describeStackResourcesResult == null || describeStackResourcesResult.getStackResources() == null ||
				describeStackResourcesResult.getStackResources().isEmpty()) {
			throw new IllegalStateException("No stack resources found in stack for EC2 instance '" + instanceId + "'");
		}

		return describeStackResourcesResult.getStackResources().get(0).getStackName();
	}
}
Fix potential null pointer exception