mystro-common 0.1.11 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +3 -0
- data/.rspec +2 -0
- data/CHANGELOG.md +42 -4
- data/Gemfile +7 -1
- data/Rakefile +137 -1
- data/lib/{mystro/ext/fog → fog/ext}/balancer.rb +0 -0
- data/lib/fog/ext/dynect/dns.rb +140 -0
- data/lib/fog/ext/dynect/models/dns/record.rb +66 -0
- data/lib/fog/ext/dynect/models/dns/records.rb +87 -0
- data/lib/fog/ext/dynect/models/dns/zone.rb +60 -0
- data/lib/fog/ext/dynect/models/dns/zones.rb +29 -0
- data/lib/fog/ext/dynect/requests/dns/delete_record.rb +56 -0
- data/lib/fog/ext/dynect/requests/dns/delete_zone.rb +42 -0
- data/lib/fog/ext/dynect/requests/dns/get_all_records.rb +56 -0
- data/lib/fog/ext/dynect/requests/dns/get_node_list.rb +56 -0
- data/lib/fog/ext/dynect/requests/dns/get_record.rb +85 -0
- data/lib/fog/ext/dynect/requests/dns/get_zone.rb +58 -0
- data/lib/fog/ext/dynect/requests/dns/post_record.rb +72 -0
- data/lib/fog/ext/dynect/requests/dns/post_session.rb +44 -0
- data/lib/fog/ext/dynect/requests/dns/post_zone.rb +71 -0
- data/lib/fog/ext/dynect/requests/dns/put_zone.rb +76 -0
- data/lib/fog/ext/dynect.rb +26 -0
- data/lib/mystro/cloud/action.rb +22 -0
- data/lib/mystro/cloud/connect/aws/balancer.rb +55 -0
- data/lib/mystro/cloud/connect/aws/compute.rb +151 -0
- data/lib/mystro/cloud/connect/aws/listener.rb +36 -0
- data/lib/mystro/cloud/connect/aws/record.rb +58 -0
- data/lib/mystro/cloud/connect/aws/zone.rb +35 -0
- data/lib/mystro/cloud/connect/aws.rb +14 -0
- data/lib/mystro/cloud/connect/dynect/record.rb +72 -0
- data/lib/mystro/cloud/connect/dynect/zone.rb +35 -0
- data/lib/mystro/cloud/connect/dynect.rb +17 -0
- data/lib/mystro/cloud/connect/fog.rb +66 -0
- data/lib/mystro/cloud/connect.rb +64 -0
- data/lib/mystro/cloud/model/balancer.rb +15 -0
- data/lib/mystro/cloud/model/compute.rb +27 -0
- data/lib/mystro/cloud/model/listener.rb +30 -0
- data/lib/mystro/cloud/model/record.rb +20 -0
- data/lib/mystro/cloud/model/volume.rb +12 -0
- data/lib/mystro/cloud/model/zone.rb +9 -0
- data/lib/mystro/cloud/model.rb +183 -0
- data/lib/mystro/cloud.rb +32 -0
- data/lib/mystro/common/version.rb +4 -3
- data/lib/mystro/dsl/balancer.rb +18 -0
- data/lib/mystro/dsl/compute.rb +57 -0
- data/lib/mystro/dsl/health.rb +7 -0
- data/lib/mystro/dsl/listener.rb +5 -0
- data/lib/mystro/dsl/oldtemplate.rb +281 -0
- data/lib/mystro/dsl/template.rb +12 -278
- data/lib/mystro/dsl/template_file.rb +18 -0
- data/lib/mystro/dsl/volume.rb +8 -0
- data/lib/mystro/dsl.rb +40 -0
- data/lib/mystro/organization.rb +83 -0
- data/lib/mystro/plugin.rb +4 -3
- data/lib/mystro/provider.rb +40 -0
- data/lib/mystro/userdata.rb +1 -1
- data/lib/mystro-common.rb +32 -31
- data/mystro-common.gemspec +2 -1
- data/spec/cloud/aws/balancer_spec.rb +10 -0
- data/spec/cloud/aws/compute_spec.rb +10 -0
- data/spec/cloud/aws/record_spec.rb +10 -0
- data/spec/cloud/dynect/record_spec.rb +10 -0
- data/spec/model/compute_spec.rb +36 -0
- data/spec/model/model_spec.rb +89 -0
- data/spec/model/record_spec.rb +27 -0
- data/spec/spec_helper.rb +36 -0
- data/spec/support/balancer.rb +49 -0
- data/spec/support/compute.rb +65 -0
- data/spec/support/record.rb +45 -0
- data/test/config.yml +71 -0
- metadata +99 -14
- data/lib/mystro/account.rb +0 -105
- data/lib/mystro/connect/balancer.rb +0 -91
- data/lib/mystro/connect/compute.rb +0 -100
- data/lib/mystro/connect/dns.rb +0 -51
- data/lib/mystro/connect/environment.rb +0 -31
- data/lib/mystro/connect.rb +0 -124
- data/lib/mystro/job.rb +0 -0
- data/lib/mystro/model.rb +0 -71
data/.rspec
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,41 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## v0.2.0:
|
4
|
+
* tests green.
|
5
|
+
* conversion work completed... still want to test things a bit
|
6
|
+
* custom create method for balancers
|
7
|
+
* conversion work nearly completed. balancers working. environment creation cleaned up
|
8
|
+
* checkin
|
9
|
+
* fix tests to properly clean up after themselves
|
10
|
+
* refactor some of the fog extension work. monkey patch fog/dynect support.
|
11
|
+
* fixes for volume support
|
12
|
+
* getting compute and records conversion completed
|
13
|
+
* disable volumes to avoid fog bug
|
14
|
+
* volume modification (changing root volume size) is working, but there's a bug in fog
|
15
|
+
* conversion work
|
16
|
+
* refactor data call to to_hash
|
17
|
+
* dsl conversion
|
18
|
+
* check in
|
19
|
+
* add access to config, allow to disable in configuration
|
20
|
+
* add raw attribute to listener
|
21
|
+
* cleanup
|
22
|
+
* add _raw to decoded object
|
23
|
+
* dynect record destroy working. refactor tests to use configuration file. add _raw attribute to models, this can contain source object (fog object). reopen fog dynect records to add find_by_name.
|
24
|
+
* working with shawncatz/fog fork
|
25
|
+
* dynect
|
26
|
+
* some refactoring, support for dynect started
|
27
|
+
* refactor to shared examples
|
28
|
+
* compute, balancers and records working. includes tests for cloud operations and models
|
29
|
+
* converted to new format, organizations now use new connect framework, started support for DNS
|
30
|
+
* balancers
|
31
|
+
* rspec integration
|
32
|
+
* add LIST to Version class. makes it easier to handle release tasks
|
33
|
+
* providers support
|
34
|
+
* orgs
|
35
|
+
|
36
|
+
## v0.1.11:
|
37
|
+
* fixes bug if disabled is not set
|
38
|
+
|
3
39
|
## v0.1.10:
|
4
40
|
* allow for disabling plugins
|
5
41
|
|
@@ -18,17 +54,19 @@
|
|
18
54
|
* changelog rake tasks
|
19
55
|
|
20
56
|
## v0.1.6:
|
21
|
-
|
22
|
-
## v0.1.5:
|
23
57
|
* update rails to 3.2.14. tweak plugins jobs output to match qujo. fix issue with getting zones through fog
|
24
58
|
* smarter errors in dns connect. add and use Account#get instead of @list attr
|
25
|
-
*
|
26
|
-
* support for templates in userdata, handled like files, but processed through erubis
|
59
|
+
* merge
|
27
60
|
* merge release v0.1.2
|
28
61
|
* new DSL framework
|
29
62
|
* ruby version file
|
30
63
|
* changelog rake tasks
|
31
64
|
|
65
|
+
## v0.1.4:
|
66
|
+
* merge
|
67
|
+
* hard code rake version in Gemfile to match mystro server
|
68
|
+
* support for templates in userdata, handled like files, but processed through erubis
|
69
|
+
|
32
70
|
## v0.1.3:
|
33
71
|
* fixes bugs with dns usage and plugin methods when no plugins are defined
|
34
72
|
* update ruby version
|
data/Gemfile
CHANGED
@@ -3,5 +3,11 @@ source 'https://rubygems.org'
|
|
3
3
|
# Specify your gem's dependencies in mystro-common.gemspec
|
4
4
|
gemspec
|
5
5
|
|
6
|
-
gem
|
6
|
+
gem 'damsel', path: '../../damsel'
|
7
|
+
|
8
|
+
gem 'rake', '10.0.4'
|
7
9
|
gem 'awesome_print'
|
10
|
+
gem 'rspec'
|
11
|
+
gem 'terminal-table'
|
12
|
+
gem 'factory_girl', '~> 4.0'
|
13
|
+
gem 'net-dns'
|
data/Rakefile
CHANGED
@@ -1,4 +1,140 @@
|
|
1
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'mystro-common'
|
4
|
+
require 'terminal-table'
|
5
|
+
require 'awesome_print'
|
6
|
+
|
7
|
+
RSpec::Core::RakeTask.new(:spec)
|
8
|
+
task :default => :spec
|
9
|
+
desc 'run tests and create computes and such that cost money'
|
10
|
+
task :spend do
|
11
|
+
Mystro.config.test!.spend = true
|
12
|
+
Rake::Task['spec'].invoke
|
13
|
+
end
|
14
|
+
def table(head, rows=nil)
|
15
|
+
if rows
|
16
|
+
t = Terminal::Table.new :headings => head, :rows => rows
|
17
|
+
else
|
18
|
+
t = Terminal::Table.new :rows => rows
|
19
|
+
end
|
20
|
+
t
|
21
|
+
end
|
22
|
+
|
23
|
+
def list(keys, list)
|
24
|
+
rows = []
|
25
|
+
list.each do |l|
|
26
|
+
row = []
|
27
|
+
keys.each do |k|
|
28
|
+
row << (l[k] || l[k.downcase] || l[k.to_sym] || l[k.downcase.to_sym])
|
29
|
+
end
|
30
|
+
rows << row
|
31
|
+
end
|
32
|
+
table(keys, rows)
|
33
|
+
end
|
34
|
+
|
35
|
+
def show(obj)
|
36
|
+
keys = obj.keys
|
37
|
+
rows = []
|
38
|
+
keys.each do |k|
|
39
|
+
list = [obj[k]].flatten
|
40
|
+
list.each do |v|
|
41
|
+
if v.is_a?(Hash)
|
42
|
+
v = v.inject([]) {|s, e| s << e.join(": ")}.join("\n")
|
43
|
+
end
|
44
|
+
v
|
45
|
+
rows << [k, v]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
table(%w{key value}, rows)
|
49
|
+
end
|
50
|
+
|
51
|
+
def options
|
52
|
+
{aws_access_key_id: 'AKIAIVMUCDVWWZFFLVGA', aws_secret_access_key: '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'}
|
53
|
+
end
|
54
|
+
|
55
|
+
#Mystro::Log.console_debug
|
56
|
+
#Mystro::Log.debug "logging ... "
|
57
|
+
|
58
|
+
desc 'get and show compute'
|
59
|
+
task :compute do
|
60
|
+
x = Mystro.compute
|
61
|
+
o = x.find("i-69d32404")
|
62
|
+
e = o.to_hash
|
63
|
+
e.merge!(name: o.name)
|
64
|
+
puts show(e)
|
65
|
+
end
|
66
|
+
|
67
|
+
desc 'get list of computes'
|
68
|
+
task :computes do
|
69
|
+
x = Mystro.compute
|
70
|
+
list = x.all
|
71
|
+
list.map! {|e| e.to_hash.merge(name: e.tags['Name'])}
|
72
|
+
puts list(%w{id name state ip dns}, list)
|
73
|
+
end
|
74
|
+
|
75
|
+
desc 'get and show balancer'
|
76
|
+
task :balancer do
|
77
|
+
x = Mystro.balancer
|
78
|
+
o = x.find 'RG-EVENTS-1'
|
79
|
+
e = o.to_hash
|
80
|
+
puts show(e)
|
81
|
+
end
|
82
|
+
|
83
|
+
desc 'get and show zone'
|
84
|
+
task :record do
|
85
|
+
o = Mystro::Organization.get('rg')
|
86
|
+
x = o.record
|
87
|
+
r = x.find_by_name 'mcstg1.rgops.com'
|
88
|
+
e = r.to_hash
|
89
|
+
puts show(e)
|
90
|
+
r = x.find '75069597'
|
91
|
+
e = r.to_hash
|
92
|
+
puts show(e)
|
93
|
+
end
|
94
|
+
|
95
|
+
desc 'get and show zone'
|
96
|
+
task :records do
|
97
|
+
x = Mystro.record
|
98
|
+
o = x.all
|
99
|
+
puts list(%w{name type ttl values}, o)
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
desc 'show default organization'
|
104
|
+
task :org do
|
105
|
+
puts Mystro.organization.to_hash.to_yaml
|
106
|
+
end
|
107
|
+
|
108
|
+
desc 'show configuration'
|
109
|
+
task :config do
|
110
|
+
puts Mystro.config.to_hash.to_yaml
|
111
|
+
end
|
112
|
+
|
113
|
+
desc 'template'
|
114
|
+
task :template, [:name] do |_, args|
|
115
|
+
name = args.name || 'hdp/live'
|
116
|
+
name.gsub!(/\.rb$/, '') if name =~ /\.rb$/
|
117
|
+
t = Mystro::Dsl.load("config/mystro/templates/#{name}.rb")
|
118
|
+
ap t
|
119
|
+
end
|
120
|
+
|
121
|
+
desc 'template cloud'
|
122
|
+
task :cloud, [:name] do |_, args|
|
123
|
+
name = args.name || 'hdp/live'
|
124
|
+
ap Mystro::Dsl.load("config/mystro/templates/#{name}.rb").actions
|
125
|
+
end
|
126
|
+
|
127
|
+
desc 'compute volumes'
|
128
|
+
task :volumes do
|
129
|
+
org = Mystro::Organization.get 'ops'
|
130
|
+
connect = org.compute
|
131
|
+
service = connect.service
|
132
|
+
template = Mystro::Dsl.load("config/mystro/templates/hdp/live.rb")
|
133
|
+
puts template.to_hash.to_yaml
|
134
|
+
#actions = template.actions
|
135
|
+
#options = connect.encode(actions.first.data)
|
136
|
+
#ap options
|
137
|
+
end
|
2
138
|
|
3
139
|
def changelog(last=nil, single=false)
|
4
140
|
command="git --no-pager log --format='%an::::%h::::%s'"
|
File without changes
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'fog/dynect'
|
2
|
+
require 'fog/dns'
|
3
|
+
|
4
|
+
module Fog
|
5
|
+
module DNS
|
6
|
+
class Dynect < Fog::Service
|
7
|
+
|
8
|
+
requires :dynect_customer, :dynect_username, :dynect_password
|
9
|
+
recognizes :timeout, :persistent
|
10
|
+
recognizes :provider # remove post deprecation
|
11
|
+
|
12
|
+
model_path 'fog/ext/dynect/models/dns'
|
13
|
+
model :record
|
14
|
+
collection :records
|
15
|
+
model :zone
|
16
|
+
collection :zones
|
17
|
+
|
18
|
+
request_path 'fog/ext/dynect/requests/dns'
|
19
|
+
request :delete_record
|
20
|
+
request :delete_zone
|
21
|
+
request :get_node_list
|
22
|
+
request :get_all_records
|
23
|
+
request :get_record
|
24
|
+
request :get_zone
|
25
|
+
request :post_record
|
26
|
+
request :post_session
|
27
|
+
request :post_zone
|
28
|
+
request :put_zone
|
29
|
+
|
30
|
+
class JobIncomplete < Error; end
|
31
|
+
|
32
|
+
class Mock
|
33
|
+
def initialize(options={})
|
34
|
+
@dynect_customer = options[:dynect_customer]
|
35
|
+
@dynect_username = options[:dynect_username]
|
36
|
+
@dynect_password = options[:dynect_password]
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.data
|
40
|
+
@data ||= {
|
41
|
+
:zones => {}
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.reset
|
46
|
+
@data = nil
|
47
|
+
end
|
48
|
+
|
49
|
+
def auth_token
|
50
|
+
@auth_token ||= Fog::Dynect::Mock.token
|
51
|
+
end
|
52
|
+
|
53
|
+
def data
|
54
|
+
self.class.data
|
55
|
+
end
|
56
|
+
|
57
|
+
def reset_data
|
58
|
+
self.class.reset
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class Real
|
63
|
+
def initialize(options={})
|
64
|
+
@dynect_customer = options[:dynect_customer]
|
65
|
+
@dynect_username = options[:dynect_username]
|
66
|
+
@dynect_password = options[:dynect_password]
|
67
|
+
|
68
|
+
@connection_options = options[:connection_options] || {}
|
69
|
+
@host = 'api-v4.dynect.net'
|
70
|
+
@port = options[:port] || 443
|
71
|
+
@path = options[:path] || '/REST'
|
72
|
+
@persistent = options[:persistent] || false
|
73
|
+
@scheme = options[:scheme] || 'https'
|
74
|
+
@version = options[:version] || '3.5.2'
|
75
|
+
@connection = Fog::Connection.new("#{@scheme}://#{@host}:#{@port}", @persistent, @connection_options)
|
76
|
+
end
|
77
|
+
|
78
|
+
def auth_token
|
79
|
+
@auth_token ||= post_session.body['data']['token']
|
80
|
+
end
|
81
|
+
|
82
|
+
def request(params)
|
83
|
+
begin
|
84
|
+
# any request could redirect to a job
|
85
|
+
params[:expects] = Array(params[:expects]) | [307]
|
86
|
+
|
87
|
+
params[:headers] ||= {}
|
88
|
+
params[:headers]['Content-Type'] = 'application/json'
|
89
|
+
params[:headers]['API-Version'] = @version
|
90
|
+
params[:headers]['Auth-Token'] = auth_token unless params[:path] == 'Session'
|
91
|
+
params[:path] = "#{@path}/#{params[:path]}" unless params[:path] =~ %r{^#{Regexp.escape(@path)}/}
|
92
|
+
|
93
|
+
response = @connection.request(params.merge!({:host => @host}))
|
94
|
+
|
95
|
+
if response.body.empty?
|
96
|
+
response.body = {}
|
97
|
+
elsif response.headers['Content-Type'] == 'application/json'
|
98
|
+
response.body = Fog::JSON.decode(response.body)
|
99
|
+
end
|
100
|
+
|
101
|
+
if response.body['status'] == 'failure'
|
102
|
+
raise Error, response.body['msgs'].first['INFO']
|
103
|
+
end
|
104
|
+
|
105
|
+
if response.status == 307 && params[:path] !~ %r{^/REST/Job/}
|
106
|
+
response = poll_job(response, params[:expects])
|
107
|
+
end
|
108
|
+
|
109
|
+
response
|
110
|
+
rescue Excon::Errors::HTTPStatusError => error
|
111
|
+
if @auth_token && error.message =~ /login: (Bad or expired credentials|inactivity logout)/
|
112
|
+
@auth_token = nil
|
113
|
+
retry
|
114
|
+
else
|
115
|
+
raise error
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
response
|
120
|
+
end
|
121
|
+
|
122
|
+
def poll_job(response, original_expects, time_to_wait = 10)
|
123
|
+
job_location = response.headers['Location']
|
124
|
+
|
125
|
+
Fog.wait_for(time_to_wait) do
|
126
|
+
response = request(:expects => original_expects, :method => :get, :path => job_location)
|
127
|
+
response.body['status'] != 'incomplete'
|
128
|
+
end
|
129
|
+
|
130
|
+
if response.body['status'] == 'incomplete'
|
131
|
+
raise JobIncomplete.new("Job #{response.body['job_id']} is still incomplete")
|
132
|
+
end
|
133
|
+
|
134
|
+
response
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'fog/core/model'
|
2
|
+
|
3
|
+
module Fog
|
4
|
+
module DNS
|
5
|
+
class Dynect
|
6
|
+
|
7
|
+
class Record < Fog::Model
|
8
|
+
extend Fog::Deprecation
|
9
|
+
|
10
|
+
identity :id
|
11
|
+
attribute :name, :aliases => [:fqdn, 'fqdn']
|
12
|
+
attribute :rdata
|
13
|
+
attribute :serial_style
|
14
|
+
attribute :ttl
|
15
|
+
attribute :type, :aliases => 'record_type'
|
16
|
+
|
17
|
+
def destroy
|
18
|
+
requires :identity, :name, :type, :zone
|
19
|
+
service.delete_record(type, zone.identity, name, identity)
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
def save
|
24
|
+
requires :name, :type, :rdata, :zone
|
25
|
+
|
26
|
+
options = {
|
27
|
+
:ttl => ttl
|
28
|
+
}
|
29
|
+
options.delete_if {|key, value| value.nil?}
|
30
|
+
|
31
|
+
data = service.post_record(type, zone.identity, name, rdata, options).body['data']
|
32
|
+
# avoid overwriting zone object with zone string
|
33
|
+
data = data.reject {|key, value| key == 'zone'}
|
34
|
+
merge_attributes(data)
|
35
|
+
|
36
|
+
zone.publish
|
37
|
+
records = service.get_record(type, zone.identity, name).body['data']
|
38
|
+
# data in format ['/REST/xRecord/domain/fqdn/identity]
|
39
|
+
records.map! do |record|
|
40
|
+
tokens = record.split('/')
|
41
|
+
{
|
42
|
+
:identity => tokens.last,
|
43
|
+
:type => tokens[2][0...-6] # everything before 'Record'
|
44
|
+
}
|
45
|
+
end
|
46
|
+
record = records.detect {|record| record[:type] == type}
|
47
|
+
merge_attributes(record)
|
48
|
+
|
49
|
+
true
|
50
|
+
end
|
51
|
+
|
52
|
+
def zone
|
53
|
+
@zone
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def zone=(new_zone)
|
59
|
+
@zone = new_zone
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'fog/core/collection'
|
2
|
+
require 'fog/ext/dynect/models/dns/record'
|
3
|
+
|
4
|
+
module Fog
|
5
|
+
module DNS
|
6
|
+
class Dynect
|
7
|
+
|
8
|
+
class Records < Fog::Collection
|
9
|
+
|
10
|
+
attribute :zone
|
11
|
+
|
12
|
+
model Fog::DNS::Dynect::Record
|
13
|
+
|
14
|
+
def all(options = {})
|
15
|
+
requires :zone
|
16
|
+
data = []
|
17
|
+
service.get_all_records(zone.domain, options).body['data'].each do |url|
|
18
|
+
(_, _, t, _, fqdn, id) = url.split('/')
|
19
|
+
type = t.gsub(/Record$/, '')
|
20
|
+
|
21
|
+
# leave out the default, read only records
|
22
|
+
# by putting this here we don't make the secondary request for these records
|
23
|
+
next if ['NS', 'SOA'].include?(type)
|
24
|
+
record = service.get_record(type, zone.domain, fqdn, 'record_id' => id).body['data']
|
25
|
+
|
26
|
+
data << {
|
27
|
+
:identity => record['record_id'],
|
28
|
+
:fqdn => record['fqdn'],
|
29
|
+
:type => record['record_type'],
|
30
|
+
:rdata => record['rdata']
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
load(data)
|
35
|
+
end
|
36
|
+
|
37
|
+
def get(record_id)
|
38
|
+
requires :zone
|
39
|
+
|
40
|
+
list = service.get_all_records(zone.domain, {}).body['data']
|
41
|
+
url = list.detect { |e| e =~ /\/#{record_id}$/ }
|
42
|
+
return unless url
|
43
|
+
(_, _, t, _, fqdn, id) = url.split('/')
|
44
|
+
type = t.gsub(/Record$/, '')
|
45
|
+
record = service.get_record(type, zone.domain, fqdn, 'record_id' => id).body['data']
|
46
|
+
|
47
|
+
new({
|
48
|
+
:identity => record['record_id'],
|
49
|
+
:fqdn => record['fqdn'],
|
50
|
+
:type => record['record_type'],
|
51
|
+
:rdata => record['rdata']
|
52
|
+
})
|
53
|
+
end
|
54
|
+
|
55
|
+
def new(attributes = {})
|
56
|
+
requires :zone
|
57
|
+
super({:zone => zone}.merge!(attributes))
|
58
|
+
end
|
59
|
+
|
60
|
+
def find_by_name(name)
|
61
|
+
requires :zone
|
62
|
+
data = []
|
63
|
+
service.get_all_records(zone.domain, {}).body['data'].select { |url| url =~ /\/#{name}\// }.each do |url|
|
64
|
+
(_, _, t, _, fqdn, id) = url.split('/')
|
65
|
+
type = t.gsub(/Record$/, '')
|
66
|
+
|
67
|
+
# leave out the default, read only records
|
68
|
+
next if ['NS', 'SOA'].include?(type)
|
69
|
+
|
70
|
+
record = service.get_record(type, zone.domain, fqdn, 'record_id' => id).body['data']
|
71
|
+
|
72
|
+
data << {
|
73
|
+
:identity => record['record_id'],
|
74
|
+
:fqdn => record['fqdn'],
|
75
|
+
:type => record['record_type'],
|
76
|
+
:rdata => record['rdata']
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
load(data)
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'fog/core/model'
|
2
|
+
require 'fog/ext/dynect/models/dns/records'
|
3
|
+
|
4
|
+
module Fog
|
5
|
+
module DNS
|
6
|
+
class Dynect
|
7
|
+
|
8
|
+
class Zone < Fog::Model
|
9
|
+
|
10
|
+
identity :domain
|
11
|
+
|
12
|
+
attribute :domain, :aliases => 'zone'
|
13
|
+
attribute :email, :aliases => 'rname'
|
14
|
+
attribute :serial
|
15
|
+
attribute :serial_style
|
16
|
+
attribute :ttl
|
17
|
+
attribute :type, :aliases => 'zone_type'
|
18
|
+
|
19
|
+
def initialize(attributes={})
|
20
|
+
super
|
21
|
+
end
|
22
|
+
|
23
|
+
def destroy
|
24
|
+
requires :domain
|
25
|
+
service.delete_zone(domain)
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
undef_method :domain=
|
30
|
+
def domain=(new_domain)
|
31
|
+
attributes[:domain] = new_domain.split('/').last
|
32
|
+
end
|
33
|
+
|
34
|
+
def publish
|
35
|
+
requires :identity
|
36
|
+
data = service.put_zone(identity, 'publish' => true)
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
def records
|
41
|
+
@records ||= Fog::DNS::Dynect::Records.new(:zone => self, :service => service)
|
42
|
+
end
|
43
|
+
|
44
|
+
def nameservers
|
45
|
+
raise 'nameservers Not Implemented'
|
46
|
+
end
|
47
|
+
|
48
|
+
def save
|
49
|
+
self.ttl ||= 3600
|
50
|
+
requires :domain, :email, :ttl
|
51
|
+
data = service.post_zone(email, ttl, domain).body['data']
|
52
|
+
merge_attributes(data)
|
53
|
+
true
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'fog/core/collection'
|
2
|
+
require 'fog/ext/dynect/models/dns/zone'
|
3
|
+
|
4
|
+
module Fog
|
5
|
+
module DNS
|
6
|
+
class Dynect
|
7
|
+
|
8
|
+
class Zones < Fog::Collection
|
9
|
+
|
10
|
+
model Fog::DNS::Dynect::Zone
|
11
|
+
|
12
|
+
def all
|
13
|
+
data = service.get_zone.body['data'].map do |zone|
|
14
|
+
{ :domain => zone }
|
15
|
+
end
|
16
|
+
load(data)
|
17
|
+
end
|
18
|
+
|
19
|
+
def get(zone_id)
|
20
|
+
new(service.get_zone('zone' => zone_id).body['data'])
|
21
|
+
rescue Excon::Errors::NotFound
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Fog
|
2
|
+
module DNS
|
3
|
+
class Dynect
|
4
|
+
class Real
|
5
|
+
|
6
|
+
# Delete a record
|
7
|
+
#
|
8
|
+
# ==== Parameters
|
9
|
+
# * type<~String> - type of record in ['AAAA', 'ANY', 'A', 'CNAME', 'DHCID', 'DNAME', 'DNSKEY', 'DS', 'KEY', 'LOC', 'MX', 'NSA', 'NS', 'PTR', 'PX', 'RP', 'SOA', 'SPF', 'SRV', 'SSHFP', 'TXT']
|
10
|
+
# * zone<~String> - zone of record
|
11
|
+
# * fqdn<~String> - fqdn of record
|
12
|
+
# * record_id<~String> - id of record
|
13
|
+
|
14
|
+
def delete_record(type, zone, fqdn, record_id)
|
15
|
+
request(
|
16
|
+
:expects => 200,
|
17
|
+
:idempotent => true,
|
18
|
+
:method => :delete,
|
19
|
+
:path => ["#{type.to_s.upcase}Record", zone, fqdn, record_id].join('/')
|
20
|
+
)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Mock
|
25
|
+
def delete_record(type, zone, fqdn, record_id)
|
26
|
+
raise Fog::DNS::Dynect::NotFound unless zone = self.data[:zones][zone]
|
27
|
+
|
28
|
+
raise Fog::DNS::Dynect::NotFound unless zone[:records][type].find { |record| record[:fqdn] == fqdn && record[:record_id] == record_id.to_i }
|
29
|
+
|
30
|
+
zone[:records_to_delete] << {
|
31
|
+
:type => type,
|
32
|
+
:fqdn => fqdn,
|
33
|
+
:record_id => record_id.to_i
|
34
|
+
}
|
35
|
+
|
36
|
+
response = Excon::Response.new
|
37
|
+
response.status = 200
|
38
|
+
|
39
|
+
response.body = {
|
40
|
+
"status" => "success",
|
41
|
+
"data" => {},
|
42
|
+
"job_id" => Fog::Dynect::Mock.job_id,
|
43
|
+
"msgs" => [{
|
44
|
+
"INFO" => "delete: Record will be deleted on zone publish",
|
45
|
+
"SOURCE" => "BLL",
|
46
|
+
"ERR_CD" => nil,
|
47
|
+
"LVL" => "INFO"
|
48
|
+
}]
|
49
|
+
}
|
50
|
+
|
51
|
+
response
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|