Skip to content

Commit

Permalink
Merge pull request #1584 from yeti-switch/1562-phonesystems-provision…
Browse files Browse the repository at this point in the history
…er-trunks-provisioning

156, [Phone.Systems provisioner] trunks provisioning
  • Loading branch information
dmitry-sinina authored Oct 22, 2024
2 parents a5b7652 + 8ab2a4a commit 3747453
Show file tree
Hide file tree
Showing 17 changed files with 942 additions and 157 deletions.
22 changes: 21 additions & 1 deletion app/admin/billing/services.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,27 @@
def create_resource(object)
object.save
rescue Billing::Provisioning::Errors::Error => e
flash[:warning] = e.message
object.errors.add(:base, e.message)
false
rescue SocketError => e
capture_exception(e)
object.errors.add(:base, e.message)
false
end

def destroy_resource(object)
object.destroy
rescue Billing::Provisioning::PhoneSystems::PhoneSystemsApiClient::NotFoundError => _e
# continue deleting Service in Yeti side because record already deleted from Phone Systems server
flash[:warning] = 'The Customer already deleted from the Phone Systems server'
# perform delete request without the Billing::Provisioning::Base#before_destroy callback
object.delete
rescue Billing::Provisioning::Errors::Error => e
object.errors.add(:base, e.message)
false
rescue SocketError => e
capture_exception(e)
object.errors.add(:base, e.message)
false
end
end
Expand Down
4 changes: 2 additions & 2 deletions app/models/billing/provisioning/phone_systems.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ def verify_service_variables!
end

def after_create
CustomerService.create_customer(service)
Provisioning::PhoneSystems::Core.provision_services(service)
end

def before_destroy
CustomerService.delete_customer(service)
Provisioning::PhoneSystems::Core.rollback_provision_services(service)
end

def self.verify_service_type_variables!(service_type)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# frozen_string_literal: true

module Billing
module Provisioning
class PhoneSystems
class ConfigurationService
def initialize(service)
@service = service
@service_variables = service.type.variables.merge(service.variables)
@api_client = PhoneSystemsApiClient.new(@service_variables)
end

def configure_services
response = configure_incoming_trunk
response = configure_gateway(response)
configure_route(response)
end

def delete_configuration
# There is no reason to send a separate requests to delete gateway and trunk in Phone Systems server
# because this entities is dependent from Customer and will be deleted automatically.
GatewayService.delete_yeti_gateway(@service)
end

private

def configure_incoming_trunk
IncomingTrunkService.new(@service).create_trunk
end

def configure_gateway(response)
gws = GatewayService.new(@service, response)
response_from_pbx = gws.create_remote_gateway
gws.create_yeti_gateway!

response_from_pbx
end

def configure_route(response)
RouteService.new(@service, response).create_route
end
end
end
end
end
33 changes: 33 additions & 0 deletions app/models/billing/provisioning/phone_systems/core.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# frozen_string_literal: true

module Billing
module Provisioning
class PhoneSystems
class Core
def initialize(service)
@service = service
@service_variables = service.type.variables.merge(service.variables)
@api_client = PhoneSystemsApiClient.new(@service_variables)
end

def provision_services
CustomerCreationService.new(@service).create_customer
ConfigurationService.new(@service).configure_services
end

def rollback_provision_services
CustomerCreationService.new(@service).delete_customer
ConfigurationService.new(@service).delete_configuration
end

def self.provision_services(service)
new(service).provision_services
end

def self.rollback_provision_services(service)
new(service).rollback_provision_services
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# frozen_string_literal: true

module Billing
module Provisioning
class PhoneSystems
class CustomerCreationService
def initialize(service)
@service = service
@service_variables = service.type.variables.merge(service.variables)
@api_client = PhoneSystemsApiClient.new(@service_variables)
end

def create_customer
payload = {
data: {
id: @service.id,
type: 'customers',
attributes: @service.variables['attributes']
}
}

response = @api_client.create_customer(payload)
@api_client.process_response(response, 'create') do |response_body|
@service.update(id: response_body.dig('data', 'id'))
end
end

def delete_customer
response = @api_client.delete_customer(@service.id)
@api_client.process_response(response, 'delete')
end
end
end
end
end
67 changes: 0 additions & 67 deletions app/models/billing/provisioning/phone_systems/customer_service.rb

This file was deleted.

81 changes: 81 additions & 0 deletions app/models/billing/provisioning/phone_systems/gateway_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# frozen_string_literal: true

module Billing
module Provisioning
class PhoneSystems
class GatewayService
def initialize(service, response = {})
@service = service
@service_variables = service.type.variables.merge(service.variables)
@api_client = PhoneSystemsApiClient.new(@service_variables)
@domain = response.dig('data', 'attributes', 'domain')
end

def create_remote_gateway
payload = {
data: {
type: 'termination_gateways',
attributes: @service_variables.fetch('ps_trm_gw', default_attributes).merge(name: phone_systems_gateway_name),
relationships: {
customer: {
data: {
type: 'customers',
id: @service.id # Service ID & pbx Customer ID is the same. CustomerCreationService#create_customer.
}
}
}
}
}
response = @api_client.create_gateway(payload)
@api_client.process_response(response, 'create gateway')
end

def default_attributes
{ host: 'sip.yeti-switch.org', authorization_name: generate_auth_username, authorization_password: generate_auth_password }
end

def create_yeti_gateway!
gateway = Gateway.new
gateway_attributes = {
name: yeti_gateway_name,
contractor_id: @service.account.contractor_id,
enabled: true,
host: @domain,
codec_group: CodecGroup.take!
}
gateway.assign_attributes(gateway_attributes)
gateway.save!
rescue ActiveRecord::RecordInvalid => e
Rails.logger.error e.message
raise Billing::Provisioning::Errors::Error, e.message
end

def delete_yeti_gateway
Gateway.delete_by(name: yeti_gateway_name)
end

def self.delete_yeti_gateway(service)
new(service).delete_yeti_gateway
end

private

def yeti_gateway_name
"ps-#{@service.id}"
end

def phone_systems_gateway_name
"gw-#{@service.uuid}"
end

def generate_auth_username
SecureRandom.alphanumeric(20)
end

def generate_auth_password
SecureRandom.alphanumeric(20)
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

module Billing
module Provisioning
class PhoneSystems
class IncomingTrunkService
def initialize(service)
@service = service
@service_variables = service.type.variables.merge(service.variables)
@api_client = PhoneSystemsApiClient.new(@service_variables)
end

def create_trunk
payload = {
data: {
type: 'incoming_trunks',
attributes: @service_variables.fetch('ps_incoming_trunk', {}).merge(name: generate_name),
relationships: {
customer: {
data: {
type: 'customers',
id: @service.id # Service ID & pbx Customer ID is the same. CustomerCreationService#create_customer.
}
}
}
}
}
response = @api_client.create_incoming_trunk(payload)
@api_client.process_response(response, 'create incoming trunk')
end

private

def generate_name
"gw-#{@service.uuid}"
end
end
end
end
end
Loading

0 comments on commit 3747453

Please sign in to comment.