1#!/usr/bin/ruby
2# frozen_string_literal: true
3
4require "date"
5require "dhall"
6require "em-hiredis"
7require "pg/em/connection_pool"
8require "em-http"
9require "em_promise"
10require "json"
11require "optparse"
12require "ruby-bandwidth-iris"
13require "securerandom"
14require "sentry-ruby"
15require "time"
16
17@verbosity = 0
18@real_data = true
19@dry_run = false
20@sources = []
21@filters = {}
22
23OptionParser.new do |opts|
24 opts.banner =
25 "Usage: porting [-vn] " \
26 "[-c CUSTOMER_ID] " \
27 "-s <bandwidth|db|fake> DHALL_CONFIG"
28
29 opts.on(
30 "-v", "--verbose",
31 "Print to terminal, run twice to not even send to customer"
32 ) do
33 @verbosity += 1
34 end
35
36 opts.on(
37 "-n", "--dry-run",
38 "Figure out what state they're in, but don't take action"
39 ) do
40 @dry_run = true
41 end
42
43 opts.on("-h", "--help", "Print this help") do
44 puts opts
45 exit
46 end
47
48 opts.on(
49 "-sSOURCE", "--source=SOURCE", "Source of ports (required, repeatable)"
50 ) do |source|
51 @sources.append source
52 end
53
54 opts.on(
55 "-cCUSTOMER_ID", "--customer-id=CUSTOMER_ID",
56 "Filter by customer ID (db source only)"
57 ) do |customer_id|
58 @filters[:customer_id] = customer_id
59 end
60end.parse!
61
62@sources = ["db", "bandwidth"] if @sources.empty?
63
64SCHEMA = "{
65 bandwidth : { account: Text, username: Text, password: Text },
66 xmpp: { jid: Text, password: Text },
67 notification: { endpoint: Text, source_number: Text },
68 pubsub: { server: Text, node: Text },
69 testing_tel: Text,
70 admin_server: Text,
71 sgx: Text,
72 sgx_creds: List { mapKey: Text, mapValue: {} }
73}"
74
75raise "Need a Dhall config" unless ARGV[0]
76
77CONFIG = Dhall::Coder
78 .new(safe: Dhall::Coder::JSON_LIKE + [Symbol, Proc])
79 .load("#{ARGV.first} : #{SCHEMA}", transform_keys: :to_sym)
80
81require_relative "../lib/blather_notify"
82require_relative "../lib/expiring_lock"
83require_relative "../lib/form_to_h"
84require_relative "../lib/porting_step_repo"
85require_relative "../lib/port_repo"
86require_relative "../lib/postgres"
87
88Faraday.default_adapter = :em_synchrony
89BandwidthIris::Client.global_options = {
90 account_id: CONFIG[:bandwidth][:account],
91 username: CONFIG[:bandwidth][:username],
92 password: CONFIG[:bandwidth][:password]
93}
94
95@output =
96 case @verbosity
97 when 0
98 FullAutomatic.new(
99 BlatherNotify::PubSub::Address.new(**CONFIG[:pubsub]),
100 CONFIG[:notification][:endpoint],
101 CONFIG[:notification][:source_number]
102 )
103 when 1
104 ObservedAuto.new(
105 CONFIG[:notification][:endpoint],
106 CONFIG[:notification][:source_number]
107 )
108 else
109 FullManual.new
110 end
111
112PORT_SOURCES = @sources.map(&:downcase).map { |source|
113 case source
114 when "bandwidth"
115 PortRepo::Bandwidth.new(@output, dry_run: @dry_run)
116 when "db"
117 PortRepo::Db.new(@output, dry_run: @dry_run, filters: @filters)
118 when "fake"
119 PortRepo::Fake.new(@output, dry_run: @dry_run)
120 else
121 puts <<~ERR
122 Invalid port source (-s / --source): #{source}.
123 Valid options: fake, db, endstream
124 ERR
125 # EINVAL
126 exit! 22
127 end
128}
129
130EM.run do
131 REDIS = EM::Hiredis.connect
132 DB = Postgres.connect(dbname: "jmp")
133
134 BlatherNotify.start(
135 CONFIG[:xmpp][:jid],
136 CONFIG[:xmpp][:password]
137 ).then {
138 EMPromise.all(PORT_SOURCES.map(&:process))
139 }.catch { |e|
140 @output.error("ROOT", :catch, e)
141 }.then { BlatherNotify.shutdown }
142end