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		jid: Text,
 30		password: Text,
 31		sgx_jmp: Text,
 32		interval: Int,
 33		max_attempts: Int
 34	}
 35DHALL
 36
 37DOMAIN = "jmp-test-#{Time.now.to_i}.snikket.chat"
 38
 39using FormToH
 40
 41class TestInstance
 42	def launch
 43		puts "Launching instance at #{DOMAIN}"
 44		BlatherNotify.execute(
 45			"snikket",
 46			{ domain: DOMAIN }.to_form(:submit)
 47		).then do |iq|
 48			@id = iq.form.field("instance-id").value.to_s
 49			@uri = iq.form.field("bootstrap-uri").value.to_s
 50		end
 51	end
 52
 53	def extract_link(res)
 54		LinkHeaderParser.parse(
 55			Array(res.response_header["LINK"].sub(/>([^:])/, ">;\\1")), base: @uri
 56		).group_by_relation_type[:alternate].find { |header|
 57			URI.parse(header.target_uri).scheme == "xmpp"
 58		}.target_uri
 59	end
 60
 61	def ping_http(attempt: 0)
 62		raise "Couldn't ping #{DOMAIN} over HTTP" if attempt > CONFIG[:max_attempts]
 63
 64		EM::HttpRequest.new(
 65			@uri, tls: { verify_peer: true }
 66		).ahead(redirects: 5).then { |res| extract_link(res) }.catch { |e|
 67			puts "HTTP ping attempt #{attempt} failed: #{e}"
 68			EM.promise_timer(CONFIG[:interval]).then {
 69				ping_http(attempt: attempt + 1)
 70			}
 71		}
 72	end
 73
 74	def ping_xmpp(attempt: 0)
 75		raise "Couldn't ping {#DOMAIN} over XMPP" if attempt > CONFIG[:max_attempts]
 76
 77		BlatherNotify.write_with_promise(
 78			Blather::Stanza::Iq::Ping.new(:get, DOMAIN)
 79		).catch { |e|
 80			puts "XMPP ping attempt #{attempt} failed: #{e}"
 81			EM.promise_timer(CONFIG[:interval]).then {
 82				ping_xmpp(attempt: attempt + 1)
 83			}
 84		}
 85	end
 86
 87	def stop
 88		puts "Stopping instance at #{DOMAIN}"
 89		BlatherNotify.execute(
 90			"stop snikket",
 91			{ instance_id: @id }.to_form(:submit)
 92		).then do |iq|
 93			raise "Couldn't stop instance: #{iq.note}" if iq.note_type == :error
 94		end
 95	end
 96
 97	def delete
 98		puts "Deleting instance at #{DOMAIN}"
 99		BlatherNotify.execute(
100			"delete snikket",
101			{ instance_id: @id }.to_form(:submit)
102		).then do |iq|
103			puts iq
104			raise "Couldn't stop instance: #{iq.note}" if iq.note_type == :error
105		end
106	end
107end
108
109EM.run do
110	instance = TestInstance.new
111
112	BlatherNotify.start(
113		CONFIG[:jid],
114		CONFIG[:password]
115	).then {
116		instance.launch
117	}.then {
118		puts "Launch instance success"
119		instance.ping_http
120	}.then {
121		puts "HTTP ping success"
122		instance.ping_xmpp
123	}.then {
124		puts "XMPP ping success"
125		instance.stop
126	}.then {
127		puts "Stop instance success"
128		instance.delete
129	}.catch { |e|
130		p e
131		exit 1
132	}.then {
133		puts "Delete instance success"
134		EM.stop
135	}
136end