porting

  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}"
 72
 73raise "Need a Dhall config" unless ARGV[0]
 74
 75CONFIG = Dhall::Coder
 76	.new(safe: Dhall::Coder::JSON_LIKE + [Symbol, Proc])
 77	.load("#{ARGV.first} : #{SCHEMA}", transform_keys: :to_sym)
 78
 79require_relative "../lib/blather_notify"
 80require_relative "../lib/expiring_lock"
 81require_relative "../lib/form_to_h"
 82require_relative "../lib/porting_step_repo"
 83require_relative "../lib/port_repo"
 84require_relative "../lib/postgres"
 85
 86Faraday.default_adapter = :em_synchrony
 87BandwidthIris::Client.global_options = {
 88	account_id: CONFIG[:bandwidth][:account],
 89	username: CONFIG[:bandwidth][:username],
 90	password: CONFIG[:bandwidth][:password]
 91}
 92
 93@output =
 94	case @verbosity
 95	when 0
 96		FullAutomatic.new(
 97			BlatherNotify::PubSub::Address.new(**CONFIG[:pubsub]),
 98			CONFIG[:notification][:endpoint],
 99			CONFIG[:notification][:source_number]
100		)
101	when 1
102		ObservedAuto.new(
103			CONFIG[:notification][:endpoint],
104			CONFIG[:notification][:source_number]
105		)
106	else
107		FullManual.new
108	end
109
110PORT_SOURCES = @sources.map(&:downcase).map { |source|
111	case source
112	when "bandwidth"
113		PortRepo::Bandwidth.new(@output, dry_run: @dry_run)
114	when "db"
115		PortRepo::Db.new(@output, dry_run: @dry_run, filters: @filters)
116	when "fake"
117		PortRepo::Fake.new(@output, dry_run: @dry_run)
118	else
119		puts <<~ERR
120			Invalid port source (-s / --source): #{source}.
121			Valid options: fake, db, endstream
122		ERR
123		# EINVAL
124		exit! 22
125	end
126}
127
128EM.run do
129	REDIS = EM::Hiredis.connect
130	DB = Postgres.connect(dbname: "jmp")
131
132	BlatherNotify.start(
133		CONFIG[:xmpp][:jid],
134		CONFIG[:xmpp][:password]
135	).then {
136		EMPromise.all(PORT_SOURCES.map(&:process))
137	}.catch { |e|
138		@output.error("ROOT", :catch, e)
139	}.then { BlatherNotify.shutdown }
140end