zold 0.11.16 → 0.11.17
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rultor.yml +3 -1
- data/bin/zold-nohup +2 -0
- data/heroku.yml +9 -0
- data/lib/zold/commands/node.rb +50 -13
- data/lib/zold/commands/remote.rb +27 -0
- data/lib/zold/commands/taxes.rb +1 -1
- data/lib/zold/remotes.rb +5 -1
- data/lib/zold/routines.rb +58 -0
- data/lib/zold/version.rb +1 -1
- data/resources/remotes +0 -1
- data/test/commands/test_remote.rb +19 -0
- data/test/test_routines.rb +41 -0
- metadata +5 -2
- data/Procfile +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c756ab9df322c31f1b31c030d2f6f56971d2ef36
|
4
|
+
data.tar.gz: c03dc1d19510c459ed571a40e60d1e47d3ececd9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a2f402cb7258a1f85966d2f9a46e15b4a12d44eccc1150259208221a98141553511b23fbec78d93a780af64a59fe94f3c58a36ab8862e442bd1b76313406eac7
|
7
|
+
data.tar.gz: 682b3ad6c5bdec21e0eb95d94c7bac6dd04ad0776027cb96716bfef916bdbb4f4ec935e84f9832b26bc05fe684cb9b7968cd0c7ddfcd3203aabd1909a3061747
|
data/.rultor.yml
CHANGED
@@ -2,6 +2,7 @@ assets:
|
|
2
2
|
rubygems.yml: zerocracy/home#assets/rubygems.yml
|
3
3
|
id_rsa: zerocracy/home#assets/heroku-key
|
4
4
|
id_rsa.pub: zerocracy/home#assets/heroku-key.pub
|
5
|
+
bonus.key: zerocracy/home#assets/zold/bonus.key
|
5
6
|
install: |
|
6
7
|
sudo apt-get -y update
|
7
8
|
sudo gem install pdd
|
@@ -28,7 +29,8 @@ release:
|
|
28
29
|
git add Gemfile.lock
|
29
30
|
git add .gitignore
|
30
31
|
git fetch
|
31
|
-
|
32
|
+
cp ../bonus.key . && git add bonus.key
|
33
|
+
git commit -m 'config' && git push -f heroku $(git symbolic-ref --short HEAD):master
|
32
34
|
curl -f --connect-timeout 15 --retry 5 --retry-delay 30 http://b1.zold.io > /dev/null
|
33
35
|
architect:
|
34
36
|
- yegor256
|
data/bin/zold-nohup
CHANGED
@@ -38,6 +38,7 @@ end
|
|
38
38
|
|
39
39
|
def exec(cmd)
|
40
40
|
Open3.popen2e(cmd) do |stdin, stdout, thr|
|
41
|
+
log("Started: #{cmd}")
|
41
42
|
stdin.close
|
42
43
|
loop do
|
43
44
|
line = stdout.gets
|
@@ -45,6 +46,7 @@ def exec(cmd)
|
|
45
46
|
log(line)
|
46
47
|
end
|
47
48
|
code = thr.value.exitstatus
|
49
|
+
log("Exit code is #{code}: #{cmd}")
|
48
50
|
raise "Exit code #{code} (non zero)" unless code.zero?
|
49
51
|
end
|
50
52
|
end
|
data/heroku.yml
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
build:
|
2
|
+
languages:
|
3
|
+
- ruby
|
4
|
+
run:
|
5
|
+
web: |
|
6
|
+
LC_ALL=UTF-8 ./bin/zold node --no-colors --verbose --trace \
|
7
|
+
--bind-port=$PORT --port=80 --host=b1.zold.io --threads=0 \
|
8
|
+
--invoice=JKFq17yipfjLtX@0000000000000000 --never-reboot \
|
9
|
+
--bonus-wallet=81c9c25789b03876 --private-key=bonus.key --bonus-amount=1
|
data/lib/zold/commands/node.rb
CHANGED
@@ -20,12 +20,15 @@
|
|
20
20
|
|
21
21
|
require 'slop'
|
22
22
|
require_relative '../score'
|
23
|
+
require_relative '../routines'
|
23
24
|
require_relative '../wallets'
|
24
25
|
require_relative '../remotes'
|
25
26
|
require_relative '../verbose_thread'
|
26
27
|
require_relative '../node/entrance'
|
27
28
|
require_relative '../node/front'
|
28
29
|
require_relative '../node/farm'
|
30
|
+
require_relative 'push'
|
31
|
+
require_relative 'pay'
|
29
32
|
|
30
33
|
# NODE command.
|
31
34
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
@@ -68,6 +71,14 @@ module Zold
|
|
68
71
|
o.bool '--never-reboot',
|
69
72
|
'Don\'t reboot when a new version shows up in the network',
|
70
73
|
default: false
|
74
|
+
o.string '--bonus-wallet',
|
75
|
+
'The ID of the wallet to regularly send bonuses from (for nodes online)'
|
76
|
+
o.string '--bonus-amount',
|
77
|
+
'The amount of ZLD to pay to each remote as a bonus',
|
78
|
+
default: '1'
|
79
|
+
o.string '--private-key',
|
80
|
+
'The location of RSA private key (default: ~/.ssh/id_rsa)',
|
81
|
+
default: '~/.ssh/id_rsa'
|
71
82
|
o.bool '--help', 'Print instructions'
|
72
83
|
end
|
73
84
|
if opts.help?
|
@@ -117,25 +128,51 @@ module Zold
|
|
117
128
|
threads: opts[:threads], strength: opts[:strength]
|
118
129
|
)
|
119
130
|
Front.set(:farm, farm)
|
120
|
-
|
121
|
-
VerboseThread.new(@log).run(true) do
|
122
|
-
loop do
|
123
|
-
sleep(60)
|
124
|
-
require_relative 'remote'
|
125
|
-
Remote.new(remotes: remotes, log: @log, farm: farm).run(%w[remote add b1.zold.io 80 --force])
|
126
|
-
Remote.new(remotes: remotes, log: @log, farm: farm).run(%w[remote trim])
|
127
|
-
Remote.new(remotes: remotes, log: @log, farm: farm).run(%w[remote update --reboot])
|
128
|
-
@log.info("Regular update of remote nodes succeeded, total=#{remotes.all.count}")
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
131
|
+
routines = routines(wallets, remotes, farm, opts)
|
132
132
|
@log.debug("Starting up the web front at http://#{opts[:host]}:#{opts[:port]}...")
|
133
133
|
begin
|
134
134
|
Front.run!
|
135
135
|
ensure
|
136
136
|
farm.stop
|
137
|
-
|
137
|
+
routines.stop
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
|
143
|
+
def routines(wallets, remotes, farm, opts)
|
144
|
+
routines = Routines.new(@log)
|
145
|
+
routines.add do
|
146
|
+
require_relative 'remote'
|
147
|
+
Remote.new(remotes: remotes, log: @log, farm: farm).run(%w[remote add b1.zold.io 80 --force])
|
148
|
+
Remote.new(remotes: remotes, log: @log, farm: farm).run(%w[remote trim])
|
149
|
+
Remote.new(remotes: remotes, log: @log, farm: farm).run(%w[remote update --reboot])
|
150
|
+
end
|
151
|
+
if opts['bonus-wallet']
|
152
|
+
routines.add do
|
153
|
+
require_relative 'remote'
|
154
|
+
winners = Remote.new(remotes: remotes, log: @log, farm: farm).run(
|
155
|
+
['remote', 'elect', opts['bonus-wallet'], '--private-key', opts['private-key']]
|
156
|
+
)
|
157
|
+
if winners.empty?
|
158
|
+
@log.info('No winners elected, won\'t pay any bonuses')
|
159
|
+
else
|
160
|
+
winners.each do |score|
|
161
|
+
Pay.new(wallets: wallets, remotes: remotes, log: @log).run(
|
162
|
+
[
|
163
|
+
'pay', opts['bonus-wallet'], score.invoice, opts['bonus-amount'],
|
164
|
+
"Hosting bonus for #{score.host}:#{score.port} #{score.value}",
|
165
|
+
'--private-key', opts['private-key']
|
166
|
+
]
|
167
|
+
)
|
168
|
+
Push.new(wallets: wallets, remotes: remotes, log: @log).run(
|
169
|
+
['push', opts['bonus-wallet']]
|
170
|
+
)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
138
174
|
end
|
175
|
+
routines
|
139
176
|
end
|
140
177
|
|
141
178
|
# Fake logging facility for Webrick
|
data/lib/zold/commands/remote.rb
CHANGED
@@ -58,6 +58,8 @@ Available commands:
|
|
58
58
|
Add a new remote node
|
59
59
|
#{Rainbow('remote remove').green} host [port]
|
60
60
|
Remove the remote node
|
61
|
+
#{Rainbow('remote elect').green}
|
62
|
+
Pick a random remote node as a target for a bonus awarding
|
61
63
|
#{Rainbow('remote trim').green}
|
62
64
|
Remote the least reliable nodes
|
63
65
|
#{Rainbow('remote update').green}
|
@@ -66,6 +68,9 @@ Available options:"
|
|
66
68
|
o.bool '--ignore-score-weakness',
|
67
69
|
'Don\'t complain when their score is too weak',
|
68
70
|
default: false
|
71
|
+
o.bool '--ignore-score-value',
|
72
|
+
'Don\'t complain when their score is too small',
|
73
|
+
default: false
|
69
74
|
o.bool '--force',
|
70
75
|
'Add/remove if if this operation is not possible',
|
71
76
|
default: false
|
@@ -88,6 +93,8 @@ Available options:"
|
|
88
93
|
add(mine[1], mine[2] ? mine[2].to_i : Remotes::PORT, opts)
|
89
94
|
when 'remove'
|
90
95
|
remove(mine[1], mine[2] ? mine[2].to_i : Remotes::PORT, opts)
|
96
|
+
when 'elect'
|
97
|
+
elect(opts)
|
91
98
|
when 'trim'
|
92
99
|
trim(opts)
|
93
100
|
when 'update'
|
@@ -139,6 +146,26 @@ Available options:"
|
|
139
146
|
@log.info("There are #{@remotes.all.count} remote nodes in the list")
|
140
147
|
end
|
141
148
|
|
149
|
+
# Returns an array of Zold::Score
|
150
|
+
def elect(opts)
|
151
|
+
scores = []
|
152
|
+
@remotes.all.sample(1).each do |winner|
|
153
|
+
@remotes.iterate(@log, farm: @farm) do |r|
|
154
|
+
next if r.host != winner[:host] || r.port != winner[:port]
|
155
|
+
res = r.http('/').get
|
156
|
+
r.assert_code(200, res)
|
157
|
+
score = Score.parse_json(JSON.parse(res.body)['score'])
|
158
|
+
r.assert_valid_score(score)
|
159
|
+
r.assert_score_ownership(score)
|
160
|
+
r.assert_score_strength(score) unless opts['ignore-score-weakness']
|
161
|
+
r.assert_score_value(score, Tax::EXACT_SCORE) unless opts['ignore-score-value']
|
162
|
+
@log.info("Elected: #{score}")
|
163
|
+
scores << score
|
164
|
+
end
|
165
|
+
end
|
166
|
+
scores
|
167
|
+
end
|
168
|
+
|
142
169
|
def trim(opts)
|
143
170
|
@remotes.all.each do |r|
|
144
171
|
remove(r[:host], r[:port], opts) if r[:errors] > Remotes::TOLERANCE
|
data/lib/zold/commands/taxes.rb
CHANGED
@@ -124,7 +124,7 @@ Available options:"
|
|
124
124
|
score = Score.parse_json(json['score'])
|
125
125
|
r.assert_valid_score(score)
|
126
126
|
r.assert_score_strength(score)
|
127
|
-
|
127
|
+
r.assert_score_value(score, Tax::EXACT_SCORE)
|
128
128
|
@log.info("#{r}: #{Rainbow(score.value).green}")
|
129
129
|
best << score
|
130
130
|
end
|
data/lib/zold/remotes.rb
CHANGED
@@ -87,7 +87,11 @@ module Zold
|
|
87
87
|
end
|
88
88
|
|
89
89
|
def assert_score_strength(score)
|
90
|
-
raise "Score is too weak #{score.strength}" if score.strength < Score::STRENGTH
|
90
|
+
raise "Score is too weak #{score.strength}: #{score}" if score.strength < Score::STRENGTH
|
91
|
+
end
|
92
|
+
|
93
|
+
def assert_score_value(score, min)
|
94
|
+
raise "Score is too small (<#{min}): #{score}" if score.value < min
|
91
95
|
end
|
92
96
|
end
|
93
97
|
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# Copyright (c) 2018 Yegor Bugayenko
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in all
|
11
|
+
# copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
# SOFTWARE.
|
20
|
+
|
21
|
+
require_relative 'log'
|
22
|
+
require_relative 'verbose_thread'
|
23
|
+
|
24
|
+
# Background routines.
|
25
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
26
|
+
# Copyright:: Copyright (c) 2018 Yegor Bugayenko
|
27
|
+
# License:: MIT
|
28
|
+
module Zold
|
29
|
+
# NODE command
|
30
|
+
class Routines
|
31
|
+
def initialize(log = Log::Quiet.new)
|
32
|
+
@log = log
|
33
|
+
@threads = []
|
34
|
+
end
|
35
|
+
|
36
|
+
def add(seconds = 60)
|
37
|
+
@threads << Thread.start do
|
38
|
+
VerboseThread.new(@log).run(true) do
|
39
|
+
Thread.current.name = 'routines'
|
40
|
+
count = 0
|
41
|
+
loop do
|
42
|
+
sleep(seconds)
|
43
|
+
yield count
|
44
|
+
count += 1
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def stop
|
51
|
+
@threads.each do |t|
|
52
|
+
t.exit
|
53
|
+
@log.debug("#{t.name} thread stopped")
|
54
|
+
end
|
55
|
+
@log.info("#{@threads.count} routine threads stopped")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/zold/version.rb
CHANGED
data/resources/remotes
CHANGED
@@ -69,4 +69,23 @@ class TestRemote < Minitest::Test
|
|
69
69
|
assert_equal(4, remotes.all.count)
|
70
70
|
end
|
71
71
|
end
|
72
|
+
|
73
|
+
def test_elects_a_remote
|
74
|
+
Dir.mktmpdir 'test' do |dir|
|
75
|
+
zero = Zold::Score::ZERO
|
76
|
+
remotes = Zold::Remotes.new(File.join(dir, 'remotes.txt'))
|
77
|
+
remotes.clean
|
78
|
+
remotes.add(zero.host, zero.port)
|
79
|
+
stub_request(:get, "http://#{zero.host}:#{zero.port}/").to_return(
|
80
|
+
status: 200,
|
81
|
+
body: {
|
82
|
+
version: Zold::VERSION,
|
83
|
+
score: zero.to_h
|
84
|
+
}.to_json
|
85
|
+
)
|
86
|
+
cmd = Zold::Remote.new(remotes: remotes, log: test_log)
|
87
|
+
winners = cmd.run(%w[remote elect --ignore-score-value])
|
88
|
+
assert_equal(1, winners.count)
|
89
|
+
end
|
90
|
+
end
|
72
91
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# Copyright (c) 2018 Yegor Bugayenko
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in all
|
11
|
+
# copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
# SOFTWARE.
|
20
|
+
|
21
|
+
require 'minitest/autorun'
|
22
|
+
require_relative 'test__helper'
|
23
|
+
require_relative '../lib/zold/routines'
|
24
|
+
|
25
|
+
# Routines test.
|
26
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
27
|
+
# Copyright:: Copyright (c) 2018 Yegor Bugayenko
|
28
|
+
# License:: MIT
|
29
|
+
class TestRoutines < Minitest::Test
|
30
|
+
def test_start_and_stop
|
31
|
+
routines = Zold::Routines.new
|
32
|
+
list = []
|
33
|
+
routines.add(0) do |i|
|
34
|
+
list << i
|
35
|
+
sleep(6000)
|
36
|
+
end
|
37
|
+
sleep 0.1 while list.empty?
|
38
|
+
routines.stop
|
39
|
+
assert_equal(1, list.count)
|
40
|
+
end
|
41
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zold
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.
|
4
|
+
version: 0.11.17
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yegor Bugayenko
|
@@ -296,7 +296,6 @@ files:
|
|
296
296
|
- Gemfile
|
297
297
|
- INSTALL.md
|
298
298
|
- LICENSE.txt
|
299
|
-
- Procfile
|
300
299
|
- README.md
|
301
300
|
- Rakefile
|
302
301
|
- appveyor.yml
|
@@ -318,6 +317,7 @@ files:
|
|
318
317
|
- fixtures/scripts/calculate-scores.sh
|
319
318
|
- fixtures/scripts/print-helps.sh
|
320
319
|
- fixtures/scripts/push-and-pull.sh
|
320
|
+
- heroku.yml
|
321
321
|
- lib/zold.rb
|
322
322
|
- lib/zold/amount.rb
|
323
323
|
- lib/zold/atomic_file.rb
|
@@ -351,6 +351,7 @@ files:
|
|
351
351
|
- lib/zold/patch.rb
|
352
352
|
- lib/zold/prefixes.rb
|
353
353
|
- lib/zold/remotes.rb
|
354
|
+
- lib/zold/routines.rb
|
354
355
|
- lib/zold/score.rb
|
355
356
|
- lib/zold/signature.rb
|
356
357
|
- lib/zold/tax.rb
|
@@ -392,6 +393,7 @@ files:
|
|
392
393
|
- test/test_patch.rb
|
393
394
|
- test/test_prefixes.rb
|
394
395
|
- test/test_remotes.rb
|
396
|
+
- test/test_routines.rb
|
395
397
|
- test/test_score.rb
|
396
398
|
- test/test_signature.rb
|
397
399
|
- test/test_tax.rb
|
@@ -463,6 +465,7 @@ test_files:
|
|
463
465
|
- test/test_patch.rb
|
464
466
|
- test/test_prefixes.rb
|
465
467
|
- test/test_remotes.rb
|
468
|
+
- test/test_routines.rb
|
466
469
|
- test/test_score.rb
|
467
470
|
- test/test_signature.rb
|
468
471
|
- test/test_tax.rb
|
data/Procfile
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
web: LC_ALL=UTF-8 ./bin/zold node --no-colors --verbose --trace --bind-port=$PORT --port=80 --host=b1.zold.io --threads=0 --invoice=JKFq17yipfjLtX@0000000000000000 --never-reboot
|