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 "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