@@ -0,0 +1,137 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require "dhall"
+require "net/http"
+require "uri"
+require "time"
+require "em-http"
+require "em-synchrony/em-http"
+require "link-header-parser"
+
+require_relative "../lib/em"
+require_relative "../lib/blather_notify"
+require_relative "../lib/form_to_h"
+require "ougai"
+
+$stdout.sync = true
+LOG = Ougai::Logger.new($stdout)
+LOG.level = ENV.fetch("LOG_LEVEL", "info")
+LOG.formatter = Ougai::Formatters::Readable.new(
+ nil,
+ nil,
+ plain: !$stdout.isatty
+)
+Blather.logger = LOG
+
+CONFIG = Dhall.load(<<-DHALL).sync
+ (#{ARGV[0]}) : {
+ node: Text,
+ jid: Text,
+ password: Text,
+ sgx_jmp: Text,
+ interval: Int,
+ max_attempts: Int
+ }
+DHALL
+
+DOMAIN = "jmp-test-#{Time.now.to_i}.snikket.chat"
+
+using FormToH
+
+class TestInstance
+ def launch
+ puts "Launching instance at #{DOMAIN}"
+ BlatherNotify.execute(
+ "snikket",
+ { domain: DOMAIN }.to_form(:submit)
+ ).then do |iq|
+ @id = iq.form.field("instance-id").value.to_s
+ @uri = iq.form.field("bootstrap-uri").value.to_s
+ end
+ end
+
+ def extract_link(res)
+ LinkHeaderParser.parse(
+ Array(res.response_header["LINK"].sub(/>([^:])/, ">;\\1")), base: @uri
+ ).group_by_relation_type[:alternate].find { |header|
+ URI.parse(header.target_uri).scheme == "xmpp"
+ }.target_uri
+ end
+
+ def ping_http(attempt: 0)
+ raise "Couldn't ping #{DOMAIN} over HTTP" if attempt > CONFIG[:max_attempts]
+
+ EM::HttpRequest.new(
+ @uri, tls: { verify_peer: true }
+ ).ahead(redirects: 5).then { |res| extract_link(res) }.catch { |e|
+ puts "HTTP ping attempt #{attempt} failed: #{e}"
+ EM.promise_timer(CONFIG[:interval]).then {
+ ping_http(attempt: attempt + 1)
+ }
+ }
+ end
+
+ def ping_xmpp(attempt: 0)
+ raise "Couldn't ping {#DOMAIN} over XMPP" if attempt > CONFIG[:max_attempts]
+
+ BlatherNotify.write_with_promise(
+ Blather::Stanza::Iq::Ping.new(:get, DOMAIN)
+ ).catch { |e|
+ puts "XMPP ping attempt #{attempt} failed: #{e}"
+ EM.promise_timer(CONFIG[:interval]).then {
+ ping_xmpp(attempt: attempt + 1)
+ }
+ }
+ end
+
+ def stop
+ puts "Stopping instance at #{DOMAIN}"
+ BlatherNotify.execute(
+ "stop snikket",
+ { instance_id: @id }.to_form(:submit)
+ ).then do |iq|
+ raise "Couldn't stop instance: #{iq.note}" if iq.note_type == :error
+ end
+ end
+
+ def delete
+ puts "Deleting instance at #{DOMAIN}"
+ BlatherNotify.execute(
+ "delete snikket",
+ { instance_id: @id }.to_form(:submit)
+ ).then do |iq|
+ puts iq
+ raise "Couldn't stop instance: #{iq.note}" if iq.note_type == :error
+ end
+ end
+end
+
+EM.run do
+ instance = TestInstance.new
+
+ BlatherNotify.start(
+ CONFIG[:jid],
+ CONFIG[:password]
+ ).then {
+ instance.launch
+ }.then {
+ puts "Launch instance success"
+ instance.ping_http
+ }.then {
+ puts "HTTP ping success"
+ instance.ping_xmpp
+ }.then {
+ puts "XMPP ping success"
+ instance.stop
+ }.then {
+ puts "Stop instance success"
+ instance.delete
+ }.catch { |e|
+ p e
+ exit 1
+ }.then {
+ puts "Delete instance success"
+ EM.stop
+ }
+end