
com.vmware.photon.controller.model.adapters.awsadapter.AWSLoadBalancerService Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 2015-2017 VMware, Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, without warranties or
* conditions of any kind, EITHER EXPRESS OR IMPLIED. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.vmware.photon.controller.model.adapters.awsadapter;
import static com.vmware.photon.controller.model.adapters.awsadapter.util.AWSClientManagerFactory.returnClientManager;
import static com.vmware.photon.controller.model.resources.SecurityGroupService.FACTORY_LINK;
import static com.vmware.photon.controller.model.tasks.ProvisionSecurityGroupTaskService.NETWORK_STATE_ID_PROP_NAME;
import static com.vmware.photon.controller.model.util.PhotonModelUriUtils.createInventoryUri;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;
import com.amazonaws.services.elasticloadbalancing.AmazonElasticLoadBalancingAsyncClient;
import com.amazonaws.services.elasticloadbalancing.model.ConfigureHealthCheckRequest;
import com.amazonaws.services.elasticloadbalancing.model.ConfigureHealthCheckResult;
import com.amazonaws.services.elasticloadbalancing.model.CreateLoadBalancerRequest;
import com.amazonaws.services.elasticloadbalancing.model.CreateLoadBalancerResult;
import com.amazonaws.services.elasticloadbalancing.model.DeleteLoadBalancerRequest;
import com.amazonaws.services.elasticloadbalancing.model.DeleteLoadBalancerResult;
import com.amazonaws.services.elasticloadbalancing.model.DeregisterInstancesFromLoadBalancerRequest;
import com.amazonaws.services.elasticloadbalancing.model.DeregisterInstancesFromLoadBalancerResult;
import com.amazonaws.services.elasticloadbalancing.model.DescribeLoadBalancersRequest;
import com.amazonaws.services.elasticloadbalancing.model.DescribeLoadBalancersResult;
import com.amazonaws.services.elasticloadbalancing.model.HealthCheck;
import com.amazonaws.services.elasticloadbalancing.model.Instance;
import com.amazonaws.services.elasticloadbalancing.model.Listener;
import com.amazonaws.services.elasticloadbalancing.model.RegisterInstancesWithLoadBalancerRequest;
import com.amazonaws.services.elasticloadbalancing.model.RegisterInstancesWithLoadBalancerResult;
import com.vmware.photon.controller.model.ComputeProperties;
import com.vmware.photon.controller.model.adapterapi.LoadBalancerInstanceRequest;
import com.vmware.photon.controller.model.adapterapi.SecurityGroupInstanceRequest;
import com.vmware.photon.controller.model.adapterapi.SecurityGroupInstanceRequest.InstanceRequestType;
import com.vmware.photon.controller.model.adapters.awsadapter.util.AWSClientManager;
import com.vmware.photon.controller.model.adapters.awsadapter.util.AWSClientManagerFactory;
import com.vmware.photon.controller.model.adapters.awsadapter.util.AWSDeferredResultAsyncHandler;
import com.vmware.photon.controller.model.adapters.util.TaskManager;
import com.vmware.photon.controller.model.resources.LoadBalancerDescriptionService.LoadBalancerDescription;
import com.vmware.photon.controller.model.resources.LoadBalancerDescriptionService.LoadBalancerDescription.HealthCheckConfiguration;
import com.vmware.photon.controller.model.resources.LoadBalancerService.LoadBalancerState;
import com.vmware.photon.controller.model.resources.LoadBalancerService.LoadBalancerStateExpanded;
import com.vmware.photon.controller.model.resources.NetworkService.NetworkState;
import com.vmware.photon.controller.model.resources.ResourceState;
import com.vmware.photon.controller.model.resources.SecurityGroupService.Protocol;
import com.vmware.photon.controller.model.resources.SecurityGroupService.SecurityGroupState;
import com.vmware.photon.controller.model.resources.SecurityGroupService.SecurityGroupState.Rule;
import com.vmware.photon.controller.model.resources.SubnetService.SubnetState;
import com.vmware.photon.controller.model.util.ClusterUtil;
import com.vmware.photon.controller.model.util.ClusterUtil.ServiceTypeCluster;
import com.vmware.xenon.common.DeferredResult;
import com.vmware.xenon.common.Operation;
import com.vmware.xenon.common.StatelessService;
import com.vmware.xenon.common.UriUtils;
import com.vmware.xenon.services.common.AuthCredentialsService.AuthCredentialsServiceState;
/**
* Adapter for provisioning a load balancer on AWS.
*/
public class AWSLoadBalancerService extends StatelessService {
public static final String SELF_LINK = AWSUriPaths.AWS_LOAD_BALANCER_ADAPTER;
private static final int MAX_NAME_LENGTH = 32;
/**
* Load balancer request context.
*/
private static class AWSLoadBalancerContext {
final LoadBalancerInstanceRequest request;
LoadBalancerStateExpanded loadBalancerStateExpanded;
AuthCredentialsServiceState credentials;
// Instances registered with the AWS load balancer
List registeredInstances;
// Instances to be registered in the load balancer based on the instances that are defined
// in the LB state and are missing from the AWS load balancer
List instanceIdsToRegister;
// Instances to be deregistered from the load balancer based on the instances that are defined
// in the AWS load balancer and are missing from the LB state
List instanceIdsToDeregister;
AmazonElasticLoadBalancingAsyncClient client;
TaskManager taskManager;
List securityGroupStates;
String vpcId;
SecurityGroupState provisionedSecurityGroupState;
AWSLoadBalancerContext(StatelessService service, LoadBalancerInstanceRequest request) {
this.request = request;
this.taskManager = new TaskManager(service, request.taskReference,
request.resourceLink());
}
}
private AWSClientManager clientManager;
/**
* Extend default 'start' logic with loading AWS client.
*/
@Override
public void handleStart(Operation op) {
this.clientManager = AWSClientManagerFactory
.getClientManager(AWSConstants.AwsClientType.LOAD_BALANCING);
super.handleStart(op);
}
/**
* Extend default 'stop' logic with releasing AWS client.
*/
@Override
public void handleStop(Operation op) {
returnClientManager(this.clientManager, AWSConstants.AwsClientType.LOAD_BALANCING);
super.handleStop(op);
}
@Override
public void handlePatch(Operation op) {
if (!op.hasBody()) {
op.fail(new IllegalArgumentException("body is required"));
return;
}
// Immediately complete the Operation from calling task.
op.complete();
// initialize context object
AWSLoadBalancerContext context = new AWSLoadBalancerContext(this,
op.getBody(LoadBalancerInstanceRequest.class));
DeferredResult.completed(context)
.thenCompose(this::populateContext)
.thenCompose(this::stripDownInvalidCharactersFromLoadBalancerName)
.thenCompose(this::handleInstanceRequest)
.whenComplete((o, e) -> {
// Once done patch the calling task with correct stage.
if (e == null) {
context.taskManager.finishTask();
} else {
context.taskManager.patchTaskToFailure(e);
}
});
}
private DeferredResult populateContext(AWSLoadBalancerContext context) {
return DeferredResult.completed(context)
.thenCompose(this::getLoadBalancerState)
.thenCompose(this::getCredentials)
.thenCompose(this::getAWSClient)
.thenCompose(this::getSecurityGroupState);
}
private DeferredResult getLoadBalancerState(
AWSLoadBalancerContext context) {
return this
.sendWithDeferredResult(
Operation.createGet(LoadBalancerStateExpanded.buildUri(
context.request.resourceReference)),
LoadBalancerStateExpanded.class)
.thenApply(lbStateExpanded -> {
if (lbStateExpanded.computes == null) {
lbStateExpanded.computes = Collections.emptySet();
}
return lbStateExpanded;
}).thenApply(state -> {
context.loadBalancerStateExpanded = state;
return context;
});
}
private DeferredResult getCredentials(AWSLoadBalancerContext context) {
URI uri = createInventoryUri(this.getHost(),
context.loadBalancerStateExpanded.endpointState.authCredentialsLink);
return this.sendWithDeferredResult(
Operation.createGet(uri), AuthCredentialsServiceState.class)
.thenApply(authCredentialsServiceState -> {
context.credentials = authCredentialsServiceState;
return context;
});
}
private DeferredResult getAWSClient(AWSLoadBalancerContext context) {
if (context.request.isMockRequest) {
return DeferredResult.completed(context);
}
DeferredResult r = new DeferredResult<>();
this.clientManager.getOrCreateLoadBalancingClientAsync(context.credentials,
context.loadBalancerStateExpanded.regionId, this, context.request.isMockRequest)
.whenComplete((client, t) -> {
if (t != null) {
r.fail(t);
return;
}
context.client = client;
r.complete(context);
});
return r;
}
private DeferredResult getSecurityGroupState(
AWSLoadBalancerContext context) {
if (context.loadBalancerStateExpanded.securityGroupLinks == null ||
context.loadBalancerStateExpanded.securityGroupLinks.isEmpty()) {
context.securityGroupStates = Collections.emptyList();
return DeferredResult.completed(context);
}
List> securityGroupDRs =
context.loadBalancerStateExpanded.securityGroupLinks.stream()
.map(context.request::buildUri)
.map(uri -> sendWithDeferredResult(Operation.createGet(uri),
SecurityGroupState.class))
.collect(Collectors.toList());
return DeferredResult.allOf(securityGroupDRs)
.thenApply(securityGroupStates -> {
context.securityGroupStates = securityGroupStates;
return context;
});
}
private DeferredResult handleInstanceRequest(
AWSLoadBalancerContext context) {
DeferredResult execution = DeferredResult.completed(context);
switch (context.request.requestType) {
case CREATE:
if (context.request.isMockRequest) {
// no need to go the end-point; just populate an dummy LB address
context.loadBalancerStateExpanded.address = "lb-mock-address.com";
execution = execution
.thenCompose(this::updateLoadBalancerState);
} else {
execution = execution
.thenCompose(this::createSecurityGroup)
.thenCompose(this::createLoadBalancer)
.thenCompose(this::configureHealthCheck)
.thenCompose(this::updateLoadBalancerState)
.thenCompose(this::assignInstances);
}
return execution;
case UPDATE:
if (context.request.isMockRequest) {
this.logFine("Mock request to update an AWS load balancer ["
+ context.loadBalancerStateExpanded.name + "] processed.");
} else {
execution = execution.thenCompose(this::getAWSLoadBalancer)
.thenCompose(this::assignInstances);
}
return execution;
case DELETE:
if (context.request.isMockRequest) {
// no need to go to the end-point
this.logFine("Mock request to delete an AWS load balancer ["
+ context.loadBalancerStateExpanded.name + "] processed.");
} else {
execution = execution
.thenCompose(this::deleteLoadBalancer)
.thenCompose(this::deleteSecurityGroup);
}
return execution.thenCompose(this::deleteLoadBalancerState);
default:
IllegalStateException ex = new IllegalStateException("Unsupported request type");
return DeferredResult.failed(ex);
}
}
/**
* Strips the name of invalid characters. In AWS Load Balancer name should contain only
* characters or digits or dash, and do not end in dash. If name ends in dash after truncating,
* keep removing trailing dashes
*/
private DeferredResult stripDownInvalidCharactersFromLoadBalancerName(
AWSLoadBalancerContext context) {
// strip down invalid characters
context.loadBalancerStateExpanded.name = context.loadBalancerStateExpanded.name.replaceAll
("[^a-zA-Z0-9-]","");
// truncate if needed
if (context.loadBalancerStateExpanded.name.length() > MAX_NAME_LENGTH) {
context.loadBalancerStateExpanded.name = context.loadBalancerStateExpanded.name
.substring(0, MAX_NAME_LENGTH);
// remove trailing dashes after truncate (not accepted by AWS)
while (context.loadBalancerStateExpanded.name.endsWith("-")) {
context.loadBalancerStateExpanded.name = context.loadBalancerStateExpanded.name
.substring(0, context.loadBalancerStateExpanded.name.length() - 1);
}
}
return DeferredResult.completed(context);
}
private DeferredResult createSecurityGroup(
AWSLoadBalancerContext context) {
return DeferredResult.completed(context)
.thenCompose(this::populateVpcIdFromSubnet)
.thenCompose(this::createSecurityGroupState)
.thenCompose(this::provisionSecurityGroup);
}
private DeferredResult populateVpcIdFromSubnet(
AWSLoadBalancerContext context) {
SubnetState subnetState = context.loadBalancerStateExpanded.subnets.stream().findFirst()
.orElse(null);
if (subnetState == null) {
return DeferredResult.completed(context);
}
Operation get = Operation.createGet(UriUtils.buildUri(getHost(), subnetState.networkLink));
return this.sendWithDeferredResult(get, NetworkState.class)
.thenApply(networkState -> {
context.vpcId = networkState.id;
return context;
});
}
private DeferredResult createSecurityGroupState(
AWSLoadBalancerContext context) {
SecurityGroupState state = new SecurityGroupState();
state.authCredentialsLink = context.credentials.documentSelfLink;
state.endpointLink = context.loadBalancerStateExpanded.endpointLink;
if (state.endpointLinks == null) {
state.endpointLinks = new HashSet<>();
}
state.endpointLinks.add(context.loadBalancerStateExpanded.endpointLink);
state.instanceAdapterReference = UriUtils.buildUri(getHost(), AWSSecurityGroupService
.SELF_LINK);
state.resourcePoolLink = context.loadBalancerStateExpanded.endpointState.resourcePoolLink;
state.customProperties = new HashMap<>(2);
state.customProperties.put(ComputeProperties.INFRASTRUCTURE_USE_PROP_NAME,
Boolean.TRUE.toString());
state.customProperties.put(AWSConstants.AWS_LOAD_BALANCER_SECURITY_GROUP,
Boolean.TRUE.toString());
state.tenantLinks = context.loadBalancerStateExpanded.tenantLinks;
state.regionId = context.loadBalancerStateExpanded.regionId;
state.name = context.loadBalancerStateExpanded.name + "_SG";
state.ingress = context.loadBalancerStateExpanded.routes.stream()
.map(routeConfiguration -> buildRule(routeConfiguration.port))
.collect(Collectors.toList());
state.egress = context.loadBalancerStateExpanded.routes.stream()
.map(routeConfiguration -> buildRule(routeConfiguration.instancePort))
.collect(Collectors.toList());
state.computeHostLink = context.loadBalancerStateExpanded.computeHostLink;
Operation operation = Operation.createPost(this, FACTORY_LINK).setBody(state);
return this.sendWithDeferredResult(operation, SecurityGroupState.class)
.thenApply(securityGroupState -> {
context.provisionedSecurityGroupState = securityGroupState;
return context;
});
}
private Rule buildRule(String port) {
Rule rule = new Rule();
//TODO determine the ip range cidr
rule.ipRangeCidr = "0.0.0.0/0";
rule.ports = port;
rule.name = port + "_rule";
rule.protocol = Protocol.TCP.getName();
return rule;
}
private SecurityGroupInstanceRequest buildSecurityGroupInstanceRequest(SecurityGroupState
securityGroupState, InstanceRequestType type,
AWSLoadBalancerContext context) {
SecurityGroupInstanceRequest req = new SecurityGroupInstanceRequest();
req.requestType = type;
req.resourceReference = UriUtils.extendUri(ClusterUtil.getClusterUri(getHost(),
ServiceTypeCluster.INVENTORY_SERVICE),
securityGroupState.documentSelfLink);
req.authCredentialsLink = securityGroupState.authCredentialsLink;
req.resourcePoolLink = securityGroupState.resourcePoolLink;
req.isMockRequest = context.request.isMockRequest;
req.customProperties = new HashMap<>();
req.customProperties.put(NETWORK_STATE_ID_PROP_NAME, context.vpcId);
return req;
}
private DeferredResult provisionSecurityGroup(
AWSLoadBalancerContext context) {
SecurityGroupInstanceRequest req = buildSecurityGroupInstanceRequest(
context.provisionedSecurityGroupState,
InstanceRequestType.CREATE, context);
Operation operation = Operation.createPatch(this,
AWSSecurityGroupService.SELF_LINK)
.setBody(req);
return sendWithDeferredResult(operation, SecurityGroupState.class)
.thenApply(sgs -> {
context.provisionedSecurityGroupState = sgs;
return context;
});
}
private DeferredResult createLoadBalancer(
AWSLoadBalancerContext context) {
CreateLoadBalancerRequest request = buildCreationRequest(context);
String message = "Create a new AWS Load Balancer with name ["
+ context.loadBalancerStateExpanded.name + "].";
AWSDeferredResultAsyncHandler handler =
new AWSDeferredResultAsyncHandler<>(this, message);
context.client.createLoadBalancerAsync(request, handler);
return handler.toDeferredResult().thenApply(result -> {
context.loadBalancerStateExpanded.address = result.getDNSName();
return context;
});
}
private DeferredResult configureHealthCheck(
AWSLoadBalancerContext context) {
ConfigureHealthCheckRequest request = buildHealthCheckRequest(context);
if (request == null) {
return DeferredResult.completed(context);
}
String message = "Configure a health check to AWS Load Balancer with name ["
+ context.loadBalancerStateExpanded.name + "].";
AWSDeferredResultAsyncHandler handler =
new AWSDeferredResultAsyncHandler<>(this, message);
context.client.configureHealthCheckAsync(request, handler);
return handler.toDeferredResult().thenApply(ignore -> context);
}
private ConfigureHealthCheckRequest buildHealthCheckRequest(AWSLoadBalancerContext context) {
HealthCheckConfiguration healthCheckConfiguration = context.loadBalancerStateExpanded.routes
.stream()
.filter(config -> config != null && config.healthCheckConfiguration != null)
.map(config -> config.healthCheckConfiguration).findFirst().orElse(null);
if (healthCheckConfiguration == null) {
return null;
}
// Construct the target HTTP:80/index.html
String target = healthCheckConfiguration.protocol + ":" + healthCheckConfiguration.port
+ healthCheckConfiguration.urlPath;
HealthCheck healthCheck = new HealthCheck()
.withHealthyThreshold(healthCheckConfiguration.healthyThreshold)
.withInterval(healthCheckConfiguration.intervalSeconds).withTarget(target)
.withTimeout(healthCheckConfiguration.timeoutSeconds)
.withUnhealthyThreshold(healthCheckConfiguration.unhealthyThreshold);
return new ConfigureHealthCheckRequest()
.withLoadBalancerName(context.loadBalancerStateExpanded.name)
.withHealthCheck(healthCheck);
}
private DeferredResult updateLoadBalancerState(
AWSLoadBalancerContext context) {
LoadBalancerState loadBalancerState = new LoadBalancerState();
loadBalancerState.address = context.loadBalancerStateExpanded.address;
loadBalancerState.name = context.loadBalancerStateExpanded.name;
if (context.provisionedSecurityGroupState != null) {
loadBalancerState.securityGroupLinks = Collections
.singletonList(context.provisionedSecurityGroupState.documentSelfLink);
}
Operation op = Operation
.createPatch(this, context.loadBalancerStateExpanded.documentSelfLink);
op.setBody(loadBalancerState);
return this.sendWithDeferredResult(op).thenApply(ignore -> context);
}
private DeferredResult getAWSLoadBalancer(
AWSLoadBalancerContext context) {
DescribeLoadBalancersRequest describeRequest = new DescribeLoadBalancersRequest()
.withLoadBalancerNames(context.loadBalancerStateExpanded.name);
String message =
"Describing AWS load balancer [" + context.loadBalancerStateExpanded.name + "].";
AWSDeferredResultAsyncHandler handler =
new AWSDeferredResultAsyncHandler<>(this, message);
context.client.describeLoadBalancersAsync(describeRequest, handler);
return handler.toDeferredResult().thenCompose(result -> {
List lbs = result
.getLoadBalancerDescriptions();
if (lbs != null && !lbs.isEmpty() && lbs.size() == 1) {
context.registeredInstances = lbs.iterator().next().getInstances();
return DeferredResult.completed(context);
}
return DeferredResult.failed(new IllegalStateException(
"Unable to describe load balancer with name '"
+ context.loadBalancerStateExpanded.name + "' for update"));
});
}
private DeferredResult assignInstances(AWSLoadBalancerContext context) {
// If the registered instances are null this is a newly provisioned load balancer
// so add all instances from the load balancer state to the registration request
if (context.registeredInstances == null) {
context.instanceIdsToRegister = context.loadBalancerStateExpanded.computes.stream()
.map(computeState -> computeState.id)
.collect(Collectors.toList());
context.instanceIdsToDeregister = Collections.emptyList();
} else {
context.instanceIdsToRegister = context.loadBalancerStateExpanded.computes.stream()
.map(computeState -> computeState.id)
.filter(csId -> context.registeredInstances.stream()
.noneMatch(i -> i.getInstanceId().equals(csId))
)
.collect(Collectors.toList());
context.instanceIdsToDeregister = context.registeredInstances.stream()
.map(Instance::getInstanceId)
.filter(instanceId -> context.loadBalancerStateExpanded.computes.stream()
.noneMatch(computeState -> computeState.id.equals(instanceId))
)
.collect(Collectors.toList());
}
return DeferredResult.completed(context)
.thenCompose(this::registerInstances)
.thenCompose(this::deregisterInstances);
}
private DeferredResult registerInstances(
AWSLoadBalancerContext context) {
// Do not try to assign instances if there aren't any
if (context.instanceIdsToRegister.isEmpty()) {
return DeferredResult.completed(context);
}
RegisterInstancesWithLoadBalancerRequest request = buildInstanceRegistrationRequest(
context);
String message = "Registering instances to AWS Load Balancer with name ["
+ context.loadBalancerStateExpanded.name + "]";
AWSDeferredResultAsyncHandler handler =
new AWSDeferredResultAsyncHandler<>(this, message);
context.client.registerInstancesWithLoadBalancerAsync(request, handler);
return handler.toDeferredResult()
.thenApply(ignore -> context);
}
private DeferredResult deregisterInstances(
AWSLoadBalancerContext context) {
// Do not try to deregister instances if there aren't any
if (context.instanceIdsToDeregister.isEmpty()) {
return DeferredResult.completed(context);
}
DeregisterInstancesFromLoadBalancerRequest request = buildInstanceDeregistrationRequest(
context);
String message = "Deregistering instances to AWS Load Balancer with name ["
+ context.loadBalancerStateExpanded.name + "]";
AWSDeferredResultAsyncHandler handler =
new AWSDeferredResultAsyncHandler<>(this, message);
context.client.deregisterInstancesFromLoadBalancerAsync(request, handler);
return handler.toDeferredResult().thenApply(ignore -> context);
}
private CreateLoadBalancerRequest buildCreationRequest(AWSLoadBalancerContext context) {
// Combine all security groups associated with the LB to a single list
Collection securityGroupsToUse = new ArrayList<>();
if (context.provisionedSecurityGroupState != null) {
securityGroupsToUse.add(context.provisionedSecurityGroupState);
}
if (context.securityGroupStates != null && !context.securityGroupStates.isEmpty()) {
securityGroupsToUse.addAll(context.securityGroupStates);
}
CreateLoadBalancerRequest request = new CreateLoadBalancerRequest()
.withLoadBalancerName(context.loadBalancerStateExpanded.name)
.withListeners(buildListeners(context))
.withSubnets(context.loadBalancerStateExpanded.subnets.stream()
.map(subnet -> subnet.id)
.collect(Collectors.toList())
)
.withSecurityGroups(
securityGroupsToUse.stream().map(sg -> sg.id).collect(Collectors.toList()));
// Set scheme to Internet-facing if specified. By default, an internal load balancer is
// created
if (!Boolean.TRUE.equals(context.loadBalancerStateExpanded.internetFacing)) {
request.setScheme("internal");
}
return request;
}
private List buildListeners(AWSLoadBalancerContext context) {
return context.loadBalancerStateExpanded.routes.stream().map(routeConfiguration -> {
Listener listener = new Listener()
.withLoadBalancerPort(Integer.parseInt(routeConfiguration.port))
.withInstancePort(Integer.parseInt(routeConfiguration.instancePort));
// Convert HTTPS protocol on the load balancer to TCP thus the load balancer will act
// as a SSL Pass-through. Set the instance protocol to be TCP as well as both protocols
// must be on the same layer
if (LoadBalancerDescription.Protocol.HTTPS.name()
.equalsIgnoreCase(routeConfiguration.protocol)) {
listener.setProtocol(LoadBalancerDescription.Protocol.TCP.name());
listener.setInstanceProtocol(LoadBalancerDescription.Protocol.TCP.name());
} else {
listener.setProtocol(routeConfiguration.protocol);
listener.setInstanceProtocol(routeConfiguration.instanceProtocol);
}
return listener;
}).collect(Collectors.toList());
}
private RegisterInstancesWithLoadBalancerRequest buildInstanceRegistrationRequest(
AWSLoadBalancerContext context) {
return new RegisterInstancesWithLoadBalancerRequest()
.withLoadBalancerName(context.loadBalancerStateExpanded.name)
.withInstances(context.instanceIdsToRegister.stream()
.map(Instance::new)
.collect(Collectors.toList())
);
}
private DeregisterInstancesFromLoadBalancerRequest buildInstanceDeregistrationRequest(
AWSLoadBalancerContext context) {
return new DeregisterInstancesFromLoadBalancerRequest()
.withLoadBalancerName(context.loadBalancerStateExpanded.name)
.withInstances(context.instanceIdsToDeregister.stream()
.map(Instance::new)
.collect(Collectors.toList())
);
}
private DeferredResult deleteLoadBalancer(
AWSLoadBalancerContext context) {
DeleteLoadBalancerRequest request = new DeleteLoadBalancerRequest()
.withLoadBalancerName(context.loadBalancerStateExpanded.name);
String message = "Delete AWS Load Balancer with name ["
+ context.loadBalancerStateExpanded.name + "]";
AWSDeferredResultAsyncHandler handler =
new AWSDeferredResultAsyncHandler<>(this, message);
context.client.deleteLoadBalancerAsync(request, handler);
return handler.toDeferredResult().thenApply(ignore -> context);
}
private DeferredResult deleteLoadBalancerState(
AWSLoadBalancerContext context) {
return this
.sendWithDeferredResult(
Operation.createDelete(this,
context.loadBalancerStateExpanded.documentSelfLink))
.thenApply(operation -> context);
}
private DeferredResult deleteSecurityGroup(
AWSLoadBalancerContext context) {
List infrastructureSecurityGroups =
context.securityGroupStates.stream()
.filter(this::isLBProvisionedSecurityGroup)
.collect(Collectors.toList());
if (infrastructureSecurityGroups.isEmpty()) {
return DeferredResult.completed(context);
}
List> deletionDRs = infrastructureSecurityGroups.stream()
.map(sg -> buildSecurityGroupInstanceRequest(sg, InstanceRequestType.DELETE,
context))
.map(req -> Operation.createPatch(this, AWSSecurityGroupService.SELF_LINK)
.setBody(req))
.map(op -> sendWithDeferredResult(op).exceptionally(th -> {
// Delete requests should not fail, only log the problem.
this.logWarning("Unable to delete security group: %s", th.getMessage());
return null;
})).collect(Collectors.toList());
return DeferredResult.allOf(deletionDRs).thenApply(ignore -> context);
}
private boolean isLBProvisionedSecurityGroup(ResourceState resource) {
return resource.customProperties != null && Boolean.TRUE.toString().equals(
resource.customProperties.get(AWSConstants.AWS_LOAD_BALANCER_SECURITY_GROUP));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy