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