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