/*************************************************************************
* Copyright 2009-2015 Eucalyptus Systems, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*
* Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta
* CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need
* additional information or have any questions.
************************************************************************/
package com.eucalyptus.resources.client;
import java.util.ArrayList;
import com.eucalyptus.cloudformation.CloudFormation;
import com.eucalyptus.cloudformation.CreateStackType;
import com.eucalyptus.cloudformation.DeleteStackType;
import com.eucalyptus.cloudformation.DescribeStackResourcesResponseType;
import com.eucalyptus.cloudformation.DescribeStackResourcesType;
import com.eucalyptus.cloudformation.DescribeStacksResponseType;
import com.eucalyptus.cloudformation.DescribeStacksType;
import com.eucalyptus.cloudformation.Parameter;
import com.eucalyptus.cloudformation.Parameters;
import com.eucalyptus.cloudformation.ResourceList;
import com.eucalyptus.cloudformation.Stack;
import com.eucalyptus.cloudformation.StackResource;
import com.eucalyptus.cloudformation.StackResources;
import com.eucalyptus.cloudformation.Stacks;
import com.eucalyptus.resources.EucalyptusActivityException;
import com.eucalyptus.util.DispatchingClient;
import com.eucalyptus.util.Exceptions;
import com.eucalyptus.util.Callback.Checked;
import com.eucalyptus.util.async.CheckedListenableFuture;
import com.eucalyptus.cloudformation.CloudFormationMessage;
public class CloudFormationClient {
private static CloudFormationClient _instance = null;
private CloudFormationClient(){ }
public static CloudFormationClient getInstance(){
if(_instance == null)
_instance = new CloudFormationClient();
return _instance;
}
private class CloudFormationContext extends AbstractClientContext<CloudFormationMessage, CloudFormation> {
private CloudFormationContext(final String userId){
super(userId, CloudFormation.class);
}
}
private abstract class CloudFormationStackTask<T extends CloudFormationMessage> extends
EucalyptusClientTask<CloudFormationMessage, CloudFormation> {
abstract T getRequest();
@Override
void dispatchInternal(ClientContext<CloudFormationMessage, CloudFormation> context,
Checked<CloudFormationMessage> callback) {
final DispatchingClient<CloudFormationMessage, CloudFormation> client = context.getClient();
client.dispatch(getRequest(), callback);
}
@Override
void dispatchSuccess(ClientContext<CloudFormationMessage, CloudFormation> context,
CloudFormationMessage response) {
}
}
private class CloudFormationCreateStackTask extends CloudFormationStackTask<CreateStackType> {
private String templateBody = null;
private String name = null;
private ArrayList<Parameter> parameters = null;
CloudFormationCreateStackTask(final String name, final String templateBody,
ArrayList<Parameter> parameters) {
this.name = name;
this.templateBody = templateBody;
this.parameters = parameters;
}
@Override
CreateStackType getRequest() {
final CreateStackType req = new CreateStackType();
req.setStackName(name);
req.setTemplateBody(templateBody);
if (parameters != null) {
Parameters params = new Parameters();
params.getMember().addAll(parameters);
req.setParameters(params);
}
ResourceList rl = new ResourceList();
rl.getMember().add("CAPABILITY_IAM");
req.setCapabilities(rl);
return req;
}
}
private class CloudFormationDeleteStackTask extends CloudFormationStackTask<DeleteStackType> {
private String name = null;
CloudFormationDeleteStackTask(final String name) {
this.name = name;
}
DeleteStackType getRequest() {
final DeleteStackType req = new DeleteStackType();
req.setStackName(name);
return req;
}
}
private class CloudFormationDescribeStackTask extends CloudFormationStackTask<DescribeStacksType> {
private String name = null;
private DescribeStacksResponseType result = null;
CloudFormationDescribeStackTask(final String name) {
this.name = name;
}
DescribeStacksType getRequest() {
final DescribeStacksType req = new DescribeStacksType();
req.setStackName(name);
return req;
}
@Override
void dispatchSuccess(ClientContext<CloudFormationMessage, CloudFormation> context,
CloudFormationMessage response) {
result = (DescribeStacksResponseType) response;
}
Stack getResult() {
Stacks stacks = result.getDescribeStacksResult() != null ?
result.getDescribeStacksResult().getStacks() : null;
if (stacks == null || stacks.getMember().isEmpty())
return null;
else
return stacks.getMember().get(0);
}
}
private class CloudFormationDescribeStackResourcesTask extends
CloudFormationStackTask<DescribeStackResourcesType> {
private String name = null;
private String logicalId = null;
private DescribeStackResourcesResponseType result = null;
CloudFormationDescribeStackResourcesTask(final String name, final String logicalId) {
this.name = name;
this.logicalId = logicalId;
}
DescribeStackResourcesType getRequest() {
final DescribeStackResourcesType req = new DescribeStackResourcesType();
req.setStackName(name);
if ( logicalId != null )
req.setLogicalResourceId(logicalId);
return req;
}
@Override
void dispatchSuccess(ClientContext<CloudFormationMessage, CloudFormation> context,
CloudFormationMessage response) {
result = (DescribeStackResourcesResponseType) response;
}
ArrayList<StackResource> getResult() {
StackResources res = result.getDescribeStackResourcesResult() != null ?
result.getDescribeStackResourcesResult().getStackResources() : null;
if ( res == null || res.getMember().isEmpty() )
return null;
else
return res.getMember();
}
}
/*
* Return stack's description or null if stack can't be found
*/
public Stack describeStack(final String userId, String name) {
final CloudFormationDescribeStackTask task = new CloudFormationDescribeStackTask(
name);
final CheckedListenableFuture<Boolean> result = task
.dispatch(new CloudFormationContext(userId));
try {
if (result.get()) {
return task.getResult();
} else
throw new EucalyptusActivityException(
task.getErrorMessage() != null ? task.getErrorMessage()
: "failed to describe stack " + name);
} catch (Exception ex) {
throw Exceptions.toUndeclared(ex);
}
}
/*
* Return stack resources or one resource by its logical.
* Return null if stack or resource can't be found
*/
public ArrayList<StackResource> describeStackResources(final String userId, String name,
String resourceLogicalId) {
final CloudFormationDescribeStackResourcesTask task =
new CloudFormationDescribeStackResourcesTask(
name, resourceLogicalId);
final CheckedListenableFuture<Boolean> result = task
.dispatch(new CloudFormationContext(userId));
try {
if (result.get()) {
return task.getResult();
} else
throw new EucalyptusActivityException(
task.getErrorMessage() != null ? task.getErrorMessage()
: "failed to describe stack " + name + " resources");
} catch (Exception ex) {
throw Exceptions.toUndeclared(ex);
}
}
public void deleteStack(final String userId, String name) {
final CloudFormationDeleteStackTask task = new CloudFormationDeleteStackTask(
name);
final CheckedListenableFuture<Boolean> result = task
.dispatch(new CloudFormationContext(userId));
try {
if (result.get()) {
return;
} else
throw new EucalyptusActivityException(
task.getErrorMessage() != null ? task.getErrorMessage()
: "failed to remove stack " + name);
} catch (Exception ex) {
throw Exceptions.toUndeclared(ex);
}
}
public void createStack(final String userId, String name, String templateBody,
ArrayList<Parameter> parameters) {
final CloudFormationCreateStackTask task = new CloudFormationCreateStackTask(
name, templateBody, parameters);
final CheckedListenableFuture<Boolean> result = task
.dispatch(new CloudFormationContext(userId));
try {
if (result.get()) {
return;
} else
throw new EucalyptusActivityException(
task.getErrorMessage() != null ? task.getErrorMessage()
: "failed to create stack " + name);
} catch (Exception ex) {
throw Exceptions.toUndeclared(ex);
}
}
}