Welcome to mirror list, hosted at ThFree Co, Russian Federation.

proxy_service.rb « aws « clusters « services « app - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: df8fc48000593be750b11d3cd6c4db0075ef924b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# 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