org.finra.dm.dao.impl.MockEc2OperationsImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.finra.dm.dao.impl.MockEc2OperationsImpl.java

Source

/*
* Copyright 2015 herd contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.finra.dm.dao.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.finra.dm.dao.Ec2Operations;

import com.amazonaws.AmazonServiceException;
import com.amazonaws.services.ec2.AmazonEC2Client;
import com.amazonaws.services.ec2.model.AvailabilityZone;
import com.amazonaws.services.ec2.model.DescribeAvailabilityZonesRequest;
import com.amazonaws.services.ec2.model.DescribeAvailabilityZonesResult;
import com.amazonaws.services.ec2.model.DescribeInstanceAttributeRequest;
import com.amazonaws.services.ec2.model.DescribeInstanceAttributeResult;
import com.amazonaws.services.ec2.model.DescribeSpotPriceHistoryRequest;
import com.amazonaws.services.ec2.model.DescribeSpotPriceHistoryResult;
import com.amazonaws.services.ec2.model.DescribeSubnetsRequest;
import com.amazonaws.services.ec2.model.DescribeSubnetsResult;
import com.amazonaws.services.ec2.model.GroupIdentifier;
import com.amazonaws.services.ec2.model.InstanceAttribute;
import com.amazonaws.services.ec2.model.ModifyInstanceAttributeRequest;
import com.amazonaws.services.ec2.model.SpotPrice;
import com.amazonaws.services.ec2.model.Subnet;

/**
 * Mock implementation of AWS EC2 operations.
 * 
 * The mock contains several pre-configured subnets, availability zones, regions, and instance types.
 */
public class MockEc2OperationsImpl implements Ec2Operations {
    public static final int AVAILABLE_IP_HIGH = 20;
    public static final int AVAILABLE_IP_LOW = 10;

    public static final String SPOT_PRICE_VERY_HIGH = "2";
    public static final String SPOT_PRICE_HIGH = "1.5";
    public static final String SPOT_PRICE_EQUAL = "1";
    public static final String SPOT_PRICE_LOW = ".5";
    public static final String SPOT_PRICE_VERY_LOW = ".25";

    public static String SUBNET_1 = "SUBNET_1";
    public static String SUBNET_2 = "SUBNET_2";
    public static String SUBNET_3 = "SUBNET_3";
    public static String SUBNET_4 = "SUBNET_4";
    public static String SUBNET_5 = "SUBNET_5";

    public static String AVAILABILITY_ZONE_1 = "AVAILABILITY_ZONE_1";
    public static String AVAILABILITY_ZONE_2 = "AVAILABILITY_ZONE_2";
    public static String AVAILABILITY_ZONE_3 = "AVAILABILITY_ZONE_3";
    public static String AVAILABILITY_ZONE_4 = "AVAILABILITY_ZONE_4";

    public static String REGION_1 = "REGION_1";
    public static String REGION_2 = "REGION_2";

    public static String INSTANCE_TYPE_1 = "INSTANCE_TYPE_1";
    public static String INSTANCE_TYPE_2 = "INSTANCE_TYPE_2";
    public static String INSTANCE_TYPE_3 = "INSTANCE_TYPE_3";

    /*
     * Pre-configured in-memory EC2 instance information.
     * These are initialized in the constructor.
     * Note that on-demand prices are database configurations, therefore are stored in the mock reference data DB script.
     */
    private Map<String, MockSubnet> mockSubnets = new HashMap<>();
    private Map<String, MockAvailabilityZone> mockAvailabilityZones = new HashMap<>();
    private Set<String> mockInstanceTypes = new HashSet<>();

    public MockEc2OperationsImpl() {
        Map<String, MockEc2Region> mockEc2Regions = new HashMap<>();

        // Pre-configure REGION_1
        {
            MockEc2Region mockEc2Region = new MockEc2Region();
            mockEc2Region.setName(REGION_1);
            mockEc2Regions.put(REGION_1, mockEc2Region);

            // Pre-configure AVAILABILITY_ZONE_1
            {
                MockAvailabilityZone availabilityZone = new MockAvailabilityZone();
                availabilityZone.setZoneName(AVAILABILITY_ZONE_1);
                mockEc2Region.putAvailabilityZone(availabilityZone);

                // Pre-configured instance types for AVAILABILITY_ZONE_1
                {
                    MockSpotPrice spotPrice = new MockSpotPrice();
                    spotPrice.setType(INSTANCE_TYPE_1);
                    spotPrice.setSpotPrice(SPOT_PRICE_LOW);
                    availabilityZone.putSpotPrice(spotPrice);
                }

                {
                    MockSpotPrice spotPrice = new MockSpotPrice();
                    spotPrice.setType(INSTANCE_TYPE_2);
                    spotPrice.setSpotPrice(SPOT_PRICE_EQUAL);
                    availabilityZone.putSpotPrice(spotPrice);
                }

                {
                    MockSpotPrice spotPrice = new MockSpotPrice();
                    spotPrice.setType(INSTANCE_TYPE_3);
                    spotPrice.setSpotPrice(SPOT_PRICE_HIGH);
                    availabilityZone.putSpotPrice(spotPrice);
                }

                // Pre-configured subnets for AVAILABILITY_ZONE_1
                {
                    MockSubnet subnet = new MockSubnet();
                    subnet.setSubnetId(SUBNET_1);
                    subnet.setAvailableIpAddressCount(AVAILABLE_IP_LOW);
                    availabilityZone.putSubnet(subnet);
                }

                {
                    MockSubnet subnet = new MockSubnet();
                    subnet.setSubnetId(SUBNET_2);
                    subnet.setAvailableIpAddressCount(AVAILABLE_IP_HIGH);
                    availabilityZone.putSubnet(subnet);
                }
            }

            // Pre-configure AVAILABILITY_ZONE_2
            {
                MockAvailabilityZone availabilityZone = new MockAvailabilityZone();
                availabilityZone.setZoneName(AVAILABILITY_ZONE_2);
                mockEc2Region.putAvailabilityZone(availabilityZone);

                // Pre-configured instance types for AVAILABILITY_ZONE_2
                {
                    MockSpotPrice spotPrice = new MockSpotPrice();
                    spotPrice.setType(INSTANCE_TYPE_1);
                    spotPrice.setSpotPrice(SPOT_PRICE_EQUAL);
                    availabilityZone.putSpotPrice(spotPrice);
                }

                // Pre-configured subnets for AVAILABILITY_ZONE_2
                {
                    MockSubnet subnet = new MockSubnet();
                    subnet.setSubnetId(SUBNET_3);
                    subnet.setAvailableIpAddressCount(AVAILABLE_IP_HIGH);
                    availabilityZone.putSubnet(subnet);
                }
            }

            // Pre-configure AVAILABILITY_ZONE_3
            {
                MockAvailabilityZone availabilityZone = new MockAvailabilityZone();
                availabilityZone.setZoneName(AVAILABILITY_ZONE_3);
                mockEc2Region.putAvailabilityZone(availabilityZone);

                // Pre-configured instance types for AVAILABILITY_ZONE_3
                {
                    MockSpotPrice spotPrice = new MockSpotPrice();
                    spotPrice.setType(INSTANCE_TYPE_1);
                    spotPrice.setSpotPrice(SPOT_PRICE_VERY_LOW);
                    availabilityZone.putSpotPrice(spotPrice);
                }

                {
                    MockSpotPrice spotPrice = new MockSpotPrice();
                    spotPrice.setType(INSTANCE_TYPE_2);
                    spotPrice.setSpotPrice(SPOT_PRICE_VERY_HIGH);
                    availabilityZone.putSpotPrice(spotPrice);
                }

                // Pre-configured subnets for AVAILABILITY_ZONE_3
                {
                    MockSubnet subnet = new MockSubnet();
                    subnet.setSubnetId(SUBNET_4);
                    subnet.setAvailableIpAddressCount(AVAILABLE_IP_LOW);
                    availabilityZone.putSubnet(subnet);
                }
            }
        }

        // Pre-configure REGION_2
        {
            MockEc2Region ec2Region = new MockEc2Region();
            ec2Region.setName(REGION_2);
            mockEc2Regions.put(REGION_2, ec2Region);

            // Pre-configure availability zones for REGION_2
            {
                MockAvailabilityZone availabilityZone = new MockAvailabilityZone();
                availabilityZone.setZoneName(AVAILABILITY_ZONE_4);
                ec2Region.putAvailabilityZone(availabilityZone);

                // Pre-configure spot prices for AVAILABILITY_ZONE_4
                {
                    MockSpotPrice spotPrice = new MockSpotPrice();
                    spotPrice.setType(INSTANCE_TYPE_1);
                    spotPrice.setSpotPrice(SPOT_PRICE_LOW);
                    availabilityZone.putSpotPrice(spotPrice);
                }

                {
                    MockSpotPrice spotPrice = new MockSpotPrice();
                    spotPrice.setType(INSTANCE_TYPE_2);
                    spotPrice.setSpotPrice(SPOT_PRICE_LOW);
                    availabilityZone.putSpotPrice(spotPrice);
                }

                // Pre-configure subnets for AVAILABILITY_ZONE_4
                {
                    MockSubnet subnet = new MockSubnet();
                    subnet.setSubnetId(SUBNET_5);
                    subnet.setAvailableIpAddressCount(AVAILABLE_IP_LOW);
                    availabilityZone.putSubnet(subnet);
                }
            }
        }

        // Populate subnets from the above configurations
        for (MockEc2Region ec2Region : mockEc2Regions.values()) {
            for (MockAvailabilityZone availabilityZone : ec2Region.getAvailabilityZones().values()) {
                for (MockSubnet subnet : availabilityZone.getSubnets().values()) {
                    mockSubnets.put(subnet.getSubnetId(), subnet);
                }
            }
        }

        // Populate availability zones from the above configurations
        for (MockEc2Region ec2Region : mockEc2Regions.values()) {
            for (MockAvailabilityZone availabilityZone : ec2Region.getAvailabilityZones().values()) {
                mockAvailabilityZones.put(availabilityZone.getZoneName(), availabilityZone);
            }
        }

        // Populate availability zones from the above configurations
        for (MockEc2Region ec2Region : mockEc2Regions.values()) {
            for (MockAvailabilityZone availabilityZone : ec2Region.getAvailabilityZones().values()) {
                for (MockSpotPrice mockSpotPrice : availabilityZone.getSpotPrices().values()) {
                    mockInstanceTypes.add(mockSpotPrice.getInstanceType());
                }
            }
        }
    }

    @Override
    public DescribeInstanceAttributeResult describeInstanceAttribute(AmazonEC2Client ec2Client,
            DescribeInstanceAttributeRequest describeInstanceAttributeRequest) {
        InstanceAttribute instanceAttribute = new InstanceAttribute();
        instanceAttribute.withGroups(new GroupIdentifier().withGroupId("A_TEST_SECURITY_GROUP"));
        return new DescribeInstanceAttributeResult().withInstanceAttribute(instanceAttribute);
    }

    @Override
    public void modifyInstanceAttribute(AmazonEC2Client ec2Client,
            ModifyInstanceAttributeRequest modifyInstanceAttributeRequest) {
        if (modifyInstanceAttributeRequest.getGroups() != null && modifyInstanceAttributeRequest.getGroups().get(0)
                .equals(MockAwsOperationsHelper.AMAZON_SERVICE_EXCEPTION)) {
            throw new AmazonServiceException(MockAwsOperationsHelper.AMAZON_SERVICE_EXCEPTION);
        }

        if (modifyInstanceAttributeRequest.getGroups() != null && modifyInstanceAttributeRequest.getGroups().get(0)
                .equals(MockAwsOperationsHelper.AMAZON_THROTTLING_EXCEPTION)) {
            AmazonServiceException throttlingException = new AmazonServiceException("test throttling exception");
            throttlingException.setErrorCode("ThrottlingException");

            throw throttlingException;
        }

    }

    /**
     * In-memory implementation of describeSubnets. Returns the subnets from the pre-configured subnets.
     * The method can be ordered to throw an AmazonServiceException with a specified error code by specifying a subnet ID with prefix "throw." followed by a
     * string indicating the error code to throw. The exception thrown in this manner will always set the status code to 500.
     */
    @Override
    public DescribeSubnetsResult describeSubnets(AmazonEC2Client ec2Client,
            DescribeSubnetsRequest describeSubnetsRequest) {
        List<Subnet> subnets = new ArrayList<>();

        List<String> requestedSubnetIds = describeSubnetsRequest.getSubnetIds();

        // add all subnets if request is empty (this is AWS behavior)
        if (requestedSubnetIds.isEmpty()) {
            requestedSubnetIds.addAll(mockSubnets.keySet());
        }

        for (String requestedSubnetId : requestedSubnetIds) {
            MockSubnet mockSubnet = mockSubnets.get(requestedSubnetId);

            // Throw exception if any of the subnet ID do not exist
            if (mockSubnet == null) {
                AmazonServiceException amazonServiceException;

                if (requestedSubnetId.startsWith("throw.")) {
                    String errorCode = requestedSubnetId.substring("throw.".length());

                    amazonServiceException = new AmazonServiceException(errorCode);
                    amazonServiceException.setErrorCode(errorCode);
                    amazonServiceException.setStatusCode(500);
                } else {
                    amazonServiceException = new AmazonServiceException(
                            "The subnet ID '" + requestedSubnetId + "' does not exist");
                    amazonServiceException.setErrorCode(Ec2DaoImpl.ERROR_CODE_SUBNET_ID_NOT_FOUND);
                    amazonServiceException.setStatusCode(400);
                }

                throw amazonServiceException;
            }

            subnets.add(mockSubnet.toAwsObject());
        }

        DescribeSubnetsResult describeSubnetsResult = new DescribeSubnetsResult();
        describeSubnetsResult.setSubnets(subnets);
        return describeSubnetsResult;
    }

    @Override
    public DescribeAvailabilityZonesResult describeAvailabilityZones(AmazonEC2Client ec2Client,
            DescribeAvailabilityZonesRequest describeAvailabilityZonesRequest) {
        List<AvailabilityZone> availabilityZones = new ArrayList<>();

        List<String> requestedZoneNames = describeAvailabilityZonesRequest.getZoneNames();

        // add all AZ if request is empty (this is AWS behavior)
        if (requestedZoneNames.isEmpty()) {
            requestedZoneNames.addAll(mockAvailabilityZones.keySet());
        }

        for (String requestedZoneName : requestedZoneNames) {
            // ignore AZ name which does not exist (this is AWS behavior)
            MockAvailabilityZone mockAvailabilityZone = mockAvailabilityZones.get(requestedZoneName);
            if (mockAvailabilityZone != null) {
                availabilityZones.add(mockAvailabilityZone.toAwsObject());
            }
        }

        DescribeAvailabilityZonesResult describeAvailabilityZonesResult = new DescribeAvailabilityZonesResult();
        describeAvailabilityZonesResult.setAvailabilityZones(availabilityZones);

        return describeAvailabilityZonesResult;
    }

    @Override
    public DescribeSpotPriceHistoryResult describeSpotPriceHistory(AmazonEC2Client ec2Client,
            DescribeSpotPriceHistoryRequest describeSpotPriceHistoryRequest) {
        List<SpotPrice> spotPriceHistories = new ArrayList<>();

        String requestedAvailabilityZone = describeSpotPriceHistoryRequest.getAvailabilityZone();

        // Get availability zones to search for
        Set<MockAvailabilityZone> requestedAvailabilityZones = new HashSet<>();

        // If requested zone is specified, get and add
        if (requestedAvailabilityZone != null) {
            requestedAvailabilityZones.add(mockAvailabilityZones.get(requestedAvailabilityZone));
        }
        // If requested zone is not specified, add all
        else {
            requestedAvailabilityZones.addAll(mockAvailabilityZones.values());
        }

        // Get instance types to search for
        List<String> requestedInstanceTypes = describeSpotPriceHistoryRequest.getInstanceTypes();
        // If not specified, add all instance types
        if (requestedInstanceTypes.isEmpty()) {
            requestedInstanceTypes.addAll(mockInstanceTypes);
        }

        // search for price for all AZ and instance types requested
        for (MockAvailabilityZone mockAvailabilityZone : requestedAvailabilityZones) {
            for (String requestedInstanceType : requestedInstanceTypes) {
                MockSpotPrice mockSpotPrice = mockAvailabilityZone.getSpotPrices().get(requestedInstanceType);
                if (mockSpotPrice != null) {
                    spotPriceHistories.add(mockSpotPrice.toAwsObject());
                }
            }
        }

        DescribeSpotPriceHistoryResult describeSpotPriceHistoryResult = new DescribeSpotPriceHistoryResult();
        describeSpotPriceHistoryResult.setSpotPriceHistory(spotPriceHistories);
        return describeSpotPriceHistoryResult;
    }
}