ec2_ultradns_updater 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ config/live.config.yaml
2
+ ec2_ultradns_updater.log
3
+ pkg
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "http://rubygems.org"
2
+ source "http://gems.github.com"
3
+
4
+
5
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,63 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ec2_ultradns_updater (0.0.1)
5
+ aws-sdk
6
+ savon
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ remote: http://gems.github.com/
11
+ specs:
12
+ akami (1.0.0)
13
+ gyoku (>= 0.4.0)
14
+ aws-sdk (1.5.2)
15
+ httparty (~> 0.7)
16
+ json (~> 1.4)
17
+ nokogiri (>= 1.4.4)
18
+ uuidtools (~> 2.1)
19
+ builder (3.0.0)
20
+ diff-lcs (1.1.3)
21
+ fakeweb (1.3.0)
22
+ gyoku (0.4.5)
23
+ builder (>= 2.1.2)
24
+ httparty (0.8.3)
25
+ multi_json (~> 1.0)
26
+ multi_xml
27
+ httpi (0.9.7)
28
+ rack
29
+ json (1.7.3)
30
+ multi_json (1.3.6)
31
+ multi_xml (0.5.1)
32
+ nokogiri (1.5.3)
33
+ nori (1.1.0)
34
+ rack (1.4.1)
35
+ rake (0.9.2.2)
36
+ rspec (2.10.0)
37
+ rspec-core (~> 2.10.0)
38
+ rspec-expectations (~> 2.10.0)
39
+ rspec-mocks (~> 2.10.0)
40
+ rspec-core (2.10.1)
41
+ rspec-expectations (2.10.0)
42
+ diff-lcs (~> 1.1.3)
43
+ rspec-mocks (2.10.1)
44
+ savon (0.9.9)
45
+ akami (~> 1.0)
46
+ builder (>= 2.1.2)
47
+ gyoku (>= 0.4.0)
48
+ httpi (~> 0.9)
49
+ nokogiri (>= 1.4.0)
50
+ nori (~> 1.1)
51
+ wasabi (~> 2.1)
52
+ uuidtools (2.1.2)
53
+ wasabi (2.1.1)
54
+ nokogiri (>= 1.4.0)
55
+
56
+ PLATFORMS
57
+ ruby
58
+
59
+ DEPENDENCIES
60
+ ec2_ultradns_updater!
61
+ fakeweb
62
+ rake
63
+ rspec
data/LICENSE ADDED
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,26 @@
1
+ # UltraDNS updater for EC2 instances
2
+
3
+ ## Description
4
+
5
+ This gem provides the capability to update your UltraDNS configured [CNAME](http://en.wikipedia.org/wiki/CNAME_record) to point to EC2 instance public hostnames.
6
+
7
+ ## Installation
8
+
9
+ ### Requires
10
+
11
+ * Ruby & Ruby developer packages needed for nokugiri dependencies (Ubuntu example)
12
+
13
+ sudo apt-get install ruby1.9.1-dev ruby1.9.1 ri1.9.1 rdoc1.9.1 irb1.9.1 libreadline-ruby1.9.1 libruby1.9.1 libopenssl-ruby
14
+ sudo apt-get install libxslt-dev libxml2-dev
15
+
16
+
17
+ gem install ec2_ultradns_updater
18
+
19
+ ## Usage
20
+
21
+ 1. Configure an EC2 instance tag with the name 'Name' and the value of the CNAME to set for the instance
22
+ 2. Create a YAML configuration (see: config/sample.config.yaml)
23
+ 3. Run: ec2_ultradns_updater -c /etc/ec2_ultradns_updater_config.yaml
24
+
25
+
26
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new
5
+
6
+ task :test => :spec
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ###
4
+ # Copyright 2012 NeuStar, Inc. All rights reserved.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+
19
+ begin
20
+ require 'ec2_ultradns_updater'
21
+
22
+ Ec2UltraDNSUpdater::CLI.run
23
+
24
+ exit 0
25
+ rescue
26
+ exit 1
27
+ end
@@ -0,0 +1,15 @@
1
+ ---
2
+ aws:
3
+ access_key_id : 'ACCESS KEY ID'
4
+ secret_access_key : 'ACCESS KEY'
5
+ name_tag : 'Name' # tag to use in AWS for the DNS cname
6
+ ultradns:
7
+ username : 'username'
8
+ password : 'password'
9
+ zone : 'yyy.zzzz.'
10
+ log_to: 'ec2_ultradns_updater.log'
11
+ # only need to set these if you want to test against the live service(s)
12
+ # test_public_hostname:
13
+ # - 'ec2-x-x-x-x.compute-1.amazonaws.com'
14
+ # - 'ec2-a-a-a-a.compute-1.amazonaws.com'
15
+ # test_cname: 'xxxx.yyy.zzzz.'
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "ec2_ultradns_updater/version"
4
+
5
+
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "ec2_ultradns_updater"
9
+ s.version = Ec2UltraDNSUpdater::VERSION
10
+ s.authors = ["ultradns"]
11
+ s.email = ["ultradns@neustar.biz"]
12
+ s.homepage = ""
13
+ s.summary = %q{Update UltraDNS for EC2 instances}
14
+ s.description = %q{Update your UltraDNS configured CNAMEs to point to EC2 instance public hostnames}
15
+
16
+ s.rubyforge_project = "ec2_ultradns_updater"
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ["lib" ,"bin"]
22
+
23
+
24
+ s.add_runtime_dependency "aws-sdk"
25
+ s.add_runtime_dependency "savon" # http://savonrb.com/
26
+
27
+ s.add_development_dependency "rake"
28
+ s.add_development_dependency "rspec"
29
+ s.add_development_dependency "fakeweb"
30
+ end
@@ -0,0 +1,94 @@
1
+ # Copyright 2012 NeuStar, Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'optparse'
16
+ require 'ostruct'
17
+ require 'yaml'
18
+
19
+
20
+ class Ec2UltraDNSUpdater::CLI
21
+
22
+ def self.run
23
+ opts = parse(ARGV)
24
+
25
+ ec2 = Ec2UltraDNSUpdater::Ec2.new(opts['aws'])
26
+ ultradns = Ec2UltraDNSUpdater::UltraDNS.new(opts['ultradns'])
27
+ name_tag_value = ec2.get_name_tag
28
+
29
+ result = ultradns.create_or_update_cname(name_tag_value, ec2.get_instance_public_hostname)
30
+ if !result
31
+ error_text = "Error Creating or Updating CNAME for #{ec2.get_instance_public_hostname} to #{name_tag_value}"
32
+ @logger.error error_text
33
+ ::Logger.new(STDERR).error error_text
34
+ end
35
+ end
36
+
37
+ def self.load_config(filename)
38
+ config = configure_logger(YAML.load_file(filename))
39
+ end
40
+
41
+ def self.configure_logger(opts)
42
+ if opts['log_to']
43
+ @logger = ::Logger.new(opts['log_to'])
44
+ end
45
+ @logger ||= ::Logger.new(STDOUT)
46
+
47
+ @logger.level = opts['verbose'] ? Logger::DEBUG : Logger::INFO
48
+
49
+ opts['aws']['logger'] = @logger if opts['aws']
50
+ opts['ultradns']['logger'] = @logger if opts['ultradns']
51
+
52
+ opts
53
+ end
54
+
55
+ def self.parse(args)
56
+ options = {}
57
+ options['aws'] = {}
58
+ options['ultradns'] = {}
59
+ options['log_to'] = ::Logger.new(STDOUT)
60
+ options['verbose'] = false
61
+
62
+ opts = OptionParser.new do |opts|
63
+ opts.banner = "Usage: ec2_ultradns_updater [options]"
64
+
65
+ opts.separator ""
66
+ opts.separator "Specific options:"
67
+
68
+ opts.on("-c", "--config config.yaml",
69
+ "Configuration for the updater") do |config|
70
+ options.merge!(load_config(config))
71
+ end
72
+ opts.separator ""
73
+
74
+ opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
75
+ options['verbose'] = v
76
+ end
77
+
78
+ opts.on_tail("-h", "--help", "Show this message") do
79
+ puts opts
80
+ exit
81
+ end
82
+
83
+ # Another typical switch to print the version.
84
+ opts.on_tail("--version", "Show version") do
85
+ puts Ec2UltraDNSUpdater::VERSION
86
+ exit
87
+ end
88
+ end
89
+
90
+ opts.parse!(args)
91
+ options
92
+ end
93
+ end
94
+
@@ -0,0 +1,53 @@
1
+ # Copyright 2012 NeuStar, Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ class Ec2UltraDNSUpdater::Ec2
17
+
18
+ def initialize(opts = {})
19
+ AWS.config(
20
+ :access_key_id => opts['access_key_id'],
21
+ :secret_access_key => opts['secret_access_key'])
22
+
23
+ @logger = opts['logger'] || Logger.new(STDOUT)
24
+ @tag_name = opts['name_tag'] || 'Name' # default to Name
25
+ end
26
+
27
+ def get_instance_id
28
+ @instance_id ||= Net::HTTP.get(URI("#{Ec2UltraDNSUpdater::EC2_META_DATA_URL}/instance-id"))
29
+ @logger.debug("Instance ID = #{@instance_id}")
30
+ @instance_id
31
+ end
32
+
33
+ def get_instance_public_hostname
34
+ @public_hostname ||= Net::HTTP.get(URI("#{Ec2UltraDNSUpdater::EC2_META_DATA_URL}/public-hostname"))
35
+ @logger.debug("Public Hostname = #{@public_hostname}")
36
+ @public_hostname
37
+ end
38
+
39
+ def get_name_tag
40
+ ec2 = AWS::EC2.new
41
+ dns_cname = ''
42
+ ec2.tags.filter('resource-id', get_instance_id()).each do |tag|
43
+ @logger.debug { tag.resource.inspect } # resource is an EC2 object, e.g. AWS::EC2::VPC
44
+ @logger.debug { tag.name }
45
+ @logger.debug { tag.value }
46
+ dns_cname = tag.value if tag.name == @tag_name
47
+ end
48
+ @logger.debug("Tagged DNS CNAME = #{dns_cname} for #{get_instance_id()}")
49
+ dns_cname
50
+ end
51
+ end
52
+
53
+
@@ -0,0 +1,25 @@
1
+ # Copyright 2012 NeuStar, Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ module Ec2UltraDNSUpdater::Preconditions
17
+
18
+ def precondition
19
+ self
20
+ end
21
+
22
+ def str_not_empty(arg, msg = "Argument may not empty")
23
+ raise msg if arg == nil || arg == ''
24
+ end
25
+ end
@@ -0,0 +1,139 @@
1
+ # Copyright 2012 NeuStar, Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ class Ec2UltraDNSUpdater::UltraDNS
17
+ include Ec2UltraDNSUpdater::Preconditions
18
+
19
+ ULTRADNS_WSDL_URL = "http://ultra-api.ultradns.com:8008/UltraDNS_WS/v01?wsdl"
20
+ CNAME_TYPE = 5
21
+
22
+ def initialize(opts = {})
23
+ @logger = opts['logger'] || Logger.new(STDOUT)
24
+
25
+ Savon.configure do |config|
26
+ config.logger = @logger
27
+ config.raise_errors = false
28
+ end
29
+ # also configure HTTPI
30
+ HTTPI.logger = @logger
31
+
32
+ @username = opts['username']
33
+ @password = opts['password']
34
+ @zone = fix_zone_name(opts['zone'] || '')
35
+
36
+ precondition.str_not_empty(@username)
37
+ precondition.str_not_empty(@password)
38
+ precondition.str_not_empty(@zone)
39
+ end
40
+
41
+ def get_cname_guid(cname)
42
+ zone = @zone
43
+ fixed_cname = fix_zone_name(cname)
44
+
45
+ guids_resp = client.request(:v01, 'getResourceRecordGUIDList') {
46
+ soap.body do |xml|
47
+ xml.resourceRecord({
48
+ "ZoneName" => zone, 'Type' => CNAME_TYPE, 'DName' => fixed_cname
49
+ })
50
+ end
51
+ }
52
+ log_error(guids_resp)
53
+
54
+ begin
55
+ guid = guids_resp[:get_resource_record_guid_list_response][:resource_record_guid_list][:guid]
56
+ @logger.debug("guid found: #{guid}")
57
+ rescue
58
+ @logger.debug("guid not found")
59
+ end
60
+ guid
61
+ end
62
+
63
+ def create_or_update_cname(cname, to_hostname)
64
+ precondition.str_not_empty(cname)
65
+ precondition.str_not_empty(to_hostname)
66
+
67
+ zone = @zone
68
+ fixed_cname = fix_zone_name(cname)
69
+ fixed_to_hostname = fix_zone_name(to_hostname)
70
+
71
+ guid = get_cname_guid(cname)
72
+
73
+ change_method = 'createResourceRecord'
74
+ record_opts = {'Type' => CNAME_TYPE, 'DName' => fixed_cname, 'TTL' => Ec2UltraDNSUpdater::DEFAULT_TTL}
75
+
76
+ if guid != nil && guid != ''
77
+ @logger.info "Updating Record Mapping: #{fixed_cname} => #{fixed_to_hostname}"
78
+ change_method = 'updateResourceRecord' # update it
79
+ record_opts['Guid'] = guid;
80
+ else
81
+ @logger.info "Creating Record Mapping: #{fixed_cname} => #{fixed_to_hostname}"
82
+ record_opts['ZoneName'] = zone;
83
+ end
84
+
85
+ resp = client.request(:v01, change_method) {
86
+ ns = ''
87
+ soap.namespaces.each do |k, v|
88
+ ns = k.gsub(/xmlns:/,'') if v =~ /schema\.ultraservice\.neustar\.com/
89
+ end
90
+ soap.body do |xml|
91
+ xml.transactionID()
92
+ xml.resourceRecord(record_opts) {
93
+ xml.tag!("#{ns}:InfoValues", {"Info1Value" => fixed_to_hostname})
94
+ }
95
+ end
96
+ }
97
+
98
+ log_error(resp)
99
+ resp.success?
100
+ end
101
+
102
+ def network_status?
103
+ resp = client.request :v01, :get_neustar_network_status
104
+ @logger.debug(resp)
105
+ log_error(resp)
106
+ resp.success?
107
+ end
108
+
109
+ def delete_record_by_guid(guid)
110
+ resp = client.request(:v01, 'deleteResourceRecord') {
111
+ soap.body do |xml|
112
+ xml.transactionID()
113
+ xml.guid(guid)
114
+ end
115
+ }
116
+ log_error(resp)
117
+ resp.success?
118
+ end
119
+
120
+ def client
121
+ soap_username = @username
122
+ soap_password = @password
123
+
124
+ @client ||= Savon::Client.new do
125
+ wsdl.document = ULTRADNS_WSDL_URL
126
+ wsse.credentials soap_username, soap_password
127
+ end
128
+ @client
129
+ end
130
+
131
+ def log_error(response)
132
+ @logger.error {response.to_xml} unless response.success?
133
+ end
134
+
135
+ # ..Must end with a '.'
136
+ def fix_zone_name(name)
137
+ name[-1] != '.' ? "#{name}." : name
138
+ end
139
+ end
@@ -0,0 +1,17 @@
1
+ # Copyright 2012 NeuStar, Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Ec2UltraDNSUpdater
16
+ VERSION = "0.0.1"
17
+ end
@@ -0,0 +1,33 @@
1
+ # Copyright 2012 NeuStar, Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'rubygems'
16
+ require 'bundler/setup'
17
+
18
+ require 'aws-sdk'
19
+ require 'savon'
20
+ require 'net/http'
21
+
22
+ require "ec2_ultradns_updater/cli"
23
+ require "ec2_ultradns_updater/ec2"
24
+ require "ec2_ultradns_updater/preconditions"
25
+ require "ec2_ultradns_updater/ultradns"
26
+ require "ec2_ultradns_updater/version"
27
+
28
+ module Ec2UltraDNSUpdater
29
+ EC2_META_DATA_URL = "http://169.254.169.254/latest/meta-data"
30
+ DEFAULT_TTL = 60
31
+
32
+ end
33
+
@@ -0,0 +1,69 @@
1
+ # Copyright 2012 NeuStar, Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'spec_helper'
16
+ require 'fakeweb'
17
+ require 'ostruct'
18
+
19
+ describe Ec2UltraDNSUpdater::Ec2 do
20
+
21
+ it "should return the instance id" do
22
+ begin
23
+ fake_id = "i-ffffffff"
24
+ FakeWeb.register_uri(:get, Ec2UltraDNSUpdater::EC2_META_DATA_URL + "/instance-id", :body => fake_id)
25
+ ec2 = Ec2UltraDNSUpdater::Ec2.new
26
+ ec2.get_instance_id.should == fake_id
27
+ ec2.get_instance_id.should == fake_id # check memoize
28
+ ensure
29
+ FakeWeb.clean_registry
30
+ end
31
+ end
32
+
33
+ it "should return the public hostname" do
34
+ begin
35
+ fake_name = "ec2-111-111-111-111.compute-1.amazonaws.com"
36
+ FakeWeb.register_uri(:get, Ec2UltraDNSUpdater::EC2_META_DATA_URL + "/public-hostname", :body => fake_name)
37
+ ec2 = Ec2UltraDNSUpdater::Ec2.new
38
+ ec2.get_instance_public_hostname.should == fake_name
39
+ ec2.get_instance_public_hostname.should == fake_name # check memoize
40
+ ensure
41
+ FakeWeb.clean_registry
42
+ end
43
+ end
44
+
45
+ it "should return the dns tag name" do
46
+ begin
47
+ tag = OpenStruct.new
48
+ tag.name = "Testname" # it expects "Name", but we configure it explictly below as an example
49
+ tag.value = "tag.test.biz"
50
+ tag.resource = 'i-eeeeee'
51
+
52
+ tags = Object.new
53
+ tags.stub(:filter).and_return([tag])
54
+
55
+ AWS::EC2.any_instance.stub(:tags).and_return(tags)
56
+ fake_name = "ec2-111-111-111-111.compute-1.amazonaws.com"
57
+ FakeWeb.register_uri(:get, Ec2UltraDNSUpdater::EC2_META_DATA_URL + "/public-hostname", :body => fake_name)
58
+ FakeWeb.register_uri(:get, Ec2UltraDNSUpdater::EC2_META_DATA_URL + "/instance-id", :body => tag.resource)
59
+
60
+ ec2 = Ec2UltraDNSUpdater::Ec2.new({'access_key_id' => 123, 'secret_access_key' => 'abc', 'name_tag' => 'Testname'})
61
+ ec2.get_name_tag.should == tag.value
62
+
63
+ ensure
64
+ AWS::EC2.any_instance.unstub(:tags)
65
+ FakeWeb.clean_registry
66
+ end
67
+ end
68
+ end
69
+
@@ -0,0 +1,77 @@
1
+ # Copyright 2012 NeuStar, Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'spec_helper'
16
+ require 'fakeweb'
17
+ require 'yaml'
18
+
19
+ describe Ec2UltraDNSUpdater::UltraDNS do
20
+
21
+ it "should raise if cname is empty" do
22
+ ultra = Ec2UltraDNSUpdater::UltraDNS.new({'username' => 'blah', 'password' => 'blah', 'zone' => 'ultrandns.com.'})
23
+ expect { ultra.create_or_update_cname }.to raise_error
24
+ end
25
+
26
+ it "should raise if to_hostname is empty" do
27
+ ultra = Ec2UltraDNSUpdater::UltraDNS.new({'username' => 'blah', 'password' => 'blah', 'zone' => 'ultrandns.com.'})
28
+ expect { ultra.create_or_update_cname("adsf", '') }.to raise_error
29
+ end
30
+
31
+ it "should fix a zone name without a trailing dot" do
32
+ ultra = Ec2UltraDNSUpdater::UltraDNS.new({'username' => 'blah', 'password' => 'blah', 'zone' => 'ultrandns.com.'})
33
+ ultra.fix_zone_name("a.b.com").should == "a.b.com."
34
+ end
35
+
36
+ it "should not change a zone name with a trailing dot" do
37
+ ultra = Ec2UltraDNSUpdater::UltraDNS.new({'username' => 'blah', 'password' => 'blah', 'zone' => 'ultrandns.com.'})
38
+ name = "a.b.biz."
39
+ ultra.fix_zone_name(name).should == name
40
+ end
41
+
42
+ ## testing with the live service we use a configuration not checked in due to passwords and such
43
+ LIVE_CONFIG = File.join(File.dirname(__FILE__), '..', '..', 'config', 'live.config.yaml')
44
+
45
+ it "should check network status" do
46
+ config = Ec2UltraDNSUpdater::CLI.load_config(LIVE_CONFIG)
47
+ config.should_not eq(nil)
48
+
49
+ ultra = Ec2UltraDNSUpdater::UltraDNS.new(config['ultradns'])
50
+ (ultra.network_status?).should eq(true)
51
+ end
52
+
53
+ it "should create a new record and then update the record" do
54
+ config = Ec2UltraDNSUpdater::CLI.load_config(LIVE_CONFIG)
55
+ config.should_not eq(nil)
56
+
57
+ ultra = Ec2UltraDNSUpdater::UltraDNS.new(config['ultradns'])
58
+ guid = ultra.get_cname_guid(config['test_cname'])
59
+ if guid != nil && guid != ''
60
+ ultra.delete_record_by_guid(guid).should eq(true)
61
+ end
62
+
63
+ result = ultra.create_or_update_cname(config['test_cname'], config['test_public_hostname'][0])
64
+ result.should eq(true)
65
+ guid_0 = ultra.get_cname_guid(config['test_cname'])
66
+ guid_0.should_not be_empty
67
+
68
+ result = ultra.create_or_update_cname(config['test_cname'], config['test_public_hostname'][1])
69
+ result.should eq(true)
70
+ guid_1 = ultra.get_cname_guid(config['test_cname'])
71
+ guid_1.should_not be_empty
72
+ guid_0.should == guid_1
73
+ #TODO, check the value
74
+ end
75
+
76
+ end
77
+
@@ -0,0 +1,17 @@
1
+ # Copyright 2012 NeuStar, Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'ec2_ultradns_updater'
16
+
17
+
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ec2_ultradns_updater
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - ultradns
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-01 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: aws-sdk
16
+ requirement: &2160602020 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2160602020
25
+ - !ruby/object:Gem::Dependency
26
+ name: savon
27
+ requirement: &2160601600 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *2160601600
36
+ - !ruby/object:Gem::Dependency
37
+ name: rake
38
+ requirement: &2160601180 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *2160601180
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec
49
+ requirement: &2160600760 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *2160600760
58
+ - !ruby/object:Gem::Dependency
59
+ name: fakeweb
60
+ requirement: &2160600340 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *2160600340
69
+ description: Update your UltraDNS configured CNAMEs to point to EC2 instance public
70
+ hostnames
71
+ email:
72
+ - ultradns@neustar.biz
73
+ executables:
74
+ - ec2_ultradns_updater
75
+ extensions: []
76
+ extra_rdoc_files: []
77
+ files:
78
+ - .gitignore
79
+ - Gemfile
80
+ - Gemfile.lock
81
+ - LICENSE
82
+ - README.md
83
+ - Rakefile
84
+ - bin/ec2_ultradns_updater
85
+ - config/sample.config.yaml
86
+ - ec2_ultradns_updater.gemspec
87
+ - lib/ec2_ultradns_updater.rb
88
+ - lib/ec2_ultradns_updater/cli.rb
89
+ - lib/ec2_ultradns_updater/ec2.rb
90
+ - lib/ec2_ultradns_updater/preconditions.rb
91
+ - lib/ec2_ultradns_updater/ultradns.rb
92
+ - lib/ec2_ultradns_updater/version.rb
93
+ - spec/lib/ec2_spec.rb
94
+ - spec/lib/ultradns_spec.rb
95
+ - spec/spec_helper.rb
96
+ homepage: ''
97
+ licenses: []
98
+ post_install_message:
99
+ rdoc_options: []
100
+ require_paths:
101
+ - lib
102
+ - bin
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ! '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ! '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubyforge_project: ec2_ultradns_updater
117
+ rubygems_version: 1.8.6
118
+ signing_key:
119
+ specification_version: 3
120
+ summary: Update UltraDNS for EC2 instances
121
+ test_files:
122
+ - spec/lib/ec2_spec.rb
123
+ - spec/lib/ultradns_spec.rb
124
+ - spec/spec_helper.rb