/*************************************************************************
* 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.cloudformation.resources.standard.actions;
import com.eucalyptus.auth.Accounts;
import com.eucalyptus.cloudformation.ValidationErrorException;
import com.eucalyptus.cloudformation.resources.ResourceAction;
import com.eucalyptus.cloudformation.resources.ResourceInfo;
import com.eucalyptus.cloudformation.resources.ResourceProperties;
import com.eucalyptus.cloudformation.resources.standard.TagHelper;
import com.eucalyptus.cloudformation.resources.standard.info.AWSElasticLoadBalancingLoadBalancerResourceInfo;
import com.eucalyptus.cloudformation.resources.standard.propertytypes.AWSElasticLoadBalancingLoadBalancerProperties;
import com.eucalyptus.cloudformation.resources.standard.propertytypes.CloudFormationResourceTag;
import com.eucalyptus.cloudformation.resources.standard.propertytypes.ElasticLoadBalancingAccessLoggingPolicy;
import com.eucalyptus.cloudformation.resources.standard.propertytypes.ElasticLoadBalancingAppCookieStickinessPolicy;
import com.eucalyptus.cloudformation.resources.standard.propertytypes.ElasticLoadBalancingLBCookieStickinessPolicyType;
import com.eucalyptus.cloudformation.resources.standard.propertytypes.ElasticLoadBalancingListener;
import com.eucalyptus.cloudformation.resources.standard.propertytypes.ElasticLoadBalancingPolicyType;
import com.eucalyptus.cloudformation.resources.standard.propertytypes.ElasticLoadBalancingPolicyTypeAttribute;
import com.eucalyptus.cloudformation.template.JsonHelper;
import com.eucalyptus.cloudformation.util.MessageHelper;
import com.eucalyptus.cloudformation.workflow.steps.Step;
import com.eucalyptus.cloudformation.workflow.steps.StepBasedResourceAction;
import com.eucalyptus.cloudformation.workflow.steps.UpdateStep;
import com.eucalyptus.cloudformation.workflow.updateinfo.UpdateType;
import com.eucalyptus.cloudformation.workflow.updateinfo.UpdateTypeAndDirection;
import com.eucalyptus.component.ServiceConfiguration;
import com.eucalyptus.component.Topology;
import com.eucalyptus.compute.common.Compute;
import com.eucalyptus.compute.common.DescribeSecurityGroupsResponseType;
import com.eucalyptus.compute.common.DescribeSecurityGroupsType;
import com.eucalyptus.compute.common.DescribeVpcsResponseType;
import com.eucalyptus.compute.common.DescribeVpcsType;
import com.eucalyptus.compute.common.Filter;
import com.eucalyptus.loadbalancing.common.LoadBalancing;
import com.eucalyptus.loadbalancing.common.msgs.AccessLog;
import com.eucalyptus.loadbalancing.common.msgs.AddTagsResponseType;
import com.eucalyptus.loadbalancing.common.msgs.AddTagsType;
import com.eucalyptus.loadbalancing.common.msgs.AppCookieStickinessPolicy;
import com.eucalyptus.loadbalancing.common.msgs.ApplySecurityGroupsToLoadBalancerType;
import com.eucalyptus.loadbalancing.common.msgs.AttachLoadBalancerToSubnetsType;
import com.eucalyptus.loadbalancing.common.msgs.AvailabilityZones;
import com.eucalyptus.loadbalancing.common.msgs.BackendServerDescription;
import com.eucalyptus.loadbalancing.common.msgs.ConfigureHealthCheckResponseType;
import com.eucalyptus.loadbalancing.common.msgs.ConfigureHealthCheckType;
import com.eucalyptus.loadbalancing.common.msgs.ConnectionSettings;
import com.eucalyptus.loadbalancing.common.msgs.CreateAppCookieStickinessPolicyResponseType;
import com.eucalyptus.loadbalancing.common.msgs.CreateAppCookieStickinessPolicyType;
import com.eucalyptus.loadbalancing.common.msgs.CreateLBCookieStickinessPolicyResponseType;
import com.eucalyptus.loadbalancing.common.msgs.CreateLBCookieStickinessPolicyType;
import com.eucalyptus.loadbalancing.common.msgs.CreateLoadBalancerListenersType;
import com.eucalyptus.loadbalancing.common.msgs.CreateLoadBalancerPolicyResponseType;
import com.eucalyptus.loadbalancing.common.msgs.CreateLoadBalancerPolicyType;
import com.eucalyptus.loadbalancing.common.msgs.CreateLoadBalancerResponseType;
import com.eucalyptus.loadbalancing.common.msgs.CreateLoadBalancerType;
import com.eucalyptus.loadbalancing.common.msgs.CrossZoneLoadBalancing;
import com.eucalyptus.loadbalancing.common.msgs.DeleteLoadBalancerListenersType;
import com.eucalyptus.loadbalancing.common.msgs.DeleteLoadBalancerPolicyType;
import com.eucalyptus.loadbalancing.common.msgs.DeleteLoadBalancerResponseType;
import com.eucalyptus.loadbalancing.common.msgs.DeleteLoadBalancerType;
import com.eucalyptus.loadbalancing.common.msgs.DeregisterInstancesFromLoadBalancerType;
import com.eucalyptus.loadbalancing.common.msgs.DescribeLoadBalancerPoliciesResponseType;
import com.eucalyptus.loadbalancing.common.msgs.DescribeLoadBalancerPoliciesType;
import com.eucalyptus.loadbalancing.common.msgs.DescribeLoadBalancersResponseType;
import com.eucalyptus.loadbalancing.common.msgs.DescribeLoadBalancersType;
import com.eucalyptus.loadbalancing.common.msgs.DescribeTagsResponseType;
import com.eucalyptus.loadbalancing.common.msgs.DescribeTagsType;
import com.eucalyptus.loadbalancing.common.msgs.DetachLoadBalancerFromSubnetsType;
import com.eucalyptus.loadbalancing.common.msgs.DisableAvailabilityZonesForLoadBalancerType;
import com.eucalyptus.loadbalancing.common.msgs.EnableAvailabilityZonesForLoadBalancerType;
import com.eucalyptus.loadbalancing.common.msgs.HealthCheck;
import com.eucalyptus.loadbalancing.common.msgs.Instance;
import com.eucalyptus.loadbalancing.common.msgs.Instances;
import com.eucalyptus.loadbalancing.common.msgs.LBCookieStickinessPolicy;
import com.eucalyptus.loadbalancing.common.msgs.Listener;
import com.eucalyptus.loadbalancing.common.msgs.ListenerDescription;
import com.eucalyptus.loadbalancing.common.msgs.Listeners;
import com.eucalyptus.loadbalancing.common.msgs.LoadBalancerAttributes;
import com.eucalyptus.loadbalancing.common.msgs.LoadBalancerDescription;
import com.eucalyptus.loadbalancing.common.msgs.LoadBalancerNames;
import com.eucalyptus.loadbalancing.common.msgs.LoadBalancerNamesMax20;
import com.eucalyptus.loadbalancing.common.msgs.ModifyLoadBalancerAttributesResponseType;
import com.eucalyptus.loadbalancing.common.msgs.ModifyLoadBalancerAttributesType;
import com.eucalyptus.loadbalancing.common.msgs.PolicyAttribute;
import com.eucalyptus.loadbalancing.common.msgs.PolicyAttributeDescription;
import com.eucalyptus.loadbalancing.common.msgs.PolicyAttributes;
import com.eucalyptus.loadbalancing.common.msgs.PolicyDescription;
import com.eucalyptus.loadbalancing.common.msgs.PolicyNames;
import com.eucalyptus.loadbalancing.common.msgs.Ports;
import com.eucalyptus.loadbalancing.common.msgs.RegisterInstancesWithLoadBalancerResponseType;
import com.eucalyptus.loadbalancing.common.msgs.RegisterInstancesWithLoadBalancerType;
import com.eucalyptus.loadbalancing.common.msgs.RemoveTagsResponseType;
import com.eucalyptus.loadbalancing.common.msgs.RemoveTagsType;
import com.eucalyptus.loadbalancing.common.msgs.SecurityGroups;
import com.eucalyptus.loadbalancing.common.msgs.SetLoadBalancerListenerSSLCertificateType;
import com.eucalyptus.loadbalancing.common.msgs.SetLoadBalancerPoliciesForBackendServerResponseType;
import com.eucalyptus.loadbalancing.common.msgs.SetLoadBalancerPoliciesForBackendServerType;
import com.eucalyptus.loadbalancing.common.msgs.SetLoadBalancerPoliciesOfListenerResponseType;
import com.eucalyptus.loadbalancing.common.msgs.SetLoadBalancerPoliciesOfListenerType;
import com.eucalyptus.loadbalancing.common.msgs.Subnets;
import com.eucalyptus.loadbalancing.common.msgs.Tag;
import com.eucalyptus.loadbalancing.common.msgs.TagDescription;
import com.eucalyptus.util.async.AsyncRequests;
import com.fasterxml.jackson.databind.node.TextNode;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import org.apache.log4j.Logger;
import javax.annotation.Nullable;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
/**
* Created by ethomas on 2/3/14.
*/
public class AWSElasticLoadBalancingLoadBalancerResourceAction extends StepBasedResourceAction {
public static final Logger LOG = Logger.getLogger(AWSElasticLoadBalancingLoadBalancerResourceAction.class);
private AWSElasticLoadBalancingLoadBalancerProperties properties = new AWSElasticLoadBalancingLoadBalancerProperties();
private AWSElasticLoadBalancingLoadBalancerResourceInfo info = new AWSElasticLoadBalancingLoadBalancerResourceInfo();
public AWSElasticLoadBalancingLoadBalancerResourceAction() {
super(fromEnum(CreateSteps.class), fromEnum(DeleteSteps.class), fromUpdateEnum(UpdateNoInterruptionSteps.class), null);
// In this case, update with replacement has a precondition check before essentially the same steps as "create". We add both.
Map<String, UpdateStep> updateWithReplacementMap = Maps.newLinkedHashMap();
updateWithReplacementMap.putAll(fromUpdateEnum(UpdateWithReplacementPreCreateSteps.class));
updateWithReplacementMap.putAll(createStepsToUpdateWithReplacementSteps(fromEnum(CreateSteps.class)));
setUpdateSteps(UpdateTypeAndDirection.UPDATE_WITH_REPLACEMENT, updateWithReplacementMap);
}
@Override
public UpdateType getUpdateType(ResourceAction resourceAction, boolean stackTagsChanged) {
UpdateType updateType = info.supportsTags() && stackTagsChanged ? UpdateType.NO_INTERRUPTION : UpdateType.NONE;
AWSElasticLoadBalancingLoadBalancerResourceAction otherAction = (AWSElasticLoadBalancingLoadBalancerResourceAction) resourceAction;
if (!Objects.equals(properties.getAccessLoggingPolicy(), otherAction.properties.getAccessLoggingPolicy())) {
updateType = UpdateType.max(updateType, UpdateType.NO_INTERRUPTION);
}
if (!Objects.equals(properties.getAppCookieStickinessPolicy(), otherAction.properties.getAppCookieStickinessPolicy())) {
updateType = UpdateType.max(updateType, UpdateType.NO_INTERRUPTION);
}
if (!Objects.equals(properties.getAvailabilityZones(), otherAction.properties.getAvailabilityZones())) {
// Replacement if removing all or adding some where none exist
boolean oldOnesExist = (properties.getAvailabilityZones() != null && !properties.getAvailabilityZones().isEmpty());
boolean newOnesExist = (otherAction.properties.getAvailabilityZones() != null &&
!otherAction.properties.getAvailabilityZones().isEmpty());
if ((oldOnesExist && !newOnesExist) || (!oldOnesExist && newOnesExist)) {
updateType = UpdateType.max(updateType, UpdateType.NEEDS_REPLACEMENT);
} else {
updateType = UpdateType.max(updateType, UpdateType.NO_INTERRUPTION);
}
}
if (!Objects.equals(properties.getConnectionDrainingPolicy(), otherAction.properties.getConnectionDrainingPolicy())) {
updateType = UpdateType.max(updateType, UpdateType.NO_INTERRUPTION);
}
if (!Objects.equals(properties.getConnectionSettings(), otherAction.properties.getConnectionSettings())) {
updateType = UpdateType.max(updateType, UpdateType.NO_INTERRUPTION);
}
if (!Objects.equals(properties.getCrossZone(), otherAction.properties.getCrossZone())) {
updateType = UpdateType.max(updateType, UpdateType.NO_INTERRUPTION);
}
if (!Objects.equals(properties.getHealthCheck(), otherAction.properties.getHealthCheck())) {
// either removing a health check or adding one from a non-existent case
if (properties.getHealthCheck() == null || otherAction.properties.getHealthCheck() == null) {
updateType = UpdateType.max(updateType, UpdateType.NEEDS_REPLACEMENT);
} else {
updateType = UpdateType.max(updateType, UpdateType.NO_INTERRUPTION);
}
}
if (!Objects.equals(properties.getInstances(), otherAction.properties.getInstances())) {
updateType = UpdateType.max(updateType, UpdateType.NO_INTERRUPTION);
}
if (!Objects.equals(properties.getLbCookieStickinessPolicy(), otherAction.properties.getLbCookieStickinessPolicy())) {
updateType = UpdateType.max(updateType, UpdateType.NO_INTERRUPTION);
}
if (!Objects.equals(properties.getListeners(), otherAction.properties.getListeners())) {
updateType = UpdateType.max(updateType, UpdateType.NO_INTERRUPTION);
}
if (!Objects.equals(properties.getLoadBalancerName(), otherAction.properties.getLoadBalancerName())) {
updateType = UpdateType.max(updateType, UpdateType.NEEDS_REPLACEMENT);
}
if (!Objects.equals(properties.getPolicies(), otherAction.properties.getPolicies())) {
updateType = UpdateType.max(updateType, UpdateType.NO_INTERRUPTION);
}
if (!Objects.equals(properties.getScheme(), otherAction.properties.getScheme())) {
updateType = UpdateType.max(updateType, UpdateType.NEEDS_REPLACEMENT);
}
if (!Objects.equals(properties.getSecurityGroups(), otherAction.properties.getSecurityGroups())) {
updateType = UpdateType.max(updateType, UpdateType.NO_INTERRUPTION);
}
if (!Objects.equals(properties.getSubnets(), otherAction.properties.getSubnets())) {
// Replacement if removing all or adding some where none exist
boolean oldOnesExist = (properties.getSubnets() != null && !properties.getSubnets().isEmpty());
boolean newOnesExist = (otherAction.properties.getSubnets() != null &&
!otherAction.properties.getSubnets().isEmpty());
if ((oldOnesExist && !newOnesExist) || (!oldOnesExist && newOnesExist)) {
updateType = UpdateType.max(updateType, UpdateType.NEEDS_REPLACEMENT);
} else {
updateType = UpdateType.max(updateType, UpdateType.NO_INTERRUPTION);
}
}
if (!Objects.equals(properties.getTags(), otherAction.properties.getTags())) {
updateType = UpdateType.max(updateType, UpdateType.NO_INTERRUPTION);
}
return updateType;
}
private enum CreateSteps implements Step {
CREATE_LOAD_BALANCER {
@Override
public ResourceAction perform(ResourceAction resourceAction) throws Exception {
AWSElasticLoadBalancingLoadBalancerResourceAction action = (AWSElasticLoadBalancingLoadBalancerResourceAction) resourceAction;
ServiceConfiguration configuration = Topology.lookup(LoadBalancing.class);
CreateLoadBalancerType createLoadBalancerType = MessageHelper.createMessage(CreateLoadBalancerType.class, action.info.getEffectiveUserId());
if (action.properties.getLoadBalancerName() == null) {
// The name here is a little weird. It needs to be no more than 32 characters
createLoadBalancerType.setLoadBalancerName(action.getDefaultPhysicalResourceId(32));
} else {
createLoadBalancerType.setLoadBalancerName(action.properties.getLoadBalancerName());
}
if ( action.properties.getAvailabilityZones( ) != null && !action.properties.getAvailabilityZones( ).isEmpty( ) ) {
AvailabilityZones availabilityZones = new AvailabilityZones();
ArrayList<String> member = Lists.newArrayList(action.properties.getAvailabilityZones());
availabilityZones.setMember(member);
createLoadBalancerType.setAvailabilityZones(availabilityZones);
}
if (action.properties.getListeners() != null) {
Listeners listeners = new Listeners();
ArrayList<Listener> member = Lists.newArrayList();
for (ElasticLoadBalancingListener elasticLoadBalancingListener: action.properties.getListeners()) {
Listener listener = convertListener(elasticLoadBalancingListener);
// TO set the policies, look at the next step
member.add(listener);
}
listeners.setMember(member);
createLoadBalancerType.setListeners(listeners);
}
createLoadBalancerType.setScheme(action.properties.getScheme());
if ( action.properties.getSecurityGroups( ) != null && !action.properties.getSecurityGroups( ).isEmpty( ) ) {
SecurityGroups securityGroups = new SecurityGroups();
ArrayList<String> member = Lists.newArrayList(action.properties.getSecurityGroups());
securityGroups.setMember(member);
createLoadBalancerType.setSecurityGroups(securityGroups);
}
if ( action.properties.getSubnets( ) != null && !action.properties.getSubnets( ).isEmpty( ) ) {
Subnets subnets = new Subnets();
ArrayList<String> member = Lists.newArrayList(action.properties.getSubnets());
subnets.setMember(member);
createLoadBalancerType.setSubnets(subnets);
}
CreateLoadBalancerResponseType createLoadBalancerResponseType = AsyncRequests.<CreateLoadBalancerType,CreateLoadBalancerResponseType> sendSync(configuration, createLoadBalancerType);
action.info.setPhysicalResourceId(createLoadBalancerType.getLoadBalancerName());
action.info.setCreatedEnoughToDelete(true);
action.info.setDnsName(JsonHelper.getStringFromJsonNode(new TextNode(createLoadBalancerResponseType.getCreateLoadBalancerResult().getDnsName())));
action.info.setReferenceValueJson(JsonHelper.getStringFromJsonNode(new TextNode(action.info.getPhysicalResourceId())));
return action;
}
},
ADD_TAGS {
@Override
public ResourceAction perform(ResourceAction resourceAction) throws Exception {
AWSElasticLoadBalancingLoadBalancerResourceAction action = (AWSElasticLoadBalancingLoadBalancerResourceAction) resourceAction;
ServiceConfiguration configuration = Topology.lookup(LoadBalancing.class);
// Create 'system' tags as admin user
String effectiveAdminUserId = Accounts.lookupPrincipalByAccountNumber(Accounts.lookupPrincipalByUserId(action.info.getEffectiveUserId()).getAccountNumber()).getUserId();
AddTagsType addSystemTagsType = MessageHelper.createPrivilegedMessage(AddTagsType.class, effectiveAdminUserId);
addSystemTagsType.setLoadBalancerNames(getLoadBalancerNames(action));
addSystemTagsType.setTags(TagHelper.convertToTagList(TagHelper.getCloudFormationResourceSystemTags(action.info, action.getStackEntity())));
AsyncRequests.<AddTagsType, AddTagsResponseType>sendSync(configuration, addSystemTagsType);
// Create non-system tags as regular user
List<CloudFormationResourceTag> tags = TagHelper.getCloudFormationResourceStackTags(action.getStackEntity());
if (action.properties.getTags() != null && !action.properties.getTags().isEmpty()) {
TagHelper.checkReservedCloudFormationResourceTemplateTags(action.properties.getTags());
tags.addAll(action.properties.getTags());
}
if (!tags.isEmpty()) {
AddTagsType addTagsType = MessageHelper.createMessage(AddTagsType.class, action.info.getEffectiveUserId());
addTagsType.setLoadBalancerNames(getLoadBalancerNames(action));
addTagsType.setTags(TagHelper.convertToTagList(tags));
AsyncRequests.<AddTagsType, AddTagsResponseType>sendSync(configuration, addTagsType);
}
return action;
}
},
ADD_INSTANCES_TO_LOAD_BALANCER {
@Override
public ResourceAction perform(ResourceAction resourceAction) throws Exception {
AWSElasticLoadBalancingLoadBalancerResourceAction action = (AWSElasticLoadBalancingLoadBalancerResourceAction) resourceAction;
ServiceConfiguration configuration = Topology.lookup(LoadBalancing.class);
if ( action.properties.getInstances( ) != null && !action.properties.getInstances( ).isEmpty( ) ) {
RegisterInstancesWithLoadBalancerType registerInstancesWithLoadBalancerType = MessageHelper.createMessage(RegisterInstancesWithLoadBalancerType.class, action.info.getEffectiveUserId());
registerInstancesWithLoadBalancerType.setLoadBalancerName(action.info.getPhysicalResourceId());
Instances instances = new Instances();
ArrayList<Instance> member = Lists.newArrayList();
for (String instanceId: action.properties.getInstances()) {
Instance instance = new Instance();
instance.setInstanceId(instanceId);
member.add(instance);
}
instances.setMember(member);
registerInstancesWithLoadBalancerType.setInstances(instances);
AsyncRequests.<RegisterInstancesWithLoadBalancerType,RegisterInstancesWithLoadBalancerResponseType> sendSync(configuration, registerInstancesWithLoadBalancerType);
}
return action;
}
},
ADD_HEALTH_CHECK_TO_LOAD_BALANCER {
@Override
public ResourceAction perform(ResourceAction resourceAction) throws Exception {
AWSElasticLoadBalancingLoadBalancerResourceAction action = (AWSElasticLoadBalancingLoadBalancerResourceAction) resourceAction;
ServiceConfiguration configuration = Topology.lookup(LoadBalancing.class);
if (action.properties.getHealthCheck() != null) {
configureHealthCheck(action, configuration);
}
return action;
}
},
ADD_POLICIES_TO_LOAD_BALANCER {
@Override
public ResourceAction perform(ResourceAction resourceAction) throws Exception {
AWSElasticLoadBalancingLoadBalancerResourceAction action = (AWSElasticLoadBalancingLoadBalancerResourceAction) resourceAction;
ServiceConfiguration configuration = Topology.lookup(LoadBalancing.class);
checkForDuplicatePolicyNames(action);
if (action.properties.getPolicies() != null) {
for (ElasticLoadBalancingPolicyType elasticLoadBalancingPropertyType: action.properties.getPolicies()) {
createLoadBalancerPolicy(action, configuration, elasticLoadBalancingPropertyType);
}
}
if (action.properties.getAppCookieStickinessPolicy() != null) {
for (ElasticLoadBalancingAppCookieStickinessPolicy elasticLoadBalancingAppCookieStickinessPolicy: action.properties.getAppCookieStickinessPolicy()) {
createAppCookieStickinessPolicy(action, configuration, elasticLoadBalancingAppCookieStickinessPolicy);
}
}
if (action.properties.getLbCookieStickinessPolicy() != null) {
for (ElasticLoadBalancingLBCookieStickinessPolicyType elasticLoadBalancingLbCookieStickinessPolicy: action.properties.getLbCookieStickinessPolicy()) {
createLBCookieStickinessPolicy(action, configuration, elasticLoadBalancingLbCookieStickinessPolicy);
}
}
return action;
}
},
ADD_LOAD_BALANCER_POLICIES_TO_LISTENERS {
@Override
public ResourceAction perform(ResourceAction resourceAction) throws Exception {
AWSElasticLoadBalancingLoadBalancerResourceAction action = (AWSElasticLoadBalancingLoadBalancerResourceAction) resourceAction;
ServiceConfiguration configuration = Topology.lookup(LoadBalancing.class);
Multimap<Integer, String> listenerPolicyMap = HashMultimap.create();
Multimap<Integer, String> backendPolicyMap = HashMultimap.create();
Set<Integer> listenerPorts = Sets.newHashSet();
// first add policies explicitly listed in the map.
if (action.properties.getListeners() != null) {
for (ElasticLoadBalancingListener elasticLoadBalancingListener : action.properties.getListeners()) {
listenerPorts.add(elasticLoadBalancingListener.getLoadBalancerPort());
if (elasticLoadBalancingListener.getPolicyNames() != null) {
listenerPolicyMap.putAll(elasticLoadBalancingListener.getLoadBalancerPort(), elasticLoadBalancingListener.getPolicyNames());
}
}
}
// now add policies by their load balancer port (assuming a proper listener exists) and backend by their instance ports
if (action.properties.getPolicies() != null) {
for (ElasticLoadBalancingPolicyType policyType : action.properties.getPolicies()) {
if (policyType.getLoadBalancerPorts() != null) {
for (Integer loadBalancerPort : policyType.getLoadBalancerPorts()) {
if (!listenerPorts.contains(loadBalancerPort)) {
throw new ValidationErrorException("Policy " + policyType.getPolicyName() + " has a load balancer port of " + loadBalancerPort + ", which has no listener defined");
} else {
listenerPolicyMap.put(loadBalancerPort, policyType.getPolicyName());
}
}
}
if (policyType.getInstancePorts() != null) {
for (Integer instancePort : policyType.getInstancePorts()) {
backendPolicyMap.put(instancePort, policyType.getPolicyName());
}
}
}
}
for (Integer listenerLBPort: listenerPolicyMap.keySet()) {
ArrayList<String> policyNamesStr = Lists.newArrayList(listenerPolicyMap.get(listenerLBPort));
SetLoadBalancerPoliciesOfListenerType setLoadBalancerPoliciesOfListenerType = MessageHelper.createMessage(SetLoadBalancerPoliciesOfListenerType.class, action.info.getEffectiveUserId());
setLoadBalancerPoliciesOfListenerType.setLoadBalancerName(action.info.getPhysicalResourceId());
setLoadBalancerPoliciesOfListenerType.setLoadBalancerPort(listenerLBPort);
PolicyNames policyNames = new PolicyNames();
policyNames.setMember(policyNamesStr);
setLoadBalancerPoliciesOfListenerType.setPolicyNames(policyNames);
AsyncRequests.<SetLoadBalancerPoliciesOfListenerType,SetLoadBalancerPoliciesOfListenerResponseType> sendSync(configuration, setLoadBalancerPoliciesOfListenerType);
}
for (Integer backendInstancePort: backendPolicyMap.keySet()) {
ArrayList<String> policyNamesStr = Lists.newArrayList(backendPolicyMap.get(backendInstancePort));
SetLoadBalancerPoliciesForBackendServerType setLoadBalancerPoliciesForBackendServerType = MessageHelper.createMessage(SetLoadBalancerPoliciesForBackendServerType.class, action.info.getEffectiveUserId());
setLoadBalancerPoliciesForBackendServerType.setLoadBalancerName(action.info.getPhysicalResourceId());
setLoadBalancerPoliciesForBackendServerType.setInstancePort(backendInstancePort);
PolicyNames policyNames = new PolicyNames();
policyNames.setMember(policyNamesStr);
setLoadBalancerPoliciesForBackendServerType.setPolicyNames(policyNames);
AsyncRequests.<SetLoadBalancerPoliciesForBackendServerType,SetLoadBalancerPoliciesForBackendServerResponseType> sendSync(configuration, setLoadBalancerPoliciesForBackendServerType);
}
return action;
}
},
SET_CROSS_ZONE_ATTRIBUTE { // For any configured load balancer attributes
@Override
public ResourceAction perform(ResourceAction resourceAction) throws Exception {
final AWSElasticLoadBalancingLoadBalancerResourceAction action =
(AWSElasticLoadBalancingLoadBalancerResourceAction) resourceAction;
final ServiceConfiguration configuration = Topology.lookup(LoadBalancing.class);
final boolean accessLogging = action.properties.getAccessLoggingPolicy( ) != null;
final boolean crossZone = action.properties.getCrossZone() != null &&
Boolean.TRUE.equals(action.properties.getCrossZone());
final boolean idleTimeout = action.properties.getConnectionSettings( ) != null &&
action.properties.getConnectionSettings( ).getIdleTimeout( ) != null;
if ( accessLogging || crossZone || idleTimeout ) {
ModifyLoadBalancerAttributesType modifyLoadBalancerAttributesType = MessageHelper.createMessage(ModifyLoadBalancerAttributesType.class, action.info.getEffectiveUserId());
modifyLoadBalancerAttributesType.setLoadBalancerName(action.info.getPhysicalResourceId());
LoadBalancerAttributes loadBalancerAttributes = new LoadBalancerAttributes();
if ( accessLogging ) {
final ElasticLoadBalancingAccessLoggingPolicy accessLoggingPolicy = action.properties.getAccessLoggingPolicy( );
final AccessLog accessLog = new AccessLog( );
accessLog.setEnabled( accessLoggingPolicy.getEnabled( ) );
accessLog.setEmitInterval( accessLoggingPolicy.getEmitInterval( ) );
accessLog.setS3BucketName( accessLoggingPolicy.getS3BucketName( ) );
accessLog.setS3BucketPrefix( accessLoggingPolicy.getS3BucketPrefix( ) );
loadBalancerAttributes.setAccessLog( accessLog );
}
if ( crossZone ) {
CrossZoneLoadBalancing crossZoneLoadBalancing = new CrossZoneLoadBalancing( );
crossZoneLoadBalancing.setEnabled( Boolean.TRUE );
loadBalancerAttributes.setCrossZoneLoadBalancing( crossZoneLoadBalancing );
}
if ( idleTimeout ) {
ConnectionSettings connectionSettings = new ConnectionSettings( );
connectionSettings.setIdleTimeout( action.properties.getConnectionSettings( ).getIdleTimeout( ) );
loadBalancerAttributes.setConnectionSettings( connectionSettings );
}
modifyLoadBalancerAttributesType.setLoadBalancerAttributes(loadBalancerAttributes);
AsyncRequests.<ModifyLoadBalancerAttributesType, ModifyLoadBalancerAttributesResponseType>sendSync(configuration, modifyLoadBalancerAttributesType);
}
return action;
}
},
PLACEHOLDER_FOR_OTHER_FIELDS { //// placeholder for ""ConnectionDrainingPolicy"
@Override
public ResourceAction perform(ResourceAction resourceAction) throws Exception {
AWSElasticLoadBalancingLoadBalancerResourceAction action = (AWSElasticLoadBalancingLoadBalancerResourceAction) resourceAction;
ServiceConfiguration configuration = Topology.lookup(LoadBalancing.class);
// not currently supported
return action;
}
},
DESCRIBE_LOAD_BALANCER_TO_GET_ATTRIBUTES {
@Override
public ResourceAction perform(ResourceAction resourceAction) throws Exception {
AWSElasticLoadBalancingLoadBalancerResourceAction action = (AWSElasticLoadBalancingLoadBalancerResourceAction) resourceAction;
ServiceConfiguration configuration = Topology.lookup(LoadBalancing.class);
return describeLoadBalancerToGetAttributes(action, configuration);
}
};
@Nullable
@Override
public Integer getTimeout() {
return null;
}
}
private static ResourceAction describeLoadBalancerToGetAttributes(AWSElasticLoadBalancingLoadBalancerResourceAction action, ServiceConfiguration configuration) throws Exception {
DescribeLoadBalancersType describeLoadBalancersType = MessageHelper.createMessage(DescribeLoadBalancersType.class, action.info.getEffectiveUserId());
describeLoadBalancersType.setLoadBalancerNames(getLoadBalancerNames(action));
DescribeLoadBalancersResponseType describeLoadBalancersResponseType = AsyncRequests.<DescribeLoadBalancersType,DescribeLoadBalancersResponseType> sendSync(configuration, describeLoadBalancersType);
if (describeLoadBalancersResponseType != null && describeLoadBalancersResponseType.getDescribeLoadBalancersResult() != null
&& describeLoadBalancersResponseType.getDescribeLoadBalancersResult().getLoadBalancerDescriptions() != null &&
describeLoadBalancersResponseType.getDescribeLoadBalancersResult().getLoadBalancerDescriptions().getMember() != null &&
describeLoadBalancersResponseType.getDescribeLoadBalancersResult().getLoadBalancerDescriptions().getMember().size() > 0) {
LoadBalancerDescription loadBalancerDescription = describeLoadBalancersResponseType.getDescribeLoadBalancersResult().getLoadBalancerDescriptions().getMember().get(0);
String canonicalHostedZoneName = loadBalancerDescription.getCanonicalHostedZoneName();
String canonicalHostedZoneNameId = loadBalancerDescription.getCanonicalHostedZoneNameID();
String sourceSecurityGroupGroupName = loadBalancerDescription.getSourceSecurityGroup().getGroupName();
String sourceSecurityGroupGroupOwnerAlias = loadBalancerDescription.getSourceSecurityGroup().getOwnerAlias();
if ("internal".equals(loadBalancerDescription.getScheme())) {
canonicalHostedZoneName = loadBalancerDescription.getDnsName();
}
action.info.setSourceSecurityGroupGroupName(JsonHelper.getStringFromJsonNode(new TextNode(sourceSecurityGroupGroupName)));
action.info.setSourceSecurityGroupOwnerAlias(JsonHelper.getStringFromJsonNode(new TextNode(sourceSecurityGroupGroupOwnerAlias)));
action.info.setCanonicalHostedZoneNameID(JsonHelper.getStringFromJsonNode(new TextNode(canonicalHostedZoneNameId)));
action.info.setCanonicalHostedZoneName(JsonHelper.getStringFromJsonNode(new TextNode(canonicalHostedZoneName)));
}
return action;
}
private static void createLBCookieStickinessPolicy(AWSElasticLoadBalancingLoadBalancerResourceAction action, ServiceConfiguration configuration, ElasticLoadBalancingLBCookieStickinessPolicyType elasticLoadBalancingLbCookieStickinessPolicy) throws Exception {
CreateLBCookieStickinessPolicyType createLBCookieStickinessPolicyType = MessageHelper.createMessage(CreateLBCookieStickinessPolicyType.class, action.info.getEffectiveUserId());
createLBCookieStickinessPolicyType.setPolicyName(elasticLoadBalancingLbCookieStickinessPolicy.getPolicyName());
createLBCookieStickinessPolicyType.setLoadBalancerName(action.info.getPhysicalResourceId());
createLBCookieStickinessPolicyType.setCookieExpirationPeriod(elasticLoadBalancingLbCookieStickinessPolicy.getCookieExpirationPeriod());
AsyncRequests.<CreateLBCookieStickinessPolicyType, CreateLBCookieStickinessPolicyResponseType>sendSync(configuration, createLBCookieStickinessPolicyType);
}
private static void createLoadBalancerPolicy(AWSElasticLoadBalancingLoadBalancerResourceAction action, ServiceConfiguration configuration, ElasticLoadBalancingPolicyType elasticLoadBalancingPropertyType) throws Exception {
CreateLoadBalancerPolicyType createLoadBalancerPolicyType = MessageHelper.createMessage(CreateLoadBalancerPolicyType.class, action.info.getEffectiveUserId());
createLoadBalancerPolicyType.setLoadBalancerName(action.info.getPhysicalResourceId());
if (elasticLoadBalancingPropertyType.getAttributes() != null) {
PolicyAttributes policyAttributes = new PolicyAttributes();
ArrayList<PolicyAttribute> member = Lists.newArrayList();
for (ElasticLoadBalancingPolicyTypeAttribute elasticLoadBalancingPolicyTypeAttribute: elasticLoadBalancingPropertyType.getAttributes()) {
PolicyAttribute policyAttribute = new PolicyAttribute();
policyAttribute.setAttributeName(elasticLoadBalancingPolicyTypeAttribute.getName());
policyAttribute.setAttributeValue(elasticLoadBalancingPolicyTypeAttribute.getValue());
member.add(policyAttribute);
}
policyAttributes.setMember(member);
createLoadBalancerPolicyType.setPolicyAttributes(policyAttributes);
}
createLoadBalancerPolicyType.setPolicyName(elasticLoadBalancingPropertyType.getPolicyName());
createLoadBalancerPolicyType.setPolicyTypeName(elasticLoadBalancingPropertyType.getPolicyType());
AsyncRequests.<CreateLoadBalancerPolicyType,CreateLoadBalancerPolicyResponseType> sendSync(configuration, createLoadBalancerPolicyType);
}
private static void createAppCookieStickinessPolicy(AWSElasticLoadBalancingLoadBalancerResourceAction action, ServiceConfiguration configuration, ElasticLoadBalancingAppCookieStickinessPolicy elasticLoadBalancingAppCookieStickinessPolicy) throws Exception {
CreateAppCookieStickinessPolicyType createAppCookieStickinessPolicyType = MessageHelper.createMessage(CreateAppCookieStickinessPolicyType.class, action.info.getEffectiveUserId());
createAppCookieStickinessPolicyType.setPolicyName(elasticLoadBalancingAppCookieStickinessPolicy.getPolicyName());
createAppCookieStickinessPolicyType.setLoadBalancerName(action.info.getPhysicalResourceId());
createAppCookieStickinessPolicyType.setCookieName(elasticLoadBalancingAppCookieStickinessPolicy.getCookieName());
AsyncRequests.<CreateAppCookieStickinessPolicyType, CreateAppCookieStickinessPolicyResponseType>sendSync(configuration, createAppCookieStickinessPolicyType);
}
private static Listener convertListener(ElasticLoadBalancingListener elasticLoadBalancingListener) {
Listener listener = new Listener();
listener.setInstancePort(elasticLoadBalancingListener.getInstancePort());
listener.setInstanceProtocol(elasticLoadBalancingListener.getInstanceProtocol());
listener.setLoadBalancerPort(elasticLoadBalancingListener.getLoadBalancerPort());
listener.setProtocol(elasticLoadBalancingListener.getProtocol());
listener.setSSLCertificateId(elasticLoadBalancingListener.getSslCertificateId());
return listener;
}
private static void configureHealthCheck(AWSElasticLoadBalancingLoadBalancerResourceAction action, ServiceConfiguration configuration) throws Exception {
ConfigureHealthCheckType configureHealthCheckType = MessageHelper.createMessage(ConfigureHealthCheckType.class, action.info.getEffectiveUserId());
configureHealthCheckType.setLoadBalancerName(action.info.getPhysicalResourceId());
HealthCheck healthCheck = new HealthCheck();
healthCheck.setHealthyThreshold(action.properties.getHealthCheck().getHealthyThreshold());
healthCheck.setInterval(action.properties.getHealthCheck().getInterval());
healthCheck.setTarget(action.properties.getHealthCheck().getTarget());
healthCheck.setTimeout(action.properties.getHealthCheck().getTimeout());
healthCheck.setUnhealthyThreshold(action.properties.getHealthCheck().getUnhealthyThreshold());
configureHealthCheckType.setHealthCheck(healthCheck);
AsyncRequests.<ConfigureHealthCheckType,ConfigureHealthCheckResponseType> sendSync(configuration, configureHealthCheckType);
}
private static LoadBalancerNames getLoadBalancerNames(AWSElasticLoadBalancingLoadBalancerResourceAction action) {
LoadBalancerNames loadBalancerNames = new LoadBalancerNames();
loadBalancerNames.setMember(Lists.newArrayList(action.info.getPhysicalResourceId()));
return loadBalancerNames;
}
private enum DeleteSteps implements Step {
DELETE_LOAD_BALANCER {
@Override
public ResourceAction perform(ResourceAction resourceAction) throws Exception {
AWSElasticLoadBalancingLoadBalancerResourceAction action = (AWSElasticLoadBalancingLoadBalancerResourceAction) resourceAction;
ServiceConfiguration configuration = Topology.lookup(LoadBalancing.class);
if (!Boolean.TRUE.equals(action.info.getCreatedEnoughToDelete())) return action;
DescribeLoadBalancersType describeLoadBalancersType = MessageHelper.createMessage(DescribeLoadBalancersType.class, action.info.getEffectiveUserId());
LoadBalancerNames loadBalancerNames = new LoadBalancerNames();
ArrayList<String> member = Lists.newArrayList(action.info.getPhysicalResourceId());
loadBalancerNames.setMember(member);
describeLoadBalancersType.setLoadBalancerNames(loadBalancerNames);
DescribeLoadBalancersResponseType describeLoadBalancersResponseType = AsyncRequests.<DescribeLoadBalancersType,DescribeLoadBalancersResponseType> sendSync(configuration, describeLoadBalancersType);
if ( describeLoadBalancersResponseType != null && describeLoadBalancersResponseType.getDescribeLoadBalancersResult() != null &&
describeLoadBalancersResponseType.getDescribeLoadBalancersResult().getLoadBalancerDescriptions() != null &&
describeLoadBalancersResponseType.getDescribeLoadBalancersResult().getLoadBalancerDescriptions().getMember() != null &&
describeLoadBalancersResponseType.getDescribeLoadBalancersResult().getLoadBalancerDescriptions().getMember().size() == 1 ) {
DeleteLoadBalancerType deleteLoadBalancerType = MessageHelper.createMessage(DeleteLoadBalancerType.class, action.info.getEffectiveUserId());
deleteLoadBalancerType.setLoadBalancerName(action.info.getPhysicalResourceId());
AsyncRequests.<DeleteLoadBalancerType,DeleteLoadBalancerResponseType> sendSync(configuration, deleteLoadBalancerType);
}
return action;
}
};
@Nullable
@Override
public Integer getTimeout() {
return null;
}
}
private enum UpdateNoInterruptionSteps implements UpdateStep {
UPDATE_LOAD_BALANCER {
@Override
public ResourceAction perform(ResourceAction oldResourceAction, ResourceAction newResourceAction) throws Exception {
AWSElasticLoadBalancingLoadBalancerResourceAction oldAction = (AWSElasticLoadBalancingLoadBalancerResourceAction) oldResourceAction;
AWSElasticLoadBalancingLoadBalancerResourceAction newAction = (AWSElasticLoadBalancingLoadBalancerResourceAction) newResourceAction;
ServiceConfiguration configuration = Topology.lookup(LoadBalancing.class);
checkForDuplicatePolicyNames(newAction);
// update the items on the main load balance.
DescribeLoadBalancersType describeLoadBalancersType = MessageHelper.createMessage(DescribeLoadBalancersType.class, newAction.info.getEffectiveUserId());
describeLoadBalancersType.setLoadBalancerNames(getLoadBalancerNames(newAction));
DescribeLoadBalancersResponseType describeLoadBalancersResponseType = AsyncRequests.<DescribeLoadBalancersType, DescribeLoadBalancersResponseType>sendSync(configuration, describeLoadBalancersType);
if (describeLoadBalancersResponseType == null || describeLoadBalancersResponseType.getDescribeLoadBalancersResult() == null ||
describeLoadBalancersResponseType.getDescribeLoadBalancersResult().getLoadBalancerDescriptions() == null ||
describeLoadBalancersResponseType.getDescribeLoadBalancersResult().getLoadBalancerDescriptions().getMember() == null ||
describeLoadBalancersResponseType.getDescribeLoadBalancersResult().getLoadBalancerDescriptions().getMember().size() != 1) {
throw new ValidationErrorException("Can not find load balancer : " + newAction.info.getPhysicalResourceId());
}
LoadBalancerDescription loadBalancerDescription = describeLoadBalancersResponseType.getDescribeLoadBalancersResult().getLoadBalancerDescriptions().getMember().get(0);
updateAZs(oldAction, newAction, configuration, loadBalancerDescription);
updateInstances(oldAction, newAction, configuration, loadBalancerDescription);
updateSecurityGroups(oldAction, newAction, configuration, loadBalancerDescription);
updateSubnets(oldAction, newAction, configuration, loadBalancerDescription);
if (newAction.properties.getHealthCheck() != null) {
configureHealthCheck(newAction, configuration);
}
updateListenersAndPolicies(oldAction, newAction, configuration);
return newAction;
}
},
UPDATE_LOAD_BALANCER_ATTRIBUTES {
@Override
public ResourceAction perform(ResourceAction oldResourceAction, ResourceAction newResourceAction) throws Exception {
AWSElasticLoadBalancingLoadBalancerResourceAction oldAction = (AWSElasticLoadBalancingLoadBalancerResourceAction) oldResourceAction;
AWSElasticLoadBalancingLoadBalancerResourceAction newAction = (AWSElasticLoadBalancingLoadBalancerResourceAction) newResourceAction;
ServiceConfiguration configuration = Topology.lookup(LoadBalancing.class);
ModifyLoadBalancerAttributesType modifyLoadBalancerAttributesType = MessageHelper.createMessage(ModifyLoadBalancerAttributesType.class, newAction.info.getEffectiveUserId());
LoadBalancerAttributes loadBalancerAttributes = new LoadBalancerAttributes();
AccessLog accessLog = new AccessLog();
if (newAction.properties.getAccessLoggingPolicy() != null) {
accessLog.setEnabled( newAction.properties.getAccessLoggingPolicy().getEnabled( ) );
accessLog.setEmitInterval( newAction.properties.getAccessLoggingPolicy().getEmitInterval( ) );
accessLog.setS3BucketName( newAction.properties.getAccessLoggingPolicy().getS3BucketName( ) );
accessLog.setS3BucketPrefix( newAction.properties.getAccessLoggingPolicy().getS3BucketPrefix( ) );
} else {
accessLog = new AccessLog();
accessLog.setEnabled( false );
}
ConnectionSettings connectionSettings = new ConnectionSettings();
if (newAction.properties.getConnectionSettings() != null) {
connectionSettings.setIdleTimeout(newAction.properties.getConnectionSettings().getIdleTimeout());
} else {
connectionSettings.setIdleTimeout(60); // default
}
CrossZoneLoadBalancing crossZoneLoadBalancing = new CrossZoneLoadBalancing();
if (newAction.properties.getCrossZone() != null) {
crossZoneLoadBalancing.setEnabled(newAction.properties.getCrossZone());
} else {
crossZoneLoadBalancing.setEnabled(false);
}
loadBalancerAttributes.setAccessLog(accessLog);
loadBalancerAttributes.setConnectionSettings(connectionSettings);
loadBalancerAttributes.setCrossZoneLoadBalancing(crossZoneLoadBalancing);
modifyLoadBalancerAttributesType.setLoadBalancerAttributes(loadBalancerAttributes);
modifyLoadBalancerAttributesType.setLoadBalancerName(newAction.info.getPhysicalResourceId());
AsyncRequests.<ModifyLoadBalancerAttributesType, ModifyLoadBalancerAttributesResponseType>sendSync(configuration, modifyLoadBalancerAttributesType);
return newAction;
}
},
UPDATE_TAGS {
@Override
public ResourceAction perform(ResourceAction oldResourceAction, ResourceAction newResourceAction) throws Exception {
AWSElasticLoadBalancingLoadBalancerResourceAction oldAction = (AWSElasticLoadBalancingLoadBalancerResourceAction) oldResourceAction;
AWSElasticLoadBalancingLoadBalancerResourceAction newAction = (AWSElasticLoadBalancingLoadBalancerResourceAction) newResourceAction;
ServiceConfiguration configuration = Topology.lookup(LoadBalancing.class);
DescribeTagsType describeTagsType = MessageHelper.createMessage(DescribeTagsType.class, newAction.info.getEffectiveUserId());
LoadBalancerNamesMax20 loadBalancerNames = new LoadBalancerNamesMax20();
loadBalancerNames.setMember(Lists.newArrayList(newAction.info.getPhysicalResourceId()));
describeTagsType.setLoadBalancerNames(loadBalancerNames);
DescribeTagsResponseType describeTagsResponseType = AsyncRequests.sendSync(configuration, describeTagsType);
if (describeTagsResponseType == null || describeTagsResponseType.getDescribeTagsResult() == null ||
describeTagsResponseType.getDescribeTagsResult().getTagDescriptions() == null ||
describeTagsResponseType.getDescribeTagsResult().getTagDescriptions().getMember() == null ||
describeTagsResponseType.getDescribeTagsResult().getTagDescriptions().getMember().size() != 1) {
throw new ValidationErrorException("Can not find load balancer : " + newAction.info.getPhysicalResourceId());
}
final TagDescription tagDescription = describeTagsResponseType.getDescribeTagsResult().getTagDescriptions().getMember().get(0);
Set<CloudFormationResourceTag> existingTags = Sets.newLinkedHashSet();
if (tagDescription != null && tagDescription.getTags() != null && tagDescription.getTags().getMember() != null) {
for (Tag tag : tagDescription.getTags().getMember()) {
CloudFormationResourceTag cfTag = new CloudFormationResourceTag();
cfTag.setKey(tag.getKey());
cfTag.setValue(tag.getValue());
existingTags.add(cfTag);
}
}
Set<CloudFormationResourceTag> newTags = Sets.newLinkedHashSet();
if (newAction.properties.getTags() != null) {
newTags.addAll(newAction.properties.getTags());
}
List<CloudFormationResourceTag> newStackTags = TagHelper.getCloudFormationResourceStackTags(newAction.getStackEntity());
if (newStackTags != null) {
newTags.addAll(newStackTags);
}
TagHelper.checkReservedCloudFormationResourceTemplateTags(newTags);
// add only 'new' tags
Set<CloudFormationResourceTag> onlyNewTags = Sets.difference(newTags, existingTags);
if (!onlyNewTags.isEmpty()) {
AddTagsType addTagsType = MessageHelper.createMessage(AddTagsType.class, newAction.info.getEffectiveUserId());
addTagsType.setLoadBalancerNames(getLoadBalancerNames(newAction));
addTagsType.setTags(TagHelper.convertToTagList(onlyNewTags));
AsyncRequests.<AddTagsType, AddTagsResponseType>sendSync(configuration, addTagsType);
}
// Get old tags...
Set<CloudFormationResourceTag> oldTags = Sets.newLinkedHashSet();
if (oldAction.properties.getTags() != null) {
oldTags.addAll(oldAction.properties.getTags());
}
List<CloudFormationResourceTag> oldStackTags = TagHelper.getCloudFormationResourceStackTags(oldAction.getStackEntity());
if (oldStackTags != null) {
oldTags.addAll(oldStackTags);
}
// remove only the old tags that are not new and that exist -- however, since remove tags only goes by tag name, we only look at tag names
Set<String> oldTagKeys = TagHelper.getTagKeyNames(oldTags);
Set<String> existingTagKeys = TagHelper.getTagKeyNames(existingTags);
Set<String> newTagKeys = TagHelper.getTagKeyNames(newTags);
Set<String> tagKeysToRemove = Sets.intersection(oldTagKeys, Sets.difference(existingTagKeys, newTagKeys));
if (!tagKeysToRemove.isEmpty()) {
RemoveTagsType removeTagsType = MessageHelper.createMessage(RemoveTagsType.class, newAction.info.getEffectiveUserId());
removeTagsType.setLoadBalancerNames(getLoadBalancerNames(newAction));
removeTagsType.setTags(TagHelper.convertToTagKeyList(tagKeysToRemove));
AsyncRequests.<RemoveTagsType, RemoveTagsResponseType>sendSync(configuration, removeTagsType);
}
return newAction;
}
},
UPDATE_DESCRIBE_LOAD_BALANCER_TO_GET_ATTRIBUTES { // just in case... not sure necessary
@Override
public ResourceAction perform(ResourceAction oldResourceAction, ResourceAction newResourceAction) throws Exception {
AWSElasticLoadBalancingLoadBalancerResourceAction oldAction = (AWSElasticLoadBalancingLoadBalancerResourceAction) oldResourceAction;
AWSElasticLoadBalancingLoadBalancerResourceAction newAction = (AWSElasticLoadBalancingLoadBalancerResourceAction) newResourceAction;
ServiceConfiguration configuration = Topology.lookup(LoadBalancing.class);
return describeLoadBalancerToGetAttributes(newAction, configuration);
}
};
@Nullable
@Override
public Integer getTimeout() {
return null;
}
}
private static void updateAZs(AWSElasticLoadBalancingLoadBalancerResourceAction oldAction, AWSElasticLoadBalancingLoadBalancerResourceAction newAction, ServiceConfiguration configuration, LoadBalancerDescription loadBalancerDescription) throws Exception {
Set<String> existingZones = Sets.newHashSet();
if (loadBalancerDescription.getAvailabilityZones() != null) {
addAllIfNotNull(existingZones, loadBalancerDescription.getAvailabilityZones().getMember());
}
Set<String> newZones = Sets.newHashSet();
addAllIfNotNull(newZones, newAction.properties.getAvailabilityZones());
Set<String> oldZones = Sets.newHashSet();
addAllIfNotNull(oldZones, oldAction.properties.getAvailabilityZones());
Set<String> zonesToAdd = Sets.difference(newZones, existingZones);
if (!zonesToAdd.isEmpty()) {
EnableAvailabilityZonesForLoadBalancerType enableAvailabilityZonesForLoadBalancerType = MessageHelper.createMessage(EnableAvailabilityZonesForLoadBalancerType.class, newAction.info.getEffectiveUserId());
enableAvailabilityZonesForLoadBalancerType.setLoadBalancerName(newAction.info.getPhysicalResourceId());
AvailabilityZones availabilityZones = new AvailabilityZones();
availabilityZones.getMember().addAll(zonesToAdd);
enableAvailabilityZonesForLoadBalancerType.setAvailabilityZones(availabilityZones);
AsyncRequests.sendSync(configuration, enableAvailabilityZonesForLoadBalancerType);
}
Set<String> zonesToRemove = Sets.difference(Sets.intersection(oldZones, existingZones), newZones);
if (!zonesToRemove.isEmpty()) {
DisableAvailabilityZonesForLoadBalancerType disableAvailabilityZonesForLoadBalancerType = MessageHelper.createMessage(DisableAvailabilityZonesForLoadBalancerType.class, newAction.info.getEffectiveUserId());
disableAvailabilityZonesForLoadBalancerType.setLoadBalancerName(newAction.info.getPhysicalResourceId());
AvailabilityZones availabilityZones = new AvailabilityZones();
availabilityZones.getMember().addAll(zonesToRemove);
disableAvailabilityZonesForLoadBalancerType.setAvailabilityZones(availabilityZones);
AsyncRequests.sendSync(configuration, disableAvailabilityZonesForLoadBalancerType);
}
}
private static void updateInstances(AWSElasticLoadBalancingLoadBalancerResourceAction oldAction, AWSElasticLoadBalancingLoadBalancerResourceAction newAction, ServiceConfiguration configuration, LoadBalancerDescription loadBalancerDescription) throws Exception {
Set<String> existingInstances = Sets.newHashSet();
if (loadBalancerDescription.getInstances() != null && loadBalancerDescription.getInstances().getMember() != null) {
for (Instance instance: loadBalancerDescription.getInstances().getMember()) {
existingInstances.add(instance.getInstanceId());
}
}
Set<String> newInstances = Sets.newHashSet();
addAllIfNotNull(newInstances, newAction.properties.getInstances());
Set<String> oldInstances = Sets.newHashSet();
addAllIfNotNull(oldInstances, oldAction.properties.getInstances());
Set<String> instancesToAdd = Sets.difference(newInstances, existingInstances);
if (!instancesToAdd.isEmpty()) {
RegisterInstancesWithLoadBalancerType registerInstancesWithLoadBalancerType = MessageHelper.createMessage(RegisterInstancesWithLoadBalancerType.class, newAction.info.getEffectiveUserId());
registerInstancesWithLoadBalancerType.setLoadBalancerName(newAction.info.getPhysicalResourceId());
Instances instances = new Instances();
for (String instanceId: instancesToAdd) {
Instance instance = new Instance();
instance.setInstanceId(instanceId);
instances.getMember().add(instance);
}
registerInstancesWithLoadBalancerType.setInstances(instances);
AsyncRequests.sendSync(configuration, registerInstancesWithLoadBalancerType);
}
Set<String> instancesToRemove = Sets.difference(Sets.intersection(oldInstances, existingInstances), newInstances);
if (!instancesToRemove.isEmpty()) {
DeregisterInstancesFromLoadBalancerType deregisterInstancesFromLoadBalancerType = MessageHelper.createMessage(DeregisterInstancesFromLoadBalancerType.class, newAction.info.getEffectiveUserId());
deregisterInstancesFromLoadBalancerType.setLoadBalancerName(newAction.info.getPhysicalResourceId());
Instances instances = new Instances();
for (String instanceId: instancesToRemove) {
Instance instance = new Instance();
instance.setInstanceId(instanceId);
instances.getMember().add(instance);
}
deregisterInstancesFromLoadBalancerType.setInstances(instances);
AsyncRequests.sendSync(configuration, deregisterInstancesFromLoadBalancerType);
}
}
private static void updateSecurityGroups(AWSElasticLoadBalancingLoadBalancerResourceAction oldAction, AWSElasticLoadBalancingLoadBalancerResourceAction newAction, ServiceConfiguration configuration, LoadBalancerDescription loadBalancerDescription) throws Exception {
if (newAction.properties.getSecurityGroups() != null && !newAction.properties.getSecurityGroups().isEmpty()) {
if (loadBalancerDescription.getVpcId() == null) throw new ValidationErrorException("Can not set Security Groups in non-vpc mode");
ApplySecurityGroupsToLoadBalancerType applySecurityGroupsToLoadBalancerType = MessageHelper.createMessage(ApplySecurityGroupsToLoadBalancerType.class, newAction.info.getEffectiveUserId());
applySecurityGroupsToLoadBalancerType.setLoadBalancerName(newAction.info.getPhysicalResourceId());
SecurityGroups securityGroups = new SecurityGroups();
securityGroups.getMember().addAll(newAction.properties.getSecurityGroups());
applySecurityGroupsToLoadBalancerType.setSecurityGroups(securityGroups);
AsyncRequests.sendSync(configuration, applySecurityGroupsToLoadBalancerType);
} else if (oldAction.properties.getSecurityGroups() != null && !oldAction.properties.getSecurityGroups().isEmpty()) {
// reset to default
ServiceConfiguration ec2Configuration = Topology.lookup(Compute.class);
if (loadBalancerDescription.getVpcId() == null) throw new ValidationErrorException("Can not set Security Groups in non-vpc mode");
DescribeVpcsType describeVpcsType = MessageHelper.createMessage(DescribeVpcsType.class, newAction.info.getEffectiveUserId());
describeVpcsType.setFilterSet(Lists.newArrayList(Filter.filter("vpc-id", loadBalancerDescription.getVpcId())));
DescribeVpcsResponseType describeVpcsResponseType = AsyncRequests.sendSync(ec2Configuration, describeVpcsType);
if (describeVpcsResponseType == null || describeVpcsResponseType.getVpcSet() == null || describeVpcsResponseType.getVpcSet().getItem() == null ||
describeVpcsResponseType.getVpcSet().getItem().isEmpty()) {
throw new ValidationErrorException("No such vpc " + loadBalancerDescription.getVpcId());
}
// special case. for some reason in the default vpc a elb specific group is created. We may want to stop this later... (TODO: revisit!!!)
boolean inDefaultVpcAndFoundElbSpecificGroup = false;
if (describeVpcsResponseType.getVpcSet().getItem().get(0).getIsDefault()) {
// value stolen from com.eucalyptus.loadbalancing.activities.EventHandlerChainNew.SecurityGroupSetup.generateDefaultVPCSecurityGroupName
String defaultVpcSecurityGroupName = String.format("default_elb_%s", UUID.nameUUIDFromBytes(loadBalancerDescription.getVpcId().getBytes(StandardCharsets.UTF_8)).toString());
DescribeSecurityGroupsType describeSecurityGroupsType = MessageHelper.createMessage(DescribeSecurityGroupsType.class, newAction.info.getEffectiveUserId());
describeSecurityGroupsType.getFilterSet().add(Filter.filter("vpc-id", loadBalancerDescription.getVpcId()));
describeSecurityGroupsType.getFilterSet().add(Filter.filter("group-name", defaultVpcSecurityGroupName));
DescribeSecurityGroupsResponseType describeSecurityGroupsResponseType = AsyncRequests.sendSync(ec2Configuration, describeSecurityGroupsType);
if (describeSecurityGroupsResponseType != null && describeSecurityGroupsResponseType.getSecurityGroupInfo() != null &&
!describeSecurityGroupsResponseType.getSecurityGroupInfo().isEmpty()) {
ApplySecurityGroupsToLoadBalancerType applySecurityGroupsToLoadBalancerType = MessageHelper.createMessage(ApplySecurityGroupsToLoadBalancerType.class, newAction.info.getEffectiveUserId());
applySecurityGroupsToLoadBalancerType.setLoadBalancerName(newAction.info.getPhysicalResourceId());
SecurityGroups securityGroups = new SecurityGroups();
securityGroups.getMember().add(describeSecurityGroupsResponseType.getSecurityGroupInfo().get(0).getGroupId());
applySecurityGroupsToLoadBalancerType.setSecurityGroups(securityGroups);
AsyncRequests.sendSync(configuration, applySecurityGroupsToLoadBalancerType);
inDefaultVpcAndFoundElbSpecificGroup = true;
}
}
if (!inDefaultVpcAndFoundElbSpecificGroup) {
DescribeSecurityGroupsType describeSecurityGroupsType = MessageHelper.createMessage(DescribeSecurityGroupsType.class, newAction.info.getEffectiveUserId());
describeSecurityGroupsType.getFilterSet().add(Filter.filter("vpc-id", loadBalancerDescription.getVpcId()));
describeSecurityGroupsType.getFilterSet().add(Filter.filter("group-name", "default"));
DescribeSecurityGroupsResponseType describeSecurityGroupsResponseType = AsyncRequests.sendSync(ec2Configuration, describeSecurityGroupsType);
if (describeSecurityGroupsResponseType != null && describeSecurityGroupsResponseType.getSecurityGroupInfo() != null &&
!describeSecurityGroupsResponseType.getSecurityGroupInfo().isEmpty()) {
ApplySecurityGroupsToLoadBalancerType applySecurityGroupsToLoadBalancerType = MessageHelper.createMessage(ApplySecurityGroupsToLoadBalancerType.class, newAction.info.getEffectiveUserId());
applySecurityGroupsToLoadBalancerType.setLoadBalancerName(newAction.info.getPhysicalResourceId());
SecurityGroups securityGroups = new SecurityGroups();
securityGroups.getMember().add(describeSecurityGroupsResponseType.getSecurityGroupInfo().get(0).getGroupId());
applySecurityGroupsToLoadBalancerType.setSecurityGroups(securityGroups);
AsyncRequests.sendSync(configuration, applySecurityGroupsToLoadBalancerType);
} else {
throw new ValidationErrorException("Could not find default group for vpc " + loadBalancerDescription.getVpcId());
}
}
}
}
private static void updateSubnets(AWSElasticLoadBalancingLoadBalancerResourceAction oldAction, AWSElasticLoadBalancingLoadBalancerResourceAction newAction, ServiceConfiguration configuration, LoadBalancerDescription loadBalancerDescription) throws Exception {
Set<String> existingSubnets = Sets.newHashSet();
if (loadBalancerDescription.getSubnets() != null) {
addAllIfNotNull(existingSubnets, loadBalancerDescription.getSubnets().getMember());
}
Set<String> newSubnets = Sets.newHashSet();
addAllIfNotNull(newSubnets, newAction.properties.getSubnets());
Set<String> oldSubnets = Sets.newHashSet();
addAllIfNotNull(oldSubnets, oldAction.properties.getSubnets());
Set<String> subnetsToAdd = Sets.difference(newSubnets, existingSubnets);
if (!subnetsToAdd.isEmpty()) {
AttachLoadBalancerToSubnetsType attachLoadBalancerToSubnets = MessageHelper.createMessage(AttachLoadBalancerToSubnetsType.class, newAction.info.getEffectiveUserId());
attachLoadBalancerToSubnets.setLoadBalancerName(newAction.info.getPhysicalResourceId());
Subnets subnets = new Subnets();
subnets.getMember().addAll(subnetsToAdd);
attachLoadBalancerToSubnets.setSubnets(subnets);
AsyncRequests.sendSync(configuration, attachLoadBalancerToSubnets);
}
Set<String> subnetsToRemove = Sets.difference(Sets.intersection(oldSubnets, existingSubnets), newSubnets);
if (!subnetsToRemove.isEmpty()) {
DetachLoadBalancerFromSubnetsType detachLoadBalancerFromSubnetsType = MessageHelper.createMessage(DetachLoadBalancerFromSubnetsType.class, newAction.info.getEffectiveUserId());
detachLoadBalancerFromSubnetsType.setLoadBalancerName(newAction.info.getPhysicalResourceId());
Subnets subnets = new Subnets();
subnets.getMember().addAll(subnetsToRemove);
detachLoadBalancerFromSubnetsType.setSubnets(subnets);
AsyncRequests.sendSync(configuration, detachLoadBalancerFromSubnetsType);
}
}
private enum UpdateWithReplacementPreCreateSteps implements UpdateStep {
CHECK_NAME_CHANGED {
@Override
public ResourceAction perform(ResourceAction oldResourceAction, ResourceAction newResourceAction) throws Exception {
AWSElasticLoadBalancingLoadBalancerResourceAction oldAction = (AWSElasticLoadBalancingLoadBalancerResourceAction) oldResourceAction;
AWSElasticLoadBalancingLoadBalancerResourceAction newAction = (AWSElasticLoadBalancingLoadBalancerResourceAction) newResourceAction;
if (oldAction.properties.getLoadBalancerName() != null && oldAction.properties.getLoadBalancerName().equals(newAction.properties.getLoadBalancerName())) {
throw new ValidationErrorException("CloudFormation cannot update a stack when a custom-named resource requires " +
"replacing. Rename " + oldAction.properties.getLoadBalancerName() + " and update the stack again.");
}
return newAction;
}
@Nullable
@Override
public Integer getTimeout() {
return null;
}
}
}
@Override
public ResourceProperties getResourceProperties() {
return properties;
}
@Override
public void setResourceProperties(ResourceProperties resourceProperties) {
properties = (AWSElasticLoadBalancingLoadBalancerProperties) resourceProperties;
}
@Override
public ResourceInfo getResourceInfo() {
return info;
}
@Override
public void setResourceInfo(ResourceInfo resourceInfo) {
info = (AWSElasticLoadBalancingLoadBalancerResourceInfo) resourceInfo;
}
private static void checkForDuplicatePolicyNames(AWSElasticLoadBalancingLoadBalancerResourceAction action) throws ValidationErrorException {
Set<String> policyNames = Sets.newHashSet();
if (action.properties.getPolicies() != null) {
for (ElasticLoadBalancingPolicyType elasticLoadBalancingPropertyType: action.properties.getPolicies()) {
if (!policyNames.contains(elasticLoadBalancingPropertyType.getPolicyName())) {
policyNames.add(elasticLoadBalancingPropertyType.getPolicyName());
} else {
throw new ValidationErrorException("Duplicate policy name: " + elasticLoadBalancingPropertyType.getPolicyName() + " found");
}
}
}
if (action.properties.getAppCookieStickinessPolicy() != null) {
for (ElasticLoadBalancingAppCookieStickinessPolicy elasticLoadBalancingAppCookieStickinessPolicy: action.properties.getAppCookieStickinessPolicy()) {
if (!policyNames.contains(elasticLoadBalancingAppCookieStickinessPolicy.getPolicyName())) {
policyNames.add(elasticLoadBalancingAppCookieStickinessPolicy.getPolicyName());
} else {
throw new ValidationErrorException("Duplicate policy name: " + elasticLoadBalancingAppCookieStickinessPolicy.getPolicyName() + " found");
}
}
}
if (action.properties.getLbCookieStickinessPolicy() != null) {
for (ElasticLoadBalancingLBCookieStickinessPolicyType elasticLoadBalancingLbCookieStickinessPolicy: action.properties.getLbCookieStickinessPolicy()) {
if (!policyNames.contains(elasticLoadBalancingLbCookieStickinessPolicy.getPolicyName())) {
policyNames.add(elasticLoadBalancingLbCookieStickinessPolicy.getPolicyName());
} else {
throw new ValidationErrorException("Duplicate policy name: " + elasticLoadBalancingLbCookieStickinessPolicy.getPolicyName() + " found");
}
}
}
}
private static void updateListeners(AWSElasticLoadBalancingLoadBalancerResourceAction oldAction, AWSElasticLoadBalancingLoadBalancerResourceAction newAction, ServiceConfiguration configuration) throws Exception {
// Get a set of listeners (i.e. load balancer ports) from the previous template
Set<Integer> oldLoadBalancerPorts = Sets.newHashSet();
if (oldAction.properties.getListeners() != null) {
for (ElasticLoadBalancingListener elasticLoadBalancingListener : oldAction.properties.getListeners()) {
oldLoadBalancerPorts.add(elasticLoadBalancingListener.getLoadBalancerPort());
}
}
// Get a set of listeners (i.e. load balancer ports) from the current template)
Set<Integer> newLoadBalancerPorts = Sets.newHashSet();
if (newAction.properties.getListeners() != null) {
for (ElasticLoadBalancingListener elasticLoadBalancingListener : newAction.properties.getListeners()) {
newLoadBalancerPorts.add(elasticLoadBalancingListener.getLoadBalancerPort());
}
}
LoadBalancerDescription loadBalancerDescription = getLoadBalancerDescription(newAction, configuration);
// Get a list of listeners (i.e. load balancer ports) from the loadBalancerDescription (i.e. current actual load balancer values). While we are at it,
// we can query the listeners themselves later, so let's build a map of listeners keyed off of the load balancer port.
// next get a list of load balancer ports from the actual load balancer (and actually keep a map for later)
Map<Integer, ListenerDescription> existingLoadBalancerPortMap = Maps.newHashMap();
if (loadBalancerDescription.getListenerDescriptions() != null && loadBalancerDescription.getListenerDescriptions().getMember() != null) {
for (ListenerDescription listenerDescription : loadBalancerDescription.getListenerDescriptions().getMember()) {
if (listenerDescription != null && listenerDescription.getListener() != null && listenerDescription.getListener().getLoadBalancerPort() != null) {
existingLoadBalancerPortMap.put(listenerDescription.getListener().getLoadBalancerPort(), listenerDescription);
}
}
}
Set<Integer> existingLoadBalancerPorts = existingLoadBalancerPortMap.keySet();
// We are updating listeners now. This is what we do.
// 1) First add any 'new' listeners to the load balancer. This will contain load balancer ports that are in the
// current template but not either in the old template or the load balancer description
Set<Integer> loadBalancerPortsOfListenersToAdd = Sets.difference(newLoadBalancerPorts, Sets.union(oldLoadBalancerPorts, existingLoadBalancerPorts));
if (newAction.properties.getListeners() != null) {
for (ElasticLoadBalancingListener elasticLoadBalancingListener : newAction.properties.getListeners()) {
if (loadBalancerPortsOfListenersToAdd.contains(elasticLoadBalancingListener.getLoadBalancerPort())) {
CreateLoadBalancerListenersType createLoadBalancerListenersType = MessageHelper.createMessage(CreateLoadBalancerListenersType.class, newAction.info.getEffectiveUserId());
createLoadBalancerListenersType.setLoadBalancerName(newAction.info.getPhysicalResourceId());
Listeners listeners = new Listeners();
Listener listener = new Listener();
listener.setSSLCertificateId(elasticLoadBalancingListener.getSslCertificateId());
listener.setProtocol(elasticLoadBalancingListener.getProtocol());
listener.setLoadBalancerPort(elasticLoadBalancingListener.getLoadBalancerPort());
listener.setInstanceProtocol(elasticLoadBalancingListener.getInstanceProtocol());
listener.setInstancePort(elasticLoadBalancingListener.getInstancePort());
listeners.getMember().add(listener);
createLoadBalancerListenersType.setListeners(listeners);
AsyncRequests.sendSync(configuration, createLoadBalancerListenersType);
}
}
}
// 2) Next, delete any listeners that are no longer in the new template. We don't delete listeners that we did not
// add ourselves, however, in case the system added some listeners, or a user manually added a listener outside
// of Cloudformation. As such, the listeners we delete contain the following attributes.
// i) They must have been added by the original template, so among the list of old listeners.
// ii) They must currently exist. (No point deleting a listener that does not exist.)
// iii) They must not be in the new listener set.
Set<Integer> loadBalancerPortsOfListenersToDelete = Sets.difference(Sets.intersection(oldLoadBalancerPorts, existingLoadBalancerPorts), newLoadBalancerPorts);
if (oldAction.properties.getListeners() != null) {
for (ElasticLoadBalancingListener elasticLoadBalancingListener : oldAction.properties.getListeners()) {
if (loadBalancerPortsOfListenersToDelete.contains(elasticLoadBalancingListener.getLoadBalancerPort())) {
DeleteLoadBalancerListenersType deleteLoadBalancerListenersType = MessageHelper.createMessage(DeleteLoadBalancerListenersType.class, oldAction.info.getEffectiveUserId());
deleteLoadBalancerListenersType.setLoadBalancerName(oldAction.info.getPhysicalResourceId());
Ports loadBalancerPorts = new Ports();
loadBalancerPorts.getMember().add(elasticLoadBalancingListener.getLoadBalancerPort().toString());
deleteLoadBalancerListenersType.setLoadBalancerPorts(loadBalancerPorts);
AsyncRequests.sendSync(configuration, deleteLoadBalancerListenersType);
}
}
}
// 3) Finally we look at listeners that exist and that are also in the new template. The state of the listener in
// the old template is irrelevant, as the existing value is more recent to compare for changes. If something has
// changed, between the existing listener and the values in the new template, depending on what exactly has changed,
// we either have to delete and re-add the listener, or simply update the SSL certificate. We don't look at policies attached to listeners
// for differences, but we do reattach current policies to the listener if they still exist. New policy attachment is handled later.
Set<Integer> loadBalancerPortsOfListenersToPossiblyUpdate = Sets.intersection(newLoadBalancerPorts, existingLoadBalancerPorts);
if (newAction.properties.getListeners() != null) {
for (ElasticLoadBalancingListener elasticLoadBalancingListener : newAction.properties.getListeners()) {
if (loadBalancerPortsOfListenersToPossiblyUpdate.contains(elasticLoadBalancingListener.getLoadBalancerPort())) {
ListenerDescription existingListenerDescription = existingLoadBalancerPortMap.get(elasticLoadBalancingListener.getLoadBalancerPort());
Listener existingListener = existingListenerDescription.getListener();
// Here are the cases we need to consider.
// i) InstancePort, Protocol, LoadBalancerPort, InstanceProtocol have not changed between the existing and new version of the listener.
// a) SSL Certificate has also not changed -- Result: do nothing
// b) SSL Certificate has changed, but it is null -- Result: odd, but perhaps a different protocol. Need to delete/recreate the listener.
// c) SSL Certificate has changed, but it is not null -- Result: call SetLoadBalancerListenerSSLCertificate()
// ii) At least one of InstancePort, Protocol, LoadBalancerPort, InstanceProtocol has changed. We need to delete/recreate the listener.
// If all fields (InstancePort, Protocol, LoadBalancerPort, InstanceProtocol, and SSLCertificateId) are the same, we need to do nothing
boolean needToDeleteAndRecreateListener;
if (Objects.equals(existingListener.getInstancePort(), elasticLoadBalancingListener.getInstancePort()) &&
Objects.equals(existingListener.getProtocol(), elasticLoadBalancingListener.getProtocol()) &&
Objects.equals(existingListener.getLoadBalancerPort(), elasticLoadBalancingListener.getLoadBalancerPort()) &&
Objects.equals(existingListener.getInstanceProtocol(), elasticLoadBalancingListener.getInstanceProtocol())) {
if (Objects.equals(existingListener.getSSLCertificateId(), elasticLoadBalancingListener.getSslCertificateId())) {
// case i a
needToDeleteAndRecreateListener = false;
} else if (elasticLoadBalancingListener.getSslCertificateId() == null) {
// case i b
// can't call SetLoadBalancerListenerSSLCertificateType on a null certificate, replace instead
needToDeleteAndRecreateListener = true;
} else {
// case i c
// just call SetLoadBalancerListenerSSLCertificateType
SetLoadBalancerListenerSSLCertificateType setLoadBalancerListenerSSLCertificateType = MessageHelper.createMessage(SetLoadBalancerListenerSSLCertificateType.class, newAction.info.getEffectiveUserId());
setLoadBalancerListenerSSLCertificateType.setLoadBalancerName(newAction.info.getPhysicalResourceId());
setLoadBalancerListenerSSLCertificateType.setLoadBalancerPort(elasticLoadBalancingListener.getLoadBalancerPort());
setLoadBalancerListenerSSLCertificateType.setSSLCertificateId(elasticLoadBalancingListener.getSslCertificateId());
AsyncRequests.sendSync(configuration, setLoadBalancerListenerSSLCertificateType);
needToDeleteAndRecreateListener = false;
}
} else { // case ii
needToDeleteAndRecreateListener = true;
}
if (needToDeleteAndRecreateListener) {
// delete the listener
DeleteLoadBalancerListenersType deleteLoadBalancerListenersType = MessageHelper.createMessage(DeleteLoadBalancerListenersType.class, oldAction.info.getEffectiveUserId());
deleteLoadBalancerListenersType.setLoadBalancerName(oldAction.info.getPhysicalResourceId());
Ports loadBalancerPorts = new Ports();
loadBalancerPorts.getMember().add(elasticLoadBalancingListener.getLoadBalancerPort().toString());
deleteLoadBalancerListenersType.setLoadBalancerPorts(loadBalancerPorts);
AsyncRequests.sendSync(configuration, deleteLoadBalancerListenersType);
// recreate the listener
CreateLoadBalancerListenersType createLoadBalancerListenersType = MessageHelper.createMessage(CreateLoadBalancerListenersType.class, newAction.info.getEffectiveUserId());
createLoadBalancerListenersType.setLoadBalancerName(newAction.info.getPhysicalResourceId());
Listeners listeners = new Listeners();
Listener listener = new Listener();
listener.setSSLCertificateId(elasticLoadBalancingListener.getSslCertificateId());
listener.setProtocol(elasticLoadBalancingListener.getProtocol());
listener.setLoadBalancerPort(elasticLoadBalancingListener.getLoadBalancerPort());
listener.setInstanceProtocol(elasticLoadBalancingListener.getInstanceProtocol());
listener.setInstancePort(elasticLoadBalancingListener.getInstancePort());
listeners.getMember().add(listener);
createLoadBalancerListenersType.setListeners(listeners);
AsyncRequests.sendSync(configuration, createLoadBalancerListenersType);
// Find the listener and reattach any policies
SetLoadBalancerPoliciesOfListenerType setLoadBalancerPoliciesOfListenerType = MessageHelper.createMessage(SetLoadBalancerPoliciesOfListenerType.class,
newAction.info.getEffectiveUserId());
setLoadBalancerPoliciesOfListenerType.setLoadBalancerName(newAction.info.getPhysicalResourceId());
setLoadBalancerPoliciesOfListenerType.setLoadBalancerPort(elasticLoadBalancingListener.getLoadBalancerPort());
PolicyNames policyNames = new PolicyNames();
if (existingListenerDescription.getPolicyNames() != null && existingListenerDescription.getPolicyNames().getMember() != null) {
policyNames.getMember().addAll(existingListenerDescription.getPolicyNames().getMember());
}
setLoadBalancerPoliciesOfListenerType.setPolicyNames(policyNames);
AsyncRequests.sendSync(configuration, setLoadBalancerPoliciesOfListenerType);
}
}
}
}
}
private static void updateListenersAndPolicies(AWSElasticLoadBalancingLoadBalancerResourceAction oldAction, AWSElasticLoadBalancingLoadBalancerResourceAction newAction, ServiceConfiguration configuration) throws Exception {
// First thing we do is detach all policies from listeners and backend service to make add/deleting easier. We don't remove ALL policies though, just those that were not added by
// someone externally. Hence, we just delete the old and new policies. we also do a new lookup against the load balancer just to make sure we are up to date.
Set<String> oldPolicyNames = getPolicyNames(oldAction);
Set<String> newPolicyNames = getPolicyNames(newAction);
LoadBalancerDescription loadBalancerDescription = getLoadBalancerDescription(newAction, configuration);
Map<Integer, Collection<String>> listenerPolicyMap = Maps.newHashMap();
if (loadBalancerDescription.getListenerDescriptions() != null && loadBalancerDescription.getListenerDescriptions().getMember() != null) {
for (ListenerDescription listenerDescription : loadBalancerDescription.getListenerDescriptions().getMember()) {
Set<String> policyNames = Sets.newHashSet();
if (listenerDescription.getPolicyNames() != null && listenerDescription.getPolicyNames().getMember() != null) {
policyNames.addAll(listenerDescription.getPolicyNames().getMember());
}
// remove the policy names we want to remove (old/new)
policyNames.removeAll(oldPolicyNames);
policyNames.removeAll(newPolicyNames);
listenerPolicyMap.put(listenerDescription.getListener().getLoadBalancerPort(), policyNames);
}
}
Map<Integer, Collection<String>> backendPolicyMap = Maps.newHashMap();
if (loadBalancerDescription.getBackendServerDescriptions() != null && loadBalancerDescription.getBackendServerDescriptions().getMember() != null) {
for (BackendServerDescription backendServerDescription : loadBalancerDescription.getBackendServerDescriptions().getMember()) {
Set<String> policyNames = Sets.newHashSet();
if (backendServerDescription.getPolicyNames() != null && backendServerDescription.getPolicyNames().getMember() != null) {
policyNames.addAll(backendServerDescription.getPolicyNames().getMember());
}
// remove the policy names we want to remove (old/new)
policyNames.removeAll(oldPolicyNames);
policyNames.removeAll(newPolicyNames);
backendPolicyMap.put(backendServerDescription.getInstancePort(), policyNames);
}
}
// now set the values to the 'removed' items
for (Integer loadBalancerPort: listenerPolicyMap.keySet()) {
SetLoadBalancerPoliciesOfListenerType setLoadBalancerPoliciesOfListenerType = MessageHelper.createMessage(SetLoadBalancerPoliciesOfListenerType.class, newAction.info.getEffectiveUserId());
setLoadBalancerPoliciesOfListenerType.setLoadBalancerPort(loadBalancerPort);
PolicyNames policyNames = new PolicyNames();
policyNames.getMember().addAll(listenerPolicyMap.get(loadBalancerPort));
setLoadBalancerPoliciesOfListenerType.setPolicyNames(policyNames);
setLoadBalancerPoliciesOfListenerType.setLoadBalancerName(newAction.info.getPhysicalResourceId());
AsyncRequests.sendSync(configuration, setLoadBalancerPoliciesOfListenerType);
}
for (Integer instancePort: backendPolicyMap.keySet()) {
SetLoadBalancerPoliciesForBackendServerType setLoadBalancerPoliciesForBackendServerType = MessageHelper.createMessage(SetLoadBalancerPoliciesForBackendServerType.class, newAction.info.getEffectiveUserId());
setLoadBalancerPoliciesForBackendServerType.setInstancePort(instancePort);
PolicyNames policyNames = new PolicyNames();
policyNames.getMember().addAll(backendPolicyMap.get(instancePort));
setLoadBalancerPoliciesForBackendServerType.setPolicyNames(policyNames);
setLoadBalancerPoliciesForBackendServerType.setLoadBalancerName(newAction.info.getPhysicalResourceId());
AsyncRequests.sendSync(configuration, setLoadBalancerPoliciesForBackendServerType);
}
updateListeners(oldAction, newAction, configuration);
updatePolicies(oldAction, newAction, configuration);
}
private static LoadBalancerDescription getLoadBalancerDescription(AWSElasticLoadBalancingLoadBalancerResourceAction newAction, ServiceConfiguration configuration) throws Exception {
DescribeLoadBalancersType describeLoadBalancersType = MessageHelper.createMessage(DescribeLoadBalancersType.class, newAction.info.getEffectiveUserId());
LoadBalancerNames loadBalancerNames = new LoadBalancerNames();
loadBalancerNames.getMember().add(newAction.info.getPhysicalResourceId());
describeLoadBalancersType.setLoadBalancerNames(loadBalancerNames);
DescribeLoadBalancersResponseType describeLoadBalancersResponseType = AsyncRequests.<DescribeLoadBalancersType,DescribeLoadBalancersResponseType> sendSync(configuration, describeLoadBalancersType);
if (describeLoadBalancersResponseType == null || describeLoadBalancersResponseType.getDescribeLoadBalancersResult() == null
|| describeLoadBalancersResponseType.getDescribeLoadBalancersResult().getLoadBalancerDescriptions() == null ||
describeLoadBalancersResponseType.getDescribeLoadBalancersResult().getLoadBalancerDescriptions().getMember() == null ||
describeLoadBalancersResponseType.getDescribeLoadBalancersResult().getLoadBalancerDescriptions().getMember().isEmpty()) {
throw new ValidationErrorException("Can't find load balancer" + newAction.info.getPhysicalResourceId());
}
return describeLoadBalancersResponseType.getDescribeLoadBalancersResult().getLoadBalancerDescriptions().getMember().get(0);
}
private static void updatePolicies(AWSElasticLoadBalancingLoadBalancerResourceAction oldAction, AWSElasticLoadBalancingLoadBalancerResourceAction newAction, ServiceConfiguration configuration) throws Exception {
// We do policies similar to how we do listeners. We delete old policies, then check for new policies, then "update" existing policies.
// For policies to be deleted, they first need to be removed from any listeners or backend servers, then removed.
// We keep a cache of policy states that we "write through" to allow for policies to be deleted and added. But to simplify that portion,
// we remove all old policies from the listeners (and backend) at the beginning, then reattach everything at the end.
LoadBalancerDescription loadBalancerDescription = getLoadBalancerDescription(newAction, configuration);
Set<String> existingPolicyNames = getPolicyNames(loadBalancerDescription);
Map<String, PolicyDescription> existingPolicyDescriptionMap = getPolicyDescriptionMap(newAction, configuration, existingPolicyNames);
Set<String> oldPolicyNames = getPolicyNames(oldAction);
Set<String> newPolicyNames = getPolicyNames(newAction);
// First add all new policies, but also make sure the policy state maps are 'up to date'
if (newAction.properties.getAppCookieStickinessPolicy() != null) {
for (ElasticLoadBalancingAppCookieStickinessPolicy policy : newAction.properties.getAppCookieStickinessPolicy()) {
if (!existingPolicyNames.contains(policy.getPolicyName())) {
createAppCookieStickinessPolicy(newAction, configuration, policy);
}
}
}
if (newAction.properties.getLbCookieStickinessPolicy() != null) {
for (ElasticLoadBalancingLBCookieStickinessPolicyType policy : newAction.properties.getLbCookieStickinessPolicy()) {
if (!existingPolicyNames.contains(policy.getPolicyName())) {
createLBCookieStickinessPolicy(newAction, configuration, policy);
}
}
}
if (newAction.properties.getPolicies() != null) {
for (ElasticLoadBalancingPolicyType policy : newAction.properties.getPolicies()) {
if (!existingPolicyNames.contains(policy.getPolicyName())) {
createLoadBalancerPolicy(newAction, configuration, policy);
}
}
}
// Now delete all old policies (but only ones that were in the original template, just in case the system added policies
for (String policyName: oldPolicyNames) {
if (existingPolicyNames.contains(policyName) && !newPolicyNames.contains(policyName)) {
deletePolicy(newAction, configuration, policyName);
}
}
// Check whether policy needs to be 'updated' What does this mean? Fields have changed.
// 1) For a new AppStickinessPolicy, we don't change anything if we have an existing AppStickinessPolicy with the
// same name and cookie name. If the cookie name is different or the existing policy type is something else,
// we need to replace the policy.
// 2) For a new LbStickinessPolicy, we don't change anything if we have an existing LbStickinessPolicy
// with the same name and cookie expioration period. If the cookie expiration period is different or
// the existing policy is a different type, we need to replace the policy.
// 3) For a general policy, we don't change anything if the policy has the same type and attribute name/values,
// otherwise we need to replace the policy.
// Finally, to simplify life, we will delete/recreate policies in place,
if (newAction.properties.getAppCookieStickinessPolicy() != null) {
for (ElasticLoadBalancingAppCookieStickinessPolicy policy: newAction.properties.getAppCookieStickinessPolicy()) {
if (existingPolicyNames.contains(policy.getPolicyName())) {
// we know a policy exists. See if it is an app cookie stickiness policy
boolean needsUpdate = true;
if (loadBalancerDescription.getPolicies() != null && loadBalancerDescription.getPolicies().getAppCookieStickinessPolicies() != null
&& loadBalancerDescription.getPolicies().getAppCookieStickinessPolicies().getMember() != null) {
for (AppCookieStickinessPolicy appCookieStickinessPolicy: loadBalancerDescription.getPolicies().getAppCookieStickinessPolicies().getMember()) {
if (appCookieStickinessPolicy.getPolicyName().equals(policy.getPolicyName()) && Objects.equals(appCookieStickinessPolicy.getCookieName(), policy.getCookieName())) {
needsUpdate = false;
break;
}
}
}
if (needsUpdate) { // delete and recreate...
deletePolicy(newAction, configuration, policy.getPolicyName());
createAppCookieStickinessPolicy(newAction, configuration, policy);
}
}
}
}
if (newAction.properties.getLbCookieStickinessPolicy() != null) {
for (ElasticLoadBalancingLBCookieStickinessPolicyType policy: newAction.properties.getLbCookieStickinessPolicy()) {
if (existingPolicyNames.contains(policy.getPolicyName())) {
// we know a policy exists. See if it is an lb cookie stickiness policy
boolean needsUpdate = true;
if (loadBalancerDescription.getPolicies() != null && loadBalancerDescription.getPolicies().getLbCookieStickinessPolicies() != null
&& loadBalancerDescription.getPolicies().getLbCookieStickinessPolicies().getMember() != null) {
for (LBCookieStickinessPolicy lbCookieStickinessPolicy: loadBalancerDescription.getPolicies().getLbCookieStickinessPolicies().getMember()) {
if (lbCookieStickinessPolicy.getPolicyName().equals(policy.getPolicyName()) && Objects.equals(lbCookieStickinessPolicy.getCookieExpirationPeriod(), policy.getCookieExpirationPeriod())) {
needsUpdate = false;
break;
}
}
}
if (needsUpdate) { // delete and recreate...
deletePolicy(newAction, configuration, policy.getPolicyName());
createLBCookieStickinessPolicy(newAction, configuration, policy);
}
}
}
}
if (newAction.properties.getPolicies() != null) {
for (ElasticLoadBalancingPolicyType policy : newAction.properties.getPolicies()) {
if (existingPolicyNames.contains(policy.getPolicyName())) {
PolicyDescription existingPolicyDescription = existingPolicyDescriptionMap.get(policy.getPolicyName());
boolean needsUpdate = false;
if (!Objects.equals(existingPolicyDescription.getPolicyTypeName(), policy.getPolicyType())) {
needsUpdate = true;
} else {
// We want to make sure attribute are 'the same'. This poses a bit of a challenge. The system may add some attributes.
// But we can't just make sure the new attributes are a subset of the existing attributes, in case we just removed some old attributes.
// So we need to check that old and new match, and that the existing contain both. Otherwise replace,
// and with 'old' we also need to get the attributes depending on type
Map<String, String> oldAttributes = Maps.newHashMap();
if (oldAction.properties.getAppCookieStickinessPolicy() != null) {
for (ElasticLoadBalancingAppCookieStickinessPolicy oldPolicy : oldAction.properties.getAppCookieStickinessPolicy()) {
if (oldPolicy.getPolicyName().equals(policy.getPolicyName())) {
oldAttributes.put("CookieName", oldPolicy.getCookieName());
break;
}
}
}
if (oldAction.properties.getLbCookieStickinessPolicy() != null) {
for (ElasticLoadBalancingLBCookieStickinessPolicyType oldPolicy : oldAction.properties.getLbCookieStickinessPolicy()) {
if (oldPolicy.getPolicyName().equals(policy.getPolicyName())) {
oldAttributes.put("CookieExpirationPeriod", String.valueOf(oldPolicy.getCookieExpirationPeriod()));
break;
}
}
}
if (oldAction.properties.getPolicies() != null) {
for (ElasticLoadBalancingPolicyType oldPolicy : oldAction.properties.getPolicies()) {
if (oldPolicy.getPolicyName().equals(policy.getPolicyName())) {
for (ElasticLoadBalancingPolicyTypeAttribute attribute : oldPolicy.getAttributes()) {
oldAttributes.put(oldAttributes.get(attribute.getName()), attribute.getValue());
}
break;
}
}
}
Map<String, String> existingAttributes = Maps.newHashMap();
if (existingPolicyDescription.getPolicyAttributeDescriptions() != null && existingPolicyDescription.getPolicyAttributeDescriptions().getMember() != null) {
for (PolicyAttributeDescription policyAttributeDescription : existingPolicyDescription.getPolicyAttributeDescriptions().getMember()) {
existingAttributes.put(policyAttributeDescription.getAttributeName(), policyAttributeDescription.getAttributeValue());
}
}
Map<String, String> newAttributes = Maps.newHashMap();
if (policy.getAttributes() != null) {
for (ElasticLoadBalancingPolicyTypeAttribute attribute : policy.getAttributes()) {
newAttributes.put(newAttributes.get(attribute.getName()), attribute.getValue());
}
}
if (!Objects.equals(oldAttributes, newAttributes)) {
needsUpdate = true;
} else {
for (String attributeName : oldAttributes.keySet()) {
if (!existingAttributes.containsKey(attributeName) || !Objects.equals(oldAttributes.get(attributeName), existingAttributes.get(attributeName))) {
needsUpdate = true;
break;
}
}
for (String attributeName : newAttributes.keySet()) {
if (!existingAttributes.containsKey(attributeName) || !Objects.equals(newAttributes.get(attributeName), existingAttributes.get(attributeName))) {
needsUpdate = true;
break;
}
}
}
}
if (needsUpdate) { // delete and recreate...
deletePolicy(newAction, configuration, policy.getPolicyName());
createLoadBalancerPolicy(newAction, configuration, policy);
}
}
}
}
// Finally attach policies to listeners and backend servers
Map<Integer, Collection<String>> newListenerPolicyMap = Maps.newHashMap();
Map<Integer, Collection<String>> newBackendPolicyMap = Maps.newHashMap();
if (newAction.properties.getListeners() != null) {
for (ElasticLoadBalancingListener elasticLoadBalancingListener : newAction.properties.getListeners()) {
newListenerPolicyMap.put(elasticLoadBalancingListener.getLoadBalancerPort(), Sets.<String>newHashSet());
if (elasticLoadBalancingListener.getPolicyNames() != null) {
newListenerPolicyMap.get(elasticLoadBalancingListener.getLoadBalancerPort()).addAll(elasticLoadBalancingListener.getPolicyNames());
}
}
}
if (newAction.properties.getPolicies() != null) {
for (ElasticLoadBalancingPolicyType policyType : newAction.properties.getPolicies()) {
if (policyType.getLoadBalancerPorts() != null) {
for (Integer loadBalancerPort : policyType.getLoadBalancerPorts()) {
if (!newListenerPolicyMap.containsKey(loadBalancerPort)) {
throw new ValidationErrorException("Policy " + policyType.getPolicyName() + " has a load balancer port of " + loadBalancerPort + ", which has no listener defined");
} else {
newListenerPolicyMap.get(loadBalancerPort).add(policyType.getPolicyName());
}
}
}
if (policyType.getInstancePorts() != null) {
for (Integer instancePort : policyType.getInstancePorts()) {
if (!newBackendPolicyMap.containsKey(instancePort)) {
newBackendPolicyMap.put(instancePort, Sets.<String>newHashSet());
}
newBackendPolicyMap.get(instancePort).add(policyType.getPolicyName());
}
}
}
}
if (loadBalancerDescription.getListenerDescriptions() != null && loadBalancerDescription.getListenerDescriptions().getMember() != null) {
for (ListenerDescription listenerDescription: loadBalancerDescription.getListenerDescriptions().getMember()) {
Set<String> policyNamesSet = Sets.newHashSet();
if (listenerDescription.getPolicyNames() != null && listenerDescription.getPolicyNames().getMember() != null) {
policyNamesSet.addAll(listenerDescription.getPolicyNames().getMember());
}
if (newListenerPolicyMap.containsKey(listenerDescription.getListener().getLoadBalancerPort())) {
policyNamesSet.addAll(newListenerPolicyMap.get(listenerDescription.getListener().getLoadBalancerPort()));
}
SetLoadBalancerPoliciesOfListenerType setLoadBalancerPoliciesOfListenerType = MessageHelper.createMessage(SetLoadBalancerPoliciesOfListenerType.class, newAction.info.getEffectiveUserId());
setLoadBalancerPoliciesOfListenerType.setLoadBalancerPort(listenerDescription.getListener().getLoadBalancerPort());
PolicyNames policyNames = new PolicyNames();
policyNames.getMember().addAll(policyNamesSet);
setLoadBalancerPoliciesOfListenerType.setPolicyNames(policyNames);
setLoadBalancerPoliciesOfListenerType.setLoadBalancerName(newAction.info.getPhysicalResourceId());
AsyncRequests.sendSync(configuration, setLoadBalancerPoliciesOfListenerType);
}
}
if (loadBalancerDescription.getBackendServerDescriptions() != null && loadBalancerDescription.getBackendServerDescriptions().getMember() != null) {
for (BackendServerDescription backendServerDescription: loadBalancerDescription.getBackendServerDescriptions().getMember()) {
Set<String> policyNamesSet = Sets.newHashSet();
if (backendServerDescription.getPolicyNames() != null && backendServerDescription.getPolicyNames().getMember() != null) {
policyNamesSet.addAll(backendServerDescription.getPolicyNames().getMember());
}
if (newBackendPolicyMap.containsKey(backendServerDescription.getInstancePort())) {
policyNamesSet.addAll(newBackendPolicyMap.get(backendServerDescription.getInstancePort()));
}
SetLoadBalancerPoliciesForBackendServerType setLoadBalancerPoliciesForBackendServerType = MessageHelper.createMessage(SetLoadBalancerPoliciesForBackendServerType.class, newAction.info.getEffectiveUserId());
setLoadBalancerPoliciesForBackendServerType.setInstancePort(backendServerDescription.getInstancePort());
PolicyNames policyNames = new PolicyNames();
policyNames.getMember().addAll(policyNamesSet);
setLoadBalancerPoliciesForBackendServerType.setPolicyNames(policyNames);
setLoadBalancerPoliciesForBackendServerType.setLoadBalancerName(newAction.info.getPhysicalResourceId());
AsyncRequests.sendSync(configuration, setLoadBalancerPoliciesForBackendServerType);
}
}
}
private static void deletePolicy(AWSElasticLoadBalancingLoadBalancerResourceAction action, ServiceConfiguration configuration, String policyName) throws Exception {
DeleteLoadBalancerPolicyType deleteLoadBalancerPolicyType = MessageHelper.createMessage(DeleteLoadBalancerPolicyType.class, action.info.getEffectiveUserId());
deleteLoadBalancerPolicyType.setPolicyName(policyName);
deleteLoadBalancerPolicyType.setLoadBalancerName(action.info.getPhysicalResourceId());
AsyncRequests.sendSync(configuration, deleteLoadBalancerPolicyType);
}
private static Map<String, PolicyDescription> getPolicyDescriptionMap(AWSElasticLoadBalancingLoadBalancerResourceAction action, ServiceConfiguration configuration, Set<String> policyNames) throws Exception {
Map<String, PolicyDescription> policyDescriptionMap = Maps.newHashMap();
DescribeLoadBalancerPoliciesType describeLoadBalancerPoliciesType = MessageHelper.createMessage(DescribeLoadBalancerPoliciesType.class, action.info.getEffectiveUserId());
describeLoadBalancerPoliciesType.setLoadBalancerName(action.info.getPhysicalResourceId());
PolicyNames policyNamesObj = new PolicyNames();
policyNamesObj.getMember().addAll(policyNames);
describeLoadBalancerPoliciesType.setPolicyNames(policyNamesObj);
DescribeLoadBalancerPoliciesResponseType describeLoadBalancerPoliciesResponseType = AsyncRequests.sendSync(configuration, describeLoadBalancerPoliciesType);
if (describeLoadBalancerPoliciesResponseType !=null && describeLoadBalancerPoliciesResponseType.getDescribeLoadBalancerPoliciesResult() != null
&& describeLoadBalancerPoliciesResponseType.getDescribeLoadBalancerPoliciesResult().getPolicyDescriptions() != null &&
describeLoadBalancerPoliciesResponseType.getDescribeLoadBalancerPoliciesResult().getPolicyDescriptions().getMember() != null) {
for (PolicyDescription policyDescription : describeLoadBalancerPoliciesResponseType.getDescribeLoadBalancerPoliciesResult().getPolicyDescriptions().getMember()) {
policyDescriptionMap.put(policyDescription.getPolicyName(), policyDescription);
}
}
return policyDescriptionMap;
}
private static Set<String> getPolicyNames(AWSElasticLoadBalancingLoadBalancerResourceAction action) {
Set<String> policyNames = Sets.newHashSet();
if (action.properties.getAppCookieStickinessPolicy() != null) {
for (ElasticLoadBalancingPolicyType policy: action.properties.getPolicies()) {
policyNames.add(policy.getPolicyName());
}
for (ElasticLoadBalancingAppCookieStickinessPolicy policy: action.properties.getAppCookieStickinessPolicy()) {
policyNames.add(policy.getPolicyName());
}
for (ElasticLoadBalancingLBCookieStickinessPolicyType policy: action.properties.getLbCookieStickinessPolicy()) {
policyNames.add(policy.getPolicyName());
}
}
return policyNames;
}
private static Set<String> getPolicyNames(LoadBalancerDescription loadBalancerDescription) {
Set<String> policyNames = Sets.newHashSet();
if (loadBalancerDescription.getPolicies() != null) {
if (loadBalancerDescription.getPolicies().getAppCookieStickinessPolicies() != null && loadBalancerDescription.getPolicies().getAppCookieStickinessPolicies().getMember() != null) {
for (AppCookieStickinessPolicy policy: loadBalancerDescription.getPolicies().getAppCookieStickinessPolicies().getMember()) {
policyNames.add(policy.getPolicyName());
}
}
if (loadBalancerDescription.getPolicies().getLbCookieStickinessPolicies() != null && loadBalancerDescription.getPolicies().getLbCookieStickinessPolicies().getMember() != null) {
for (LBCookieStickinessPolicy policy: loadBalancerDescription.getPolicies().getLbCookieStickinessPolicies().getMember()) {
policyNames.add(policy.getPolicyName());
}
}
if (loadBalancerDescription.getPolicies().getOtherPolicies() != null) {
addAllIfNotNull(policyNames, loadBalancerDescription.getPolicies().getOtherPolicies().getMember());
}
}
return policyNames;
}
private static <T> Collection<T> addAllIfNotNull(Collection<T> originalCollection, Collection<T> itemsToAdd) {
if (itemsToAdd != null) {
originalCollection.addAll(itemsToAdd);
}
return originalCollection;
}
}