mystro-common 0.1.11 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. data/.gitignore +3 -0
  2. data/.rspec +2 -0
  3. data/CHANGELOG.md +42 -4
  4. data/Gemfile +7 -1
  5. data/Rakefile +137 -1
  6. data/lib/{mystro/ext/fog → fog/ext}/balancer.rb +0 -0
  7. data/lib/fog/ext/dynect/dns.rb +140 -0
  8. data/lib/fog/ext/dynect/models/dns/record.rb +66 -0
  9. data/lib/fog/ext/dynect/models/dns/records.rb +87 -0
  10. data/lib/fog/ext/dynect/models/dns/zone.rb +60 -0
  11. data/lib/fog/ext/dynect/models/dns/zones.rb +29 -0
  12. data/lib/fog/ext/dynect/requests/dns/delete_record.rb +56 -0
  13. data/lib/fog/ext/dynect/requests/dns/delete_zone.rb +42 -0
  14. data/lib/fog/ext/dynect/requests/dns/get_all_records.rb +56 -0
  15. data/lib/fog/ext/dynect/requests/dns/get_node_list.rb +56 -0
  16. data/lib/fog/ext/dynect/requests/dns/get_record.rb +85 -0
  17. data/lib/fog/ext/dynect/requests/dns/get_zone.rb +58 -0
  18. data/lib/fog/ext/dynect/requests/dns/post_record.rb +72 -0
  19. data/lib/fog/ext/dynect/requests/dns/post_session.rb +44 -0
  20. data/lib/fog/ext/dynect/requests/dns/post_zone.rb +71 -0
  21. data/lib/fog/ext/dynect/requests/dns/put_zone.rb +76 -0
  22. data/lib/fog/ext/dynect.rb +26 -0
  23. data/lib/mystro/cloud/action.rb +22 -0
  24. data/lib/mystro/cloud/connect/aws/balancer.rb +55 -0
  25. data/lib/mystro/cloud/connect/aws/compute.rb +151 -0
  26. data/lib/mystro/cloud/connect/aws/listener.rb +36 -0
  27. data/lib/mystro/cloud/connect/aws/record.rb +58 -0
  28. data/lib/mystro/cloud/connect/aws/zone.rb +35 -0
  29. data/lib/mystro/cloud/connect/aws.rb +14 -0
  30. data/lib/mystro/cloud/connect/dynect/record.rb +72 -0
  31. data/lib/mystro/cloud/connect/dynect/zone.rb +35 -0
  32. data/lib/mystro/cloud/connect/dynect.rb +17 -0
  33. data/lib/mystro/cloud/connect/fog.rb +66 -0
  34. data/lib/mystro/cloud/connect.rb +64 -0
  35. data/lib/mystro/cloud/model/balancer.rb +15 -0
  36. data/lib/mystro/cloud/model/compute.rb +27 -0
  37. data/lib/mystro/cloud/model/listener.rb +30 -0
  38. data/lib/mystro/cloud/model/record.rb +20 -0
  39. data/lib/mystro/cloud/model/volume.rb +12 -0
  40. data/lib/mystro/cloud/model/zone.rb +9 -0
  41. data/lib/mystro/cloud/model.rb +183 -0
  42. data/lib/mystro/cloud.rb +32 -0
  43. data/lib/mystro/common/version.rb +4 -3
  44. data/lib/mystro/dsl/balancer.rb +18 -0
  45. data/lib/mystro/dsl/compute.rb +57 -0
  46. data/lib/mystro/dsl/health.rb +7 -0
  47. data/lib/mystro/dsl/listener.rb +5 -0
  48. data/lib/mystro/dsl/oldtemplate.rb +281 -0
  49. data/lib/mystro/dsl/template.rb +12 -278
  50. data/lib/mystro/dsl/template_file.rb +18 -0
  51. data/lib/mystro/dsl/volume.rb +8 -0
  52. data/lib/mystro/dsl.rb +40 -0
  53. data/lib/mystro/organization.rb +83 -0
  54. data/lib/mystro/plugin.rb +4 -3
  55. data/lib/mystro/provider.rb +40 -0
  56. data/lib/mystro/userdata.rb +1 -1
  57. data/lib/mystro-common.rb +32 -31
  58. data/mystro-common.gemspec +2 -1
  59. data/spec/cloud/aws/balancer_spec.rb +10 -0
  60. data/spec/cloud/aws/compute_spec.rb +10 -0
  61. data/spec/cloud/aws/record_spec.rb +10 -0
  62. data/spec/cloud/dynect/record_spec.rb +10 -0
  63. data/spec/model/compute_spec.rb +36 -0
  64. data/spec/model/model_spec.rb +89 -0
  65. data/spec/model/record_spec.rb +27 -0
  66. data/spec/spec_helper.rb +36 -0
  67. data/spec/support/balancer.rb +49 -0
  68. data/spec/support/compute.rb +65 -0
  69. data/spec/support/record.rb +45 -0
  70. data/test/config.yml +71 -0
  71. metadata +99 -14
  72. data/lib/mystro/account.rb +0 -105
  73. data/lib/mystro/connect/balancer.rb +0 -91
  74. data/lib/mystro/connect/compute.rb +0 -100
  75. data/lib/mystro/connect/dns.rb +0 -51
  76. data/lib/mystro/connect/environment.rb +0 -31
  77. data/lib/mystro/connect.rb +0 -124
  78. data/lib/mystro/job.rb +0 -0
  79. data/lib/mystro/model.rb +0 -71
@@ -0,0 +1,151 @@
1
+ module Mystro
2
+ module Cloud
3
+ module Aws
4
+ class Compute < Connect
5
+ manages 'Fog::Compute', :servers
6
+
7
+ def all(filters={})
8
+ decode(service.send(collection).all(filters))
9
+ end
10
+
11
+ def running
12
+ all({"instance-state-name" => "running"})
13
+ end
14
+
15
+ def create(model)
16
+ e = encode(model)
17
+ r = service.send(collection).create(e)
18
+ model.id = r.id
19
+ tag(model)
20
+ model
21
+ end
22
+
23
+ def tag(model)
24
+ unless model.id
25
+ Mystro::Log.warn "tag called with no id"
26
+ return
27
+ end
28
+ t = model.tags
29
+ service.create_tags(model.id, t)
30
+ end
31
+
32
+ def untag
33
+ raise "write me"
34
+ end
35
+
36
+ protected
37
+
38
+ def _decode(server)
39
+ #Mystro::Log.debug "decode: #{server.inspect}"
40
+ model = Mystro::Cloud::Compute.new
41
+ model.id = server.id
42
+ model.image = server.image_id
43
+ model.flavor = server.flavor_id
44
+ model.dns = server.dns_name
45
+ model.ip = server.public_ip_address
46
+ model.private_dns = server.private_dns_name
47
+ model.private_ip = server.private_ip_address
48
+ model.state = server.state
49
+ model.region = service.region
50
+ model.keypair = server.key_name
51
+ model.groups = server.groups #.map {|e| e.name}
52
+ model.tags = server.tags #.inject({}){|h, e| h[e.first] = e.last; h} if server.tags
53
+ model.userdata = server.user_data
54
+ model.zone = server.availability_zone
55
+ model._raw = server
56
+ #Mystro::Log.debug "decode: #{model.inspect}"
57
+ model
58
+ end
59
+
60
+ def _encode(model)
61
+ Mystro::Log.debug "encode: #{model.inspect}"
62
+ options = {
63
+ image_id: model.image,
64
+ flavor_id: model.flavor,
65
+ key_name: model.keypair,
66
+ groups: model.groups,
67
+ region: model.region,
68
+ user_data: model.userdata,
69
+ }
70
+ #TODO: disable volumes until we can figure out fix for fog
71
+ map = mapping(model)
72
+ options[:block_device_mapping] = map if map
73
+ Mystro::Log.debug "encode: #{options.inspect}"
74
+ options
75
+ end
76
+
77
+ def mapping(model)
78
+ return unless model.volumes
79
+
80
+ image = service.images.get(model.image)
81
+ map = map_transform(image.block_device_mapping)
82
+ devices = map.keys
83
+ last = devices.last
84
+ root = image.root_device_name
85
+ model.volumes.each do |volume|
86
+ dev = volume.device || volume.name
87
+ if dev == :root && image.root_device_type != "ebs"
88
+ Mystro::Log.error "trying to change ephemeral root volume"
89
+ return
90
+ end
91
+ if dev == :root || dev == 'root'
92
+ dev = root
93
+ unless map[dev]
94
+ Mystro::Log.error "something wrong, trying to change root volume: #{volume.inspect}"
95
+ return
96
+ end
97
+ end
98
+ if volume.device == :next
99
+ last = last.next
100
+ map[last] = {
101
+ 'deviceName' => last,
102
+ 'volumeSize' => volume.size,
103
+ 'deleteOnTermination' => volume.dot,
104
+ 'snapshotId' => volume.snapshot,
105
+ 'virtualName' => volume.virtual,
106
+ }
107
+ elsif !map[dev]
108
+ map[dev] = {
109
+ 'deviceName' => dev,
110
+ 'volumeSize' => volume.size,
111
+ 'deleteOnTermination' => volume.dot,
112
+ 'snapshotId' => volume.snapshot,
113
+ 'virtualName' => volume.virtual,
114
+ }
115
+ else
116
+ map[dev]['volumeSize'] = volume.size.to_s if volume.size
117
+ map[dev]['snapshotId'] = volume.snapshot if volume.snapshot
118
+ map[dev]['deleteOnTermination'] = volume.dot if volume.dot
119
+ end
120
+ end
121
+ change_keys(map_untransform(map))
122
+ end
123
+
124
+ def change_keys(map)
125
+ name_mapping = {
126
+ 'deviceName' => 'DeviceName',
127
+ 'virtualName' => 'VirtualName',
128
+ 'snapshotId' => 'Ebs.SnapshotId',
129
+ 'volumeSize' => 'Ebs.VolumeSize',
130
+ 'deleteOnTermination' => 'Ebs.DeleteOnTermination',
131
+ }
132
+ map.map do |volume|
133
+ out = {}
134
+ name_mapping.each do |key, value|
135
+ out[value] = volume[key].to_s if volume[key]
136
+ end
137
+ out
138
+ end
139
+ end
140
+
141
+ def map_transform(map)
142
+ map.inject({}) { |h, e| h[e['deviceName']] = e; h }
143
+ end
144
+
145
+ def map_untransform(map)
146
+ map.inject([]) { |a, e| a << e.last }
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,36 @@
1
+ module Mystro
2
+ module Cloud
3
+ module Aws
4
+ class Listener < Connect
5
+
6
+ protected
7
+
8
+ def _decode(listener)
9
+ model = Mystro::Cloud::Listener.new
10
+ model.to_port = listener.instance_port
11
+ model.to_protocol = listener.instance_protocol
12
+ model.port = listener.lb_port
13
+ model.protocol = listener.protocol
14
+ model.cert = listener.ssl_id
15
+ model.policy = listener.policy_names
16
+ model._raw = listener
17
+ model
18
+ end
19
+
20
+ def _encode(model)
21
+ {
22
+ 'Listener' => {
23
+ "Protocol" => model.protocol,
24
+ "LoadBalancerPort" => model.port,
25
+ "InstanceProtocol" => model.to_protocol,
26
+ "InstancePort" => model.to_port,
27
+ "SSLCertificateId" => model.cert,
28
+ "PolicyNames" => []
29
+ },
30
+ 'PolicyNames' => []
31
+ }
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,58 @@
1
+ require 'ipaddress'
2
+
3
+ module Mystro
4
+ module Cloud
5
+ module Aws
6
+ class Record < Connect
7
+ manages 'Fog::DNS', :records
8
+
9
+ def find_by_name(name)
10
+ find(name)
11
+ end
12
+
13
+ def service
14
+ @service ||= begin
15
+ list = zones.service.zones.all
16
+ z = @config[:zone]
17
+ s = list.detect {|e| e.domain == "#{z}."}
18
+ s
19
+ end
20
+ end
21
+
22
+ protected
23
+
24
+ def _decode(object)
25
+ Mystro::Log.debug "decode: #{object.inspect}"
26
+ model = Mystro::Cloud::Record.new
27
+ n = object.name.gsub(/\.$/, '')
28
+ # AWS records have no id, fog uses name instead
29
+ model.id = n
30
+ model.name = n
31
+ model.values = object.value
32
+ model.ttl = object.ttl
33
+ model.type = object.type
34
+ model._raw = object
35
+ Mystro::Log.debug "decode: #{model.inspect}"
36
+ model
37
+ end
38
+
39
+ def _encode(model)
40
+ Mystro::Log.debug "encode: #{model.inspect}"
41
+ n = model.name
42
+ n += '.' unless n =~ /\.$/
43
+ options = ::IPAddress.valid?(model.values.first) ?
44
+ {name: n, value: model.values, type: 'A', ttl: model.ttl } :
45
+ {name: model.name, value: model.values, type: 'CNAME', ttl: model.ttl }
46
+ Mystro::Log.debug "encode: #{options.inspect}"
47
+ options
48
+ end
49
+
50
+ private
51
+
52
+ def zones
53
+ Mystro::Cloud::Aws::Zone.new(@options, @config)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,35 @@
1
+ module Mystro
2
+ module Cloud
3
+ module Aws
4
+ class Zone < Connect
5
+ manages 'Fog::DNS', :zones
6
+
7
+ protected
8
+
9
+ def _decode(object)
10
+ Mystro::Log.debug "decode: #{object.inspect}"
11
+ model = Mystro::Cloud::Zone.new
12
+ model.id = object.id
13
+ model.domain = object.domain
14
+ model._raw = object
15
+ Mystro::Log.debug "decode: #{model.inspect}"
16
+ model
17
+ end
18
+
19
+ def _encode(model)
20
+ Mystro::Log.debug "encode: #{model.inspect}"
21
+ options = {
22
+ #image_id: model.image,
23
+ #flavor_id: model.flavor,
24
+ #key_name: model.keypair,
25
+ #groups: model.groups,
26
+ #region: model.region,
27
+ #user_data: model.userdata,
28
+ }
29
+ Mystro::Log.debug "encode: #{options.inspect}"
30
+ options
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,14 @@
1
+ require 'mystro/cloud/connect/fog'
2
+ module Mystro
3
+ module Cloud
4
+ module Aws
5
+ class Connect < Mystro::Cloud::Fog::Connect
6
+ end
7
+ end
8
+ end
9
+ end
10
+
11
+ Dir["#{File.dirname(__FILE__)}/aws/*rb"].each do |file|
12
+ #puts "aws: #{file}"
13
+ require "#{file.gsub(/\.rb/, '')}"
14
+ end
@@ -0,0 +1,72 @@
1
+ require 'ipaddress'
2
+ #require 'ext/fog/dynect/models/dns/records'
3
+
4
+ module Mystro
5
+ module Cloud
6
+ module Dynect
7
+ class Record < Connect
8
+ manages 'Fog::DNS', :records
9
+
10
+ def find_by_name(name)
11
+ #decode(fog.all.detect { |e| e.name == name })
12
+ decode(service.send(collection).find_by_name(name).detect { |e| e.name == name })
13
+ end
14
+
15
+ def destroy(model)
16
+ raise "destroy argument should be Mystro::Cloud::Model: #{model.inspect}" unless model.is_a?(Mystro::Cloud::Model)
17
+ e = find_by_name(model.name)
18
+ Mystro::Log.debug "destroy: #{e.inspect}"
19
+ e._raw.destroy if e && e._raw
20
+ service.publish
21
+ end
22
+
23
+ def service
24
+ @service ||= begin
25
+ list = zones.service.zones.all
26
+ list.detect { |e| e.domain == @config[:zone] }
27
+ end
28
+ end
29
+
30
+ def decode(object)
31
+ return super unless object.is_a?(Array)
32
+ list = super
33
+ # filter out records that we don't need (TXT, etc)
34
+ list.reject {|e| %w{A CNAME}.include?(e.type) }
35
+ list
36
+ end
37
+
38
+ protected
39
+
40
+ def _decode(object)
41
+ Mystro::Log.debug "decode: #{object.inspect}"
42
+ model = Mystro::Cloud::Record.new
43
+ model.id = object.id
44
+ model.name = object.name.gsub(/\.$/, '')
45
+ model.values = [object.type == 'CNAME' ? object.rdata['cname'] : object.rdata['address']]
46
+ model.ttl = object.ttl
47
+ model.type = object.type
48
+ model._raw = object
49
+ Mystro::Log.debug "decode: #{model.inspect}"
50
+ model
51
+ end
52
+
53
+ def _encode(model)
54
+ Mystro::Log.debug "encode: #{model.type} #{model.inspect}"
55
+ n = model.name
56
+ n += '.' unless n =~ /\.$/
57
+ options = model.type == 'A' ?
58
+ {id: model.id, name: model.name, rdata: {'address' => model.values.first}, ttl: model.ttl, type: 'A'} :
59
+ {id: model.id, name: model.name, rdata: {'cname' => model.values.first}, ttl: model.ttl, type: 'CNAME'}
60
+ Mystro::Log.debug "encode: #{options.inspect}"
61
+ options
62
+ end
63
+
64
+ private
65
+
66
+ def zones
67
+ Mystro::Cloud::Aws::Zone.new(@options, @config)
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,35 @@
1
+ module Mystro
2
+ module Cloud
3
+ module Dynect
4
+ class Zone < Connect
5
+ manages 'Fog::DNS', :zones
6
+
7
+ protected
8
+
9
+ def _decode(object)
10
+ Mystro::Log.debug "decode: #{object.inspect}"
11
+ model = Mystro::Cloud::Zone.new
12
+ model.id = object.id
13
+ model.domain = object.domain
14
+ model._raw = object
15
+ Mystro::Log.debug "decode: #{model.inspect}"
16
+ model
17
+ end
18
+
19
+ def _encode(model)
20
+ Mystro::Log.debug "encode: #{model.inspect}"
21
+ options = {
22
+ #image_id: model.image,
23
+ #flavor_id: model.flavor,
24
+ #key_name: model.keypair,
25
+ #groups: model.groups,
26
+ #region: model.region,
27
+ #user_data: model.userdata,
28
+ }
29
+ Mystro::Log.debug "encode: #{options.inspect}"
30
+ options
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,17 @@
1
+ require 'mystro/cloud/connect/fog'
2
+ require 'fog/ext/dynect'
3
+
4
+ module Mystro
5
+ module Cloud
6
+ module Dynect
7
+ class Connect < Mystro::Cloud::Fog::Connect
8
+
9
+ end
10
+ end
11
+ end
12
+ end
13
+
14
+ Dir["#{File.dirname(__FILE__)}/dynect/*rb"].each do |file|
15
+ #puts "dynect: #{file}"
16
+ require "#{file.gsub(/\.rb/, '')}"
17
+ end
@@ -0,0 +1,66 @@
1
+ require 'fog'
2
+ require 'fog/ext/balancer'
3
+
4
+ module Mystro
5
+ module Cloud
6
+ module Fog
7
+ class Connect < Mystro::Cloud::Connect
8
+ attr_reader :options
9
+
10
+ def initialize(options, config=nil)
11
+ @options = options
12
+ @config = config
13
+ @service = nil
14
+ @fog = nil
15
+ end
16
+
17
+ def all
18
+ decode(service.send(collection).all)
19
+ end
20
+
21
+ def find(id)
22
+ i = service.send(collection).get(id)
23
+ raise Mystro::Cloud::NotFound, "could not find #{id}" unless i
24
+ decode(i)
25
+ end
26
+
27
+ def create(model)
28
+ enc = encode(model)
29
+ o = service.send(collection).create(enc)
30
+ decode(o)
31
+ end
32
+
33
+ def destroy(model)
34
+ Mystro::Log.debug "destroy: #{model.inspect}"
35
+ raise "destroy argument should be Mystro::Cloud::Model: #{model.inspect}" unless model.is_a?(Mystro::Cloud::Model)
36
+ e = service.send(collection).get(model.identity)
37
+ raise "object not found for id: #{model.identity}" unless e
38
+ e.destroy
39
+ end
40
+
41
+ def collection
42
+ @collection ||= self.class.collection
43
+ end
44
+
45
+ def service
46
+ @service ||= begin
47
+ model = self.class.model
48
+ s = model.constantize.new(@options)
49
+ s
50
+ end
51
+ end
52
+
53
+ class << self
54
+ attr_reader :model, :collection
55
+
56
+ protected
57
+
58
+ def manages(fog_model, fog_collection)
59
+ @model = fog_model
60
+ @collection = fog_collection
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,64 @@
1
+ module Mystro
2
+ module Cloud
3
+ class Connect
4
+ attr_reader :options, :config
5
+
6
+ def initialize(options, config)
7
+ @options = options
8
+ @config = config
9
+ end
10
+
11
+ def all
12
+ raise "not implemented"
13
+ end
14
+
15
+ def find(id)
16
+ raise "not implemented"
17
+ end
18
+
19
+ def create(model)
20
+ raise "not implemented"
21
+ end
22
+
23
+ def destroy(model)
24
+ raise "not implemented"
25
+ end
26
+
27
+ def encode(model)
28
+ raise "encode: model is nil" unless model
29
+ model.is_a?(Array) ? model.map {|e| _encode(e)} : _encode(model)
30
+ end
31
+
32
+ def decode(object)
33
+ raise "decode: object is nil" unless object
34
+ object.is_a?(Array) ? object.map {|e| _decode(e)} : _decode(object)
35
+ end
36
+
37
+ protected
38
+
39
+ def _encode(model)
40
+ raise "not implemented"
41
+ end
42
+
43
+ def _decode(object)
44
+ raise "not implemented"
45
+ end
46
+
47
+ class << self
48
+ attr_reader :model, :collection, :klass, :decoders
49
+
50
+ protected
51
+
52
+ def manages(fog_model, fog_collection)
53
+ @model = fog_model
54
+ @collection = fog_collection
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ Dir["#{File.dirname(__FILE__)}/connect/*rb"].each do |file|
62
+ #puts "connect: #{file}"
63
+ require "#{file.gsub(/\.rb/, '')}"
64
+ end
@@ -0,0 +1,15 @@
1
+ module Mystro
2
+ module Cloud
3
+ class Balancer < Model
4
+ identity :id
5
+ attribute :name
6
+ attribute :dns
7
+ attribute :computes, type: Array, of: String
8
+ attribute :zones, type: Array, of: String
9
+ attribute :health, type: Hash
10
+ attribute :listeners, type: Array, of: Hash
11
+ attribute :primary, type: :boolean
12
+ attribute :_raw, type: Object, required: false
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,27 @@
1
+ module Mystro
2
+ module Cloud
3
+ class Compute < Model
4
+ identity :id
5
+ attribute :name, required: false
6
+ attribute :image, type: String
7
+ attribute :flavor, type: String
8
+ attribute :region, type: String
9
+ attribute :dns, type: String, required: false
10
+ attribute :ip, type: String, required: false
11
+ attribute :private_dns, type: String, required: false
12
+ attribute :private_ip, type: String, required: false
13
+ attribute :state, type: String
14
+ attribute :keypair, aliases:[:key], type: String
15
+ attribute :userdata, type: String, required: false
16
+ attribute :groups, type: Array, of: String
17
+ attribute :tags, type: Hash, required: false
18
+ attribute :zone # availability zone
19
+ has_many :volumes, type: 'Volume', required: false
20
+ attribute :_raw, type: Object, required: false
21
+
22
+ def name
23
+ tags && tags['Name']
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,30 @@
1
+ module Mystro
2
+ module Cloud
3
+ class Listener < Model
4
+ attribute :to_protocol
5
+ attribute :to_port, type: Integer
6
+ attribute :port, type: Integer
7
+ attribute :protocol
8
+ attribute :policy, type: Array, required: false
9
+ attribute :cert, required: false
10
+ attribute :_raw, type: Object, required: false
11
+
12
+ def from
13
+ "#{protocol}:#{port}"
14
+ end
15
+
16
+ def to
17
+ "#{to_protocol}:#{to_port}"
18
+ end
19
+
20
+ def to_hash
21
+ {
22
+ to: to,
23
+ from: from,
24
+ policy: policy,
25
+ cert: cert,
26
+ }.delete_if {|k, v| v.nil?}
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,20 @@
1
+ require 'ipaddress'
2
+
3
+ module Mystro
4
+ module Cloud
5
+ class Record < Model
6
+ identity :id
7
+ attribute :name
8
+ attribute :values, type: Array, of: String
9
+ attribute :ttl, type: Integer
10
+ attribute :type
11
+ attribute :_raw, type: Object, required: false
12
+
13
+ # TODO: not sure why this doesn't work, keeps returning 'A'
14
+ #def type
15
+ # puts "TYPE: #{@data[:type]} ip?=#{::IPAddress.valid?(values.first)}"
16
+ # @data[:type] || ::IPAddress.valid?(values.first) ? 'A' : 'CNAME'
17
+ #end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,12 @@
1
+ module Mystro
2
+ module Cloud
3
+ class Volume < Model
4
+ attribute :name
5
+ attribute :device, required: false
6
+ attribute :size
7
+ attribute :dot, required: false
8
+ attribute :snapshot, required: false
9
+ attribute :virtual, required: false
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ module Mystro
2
+ module Cloud
3
+ class Zone < Model
4
+ identity :id
5
+ attribute :domain
6
+ attribute :_raw, type: Object, required: false
7
+ end
8
+ end
9
+ end