test_snikket_launch

  1#!/usr/bin/env ruby
  2# frozen_string_literal: true
  3
  4require "dhall"
  5require "net/http"
  6require "uri"
  7require "time"
  8require "em-http"
  9require "em-synchrony/em-http"
 10require "link-header-parser"
 11
 12require_relative "../lib/em"
 13require_relative "../lib/blather_notify"
 14require_relative "../lib/form_to_h"
 15require "ougai"
 16
 17$stdout.sync = true
 18LOG = Ougai::Logger.new($stdout)
 19LOG.level = ENV.fetch("LOG_LEVEL", "info")
 20LOG.formatter = Ougai::Formatters::Readable.new(
 21	nil,
 22	nil,
 23	plain: !$stdout.isatty
 24)
 25Blather.logger = LOG
 26
 27CONFIG = Dhall.load(<<-DHALL).sync
 28	(#{ARGV[0]}) : {
 29		node: Text,
 30		jid: Text,
 31		password: Text,
 32		sgx_jmp: Text,
 33		interval: Int,
 34		max_attempts: Int
 35	}
 36DHALL
 37
 38DOMAIN = "jmp-test-#{Time.now.to_i}.snikket.chat"
 39
 40using FormToH
 41
 42class TestInstance
 43	def launch
 44		puts "Launching instance at #{DOMAIN}"
 45		BlatherNotify.execute(
 46			"snikket",
 47			{ domain: DOMAIN }.to_form(:submit)
 48		).then do |iq|
 49			@id = iq.form.field("instance-id").value.to_s
 50			@uri = iq.form.field("bootstrap-uri").value.to_s
 51		end
 52	end
 53
 54	def extract_link(res)
 55		LinkHeaderParser.parse(
 56			Array(res.response_header["LINK"].sub(/>([^:])/, ">;\\1")), base: @uri
 57		).group_by_relation_type[:alternate].find { |header|
 58			URI.parse(header.target_uri).scheme == "xmpp"
 59		}.target_uri
 60	end
 61
 62	def ping_http(attempt: 0)
 63		raise "Couldn't ping #{DOMAIN} over HTTP" if attempt > CONFIG[:max_attempts]
 64
 65		EM::HttpRequest.new(
 66			@uri, tls: { verify_peer: true }
 67		).ahead(redirects: 5).then { |res| extract_link(res) }.catch { |e|
 68			puts "HTTP ping attempt #{attempt} failed: #{e}"
 69			EM.promise_timer(CONFIG[:interval]).then {
 70				ping_http(attempt: attempt + 1)
 71			}
 72		}
 73	end
 74
 75	def ping_xmpp(attempt: 0)
 76		raise "Couldn't ping {#DOMAIN} over XMPP" if attempt > CONFIG[:max_attempts]
 77
 78		BlatherNotify.write_with_promise(
 79			Blather::Stanza::Iq::Ping.new(:get, DOMAIN)
 80		).catch { |e|
 81			puts "XMPP ping attempt #{attempt} failed: #{e}"
 82			EM.promise_timer(CONFIG[:interval]).then {
 83				ping_xmpp(attempt: attempt + 1)
 84			}
 85		}
 86	end
 87
 88	def stop
 89		puts "Stopping instance at #{DOMAIN}"
 90		BlatherNotify.execute(
 91			"stop snikket",
 92			{ instance_id: @id }.to_form(:submit)
 93		).then do |iq|
 94			raise "Couldn't stop instance: #{iq.note}" if iq.note_type == :error
 95		end
 96	end
 97
 98	def delete
 99		puts "Deleting instance at #{DOMAIN}"
100		BlatherNotify.execute(
101			"delete snikket",
102			{ instance_id: @id }.to_form(:submit)
103		).then do |iq|
104			puts iq
105			raise "Couldn't stop instance: #{iq.note}" if iq.note_type == :error
106		end
107	end
108end
109
110EM.run do
111	instance = TestInstance.new
112
113	BlatherNotify.start(
114		CONFIG[:jid],
115		CONFIG[:password]
116	).then {
117		instance.launch
118	}.then {
119		puts "Launch instance success"
120		instance.ping_http
121	}.then {
122		puts "HTTP ping success"
123		instance.ping_xmpp
124	}.then {
125		puts "XMPP ping success"
126		instance.stop
127	}.then {
128		puts "Stop instance success"
129		instance.delete
130	}.catch { |e|
131		p e
132		exit 1
133	}.then {
134		puts "Delete instance success"
135		EM.stop
136	}
137end