Class: Cyoi::Providers::Clients::FogProviderClient

Inherits:
Object
  • Object
show all
Defined in:
lib/cyoi/providers/clients/fog_provider_client.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attributes) ⇒ FogProviderClient

Returns a new instance of FogProviderClient.



10
11
12
13
14
# File 'lib/cyoi/providers/clients/fog_provider_client.rb', line 10

def initialize(attributes)
  @attributes = attributes.is_a?(Hash) ? ReadWriteSettings.new(attributes) : attributes
  raise "@attributes must be ReadWriteSettings (or Hash)" unless @attributes.is_a?(ReadWriteSettings)
  setup_fog_connection unless attributes.delete("skip_fog_setup")
end

Instance Attribute Details

#attributesObject (readonly)

Returns the value of attribute attributes.



8
9
10
# File 'lib/cyoi/providers/clients/fog_provider_client.rb', line 8

def attributes
  @attributes
end

#fog_computeObject (readonly)

Returns the value of attribute fog_compute.



7
8
9
# File 'lib/cyoi/providers/clients/fog_provider_client.rb', line 7

def fog_compute
  @fog_compute
end

Instance Method Details

#authorize_port_range(sg, port_range, protocol, ip_range) ⇒ Object



172
173
174
# File 'lib/cyoi/providers/clients/fog_provider_client.rb', line 172

def authorize_port_range(sg, port_range, protocol, ip_range)
  raise "must implement"
end

#cleanup_unused_ip_addressesObject

Destroy all IP addresses that aren’t bound to a server



97
98
99
100
101
102
103
104
105
# File 'lib/cyoi/providers/clients/fog_provider_client.rb', line 97

def cleanup_unused_ip_addresses
  fog_compute.addresses.each do |a|
    unless a.server
      print "Deleting unused IP address #{a.public_ip}... "
      a.destroy
      puts "done"
    end
  end
end

#create_blobstore(blobstore_name) ⇒ Object

Creates a bucket/object-store/directory/blobstore To be overridden to make the bucket publicly read-only per IaaS.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/cyoi/providers/clients/fog_provider_client.rb', line 29

def create_blobstore(blobstore_name)
  unless supports_blobstore_service?
    puts "Provider does not support blobstore service"
    false
  else
    print "Creating publicly readable blobstore #{blobstore_name}... "
    blobstore = fog_storage.directories.create(key: blobstore_name)
    puts "done"
    blobstore
  end
rescue Excon::Errors::Forbidden => e
  puts "failed: credentials do not allow blobstore to be created"
  false
rescue Excon::Errors::Conflict => e
  puts "failed: blobstore already exists but owned by someone else"
  false
end

#create_key_pair(key_pair_name) ⇒ Object



47
48
49
50
51
52
# File 'lib/cyoi/providers/clients/fog_provider_client.rb', line 47

def create_key_pair(key_pair_name)
  print "Acquiring a key pair #{key_pair_name}... "
  key_pair = fog_compute.key_pairs.create(:name => key_pair_name)
  puts "done"
  key_pair
end

#create_security_group(security_group_name, description, defns, extra_attributes = {}) ⇒ Object

Creates or reuses an security group and opens ports.

security_group_name is the name to be created or reused ports is a hash of name/port for ports to open

protocol defaults to TCP You can also use a more verbose ports using the format:

  • 22,

  • { ports: (80..82) },

  • { protocol: “udp”, ports: (60000..60050) }

  • { protocol: “rdp”, ports: (3398..3398), ip_ranges: [ { cidrIp: “196.212.12.34/32” } ] }

In this example,

* TCP 22 will be opened for ssh from any ip_range,
* TCP ports 80, 81, 82 for http from any ip_range,
* UDP 60000 -> 60050 for mosh from any ip_range and
* TCP 3398 for RDP from ip range: 96.212.12.34/32


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
# File 'lib/cyoi/providers/clients/fog_provider_client.rb', line 124

def create_security_group(security_group_name, description, defns, extra_attributes={})
  security_groups = fog_compute.security_groups
  sg = security_groups.find do |s|
    if extra_attributes[:vpc_id]
      s.name == security_group_name && s.vpc_id == extra_attributes[:vpc_id]
    else
      s.name == security_group_name
    end
  end

  suffix = extra_attributes[:vpc_id] ? " for the VPC" : ""
  unless sg
    attributes = {name: security_group_name, description: description}.merge(extra_attributes)
    sg = fog_compute.security_groups.create(attributes)
    puts "Created security group #{security_group_name}#{suffix}"
  else
    puts "Reusing security group #{security_group_name}#{suffix}"
  end
  ip_permissions = ip_permissions(sg)
  ports_opened = 0

  # Unnest { ports: 22 } and { ports: { ports: 22..22 }} legacy inputs
  if defns.is_a?(Hash) && defns[:ports].is_a?(Hash)
    defns = defns[:ports]
  end

  unless defns.is_a?(Array)
    defns = [defns]
  end
  defns.each do |port_defn|
    port_defns = port_defn.is_a?(Array) ? port_defn : [port_defn]
    port_defns.each do |port_defn|
      (protocol, port_range, ip_range) = extract_port_definition(port_defn)
      unless port_open?(ip_permissions, port_range, protocol, ip_range)
        authorize_port_range(sg, port_range, protocol, ip_range)
        puts " -> opened #{security_group_name} ports #{protocol.upcase} #{port_range.min}..#{port_range.max} from IP range #{ip_range}"
        ports_opened += 1
      end
    end
  end
  puts " -> no additional ports opened" if ports_opened == 0
  true
end

#delete_key_pair_if_exists(key_pair_name) ⇒ Object



69
70
71
72
73
74
75
# File 'lib/cyoi/providers/clients/fog_provider_client.rb', line 69

def delete_key_pair_if_exists(key_pair_name)
  if fog_key_pair = fog_compute.key_pairs.get(key_pair_name)
    print "Destroying key pair #{key_pair_name}... "
    fog_key_pair.destroy
    puts "done"
  end
end

#delete_servers_with_name(name) ⇒ Object



77
78
79
80
81
82
83
# File 'lib/cyoi/providers/clients/fog_provider_client.rb', line 77

def delete_servers_with_name(name)
  fog_compute.servers.select {|s| s.tags["Name"].downcase == name.downcase }.each do |server|
    print "Destroying server #{server.id}... "
    server.destroy
    puts "done"
  end
end

#delete_volumes_with_name(name) ⇒ Object



85
86
87
88
89
90
91
92
93
94
# File 'lib/cyoi/providers/clients/fog_provider_client.rb', line 85

def delete_volumes_with_name(name)
  fog_compute.volumes.select do |v|
    volume_name = v.tags["Name"]
    volume_name && volume_name.downcase == name.downcase
  end.each do |volume|
    print "Destroying volume #{volume.id}... "
    volume.destroy
    puts "done"
  end
end

#extract_port_definition(port_defn) ⇒ Object

Any of the following port_defn can be used: {

ssh: 22,
http: { ports: (80..82) },
mosh: { protocol: "udp", ports: (60000..60050) }
mosh: { protocol: "rdp", ports: (3398..3398), ip_range: "196.212.12.34/32" }

} In this example,

* TCP 22 will be opened for ssh from any ip_range,
* TCP ports 80, 81, 82 for http from any ip_range,
* UDP 60000 -> 60050 for mosh from any ip_range and
* TCP 3398 for RDP from ip range: 96.212.12.34/32


192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/cyoi/providers/clients/fog_provider_client.rb', line 192

def extract_port_definition(port_defn)
  protocol = "tcp"
  ip_range = "0.0.0.0/0"
  if port_defn.is_a? Integer
    port_range = (port_defn..port_defn)
  elsif port_defn.is_a? Range
    port_range = port_defn
  elsif port_defn.is_a? Hash
    protocol = port_defn[:protocol] if port_defn[:protocol]
    port_range = port_defn[:ports]  if port_defn[:ports]
    if port_range.is_a? Integer
      port_range = (port_range..port_range)
    end
    ip_range = port_defn[:ip_range] if port_defn[:ip_range]
  end
  [protocol, port_range, ip_range]
end

#find_unused_public_ip_address(options = {}) ⇒ Object



214
215
216
217
218
# File 'lib/cyoi/providers/clients/fog_provider_client.rb', line 214

def find_unused_public_ip_address(options={})
  if address = fog_compute.addresses.find { |s| s.server_id.nil? }
    address.public_ip
  end
end

#ip_permissions(sg) ⇒ Object



176
177
178
# File 'lib/cyoi/providers/clients/fog_provider_client.rb', line 176

def ip_permissions(sg)
  raise "must implement"
end

#port_open?(ip_permissions, port_range, protocol, ip_range) ⇒ Boolean

Returns:

  • (Boolean)


168
169
170
# File 'lib/cyoi/providers/clients/fog_provider_client.rb', line 168

def port_open?(ip_permissions, port_range, protocol, ip_range)
  raise "must implement"
end

#provision_or_reuse_public_ip_address(options = {}) ⇒ Object



210
211
212
# File 'lib/cyoi/providers/clients/fog_provider_client.rb', line 210

def provision_or_reuse_public_ip_address(options={})
  provision_public_ip_address(options) || find_unused_public_ip_address(options)
end

#set_resource_name(resource, name) ⇒ Object

set_resource_name(fog_server, “inception”) set_resource_name(volume, “inception-root”) set_resource_name(volume, “inception-store”)



65
66
67
# File 'lib/cyoi/providers/clients/fog_provider_client.rb', line 65

def set_resource_name(resource, name)
  fog_compute.tags.create :key => "Name", :value => name, :resource_id => resource.id
end

#setup_fog_connectionObject

Implement in subclasses



17
18
# File 'lib/cyoi/providers/clients/fog_provider_client.rb', line 17

def setup_fog_connection
end

#supports_blobstore_service?Boolean

Returns:

  • (Boolean)


20
21
22
23
24
# File 'lib/cyoi/providers/clients/fog_provider_client.rb', line 20

def supports_blobstore_service?
  fog_storage
rescue
  false
end

#valid_key_pair_fingerprint?(key_pair_name, fingerprint) ⇒ Boolean

Returns:

  • (Boolean)


54
55
56
57
58
59
60
# File 'lib/cyoi/providers/clients/fog_provider_client.rb', line 54

def valid_key_pair_fingerprint?(key_pair_name, fingerprint)
  if fog_key_pair = fog_compute.key_pairs.get(key_pair_name)
    fog_key_pair.fingerprint == fingerprint
  else
    false
  end
end