debian-mirror-gitlab/app/services/clusters/aws/proxy_service.rb
2019-12-26 22:10:19 +05:30

134 lines
3 KiB
Ruby

# frozen_string_literal: true
module Clusters
module Aws
class ProxyService
DEFAULT_REGION = 'us-east-1'
BadRequest = Class.new(StandardError)
Response = Struct.new(:status, :body)
def initialize(role, params:)
@role = role
@params = params
end
def execute
api_response = request_from_api!
Response.new(:ok, api_response.to_hash)
rescue *service_errors
Response.new(:bad_request, {})
end
private
attr_reader :role, :params
def request_from_api!
case requested_resource
when 'key_pairs'
ec2_client.describe_key_pairs
when 'instance_types'
instance_types
when 'roles'
iam_client.list_roles
when 'regions'
ec2_client.describe_regions
when 'security_groups'
raise BadRequest unless vpc_id.present?
ec2_client.describe_security_groups(vpc_filter)
when 'subnets'
raise BadRequest unless vpc_id.present?
ec2_client.describe_subnets(vpc_filter)
when 'vpcs'
ec2_client.describe_vpcs
else
raise BadRequest
end
end
def requested_resource
params[:resource]
end
def vpc_id
params[:vpc_id]
end
def region
params[:region] || DEFAULT_REGION
end
def vpc_filter
{
filters: [{
name: "vpc-id",
values: [vpc_id]
}]
}
end
##
# Unfortunately the EC2 API doesn't provide a list of
# possible instance types. There is a workaround, using
# the Pricing API, but instead of requiring the
# user to grant extra permissions for this we use the
# values that validate the CloudFormation template.
def instance_types
{
instance_types: cluster_stack_instance_types.map { |type| Hash(instance_type_name: type) }
}
end
def cluster_stack_instance_types
YAML.safe_load(stack_template).dig('Parameters', 'NodeInstanceType', 'AllowedValues')
end
def stack_template
File.read(Rails.root.join('vendor', 'aws', 'cloudformation', 'eks_cluster.yaml'))
end
def ec2_client
::Aws::EC2::Client.new(client_options)
end
def iam_client
::Aws::IAM::Client.new(client_options)
end
def credentials
Clusters::Aws::FetchCredentialsService.new(role, region: region).execute
end
def client_options
{
credentials: credentials,
region: region,
http_open_timeout: 5,
http_read_timeout: 10
}
end
def service_errors
[
BadRequest,
Clusters::Aws::FetchCredentialsService::MissingRoleError,
::Aws::Errors::MissingCredentialsError,
::Aws::EC2::Errors::ServiceError,
::Aws::IAM::Errors::ServiceError,
::Aws::STS::Errors::ServiceError
]
end
end
end
end