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