plesk_lib 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.md +89 -0
  7. data/Rakefile +1 -0
  8. data/lib/plesk_lib.rb +29 -0
  9. data/lib/plesk_lib/account.rb +14 -0
  10. data/lib/plesk_lib/actions/base.rb +61 -0
  11. data/lib/plesk_lib/actions/change_customer_password.rb +27 -0
  12. data/lib/plesk_lib/actions/create_account.rb +23 -0
  13. data/lib/plesk_lib/actions/create_customer.rb +21 -0
  14. data/lib/plesk_lib/actions/create_reseller.rb +22 -0
  15. data/lib/plesk_lib/actions/create_service_plan.rb +327 -0
  16. data/lib/plesk_lib/actions/create_subscription.rb +55 -0
  17. data/lib/plesk_lib/actions/get_statistics.rb +61 -0
  18. data/lib/plesk_lib/actions/list_customers.rb +51 -0
  19. data/lib/plesk_lib/actions/list_service_plans.rb +60 -0
  20. data/lib/plesk_lib/actions/list_subscriptions.rb +42 -0
  21. data/lib/plesk_lib/customer.rb +4 -0
  22. data/lib/plesk_lib/reseller.rb +5 -0
  23. data/lib/plesk_lib/server.rb +23 -0
  24. data/lib/plesk_lib/service_plan.rb +17 -0
  25. data/lib/plesk_lib/subscription.rb +14 -0
  26. data/lib/plesk_lib/version.rb +3 -0
  27. data/plesk_lib.gemspec +30 -0
  28. data/spec/actions/change_customer_password_spec.rb +29 -0
  29. data/spec/actions/create_customer_spec.rb +50 -0
  30. data/spec/actions/create_reseller_spec.rb +35 -0
  31. data/spec/actions/create_service_plan_spec.rb +33 -0
  32. data/spec/actions/create_subscription_spec.rb +21 -0
  33. data/spec/actions/get_statistics_spec.rb +15 -0
  34. data/spec/actions/list_customers_spec.rb +31 -0
  35. data/spec/actions/list_service_plans_spec.rb +31 -0
  36. data/spec/actions/list_subscriptions.rb +31 -0
  37. data/spec/customer_spec.rb +21 -0
  38. data/spec/reseller_spec.rb +22 -0
  39. data/spec/server_spec.rb +48 -0
  40. data/spec/spec_helper.rb +28 -0
  41. data/spec/vcr/customer/change_password_existing_user.yml +57 -0
  42. data/spec/vcr/customer/change_password_missing_user.yml +57 -0
  43. data/spec/vcr/customer/list_customers.yml +57 -0
  44. data/spec/vcr/customer/list_customers_filtered.yml +57 -0
  45. data/spec/vcr/customer/minimal.yml +112 -0
  46. data/spec/vcr/customer/minimal_exists.yml +112 -0
  47. data/spec/vcr/customer/minimal_with_owner.yml +58 -0
  48. data/spec/vcr/reseller/minimal.yml +58 -0
  49. data/spec/vcr/reseller/minimal_exists.yml +58 -0
  50. data/spec/vcr/server/get_statistics.yml +57 -0
  51. data/spec/vcr/service_plan/create_minimal.yml +58 -0
  52. data/spec/vcr/service_plan/create_minimal_with_owner.yml +58 -0
  53. data/spec/vcr/service_plan/list_admin.yml +57 -0
  54. data/spec/vcr/service_plan/list_all.yml +57 -0
  55. data/spec/vcr/subscription/create.yml +57 -0
  56. data/spec/vcr/subscription/list_subscriptions.yml +57 -0
  57. data/spec/vcr/subscription/list_subscriptions_filtered.yml +57 -0
  58. metadata +257 -0
@@ -0,0 +1,55 @@
1
+ class PleskLib::Actions::CreateSubscription < PleskLib::Actions::Base
2
+ attr_reader :subscription, :plesk_id, :guid
3
+
4
+ def initialize(subscription)
5
+ @subscription = subscription
6
+ end
7
+
8
+ # Creates Object & Packet
9
+ def build_xml
10
+ xml = Builder::XmlMarkup.new
11
+ xml.instruct!
12
+ xml.packet(:version => '1.6.3.5') {
13
+ xml.webspace {
14
+ xml.add {
15
+ xml.gen_setup{
16
+ xml.name(subscription.name)
17
+ if subscription.owner_id.present?
18
+ xml.tag!('owner-id', subscription.owner_id)
19
+ end
20
+ if subscription.owner_login.present?
21
+ xml.tag!('owner-login', subscription.owner_login)
22
+ end
23
+ xml.ip_address(subscription.ip_address)
24
+ }
25
+ xml.hosting{
26
+ xml.vrt_hst{
27
+ xml.property{
28
+ xml.name('ftp_login')
29
+ xml.value(subscription.ftp_login)
30
+ }
31
+ xml.property{
32
+ xml.name('ftp_password')
33
+ xml.value(subscription.ftp_password)
34
+ }
35
+ xml.ip_address(subscription.ip_address)
36
+ }
37
+ }
38
+ if subscription.service_plan_id.present?
39
+ xml.tag!('plan-id', subscription.service_plan_id)
40
+ end
41
+ if subscription.service_plan_name.present?
42
+ xml.tag!('plan-name', subscription.service_plan_name)
43
+ end
44
+ }
45
+ }
46
+ }
47
+ xml.target!
48
+ end
49
+
50
+ def analyse(xml_document)
51
+ add_node = xml_document.root.locate('*/result').first
52
+ @plesk_id = add_node.id.text.to_i
53
+ @guid = add_node.guid.text
54
+ end
55
+ end
@@ -0,0 +1,61 @@
1
+ class PleskLib::Actions::GetStatistics < PleskLib::Actions::Base
2
+ attr_reader :statistics
3
+
4
+ def build_xml
5
+ xml = Builder::XmlMarkup.new
6
+ xml.instruct!
7
+ xml.packet(:version => '1.6.3.5') {
8
+ xml.server{
9
+ xml.get{
10
+ xml.stat()
11
+ }
12
+ }
13
+ }
14
+ return xml.target!
15
+ end
16
+
17
+ def analyse(xml_document)
18
+ status_root = xml_document.root.server.get.result.stat
19
+ @statistics = {}
20
+ object_stats = {}
21
+ device_stats = {}
22
+
23
+ status_root.objects.nodes.each do |node|
24
+ object_stats[node.name] = node.text.to_i
25
+ end
26
+
27
+ status_root.load_avg.nodes.each do |node|
28
+ @statistics[node.name] = node.text.to_f / 100
29
+ end
30
+
31
+ status_root.mem.nodes.each do |node|
32
+ @statistics['mem_' + node.name] = BigDecimal.new(node.text)
33
+ end
34
+
35
+ status_root.swap.nodes.each do |node|
36
+ @statistics['swap_' + node.name] = BigDecimal.new(node.text)
37
+ end
38
+
39
+ status_root.diskspace.nodes.each do |device_node|
40
+ device_name = nil, device_attrs = {}
41
+ device_node.nodes.each do |attr_node|
42
+ if attr_node.name == 'name'
43
+ device_name = attr_node.text
44
+ else
45
+ device_attrs[attr_node.name] = BigDecimal.new(attr_node.text)
46
+ end
47
+ end
48
+ device_stats[device_name] = device_attrs
49
+ end
50
+
51
+ status_root.version.nodes.each do |node|
52
+ @statistics[node.name] = node.text
53
+ end
54
+
55
+ status_root.other.nodes.each do |node|
56
+ @statistics[node.name] = node.name == 'uptime' ? node.text.to_i : node.text
57
+ end
58
+
59
+ @statistics.merge!({objects: object_stats, devices: device_stats})
60
+ end
61
+ end
@@ -0,0 +1,51 @@
1
+ class PleskLib::Actions::ListCustomers < PleskLib::Actions::Base
2
+ attr_reader :customers
3
+
4
+ MAPPING = {
5
+ 'cr_date' => 'created_at', 'cname' => 'company_name', 'pname' => 'person_name',
6
+ 'login' => 'login', 'status' => 'status', 'phone' => 'phone', 'fax' => 'fax',
7
+ 'email' => 'email', 'address' => 'address', 'city' => 'city', 'state' => 'state',
8
+ 'pcode' => 'postal_code', 'country' => 'country', 'locale' => 'locale',
9
+ 'guid' => 'guid', 'owner-id' => 'owner_id', 'vendor-guid' => 'vendor_guid',
10
+ 'external-id' => 'external_id', 'password' => 'password',
11
+ 'password_type' => 'password_type'
12
+ }
13
+
14
+ def initialize(owner_id = nil)
15
+ @owner_id = owner_id
16
+ end
17
+
18
+ def build_xml
19
+ xml = Builder::XmlMarkup.new
20
+ xml.instruct!
21
+ xml.packet(:version => '1.6.3.5') {
22
+ xml.customer {
23
+ xml.get {
24
+ xml.filter {
25
+ xml.tag!('owner-id', @owner_id) if @owner_id.present?
26
+ }
27
+ xml.dataset {
28
+ xml.gen_info
29
+ xml.stat
30
+ }
31
+ }
32
+ }
33
+ }
34
+ return xml.target!
35
+ end
36
+
37
+ def analyse(xml_document)
38
+ @customers = []
39
+ xml_document.root.customer.get.nodes.each do |customer_node|
40
+ customer = PleskLib::Customer.new(nil)
41
+ customer_node.data.gen_info.nodes.each do |attribute_node|
42
+ customer_attribute = MAPPING[attribute_node.name]
43
+ next if customer_attribute.blank? || !customer.respond_to?(customer_attribute) ||
44
+ attribute_node.text.blank?
45
+ customer.send("#{customer_attribute}=", attribute_node.text)
46
+ end
47
+ customer.status = customer.status.to_i
48
+ @customers << customer
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,60 @@
1
+ class PleskLib::Actions::ListServicePlans < PleskLib::Actions::Base
2
+ attr_reader :service_plans
3
+
4
+ def initialize(owner_id = nil)
5
+ @owner_id = owner_id
6
+ end
7
+
8
+ MAPPING = {
9
+ 'cr_date' => 'created_at', 'cname' => 'company_name', 'pname' => 'person_name',
10
+ 'login' => 'login', 'status' => 'status', 'phone' => 'phone', 'fax' => 'fax',
11
+ 'email' => 'email', 'address' => 'address', 'city' => 'city', 'state' => 'state',
12
+ 'pcode' => 'postal_code', 'country' => 'country', 'locale' => 'locale',
13
+ 'guid' => 'guid', 'owner-id' => 'owner_id', 'vendor-guid' => 'vendor_guid',
14
+ 'external-id' => 'external_id', 'password' => 'password',
15
+ 'password_type' => 'password_type'
16
+ }
17
+
18
+ def build_xml
19
+ xml = Builder::XmlMarkup.new
20
+ xml.instruct!
21
+ xml.packet(:version => '1.6.3.5') {
22
+ xml.tag!('service-plan') {
23
+ xml.get {
24
+ xml.filter
25
+ if @owner_id.present?
26
+ xml.tag!('owner-id', @owner_id)
27
+ else
28
+ xml.tag!('owner-all')
29
+ end
30
+ }
31
+ }
32
+ }
33
+ return xml.target!
34
+ end
35
+
36
+ def analyse(xml_document)
37
+ @service_plans = []
38
+ xml_document.root.send('service-plan').get.nodes.each do |plan_el|
39
+ service_plan = PleskLib::ServicePlan.new(plan_el.locate('name').first.text)
40
+ # binding.pry
41
+ service_plan.id = plan_el.send('id').text.to_i
42
+ service_plan.external_id = plan_el.send('external-id').text
43
+ service_plan.guid = plan_el.send('guid').text
44
+
45
+ owner_id_nodes = plan_el.locate('owner-id')
46
+ if owner_id_nodes.first.present?
47
+ service_plan.owner_id = owner_id_nodes.first.text.to_i
48
+ end
49
+
50
+ # plan_el.elements['data//gen_info'].each_element do |attribute|
51
+ # service_plan_attribute = MAPPING[attribute.name]
52
+ # next if service_plan_attribute.blank? || !service_plan.respond_to?(service_plan_attribute) ||
53
+ # attribute.text.blank?
54
+ # service_plan.send("#{service_plan_attribute}=", attribute.text)
55
+ # end
56
+ # service_plan.status = service_plan.status.to_i
57
+ @service_plans << service_plan
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,42 @@
1
+ class PleskLib::Actions::ListSubscriptions < PleskLib::Actions::Base
2
+ attr_reader :subscriptions
3
+
4
+ def initialize(owner_id = nil)
5
+ @owner_id = owner_id
6
+ end
7
+
8
+ def build_xml
9
+ xml = Builder::XmlMarkup.new
10
+ xml.instruct!
11
+ xml.packet(:version => '1.6.3.5') {
12
+ xml.webspace {
13
+ xml.get {
14
+ xml.filter {
15
+ xml.tag!('owner-id', @owner_id) if @owner_id.present?
16
+ }
17
+ xml.dataset {
18
+ xml.gen_info
19
+ xml.hosting
20
+ }
21
+ }
22
+ }
23
+ }
24
+ return xml.target!
25
+ end
26
+
27
+ def analyse(xml_document)
28
+ @subscriptions = []
29
+ xml_document.root.webspace.get.nodes.each do |webspace_node|
30
+ subscription = PleskLib::Subscription.new
31
+ # binding.pry
32
+ webspace_node.data.gen_info.nodes.each do |attribute_node|
33
+ subscription_attribute = attribute_node.name.underscore
34
+ next if !subscription.respond_to?(subscription_attribute) ||
35
+ attribute_node.text.blank?
36
+ subscription.send("#{subscription_attribute}=", attribute_node.text)
37
+ end
38
+ subscription.id = webspace_node.id.text.to_i
39
+ @subscriptions << subscription
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,4 @@
1
+ module PleskLib
2
+ class Customer < Account
3
+ end
4
+ end
@@ -0,0 +1,5 @@
1
+ module PleskLib
2
+ class Reseller < Account
3
+ attr_accessor :service_plan_id
4
+ end
5
+ end
@@ -0,0 +1,23 @@
1
+ module PleskLib
2
+ class Server
3
+ attr_accessor :host, :password, :username
4
+
5
+ def initialize(host, username, password)
6
+ @host = host
7
+ @username = username
8
+ @password = password
9
+ end
10
+
11
+ def method_missing(method_name, *args)
12
+ begin
13
+ action_class = "PleskLib::Actions::#{method_name.to_s.camelize}".constantize
14
+ rescue NameError => e
15
+ raise NoMethodError, "The Action #{e.name} is not available. Please check the action docs."
16
+ else
17
+ action = action_class.new(*args)
18
+ action.execute_on(self)
19
+ return action
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ module PleskLib
2
+ class ServicePlan
3
+ attr_accessor :name, :mailboxes, :domains, :traffic, :storage, :external_id,
4
+ :owner_id, :id, :guid
5
+
6
+ def initialize(name, attributes = {})
7
+ @name = name
8
+ attributes.each_pair do |key, value|
9
+ send("#{key}=", value)
10
+ end if attributes.present?
11
+ end
12
+
13
+ def to_s
14
+ "#<#{self.class}: id=#{self.id} name=#{self.name}, guid: #{self.guid}>"
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ module PleskLib
2
+ class Subscription
3
+ attr_accessor :id, :ip_address, :name, :owner_id, :owner_login,
4
+ :service_plan_name, :service_plan_id, :customer_account_id,
5
+ :reseller_account_id, :external_id, :guid, :vendor_guid,
6
+ :ftp_login, :ftp_password
7
+
8
+ def initialize(attributes = {})
9
+ attributes.each_pair do |key, value|
10
+ send("#{key}=", value)
11
+ end if attributes.present?
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,3 @@
1
+ module PleskLib
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'plesk_lib/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "plesk_lib"
8
+ spec.version = PleskLib::VERSION
9
+ spec.authors = ["Phillipp Röll"]
10
+ spec.email = ["phillipp.roell@trafficplex.de"]
11
+ spec.summary = %q{Plesk 11 provisioning library. Extracted out of plesk_kit}
12
+ spec.description = %q{Add customers, resellers, service plans and subscriptions to plesk via the XML RPC API}
13
+ spec.homepage = "https://github.com/phillipp/plesk_lib"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_runtime_dependency "activesupport", ">= 3.0.0"
22
+ spec.add_runtime_dependency "ox", "~> 2.1.1"
23
+ spec.add_runtime_dependency "builder", "~> 3.2.2"
24
+ spec.add_development_dependency "bundler", "~> 1.5"
25
+ spec.add_development_dependency "rake"
26
+ spec.add_development_dependency "rspec", "~> 2.14.1"
27
+ spec.add_development_dependency "vcr", "~> 2.8.0"
28
+ spec.add_development_dependency "webmock", "~> 1.17.4"
29
+ spec.add_development_dependency "pry", "~> 0.9.12.6"
30
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe PleskLib::Actions::ChangeCustomerPassword do
4
+ let(:server) { PleskLib::Server.new('10.0.0.158', 'admin', 'ccsnDxnWy2j0') }
5
+
6
+ context 'when user exists on the server' do
7
+ let(:customer) { PleskLib::Customer.new('user91') }
8
+
9
+ it 'should reset the customers password' do
10
+ VCR.use_cassette 'customer/change_password_existing_user', match_requests_on: [:method, :uri, :body] do
11
+ action = PleskLib::Actions::ChangeCustomerPassword.new(customer, 'new_password')
12
+ action.execute_on(server)
13
+ end
14
+ end
15
+ end
16
+
17
+ context 'when user is missing' do
18
+ let(:customer) { PleskLib::Customer.new('unknownuser') }
19
+
20
+ it 'should raise a AccountNotFound exception' do
21
+ VCR.use_cassette 'customer/change_password_missing_user', match_requests_on: [:method, :uri, :body] do
22
+ action = PleskLib::Actions::ChangeCustomerPassword.new(customer, 'new_password')
23
+ expect {
24
+ action.execute_on(server)
25
+ }.to raise_error(PleskLib::AccountNotFound)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe PleskLib::Actions::CreateCustomer do
4
+ let(:customer_attributes) do
5
+ { password: 'customer_secret', phone: '0000000000',
6
+ email: 'noreply@ausupport.com.au', country: 'AU',
7
+ person_name: 'FirstName LastName', company_name: 'My Company' }
8
+ end
9
+
10
+ let(:server) { PleskLib::Server.new('10.0.0.158', 'admin', 'ccsnDxnWy2j0') }
11
+ let(:customer) { PleskLib::Customer.new('cust91', customer_attributes) }
12
+
13
+ context 'when login is available on the plesk server' do
14
+ it 'should create a customer' do
15
+ VCR.use_cassette 'customer/minimal', match_requests_on: [:method, :uri, :body] do
16
+ action = PleskLib::Actions::CreateCustomer.new(customer)
17
+ action.execute_on(server)
18
+ action.plesk_id.to_i.should > 0
19
+ end
20
+ end
21
+ end
22
+
23
+ context 'when an owner id is set' do
24
+ let(:customer) { PleskLib::Customer.new('cust8891', customer_attributes) }
25
+ let(:customer_attributes) do
26
+ { password: 'customer_secret', phone: '0000000000',
27
+ email: 'noreply@ausupport.com.au', country: 'AU',
28
+ person_name: 'FirstName LastName', company_name: 'My Company',
29
+ owner_id: 3 }
30
+ end
31
+ it 'should create a customer' do
32
+ VCR.use_cassette 'customer/minimal_with_owner', match_requests_on: [:method, :uri, :body] do
33
+ action = PleskLib::Actions::CreateCustomer.new(customer)
34
+ action.execute_on(server)
35
+ action.plesk_id.to_i.should > 0
36
+ end
37
+ end
38
+ end
39
+
40
+ context 'when login is already taken' do
41
+ it 'should raise a LoginAlreadyTaken exception' do
42
+ VCR.use_cassette 'customer/minimal_exists', match_requests_on: [:method, :uri, :body] do
43
+ action = PleskLib::Actions::CreateCustomer.new(customer)
44
+ expect {
45
+ action.execute_on(server)
46
+ }.to raise_error(PleskLib::LoginAlreadyTaken)
47
+ end
48
+ end
49
+ end
50
+ end