moniker_activeresource 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,20 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem "activemodel", "~> 3.2.12", :require => 'active_model'
4
+ gem "activeresource", "~> 3.2.12", :require => 'active_resource'
5
+
6
+ gem "oj", "~> 1.2.9"
7
+
8
+ group :development, :test do
9
+ gem "shoulda", ">= 0"
10
+ gem "rdoc", "~> 3.12"
11
+ gem "jeweler", "~> 1.8.4"
12
+ gem "simplecov", ">= 0"
13
+ gem 'test-unit'
14
+ end
15
+
16
+ # Security fixes
17
+ gem "json", "~> 1.7.7"
18
+
19
+ # OpenStack ActiveResource
20
+ gem 'openstack_activeresource', '~> 0.5.0'
data/Gemfile.lock ADDED
@@ -0,0 +1,63 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ activemodel (3.2.12)
5
+ activesupport (= 3.2.12)
6
+ builder (~> 3.0.0)
7
+ activeresource (3.2.12)
8
+ activemodel (= 3.2.12)
9
+ activesupport (= 3.2.12)
10
+ activesupport (3.2.12)
11
+ i18n (~> 0.6)
12
+ multi_json (~> 1.0)
13
+ bourne (1.1.2)
14
+ mocha (= 0.10.5)
15
+ builder (3.0.4)
16
+ git (1.2.5)
17
+ i18n (0.6.4)
18
+ jeweler (1.8.4)
19
+ bundler (~> 1.0)
20
+ git (>= 1.2.5)
21
+ rake
22
+ rdoc
23
+ json (1.7.7)
24
+ metaclass (0.0.1)
25
+ mocha (0.10.5)
26
+ metaclass (~> 0.0.1)
27
+ multi_json (1.6.1)
28
+ oj (1.2.13)
29
+ openstack_activeresource (0.5.0)
30
+ activemodel (~> 3.2.12)
31
+ activeresource (~> 3.2.12)
32
+ json (~> 1.7.7)
33
+ oj (~> 1.2.9)
34
+ rake (10.0.3)
35
+ rdoc (3.12.2)
36
+ json (~> 1.4)
37
+ shoulda (3.3.2)
38
+ shoulda-context (~> 1.0.1)
39
+ shoulda-matchers (~> 1.4.1)
40
+ shoulda-context (1.0.2)
41
+ shoulda-matchers (1.4.2)
42
+ activesupport (>= 3.0.0)
43
+ bourne (~> 1.1.2)
44
+ simplecov (0.7.1)
45
+ multi_json (~> 1.0)
46
+ simplecov-html (~> 0.7.1)
47
+ simplecov-html (0.7.1)
48
+ test-unit (2.5.4)
49
+
50
+ PLATFORMS
51
+ ruby
52
+
53
+ DEPENDENCIES
54
+ activemodel (~> 3.2.12)
55
+ activeresource (~> 3.2.12)
56
+ jeweler (~> 1.8.4)
57
+ json (~> 1.7.7)
58
+ oj (~> 1.2.9)
59
+ openstack_activeresource (~> 0.5.0)
60
+ rdoc (~> 3.12)
61
+ shoulda
62
+ simplecov
63
+ test-unit
data/LICENSE.txt ADDED
@@ -0,0 +1,16 @@
1
+ Moniker-ActiveResource
2
+ Copyright (c) 2013 Davide Guerri (@dguerri davide.guerri@gmail.com)
3
+
4
+ This program is free software: you can redistribute it and/or modify
5
+ it under the terms of the GNU General Public License as published by
6
+ the Free Software Foundation, either version 3 of the License, or
7
+ (at your option) any later version.
8
+
9
+ This program is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU General Public License for more details.
13
+
14
+ You should have received a copy of the GNU General Public License
15
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
data/README.rdoc ADDED
@@ -0,0 +1,156 @@
1
+ = moniker_activeresource
2
+
3
+ Moniker Ruby and RoR bindings implemented with ActiveResource
4
+
5
+ Moniker - DNS for OpenStack — Read more at https://launchpad.net/moniker
6
+
7
+ Please note: Moniker is still in alpha stage so is the same for this gem!
8
+
9
+ Tested on Moniker commit 2c66df879574cb595bd8f703818f503badce3bad
10
+
11
+ == Installation
12
+
13
+ Not yet released on rubygems.
14
+ To install this gem clone this repository and:
15
+
16
+ gem install bundler # If not already installed
17
+ bundle install
18
+ rake install
19
+
20
+ == Sample usage
21
+
22
+ This section is incomplete. Please see unit tests for more info.
23
+
24
+ === Keystone authentication and Moniker setup
25
+
26
+ OpenStack::Keystone::Public::Base.site = "https://my.api.com:5000/v2.0/"
27
+
28
+ auth = OpenStack::Keystone::Public::Auth.new :username => "me",
29
+ :password => "my pass",
30
+ :tenant_id => "my_tenant"
31
+
32
+ if auth.save
33
+ Moniker::Base.token = auth.token
34
+ Moniker::Base.site = auth.endpoint_for('dns').publicURL
35
+ # *** Set the sudo tenant id (if needed!)
36
+ Moniker::Base.sudo_tenant = "another tenant id"
37
+ else
38
+ raise "Cannot authenticate!"
39
+ end
40
+
41
+ === Create a new server (requires an administrative role)
42
+
43
+ new_server = Moniker::Server.create :name => "test.test-server.test."
44
+
45
+ === List existing server (requires an administrative role)
46
+
47
+ servers = Moniker::Server.all
48
+
49
+ === Get a server (requires an administrative role)
50
+
51
+ # By name
52
+ server = Moniker::Server.find_by_name "test.test-server.test."
53
+ # By id
54
+ Moniker::Server.find "ffffffff-ffff-ffff-ffff-ffffffffffff"
55
+
56
+ === Update a server (requires an administrative role)
57
+
58
+ server = Moniker::Server.find_by_name "test.test-server.test."
59
+ server.update_attributes :name => "up-test.test-server.test."
60
+ server.save
61
+ # Done! Now revert
62
+ server.name = "test.test-server.test."
63
+ server.save
64
+
65
+ === Destroy a server (requires an administrative role)
66
+
67
+ server = Moniker::Server.find_by_name "test.test-server.test."
68
+ server.destroy
69
+
70
+ === Create a new domain (depending on your configuration, this might require an administrative role)
71
+
72
+ new_domain = Moniker::Domain.create :name => "test.test-domain.test.", :email => "fake@pretend.net"
73
+
74
+ === List existing domains
75
+
76
+ domains = Moniker::Domain.all
77
+
78
+ === Get a domain
79
+
80
+ # By name
81
+ domain = Moniker::Domain.find_by_name "test.test-domain.test."
82
+ # By id
83
+ Moniker::Domain.find "ffffffff-ffff-ffff-ffff-ffffffffffff"
84
+
85
+ === Update a domain (depending on your configuration, this might require an administrative role)
86
+
87
+ domain = Moniker::Domain.find_by_name n"test.test-domain.test."ame
88
+ domain.update_attributes :ttl => 225
89
+ domain.save
90
+ # Again but now without update_attributes
91
+ domain.ttl = 128
92
+ domain.save
93
+
94
+ === Destroy a domain (depending on your configuration, this might require an administrative role)
95
+
96
+ domain = Moniker::Domain.find_by_name n"test.test-domain.test."ame
97
+ domain.destroy
98
+
99
+ === Create a new record
100
+
101
+ domain = Moniker::Domain.find_by_name "test.test-domain.test."
102
+ new_record = Moniker::Record.create :name => record_name,
103
+ :type => "A",
104
+ :data => "1.1.1.1",
105
+ :domain_id => domain.id
106
+
107
+ === List existing records in a domain
108
+
109
+ domain = Moniker::Domain.find_by_name "test.test-domain.test."
110
+ records = Moniker::Record.all :params => {:domain_id => domain.id}
111
+
112
+ === Get a record in a domain
113
+
114
+ domain = Moniker::Domain.find_by_name "test.test-domain.test."
115
+ # All by name
116
+ records = Moniker::Record.find_all_by_name record_name, :params => {:domain_id => domain.id}
117
+ # All by type
118
+ records = Moniker::Record.find_all_by_type "AAAA", :params => {:domain_id => domain.id}
119
+ # All by data
120
+ records = Moniker::Record.find_all_by_data "1.1.1.1", :params => {:domain_id => domain.id}
121
+ # By id
122
+ record = Moniker::Record.find "ffffffff-ffff-ffff-ffff-ffffffffffff", :params => {:domain_id => domain.id}
123
+
124
+ === Update a record in a domain
125
+
126
+ record = Moniker::Record.find "ffffffff-ffff-ffff-ffff-ffffffffffff", :params => {:domain_id => domain.id}
127
+ record.update_attributes :ttl => 225
128
+ record.save
129
+ # Again but now without update_attributes
130
+ record.ttl = 128
131
+ record.save
132
+
133
+ === Destroy a record in a domain
134
+
135
+ record = Moniker::Record.find "ffffffff-ffff-ffff-ffff-ffffffffffff", :params => {:domain_id => domain.id}
136
+ record.destroy
137
+
138
+ == Known limitation
139
+
140
+ Works only with OpenStack Keystone authentication
141
+
142
+ == Contributing to moniker_activeresource
143
+
144
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
145
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
146
+ * Fork the project.
147
+ * Start a feature/bugfix branch.
148
+ * Commit and push until you are happy with your contribution.
149
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
150
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
151
+
152
+ == Copyright
153
+
154
+ Copyright (c) 2013 Davide Guerri (@dguerri davide.guerri@gmail.com). See LICENSE.txt for
155
+ further details.
156
+
data/Rakefile ADDED
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "moniker_activeresource"
18
+ gem.homepage = "https://github.com/Unidata-SpA/moniker_activeresource"
19
+ gem.license = "GPLv3"
20
+ gem.summary = %Q{Moniker Ruby and RoR bindings implemented with ActiveResource}
21
+ gem.description = %Q{Moniker Ruby and RoR bindings implemented with ActiveResource - See also http://www.unicloud.it}
22
+ gem.email = "d.guerri@rd.unidata.it"
23
+ gem.authors = ["Davide Guerri"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ desc "Code coverage detail"
29
+ task :simplecov do
30
+ ENV['COVERAGE'] = "true"
31
+ Rake::Task['<%= test_task %>'].execute
32
+ end
33
+
34
+ task :default => :test
35
+
36
+ require 'rdoc/task'
37
+ Rake::RDocTask.new do |rdoc|
38
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
39
+
40
+ rdoc.rdoc_dir = 'rdoc'
41
+ rdoc.title = "Moniker-Activeresource #{version}"
42
+ rdoc.rdoc_files.include('README*')
43
+ rdoc.rdoc_files.include('lib/**/*.rb')
44
+ end
45
+
46
+ require 'rake/testtask'
47
+
48
+ Rake::TestTask.new do |t|
49
+ t.libs << "test"
50
+ t.test_files = FileList['test/test*.rb']
51
+ t.verbose = true
52
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/lib/hot_fixes.rb ADDED
@@ -0,0 +1,60 @@
1
+ # This file is part of the Moniker-ActiveResource
2
+ #
3
+ # Copyright (C) 2013 Unidata S.p.A. (Davide Guerri - davide.guerri@gmail.com)
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ # Reopens ActiveResource::Base to fix "ActiveResource nested resources not being persisted"
19
+ # See https://github.com/rails/rails/pull/3107
20
+ # and https://github.com/rails/activeresource/pull/30
21
+ # Fixes non yet included in any ActiveResource releases (as of 2013-02-28)
22
+ module ActiveResource # :nodoc:
23
+ class Base
24
+
25
+ def load(attributes, remove_root = false)
26
+ raise ArgumentError, "expected an attributes Hash, got #{attributes.inspect}" unless attributes.is_a?(Hash)
27
+ @prefix_options, attributes = split_options(attributes)
28
+
29
+ if attributes.keys.size == 1
30
+ remove_root = self.class.element_name == attributes.keys.first.to_s
31
+ end
32
+
33
+ attributes = Formats.remove_root(attributes) if remove_root
34
+
35
+ attributes.each do |key, value|
36
+ @attributes[key.to_s] =
37
+ case value
38
+ when Array
39
+ resource = nil
40
+ value.map do |attrs|
41
+ if attrs.is_a?(Hash)
42
+ resource ||= find_or_create_resource_for_collection(key)
43
+ resource.new(attrs, attrs.has_key?(resource.primary_key.to_s))
44
+ else
45
+ attrs.duplicable? ? attrs.dup : attrs
46
+ end
47
+ end
48
+ when Hash
49
+ resource = find_or_create_resource_for(key)
50
+ resource.new(value, value.has_key?(resource.primary_key.to_s))
51
+ else
52
+ value.duplicable? ? value.dup : value
53
+ end
54
+ end
55
+
56
+ self
57
+ end
58
+
59
+ end
60
+ end
data/lib/moniker.rb ADDED
@@ -0,0 +1,43 @@
1
+ # This file is part of the Moniker-ActiveResource
2
+ #
3
+ # Copyright (C) 2013 Unidata S.p.A. (Davide Guerri - davide.guerri@gmail.com)
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require 'rubygems'
19
+ require 'bundler'
20
+
21
+ libdir = File.dirname(__FILE__)
22
+ Dir.chdir libdir do
23
+ Bundler.setup
24
+ end
25
+ Bundler.require :default
26
+
27
+ open_stack_path = File.expand_path('..', __FILE__)
28
+ $:.unshift(open_stack_path) if File.directory?(open_stack_path) && !$:.include?(open_stack_path)
29
+
30
+ # Load locales for countries from +locale+ directory
31
+ I18n.load_path += Dir[ File.join(File.dirname(__FILE__), 'locale', '*.{rb,yml}') ]
32
+
33
+ module Moniker
34
+ extend ActiveSupport::Autoload
35
+
36
+ load 'hot_fixes.rb'
37
+
38
+ autoload :Base
39
+ autoload :Common
40
+ autoload :Server
41
+ autoload :Domain
42
+ autoload :Record
43
+ end
@@ -0,0 +1,133 @@
1
+ # This file is part of the Moniker-ActiveResource
2
+ #
3
+ # Copyright (C) 2012 Unidata S.p.A. (Davide Guerri - davide.guerri@gmail.com)
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ module Moniker
19
+
20
+ DATETIME_FORMAT="%Y-%m-%dT%H:%M:%S"
21
+ IPV4_REGEX= /\A(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\Z/
22
+ IPV4_CIDR_REGEX= /\A(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/(3[0-2]|[1-2][0-9]|[0-9])\Z/
23
+
24
+ class Base < ActiveResource::Base
25
+
26
+ self.format = :json
27
+ self.timeout = 5
28
+
29
+ # Set the X-Auth-Token header if the OpenStack authentication token is present
30
+ # Set the X-Moniker-Sudo-Tenant-ID if a Moniker administrative access is required
31
+ def self.headers
32
+ if defined?(@headers)
33
+ _headers = @headers
34
+ elsif self != Moniker::Base && superclass.headers
35
+ _headers = superclass.headers
36
+ else
37
+ _headers = @headers || {}
38
+ end
39
+
40
+ if self.token.present?
41
+ _headers['X-Auth-Token'] = self.token
42
+ end
43
+
44
+ if self.sudo_tenant.present?
45
+ _headers['X-Moniker-Sudo-Tenant-ID'] = self.sudo_tenant
46
+ end
47
+
48
+ _headers
49
+ end
50
+
51
+ # The following 2 methods overloading are required for Rails applications
52
+
53
+ # Get the Moniker endpoint
54
+ def self.site
55
+ if self == OpenStack::Nova::Compute::Base
56
+ Thread.current[:moniker_site]
57
+ else
58
+ super
59
+ end
60
+ end
61
+
62
+ # Set the Moniker endpoint
63
+ def self.site=(site)
64
+ super(site)
65
+ Thread.current[:moniker_site] = @site
66
+ # Regenerate the prefix method
67
+ default = @site.path
68
+ default << '/' unless default[-1..-1] == '/'
69
+ # generate the actual method based on the current site path
70
+ self.prefix = default
71
+
72
+ @site
73
+ end
74
+
75
+ protected
76
+
77
+ # Set the authentication token
78
+ def self.token=(token)
79
+ # Trying to be thread safe here...
80
+ Thread.current[:open_stack_token] = token.is_a?(OpenStack::Keystone::Public::Auth::Token) ? token.id : token
81
+ end
82
+
83
+ # Get the current authentication token
84
+ def self.token
85
+ # Trying to be thread safe here...
86
+ Thread.current[:open_stack_token]
87
+ end
88
+
89
+ # Set the sudo-tenant for administrative access
90
+ def self.sudo_tenant=(tenant)
91
+ # Trying to be thread safe here...
92
+ Thread.current[:moniker_sudo_tenant] = token.is_a?(OpenStack::Keystone::Admin::Tenant) ? tenant.id : tenant
93
+ end
94
+
95
+ # Get the current sudo-tenant for administrative access
96
+ def self.sudo_tenant
97
+ # Trying to be thread safe here...
98
+ Thread.current[:moniker_sudo_tenant]
99
+ end
100
+ end
101
+
102
+ end
103
+
104
+ # Reopen ActiveResource::ClientError to add the proper parsing for OpenStack errors
105
+ class ActiveResource::ClientError < ActiveResource::ConnectionError
106
+ alias old_message message
107
+ alias old_to_s to_s
108
+
109
+ def message
110
+ decoded_error = decode_openstack_error
111
+ decoded_error.nil? ? @message : decoded_error
112
+ rescue Exception => e
113
+ # Fallback to the original method
114
+ @message
115
+ end
116
+
117
+ def to_s
118
+ decoded_error = decode_openstack_error
119
+ decoded_error.nil? ? old_to_s : decoded_error
120
+ rescue Exception => e
121
+ # Fallback to the original method
122
+ old_to_s
123
+ end
124
+
125
+ private
126
+
127
+ def decode_openstack_error
128
+ decoded_body = ActiveSupport::JSON.decode(self.response.body)
129
+
130
+ decoded_body[decoded_body.keys[0]]['message']
131
+ end
132
+
133
+ end