epp-client-hostmaster 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 ADDED
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .idea
19
+ .DS_Store
20
+ dev
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in epp-client.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Yuriy Kolodovskyy
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,144 @@
1
+ # Hostmaster.UA EPP client library
2
+
3
+ EPP (Extensible Provisioning Protocol) client library based on [epp-client-base](https://rubygems.org/gems/epp-client-base) gem.
4
+ Full specification see at [Hostmaster.UA EPP Project](https://epp.hostmaster.ua).
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'epp-client-hostmaster'
11
+
12
+ or this line:
13
+
14
+ gem 'epp-client-hostmaster', git: 'https://github.com/kolodovskyy/epp-client-hostmaster.git'
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install epp-client-hostmaster
23
+
24
+ ## Usage (example)
25
+
26
+ require "epp-client/hostmaster"
27
+
28
+ #ENV['EPP_CLIENT_DEBUG'] = 'yes'
29
+
30
+ c = EPPClient::Hostmaster.new(
31
+ client_id: 'LOGIN',
32
+ password: 'PASSWORD',
33
+ ssl_cert: 'epp.crt',
34
+ ssl_key: 'epp.key'
35
+ )
36
+
37
+ begin
38
+ c.open_connection
39
+ c.login
40
+ c.hello
41
+
42
+ c.contact_check 'test1', 'test2'
43
+ puts c.contact_info 'test1'
44
+
45
+ c.contact_create(
46
+ id: 'test2',
47
+ postalInfo: {
48
+ loc: {
49
+ name: 'Test name',
50
+ org: 'Test organization',
51
+ addr: {
52
+ street: [ 'Test street' ],
53
+ city: 'Kiev',
54
+ pc: '00000',
55
+ cc: 'UA'
56
+ }
57
+ }
58
+ },
59
+ voice: '+380.441234567',
60
+ fax: '+380.441234567',
61
+ email: 'test@test.com',
62
+ authInfo: 'testpassword'
63
+ )
64
+
65
+ c.contact_update(
66
+ id: 'test',
67
+ chg: {
68
+ fax: '+380.447654321'
69
+ }
70
+ )
71
+
72
+ c.contact_delete 'test2'
73
+
74
+ c.host_check 'ns1.test.epp.ua', 'ns2.test.epp.ua'
75
+ c.host_info 'ns1.test.epp.ua'
76
+ c.host_create name: 'ns2.test.epp.ua', addrv4: [ '8.8.8.8' ]
77
+ c.host_update(
78
+ name: 'ns2.test.epp.ua',
79
+ rem: {
80
+ addrv4: '8.8.8.8'
81
+ },
82
+ add: {
83
+ addrv4: '8.8.8.8'
84
+ }
85
+ )
86
+ c.host_delete 'ns2.test.epp.ua'
87
+
88
+ puts c.domain_check 'test1.epp.ua', 'test2.epp.ua'
89
+ puts c.domain_info 'test1.epp.ua'
90
+ c.domain_create(
91
+ name: 'test3.epp.ua',
92
+ period: {
93
+ unit: 'y',
94
+ number: '1'
95
+ },
96
+ ns: [ 'ns1.test.epp.ua' ],
97
+ registrant: 'test',
98
+ contacts: {
99
+ admin: [ 'test' ],
100
+ tech: [ 'test' ]
101
+ }
102
+ )
103
+
104
+ puts c.domain_renew(
105
+ name: 'test.epp.ua',
106
+ curExpDate: '2013-11-19',
107
+ period: {
108
+ unit: 'y',
109
+ number: '1'
110
+ }
111
+ )
112
+
113
+ c.domain_delete('test.epp.ua')
114
+ c.domain_restore('test.epp.ua')
115
+
116
+ c.domain_update(
117
+ name: 'test.epp.ua',
118
+ chg: {
119
+ registrant: 'test1'
120
+ }
121
+ )
122
+
123
+ puts c.poll_req
124
+ puts c.poll_ack
125
+
126
+ puts c.transfer_request name: 'test-transfer.epp.ua', authInfo: '111'
127
+ puts c.transfer_cancel 'test-transfer.epp.ua'
128
+ puts c.transfer_query 'test-transfer.epp.ua'
129
+
130
+ c.logout
131
+ rescue => error
132
+ puts error.to_s
133
+ puts error.backtrace
134
+ ensure
135
+ c.close_connection
136
+ end
137
+
138
+ ## Maintainers and Authors
139
+
140
+ Yuriy Kolodovskyy (https://github.com/kolodovskyy)
141
+
142
+ ## License
143
+
144
+ MIT License. Copyright 2012 [Yuriy Kolodovskyy](http://twitter.com/kolodovskyy)
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'epp-client'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "epp-client-hostmaster"
8
+ gem.version = EPPClient::Hostmaster::VERSION
9
+ gem.authors = ["Yuriy Kolodovskyy"]
10
+ gem.email = %w{kolodovskyy@ukrindex.com}
11
+ gem.description = %q{Hostmaster.UA EPP client library}
12
+ gem.summary = %q{Hostmaster.UA EPP client library}
13
+ gem.homepage = "https://github.com/kolodovskyy/epp-client-hostmaster"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = %w{lib}
19
+
20
+ gem.add_development_dependency "bundler"
21
+ gem.add_dependency('epp-client-base', '~> 0.11.0')
22
+ gem.add_dependency('builder', '~> 3.1.4')
23
+ end
@@ -0,0 +1,9 @@
1
+ module EPPClient
2
+ module HostmasterConnection
3
+ def send_frame(xml)
4
+ @sent_frame = xml
5
+ @socket.write([xml.bytesize + 4].pack("N") + xml)
6
+ sent_frame_to_xml
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,149 @@
1
+ module EPPClient
2
+ module HostmasterContact
3
+ def contact_check_xml(*contacts)
4
+ command do |xml|
5
+ xml.check do
6
+ xml.contact :check, 'xmlns:contact' => EPPClient::SCHEMAS_URL['contact-1.1'] do
7
+ contacts.each { |c| xml.contact :id, c }
8
+ end
9
+ end
10
+ end
11
+ end
12
+
13
+ def contact_info_xml(args)
14
+ command do |xml|
15
+ xml.info do
16
+ xml.contact :info, 'xmlns:contact' => EPPClient::SCHEMAS_URL['contact-1.1'] do
17
+ xml.contact :id, args[:id]
18
+ if args.key? :authInfo
19
+ xml.contact :authInfo do
20
+ xml.contact :pw, args[:authInfo]
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ def contact_create_xml(contact)
29
+ command do |xml|
30
+ xml.create do
31
+ xml.contact :create, 'xmlns:contact' => EPPClient::SCHEMAS_URL['contact-1.1'] do
32
+ if contact.key?(:id)
33
+ xml.contact :id, contact[:id]
34
+ else
35
+ xml.contact :id, 'autonic'
36
+ end
37
+ contact[:postalInfo].each do |type,infos|
38
+ xml.contact :postalInfo, type: type do
39
+ xml.contact :name, infos[:name]
40
+ xml.contact :org, infos[:org] if infos.key?(:org)
41
+ xml.contact :addr do
42
+ infos[:addr][:street].each do |street|
43
+ xml.contact :street, street
44
+ end
45
+ xml.contact :city, infos[:addr][:city]
46
+ xml.contact :sp, infos[:addr][:sp] if infos[:addr].key? :sp
47
+ xml.contact :pc, infos[:addr][:pc] if infos[:addr].key? :pc
48
+ xml.contact :cc, infos[:addr][:cc]
49
+ end
50
+ end
51
+ end
52
+ xml.contact :voice, contact[:voice] if contact.key? :voice
53
+ xml.contact :fax, contact[:fax] if contact.key? :fax
54
+ xml.contact :email, contact[:email]
55
+ xml.contact :authInfo do
56
+ xml.contact :pw, contact[:authInfo]
57
+ end
58
+ if contact.key?(:disclose)
59
+ xml.contact :disclose, flag: '1' do # TODO: parameter for flag need
60
+ contact[:disclose].each do |disc|
61
+ if disc.key?(:type)
62
+ xml.contact disc[:name], type: disc[:type]
63
+ else
64
+ xml.contact disc[:name]
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ def contact_delete_xml(contact)
75
+ command do |xml|
76
+ xml.delete do
77
+ xml.contact :delete, 'xmlns:contact' => EPPClient::SCHEMAS_URL['contact-1.1'] do
78
+ xml.contact :id, contact
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ def contact_update_xml(args)
85
+ command do |xml|
86
+ xml.update do
87
+ xml.contact :update, 'xmlns:contact' => EPPClient::SCHEMAS_URL['contact-1.1'] do
88
+ xml.contact :id, args[:id]
89
+ if args.key?(:add) && args[:add].key?(:status)
90
+ xml.contact :add do
91
+ args[:add][:status].each do |s|
92
+ xml.contact :status, s: s
93
+ end
94
+ end
95
+ end
96
+ if args.key?(:rem) && args[:rem].key?(:status)
97
+ xml.contact :rem do
98
+ args[:rem][:status].each do |s|
99
+ xml.contact :status, s: s
100
+ end
101
+ end
102
+ end
103
+ if args.key?(:chg)
104
+ contact = args[:chg]
105
+ xml.contact :chg do
106
+ if contact.key?(:postalInfo)
107
+ contact[:postalInfo].each do |type,infos|
108
+ xml.contact :postalInfo, type: type do
109
+ xml.contact :name, infos[:name]
110
+ xml.contact :org, infos[:org] if infos.key? :org
111
+ xml.contact :addr do
112
+ infos[:addr][:street].each do |street|
113
+ xml.contact :street, street
114
+ end
115
+ xml.contact :city, infos[:addr][:city]
116
+ xml.contact :sp, infos[:addr][:sp] if infos[:addr].key? :sp
117
+ xml.contact :pc, infos[:addr][:pc] if infos[:addr].key? :pc
118
+ xml.contact :cc, infos[:addr][:cc]
119
+ end
120
+ end
121
+ end
122
+ end
123
+ [:voice, :fax, :email].each do |val|
124
+ xml.contact val, contact[val] if contact.key? val
125
+ end
126
+ if contact.key?(:authInfo)
127
+ xml.contact :authInfo do
128
+ xml.contact :pw, contact[:authInfo]
129
+ end
130
+ end
131
+ if contact.key?(:disclose)
132
+ xml.contact :disclose, flag: '1' do # TODO: parameter for flag need
133
+ contact[:disclose].each do |disc|
134
+ if disc.key?(:type)
135
+ xml.contact disc[:name], type: disc[:type]
136
+ else
137
+ xml.contact disc[:name]
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,183 @@
1
+ module EPPClient
2
+ module HostmasterDomain
3
+ def domain_check_xml(*domains) # :nodoc:
4
+ command do |xml|
5
+ xml.check do
6
+ xml.domain :check, 'xmlns:domain' => EPPClient::SCHEMAS_URL['domain-1.1'] do
7
+ domains.each {|domain| xml.domain :name, domain}
8
+ end
9
+ end
10
+ end
11
+ end
12
+
13
+ def domain_info_xml(args)
14
+ command do |xml|
15
+ xml.info do
16
+ xml.domain :info, 'xmlns:domain' => EPPClient::SCHEMAS_URL['domain-1.1'] do
17
+ xml.domain :name, args[:name]
18
+ if args.key? :authInfo
19
+ xml.domain :authInfo do
20
+ xml.domain :pw, args[:authInfo]
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ def domain_nss_xml(xml, nss)
29
+ xml.domain :ns do
30
+ if nss.first.is_a? Hash
31
+ nss.each do |ns|
32
+ xml.domain :hostAttr do
33
+ xml.domain :hostName, ns[:hostName]
34
+ if ns.key?(:hostAddrv4)
35
+ ns[:hostAddrv4].each do |v4|
36
+ xml.domain :hostAddr, {:ip => :v4}, v4
37
+ end
38
+ end
39
+ if ns.key?(:hostAddrv6)
40
+ ns[:hostAddrv6].each do |v6|
41
+ xml.domain :hostAddr, {:ip => :v6}, v6
42
+ end
43
+ end
44
+ end
45
+ end
46
+ else
47
+ nss.each do |ns|
48
+ xml.domain :hostObj, ns
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ def domain_contacts_xml(xml, args)
55
+ args.each do |type,contacts|
56
+ contacts.each do |c|
57
+ xml.domain :contact, { type: type }, c
58
+ end
59
+ end
60
+ end
61
+
62
+ def domain_period_xml(xml, period)
63
+ xml.domain :period, { unit: period[:unit] }, period[:number]
64
+ end
65
+
66
+ def domain_create_xml(args) #:nodoc:
67
+ command do |xml|
68
+ xml.create do
69
+ xml.domain :create, 'xmlns:domain' => EPPClient::SCHEMAS_URL['domain-1.1'] do
70
+ xml.domain :name, args[:name]
71
+ domain_period_xml(xml, args[:period]) if args.key?(:period)
72
+ domain_nss_xml(xml, args[:ns]) if args.key? :ns
73
+ xml.domain :registrant, args[:registrant]
74
+ domain_contacts_xml(xml, args[:contacts])
75
+ xml.domain :license, args[:license] if args.key? :license
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ def domain_create_process(xml) #:nodoc:
82
+ dom = xml.xpath('epp:resData/domain:creData', EPPClient::SCHEMAS_URL)
83
+ ret = {
84
+ name: dom.xpath('domain:name', EPPClient::SCHEMAS_URL).text,
85
+ crDate: DateTime.parse(dom.xpath('domain:crDate', EPPClient::SCHEMAS_URL).text),
86
+ exDate: DateTime.parse(dom.xpath('domain:exDate', EPPClient::SCHEMAS_URL).text),
87
+ }
88
+ end
89
+
90
+
91
+ def domain_delete_xml(domain) #:nodoc:
92
+ command do |xml|
93
+ xml.delete do
94
+ xml.domain :delete, 'xmlns:domain' => EPPClient::SCHEMAS_URL['domain-1.1'] do
95
+ xml.domain :name, domain
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ def domain_renew_xml(domain)
102
+ command do |xml|
103
+ xml.renew do
104
+ xml.domain :renew, 'xmlns:domain' => EPPClient::SCHEMAS_URL['domain-1.1'] do
105
+ xml.domain :name, domain[:name]
106
+ xml.domain :curExpDate, domain[:curExpDate].strftime('%Y-%m-%d')
107
+ domain_period_xml(xml, domain[:period])
108
+ end
109
+ end
110
+ end
111
+ end
112
+
113
+ # Renew a domain
114
+ #
115
+ # Takes a hash as an argument, containing the following keys :
116
+ #
117
+ # [<tt>:name</tt>] the domain name
118
+ # [<tt>:period</tt>]
119
+ # an optionnal hash containing the period for withch the domain is
120
+ # registered with the following keys :
121
+ # [<tt>:unit</tt>] the unit of time, either "m"onth or "y"ear.
122
+ # [<tt>:number</tt>] the number of unit of time.
123
+ # [<tt>:curExpDate</tt>]
124
+ # the date identifying the current end of the domain object
125
+ # registration period.
126
+ # Returns a hash with the following keys :
127
+ #
128
+ # [<tt>:name</tt>] the fully qualified name of the domain object.
129
+ # [<tt>:exDate</tt>]
130
+ # the date and time identifying the end of the domain object's
131
+ # registration period.
132
+ def domain_renew(domain)
133
+ domain[:curExpDate] = DateTime.parse(domain[:curExpDate]) unless domain[:curExpDate].is_a? DateTime
134
+ response = send_request(domain_renew_xml(domain))
135
+ get_result(:xml => response, :callback => :domain_renew_process)
136
+ end
137
+
138
+ def domain_renew_process(xml) #:nodoc:
139
+ dom = xml.xpath('epp:resData/domain:renData', EPPClient::SCHEMAS_URL)
140
+ ret = {
141
+ name: dom.xpath('domain:name', EPPClient::SCHEMAS_URL).text,
142
+ exDate: DateTime.parse(dom.xpath('domain:exDate', EPPClient::SCHEMAS_URL).text)
143
+ }
144
+ end
145
+
146
+ def domain_update_xml(args) #:nodoc:
147
+ command do |xml|
148
+ xml.update do
149
+ xml.domain :update, 'xmlns:domain' => EPPClient::SCHEMAS_URL['domain-1.1'] do
150
+ xml.domain :name, args[:name]
151
+ [:add, :rem].each do |ar|
152
+ next unless args.key?(ar) && (args[ar].key?(:ns) || args[ar].key?(:contacts) || args[ar].key?(:status))
153
+ xml.domain ar do
154
+ domain_nss_xml(xml, args[ar][:ns]) if args[ar].key? :ns
155
+ domain_contacts_xml(xml, args[ar][:contacts]) if args[ar].key? :contacts
156
+ if args[ar].key? :status
157
+ args[ar][:status].each do |st,text|
158
+ if text.nil?
159
+ xml.domain :status, s: st
160
+ else
161
+ xml.domain :status, { s: st }, text
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
167
+ if args.key?(:chg) && (args[:chg].key?(:registrant) || args[:chg].key?(:authInfo))
168
+ xml.domain :chg do
169
+ xml.domain :registrant, args[:chg][:registrant] if args[:chg].key? :registrant
170
+ if args[:chg].key? :authInfo
171
+ xml.domain :authInfo do
172
+ xml.domain :pw, args[:chg][:authInfo]
173
+ end
174
+ end
175
+ end
176
+ end
177
+ end
178
+ end
179
+ end
180
+ end
181
+
182
+ end
183
+ end
@@ -0,0 +1,223 @@
1
+ require "ipaddr"
2
+
3
+ module EPPClient
4
+ module HostmasterHost
5
+ def host_check_xml(*hosts) #:nodoc:
6
+ command do |xml|
7
+ xml.check do
8
+ xml.host :check, 'xmlns:host' => EPPClient::SCHEMAS_URL['host-1.1'] do
9
+ hosts.each { |host| xml.host :name, host }
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ # Check the availability of hosts
16
+ #
17
+ # takes list of hosts as arguments
18
+ #
19
+ # returns an array of hashes containing three fields :
20
+ # [<tt>:name</tt>] the host name
21
+ # [<tt>:avail</tt>] availability
22
+ # [<tt>:reason</tt>]
23
+ # the server-specific text to help explain why the object cannot be
24
+ # provisioned.
25
+ #
26
+ def host_check(*hosts)
27
+ hosts.flatten!
28
+
29
+ response = send_request(host_check_xml(*hosts))
30
+ get_result(:xml => response, :callback => :host_check_process)
31
+ end
32
+
33
+ def host_check_process(xml) #:nodoc:
34
+ xml.xpath('epp:resData/host:chkData/host:cd', EPPClient::SCHEMAS_URL).map do |dom|
35
+ ret = {
36
+ name: dom.xpath('host:name', EPPClient::SCHEMAS_URL).text,
37
+ avail: dom.xpath('host:name', EPPClient::SCHEMAS_URL).attr('avail').value == '1',
38
+ }
39
+ unless (reason = dom.xpath('host:reason', EPPClient::SCHEMAS_URL).text).empty?
40
+ ret[:reason] = reason
41
+ end
42
+ ret
43
+ end
44
+ end
45
+
46
+ def host_info_xml(args) #:nodoc:
47
+ command do |xml|
48
+ xml.info do
49
+ xml.host :info, 'xmlns:host' => EPPClient::SCHEMAS_URL['host-1.1'] do
50
+ xml.host :name, args[:name]
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ # Returns the informations about a host
57
+ #
58
+ # Takes either a unique argument, either
59
+ # a string, representing the host name
60
+ # or a hash with the following keys :
61
+ # [<tt>:name</tt>] the host name
62
+ #
63
+ # Returned is a hash mapping:
64
+ # [<tt>:name</tt>] host name.
65
+ # [<tt>:roid</tt>]
66
+ # the Repository Object IDentifier assigned to the host object when
67
+ # the object was created.
68
+ # [<tt>:status</tt>] the status or array of statuses of the host object.
69
+ # [<tt>:addrv4</tt>] array with IPv4 addresses.
70
+ # [<tt>:addrv6</tt>] array with IPv6 addresses.
71
+ # [<tt>:clID</tt>] the identifier of the sponsoring client.
72
+ # [<tt>:crID</tt>]
73
+ # the identifier of the client that created the host object.
74
+ # [<tt>:crDate</tt>] the date and time of host object creation.
75
+ # [<tt>:upID</tt>]
76
+ # the optional identifier of the client that last updated the host
77
+ # object.
78
+ # [<tt>:upDate</tt>]
79
+ # the optional date and time of the most recent host object
80
+ # modification.
81
+ # [<tt>:trDate</tt>]
82
+ # the optional date and time of the most recent successful host object
83
+ # transfer.
84
+ def host_info(args)
85
+ args = { name: args } if args.is_a? String
86
+ response = send_request(host_info_xml(args))
87
+ get_result(:xml => response, :callback => :host_info_process)
88
+ end
89
+
90
+ def host_info_process(xml) #:nodoc:
91
+ host = xml.xpath('epp:resData/host:infData', EPPClient::SCHEMAS_URL)
92
+ ret = {
93
+ name: host.xpath('host:name', EPPClient::SCHEMAS_URL).text,
94
+ roid: host.xpath('host:roid', EPPClient::SCHEMAS_URL).text,
95
+ }
96
+ if (status = host.xpath('host:status', EPPClient::SCHEMAS_URL)).size > 0
97
+ ret[:status] = status.map {|s| s.attr('s')}
98
+ end
99
+
100
+ if (value = host.xpath('host:addr', EPPClient::SCHEMAS_URL, ip: 'v4')).size > 0
101
+ ret[:addrv4] = value.map {|ip| IPAddr.new(ip.text)}
102
+ end
103
+ if (value = host.xpath('host:addr', EPPClient::SCHEMAS_URL, ip: 'v6')).size > 0
104
+ ret[:addrv6] = value.map {|ip| IPAddr.new(ip.text)}
105
+ end
106
+
107
+ %w(clID crID upID).each do |val|
108
+ if (value = host.xpath("host:#{val}", EPPClient::SCHEMAS_URL)).size > 0
109
+ ret[val.to_sym] = value.text
110
+ end
111
+ end
112
+ %w(crDate upDate trDate).each do |val|
113
+ if (date = host.xpath("host:#{val}", EPPClient::SCHEMAS_URL)).size > 0
114
+ ret[val.to_sym] = DateTime.parse(date.text)
115
+ end
116
+ end
117
+ ret
118
+ end
119
+
120
+ def host_create_xml(host) #:nodoc:
121
+ command do |xml|
122
+ xml.create do
123
+ xml.host :create, 'xmlns:host' => EPPClient::SCHEMAS_URL['host-1.1'] do
124
+ xml.host :name, host[:name]
125
+ %w(addrv4 addrv6).each do |type|
126
+ next unless host.key? type
127
+ host[type].each {|ip| xml.host :addr, ip}
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+
134
+ # Creates a host
135
+ #
136
+ # Takes a hash as an argument containing the following keys :
137
+ # [<tt>:name</tt>] host name.
138
+ # [<tt>:addrv4</tt>] array with IPv4 addresses.
139
+ # [<tt>:addrv6</tt>] array with IPv6 addresses.
140
+ def host_create(host)
141
+ %w(addrv4 addrv6).each do |type|
142
+ next unless host.key? type
143
+ host[type] = [ host[type] ] unless host[type].is_a? Array
144
+ end
145
+ response = send_request(host_create_xml(host))
146
+ get_result(:xml => response, :callback => :host_create_process)
147
+ end
148
+
149
+ def host_create_process(xml) #:nodoc:
150
+ host = xml.xpath('epp:resData/host:creData', EPPClient::SCHEMAS_URL)
151
+ {
152
+ name: host.xpath('host:name', EPPClient::SCHEMAS_URL).text,
153
+ crDate: DateTime.parse(host.xpath('host:crDate', EPPClient::SCHEMAS_URL).text)
154
+ }
155
+ end
156
+
157
+ def host_delete_xml(host) #:nodoc:
158
+ command do |xml|
159
+ xml.delete do
160
+ xml.host :delete, 'xmlns:host' => EPPClient::SCHEMAS_URL['host-1.1'] do
161
+ xml.host :name, host
162
+ end
163
+ end
164
+ end
165
+ end
166
+
167
+ # Deletes a host
168
+ #
169
+ # Takes a single host for argument.
170
+ #
171
+ # Returns true on success, or raises an exception.
172
+ def host_delete(host)
173
+ response = send_request(host_delete_xml(host))
174
+ get_result(response)
175
+ end
176
+
177
+ def host_update_xml(args) #:nodoc:
178
+ command do |xml|
179
+ xml.update do
180
+ xml.host :update, 'xmlns:host' => EPPClient::SCHEMAS_URL['host-1.1'] do
181
+ xml.host :name, args[:name]
182
+ [:add, :rem].each do |operation|
183
+ if args.key? operation
184
+ xml.host operation do
185
+ args[operation][:status].each {|s| xml.host :status, s: s} if args[operation].key? :status
186
+ %w(addrv4 addrv6).each do |type|
187
+ next unless args[operation].key? type
188
+ args[operation][type].each {|a| xml.host type, a}
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
194
+ end
195
+ end
196
+ end
197
+
198
+ # Updates a host
199
+ #
200
+ # Takes a hash with the name, and at least one of the following keys :
201
+ # [<tt>:name</tt>]
202
+ # the server-unique identifier of the host object to be updated.
203
+ # [<tt>:add</tt>/<tt>:rem</tt>]
204
+ # adds or removes the following data from the host object :
205
+ # [<tt>:addrv4</tt>] an array of IPv4 addresses.
206
+ # [<tt>:addrv6</tt>] an array of IPv6 addresses.
207
+ # [<tt>:status</tt>] an array of status to add to/remove from the object.
208
+ #
209
+ # Returns true on success, or raises an exception.
210
+ def host_update(args)
211
+ [:add, :rem].each do |operation|
212
+ next unless args.key?(operation)
213
+ %w(addrv4 addrv6).each do |type|
214
+ next unless args[operation].key? type
215
+ args[operation][type] = [ args[operation[type]] ] unless args[operation][type].is_a? Array
216
+ end
217
+ end
218
+ response = send_request(host_update_xml(args))
219
+ get_result(response)
220
+ end
221
+
222
+ end
223
+ end
@@ -0,0 +1,27 @@
1
+ module EPPClient
2
+ module HostmasterRGP
3
+ def domain_restore_xml(domain)
4
+ command do |xml|
5
+ xml.update do
6
+ xml.domain :update, 'xmlns:domain' => EPPClient::SCHEMAS_URL['domain-1.1'] do
7
+ xml.domain :name, domain
8
+ end
9
+ end
10
+ xml.extension do
11
+ xml.rgp :update, 'xmlns:rgp' => EPPClient::SCHEMAS_URL['rgp-1.1'] do
12
+ xml.rgp :restore, op: 'request'
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ # Restore a domain
19
+ # Takes a single fully qualified domain name for argument.:
20
+ #
21
+ # Returns an array of rgpStatus.
22
+ def domain_restore(domain)
23
+ response = send_request(domain_restore_xml(domain))
24
+ get_result(:xml => response)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,42 @@
1
+ module EPPClient
2
+ module HostmasterTransfer
3
+ def transfer_xml(domain, op)
4
+ command do |xml|
5
+ xml.transfer op: op do
6
+ xml.domain :transfer, 'xmlns:domain' => EPPClient::SCHEMAS_URL['domain-1.1'] do
7
+ xml.domain :name, domain[:name]
8
+ domain_period_xml(xml, domain[:period]) if domain.key? :period
9
+ if domain.key? :authInfo
10
+ xml.domain :authInfo do
11
+ xml.domain :pw, domain[:authInfo]
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ def transfer(domain, op)
20
+ domain = { name: domain } if domain.is_a? String
21
+ response = send_request(transfer_xml(domain, op))
22
+ get_result(:xml => response, :callback => :transfer_process)
23
+ end
24
+
25
+ %w(request cancel approve reject query).each do |op|
26
+ define_method("transfer_#{op}") { |domain| transfer(domain, op.to_sym) }
27
+ end
28
+
29
+ def transfer_process(xml)
30
+ trn = xml.xpath('epp:resData/domain:trnData', EPPClient::SCHEMAS_URL)
31
+ {
32
+ name: trn.xpath('domain:name', EPPClient::SCHEMAS_URL).text,
33
+ trStatus: trn.xpath('domain:trStatus', EPPClient::SCHEMAS_URL).text,
34
+ reID: trn.xpath('domain:reID', EPPClient::SCHEMAS_URL).text,
35
+ reDate: DateTime.parse(trn.xpath('domain:reDate', EPPClient::SCHEMAS_URL).text),
36
+ acID: trn.xpath('domain:acID', EPPClient::SCHEMAS_URL).text,
37
+ acDate: DateTime.parse(trn.xpath('domain:acDate', EPPClient::SCHEMAS_URL).text),
38
+ exDate: DateTime.parse(trn.xpath('domain:exDate', EPPClient::SCHEMAS_URL).text)
39
+ }
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,7 @@
1
+ module EPPClient
2
+ module HostmasterXML
3
+ def hello
4
+ send_request(builder {|xml| xml.hello})
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,41 @@
1
+ require "epp-client/base"
2
+ require "epp-client/hostmaster-xml"
3
+ require "epp-client/hostmaster-connection"
4
+ require "epp-client/hostmaster-domain"
5
+ require "epp-client/hostmaster-contact"
6
+ require "epp-client/hostmaster-host"
7
+ require "epp-client/hostmaster-rgp"
8
+ require "epp-client/hostmaster-transfer"
9
+
10
+ module EPPClient
11
+ class Hostmaster < Base
12
+ VERSION = '0.2.0'
13
+
14
+ SCHEMAS = %w(domain-1.1 host-1.1 contact-1.1 rgp-1.1)
15
+
16
+ EPPClient::SCHEMAS_URL.merge!(SCHEMAS.inject({}) do |a,s|
17
+ a[s.sub(/-1\.1$/, '')] = "http://hostmaster.ua/epp/#{s}" if s =~ /-1\.1$/
18
+ a[s] = "http://hostmaster.ua/epp/#{s}"
19
+ a
20
+ end)
21
+
22
+ include EPPClient::HostmasterXML
23
+ include EPPClient::HostmasterConnection
24
+ include EPPClient::HostmasterDomain
25
+ include EPPClient::HostmasterContact
26
+ include EPPClient::HostmasterHost
27
+ include EPPClient::HostmasterRGP
28
+ include EPPClient::HostmasterTransfer
29
+
30
+ def initialize(attrs)
31
+ unless attrs.key?(:client_id) && attrs.key?(:password) && attrs.key?(:ssl_cert) && attrs.key?(:ssl_key)
32
+ raise ArgumentError, "client_id, password, ssl_cert and ssl_key are required"
33
+ end
34
+ attrs[:server] ||= 'epp.hostmaster.ua'
35
+ attrs[:port] ||= 700
36
+ attrs[:version] ||= '1.0'
37
+ @services = EPPClient::SCHEMAS_URL.values_at('domain', 'host', 'contact')
38
+ super(attrs)
39
+ end
40
+ end
41
+ end
data/lib/epp-client.rb ADDED
@@ -0,0 +1 @@
1
+ require "epp-client/hostmaster"
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: epp-client-hostmaster
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Yuriy Kolodovskyy
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-19 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: epp-client-base
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 0.11.0
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 0.11.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: builder
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 3.1.4
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 3.1.4
62
+ description: Hostmaster.UA EPP client library
63
+ email:
64
+ - kolodovskyy@ukrindex.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - Gemfile
71
+ - LICENSE.txt
72
+ - README.md
73
+ - Rakefile
74
+ - epp-client-hostmaster.gemspec
75
+ - lib/epp-client.rb
76
+ - lib/epp-client/hostmaster-connection.rb
77
+ - lib/epp-client/hostmaster-contact.rb
78
+ - lib/epp-client/hostmaster-domain.rb
79
+ - lib/epp-client/hostmaster-host.rb
80
+ - lib/epp-client/hostmaster-rgp.rb
81
+ - lib/epp-client/hostmaster-transfer.rb
82
+ - lib/epp-client/hostmaster-xml.rb
83
+ - lib/epp-client/hostmaster.rb
84
+ homepage: https://github.com/kolodovskyy/epp-client-hostmaster
85
+ licenses: []
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 1.8.24
105
+ signing_key:
106
+ specification_version: 3
107
+ summary: Hostmaster.UA EPP client library
108
+ test_files: []