File: servers.rb

package info (click to toggle)
ruby-fog-aws 3.3.0-5
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 7,816 kB
  • sloc: ruby: 68,587; makefile: 6
file content (213 lines) | stat: -rw-r--r-- 7,305 bytes parent folder | download
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
require 'fog/aws/models/compute/server'

module Fog
  module AWS
    class Compute
      class Servers < Fog::Collection
        attribute :filters

        model Fog::AWS::Compute::Server

        # Creates a new server
        #
        # AWS.servers.new
        #
        # ==== Returns
        #
        # Returns the details of the new server
        #
        #>> AWS.servers.new
        #  <Fog::AWS::Compute::Server
        #    id=nil,
        #    ami_launch_index=nil,
        #    availability_zone=nil,
        #    block_device_mapping=nil,
        #    network_interfaces=nil,
        #    client_token=nil,
        #    dns_name=nil,
        #    groups=["default"],
        #    flavor_id="m1.small",
        #    image_id=nil,
        #    ip_address=nil,
        #    kernel_id=nil,
        #    key_name=nil,
        #    created_at=nil,
        #    monitoring=nil,
        #    product_codes=nil,
        #    private_dns_name=nil,
        #    private_ip_address=nil,
        #    ramdisk_id=nil,
        #    reason=nil,
        #    root_device_name=nil,
        #    root_device_type=nil,
        #    state=nil,
        #    state_reason=nil,
        #    subnet_id=nil,
        #    tags=nil,
        #    user_data=nil
        #  >
        #

        def initialize(attributes)
          self.filters ||= {}
          super
        end

        def all(filters = self.filters)
          unless filters.is_a?(Hash)
            Fog::Logger.deprecation("all with #{filters.class} param is deprecated, use all('instance-id' => []) instead [light_black](#{caller.first})[/]")
            filters = {'instance-id' => [*filters]}
          end
          self.filters = filters
          data = service.describe_instances(filters).body
          load(
            data['reservationSet'].map do |reservation|
              reservation['instancesSet'].map do |instance|
                instance.merge(:groups => reservation['groupSet'], :security_group_ids => reservation['groupIds'])
              end
            end.flatten
          )
        end

        # Create between m and n servers with the server options specified in
        # new_attributes.  Equivalent to this loop, but happens in 1 request:
        #
        #    1.upto(n).map { create(new_attributes) }
        #
        # See the AWS RunInstances API.
        def create_many(min_servers = 1, max_servers = nil, new_attributes = {})
          max_servers ||= min_servers
          template = new(new_attributes)
          save_many(template, min_servers, max_servers)
        end

        # Bootstrap between m and n servers with the server options specified in
        # new_attributes.  Equivalent to this loop, but happens in 1 AWS request
        # and the machines' spinup will happen in parallel:
        #
        #   1.upto(n).map { bootstrap(new_attributes) }
        #
        # See the AWS RunInstances API.
        def bootstrap_many(min_servers = 1, max_servers = nil, new_attributes = {})
          template = service.servers.new(new_attributes)
          _setup_bootstrap(template)

          servers = save_many(template, min_servers, max_servers)
          servers.each do |server|
            server.wait_for { ready? }
            server.setup(:key_data => [server.private_key])
          end
          servers
        end

        def bootstrap(new_attributes = {})
          bootstrap_many(1, 1, new_attributes).first
        end

        # Used to retrieve a server
        #
        # server_id is required to get the associated server information.
        #
        # You can run the following command to get the details:
        # AWS.servers.get("i-5c973972")
        #
        # ==== Returns
        #
        #>> AWS.servers.get("i-5c973972")
        #  <Fog::AWS::Compute::Server
        #    id="i-5c973972",
        #    ami_launch_index=0,
        #    availability_zone="us-east-1b",
        #    block_device_mapping=[],
        #    client_token=nil,
        #    dns_name="ec2-25-2-474-44.compute-1.amazonaws.com",
        #    groups=["default"],
        #    flavor_id="m1.small",
        #    image_id="test",
        #    ip_address="25.2.474.44",
        #    kernel_id="aki-4e1e1da7",
        #    key_name=nil,
        #    created_at=Mon Nov 29 18:09:34 -0500 2010,
        #    monitoring=false,
        #    product_codes=[],
        #    private_dns_name="ip-19-76-384-60.ec2.internal",
        #    private_ip_address="19.76.384.60",
        #    ramdisk_id="ari-0b3fff5c",
        #    reason=nil,
        #    root_device_name=nil,
        #    root_device_type="instance-store",
        #    state="running",
        #    state_reason={},
        #    subnet_id=nil,
        #    tags={},
        #    user_data=nil
        #  >
        #

        def get(server_id)
          if server_id
            self.class.new(:service => service).all('instance-id' => server_id).first
          end
        rescue Fog::Errors::NotFound
          nil
        end

        # From a template, create between m-n servers (see the AWS RunInstances API)
        def save_many(template, min_servers = 1, max_servers = nil)
          max_servers ||= min_servers
          data = service.run_instances(template.image_id, min_servers, max_servers, template.run_instance_options)
          # For some reason, AWS sometimes returns empty results alongside the real ones.  Thus the select
          data.body['instancesSet'].select { |instance_set| instance_set['instanceId'] }.map do |instance_set|
            server = template.dup
            server.merge_attributes(instance_set)
            # expect eventual consistency
            if (tags = server.tags) && tags.size > 0
              Fog.wait_for { server.reload rescue nil }
              Fog.wait_for {
                begin
                  service.create_tags(server.identity, tags)
                rescue Fog::AWS::Compute::NotFound
                  false
                end
              }
            end
            server
          end
        end

        private

        def _setup_bootstrap(server)
          unless server.key_name
            # first or create fog_#{credential} keypair
            name = Fog.respond_to?(:credential) && Fog.credential || :default
            unless server.key_pair = service.key_pairs.get("fog_#{name}")
              server.key_pair = service.key_pairs.create(
                :name => "fog_#{name}",
                :public_key => server.public_key
              )
            end
          end

          security_group = service.security_groups.get(server.groups.first)
          if security_group.nil?
            raise Fog::AWS::Compute::Error, "The security group" \
              " #{server.groups.first} doesn't exist."
          end

          # make sure port 22 is open in the first security group
          authorized = security_group.ip_permissions.find do |ip_permission|
            ip_permission['ipRanges'].find { |ip_range| ip_range['cidrIp'] == '0.0.0.0/0' } &&
            ip_permission['fromPort'] == 22 &&
            ip_permission['ipProtocol'] == 'tcp' &&
            ip_permission['toPort'] == 22
          end

          unless authorized
            security_group.authorize_port_range(22..22)
          end
        end
      end
    end
  end
end