warg 0.1.1 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/bin/console-playground +0 -1
  3. data/lib/warg.rb +201 -206
  4. metadata +30 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a2f032dcff2708b375e016c4ed2b8809ef80784c1fa3845cf5e480c279003fd7
4
- data.tar.gz: c17eab82ffa3f6e1ae78e1aeabaf460c2596d1d4d7c9c9633be7112d3687d7b7
3
+ metadata.gz: 32b9aa5eb2e34d4cad9498e0befaee2e6b0918393cb5843c7e50dea4764f74e1
4
+ data.tar.gz: 540df3adc335e5a5a211baa8a8ee87226ae233e8157481dfd6703a3ee018ee83
5
5
  SHA512:
6
- metadata.gz: 8b11f96e8c293f3005767d6471b58e04942121d8b87dbb6f61a9094182cbad8dc779e46c9f6c1d92ce0338e92a85a2231b58a88a1b2e55124028a8141ea04f64
7
- data.tar.gz: 700b611540d8f704e8ea57d11d5be633c78a6e8050745f22a1096dd40e7eebf17f27a2f6280ba4e3c3cdca404fd8799f883f9b03ae6b65f7ac2944a557f685af
6
+ metadata.gz: 8914b0f531a6b88f72eea6f6bd78459c7aa57ceab3f58d9ca83371ab76cd534ba9bd5a33f607e5ac399412256932354322445554e2f48cdee3e55da054dce0fa
7
+ data.tar.gz: ad41bbea8f475eddb3c255d1bc19498bc2510a471af4fd5f27598cf15fc3926cb9827a4995010c6e3e3684ae46524cb41a25d7ef31d8371f33d50e16e3b94b73
@@ -23,7 +23,6 @@ end
23
23
  require "pry"
24
24
 
25
25
  # NOTE: Unsure why `"set"` needs to be loaded here
26
- require "set"
27
26
  require "warg"
28
27
 
29
28
  console = Warg::Console.new
data/lib/warg.rb CHANGED
@@ -594,38 +594,6 @@ module Warg
594
594
  outcome
595
595
  end
596
596
 
597
- def defer(command, banner, &block)
598
- run_object = BlockProxy.new(banner, &block)
599
- hosts = CollectionProxy.new
600
-
601
- Executor::Deferred.new(command, run_object, hosts, :serial)
602
- end
603
-
604
- class BlockProxy
605
- def initialize(banner, &block)
606
- @banner = banner
607
- @block = block
608
- end
609
-
610
- def to_s
611
- @banner.dup
612
- end
613
-
614
- def to_proc
615
- @block
616
- end
617
- end
618
-
619
- class CollectionProxy
620
- def run_block(run_object, **)
621
- outcome = LOCALHOST.run(&run_object)
622
-
623
- execution_result = Executor::Result.new
624
- execution_result.update(outcome)
625
- execution_result
626
- end
627
- end
628
-
629
597
  class CommandOutcome
630
598
  attr_accessor :error
631
599
 
@@ -683,6 +651,10 @@ module Warg
683
651
  end
684
652
  end
685
653
 
654
+ def failure_reason
655
+ error
656
+ end
657
+
686
658
  def failure_summary
687
659
  error && error.full_message
688
660
  end
@@ -1378,11 +1350,12 @@ module Warg
1378
1350
  class Context < Config
1379
1351
  attr_reader :argv
1380
1352
  attr_reader :parser
1353
+ attr_reader :playlist
1381
1354
 
1382
- def initialize(argv)
1355
+ def initialize(argv, playlist)
1383
1356
  @argv = argv
1357
+ @playlist = playlist
1384
1358
  @parser = OptionParser.new
1385
- @playlist = Playlist.new
1386
1359
 
1387
1360
  @parser.on("-t", "--target HOSTS", Array, "hosts to use") do |hosts_data|
1388
1361
  hosts_data.each { |host_data| hosts.add(host_data) }
@@ -1395,16 +1368,6 @@ module Warg
1395
1368
  @parser.parse(@argv)
1396
1369
  end
1397
1370
 
1398
- def queue!(command)
1399
- @playlist.queue(command)
1400
- end
1401
-
1402
- def run!
1403
- Console.hostname_width = hosts.map { |host| host.address.length }.max
1404
-
1405
- @playlist.start
1406
- end
1407
-
1408
1371
  def copy(config)
1409
1372
  config.hosts.each do |host|
1410
1373
  hosts.add(host)
@@ -1416,30 +1379,53 @@ module Warg
1416
1379
  end
1417
1380
  end
1418
1381
  end
1382
+ end
1419
1383
 
1420
- class Playlist
1421
- def initialize
1422
- @playing_at = 0
1423
- @insert_at = 0
1424
- @items = []
1425
- @started = false
1426
- end
1384
+ class Playlist
1385
+ attr_reader :insert_at
1427
1386
 
1428
- def start
1429
- @started = true
1430
- @insert_at = 1
1387
+ def initialize
1388
+ @start = @insert_at = Start.new
1389
+ end
1390
+
1391
+ def play
1392
+ playing = @insert_at = @start
1393
+ command = nil
1394
+
1395
+ while playing.next
1396
+ playing = @insert_at = playing.next
1397
+
1398
+ if command != playing.command
1399
+ command = playing.command
1400
+
1401
+ Warg.console.puts Console::SGR(command.command_name.console).with(text_color: :blue, effect: :bold)
1402
+ end
1403
+
1404
+ Warg.console.puts Console::SGR(" -> #{playing.banner}").with(text_color: :magenta)
1431
1405
 
1432
- until @playing_at >= @items.length
1433
- @items[@playing_at].run
1406
+ result = playing.run
1434
1407
 
1435
- @playing_at += 1
1436
- @insert_at = @playing_at + 1
1408
+ if result.failed?
1409
+ command.on_failure(result)
1437
1410
  end
1438
1411
  end
1412
+ end
1413
+
1414
+ def queue(command_step)
1415
+ if @insert_at.next
1416
+ command_step.next = @insert_at.next
1417
+ end
1418
+
1419
+ command_step.previous = @insert_at
1420
+ @insert_at.next = command_step
1421
+
1422
+ @insert_at = command_step
1423
+ end
1424
+
1425
+ class Start
1426
+ attr_accessor :next
1439
1427
 
1440
- def queue(command)
1441
- @items.insert(@insert_at, command)
1442
- @insert_at += 1
1428
+ def previous
1443
1429
  end
1444
1430
  end
1445
1431
  end
@@ -1448,11 +1434,12 @@ module Warg
1448
1434
  def initialize(argv)
1449
1435
  @argv = argv.dup
1450
1436
  @path = nil
1437
+ @playlist = Playlist.new
1451
1438
 
1452
1439
  find_warg_directory!
1453
1440
  load_config!
1454
1441
 
1455
- @context = Context.new(@argv)
1442
+ @context = Context.new(@argv, @playlist)
1456
1443
  @context.copy(Warg.config)
1457
1444
 
1458
1445
  load_scripts!
@@ -1470,8 +1457,10 @@ module Warg
1470
1457
  @command.(@context)
1471
1458
  @context.parse_options!
1472
1459
 
1460
+ Console.hostname_width = @context.hosts.map { |host| host.address.length }.max
1461
+
1473
1462
  Warg.console.redirecting_stdout_and_stderr do
1474
- @context.run!
1463
+ @playlist.play
1475
1464
  end
1476
1465
  end
1477
1466
 
@@ -1545,7 +1534,7 @@ module Warg
1545
1534
  object = Class.new do
1546
1535
  include Command::BehaviorWithoutRegistration
1547
1536
 
1548
- def setup
1537
+ def run
1549
1538
  run_script
1550
1539
  end
1551
1540
  end
@@ -1619,127 +1608,6 @@ module Warg
1619
1608
  end
1620
1609
  end
1621
1610
 
1622
- class Deferred
1623
- def initialize(command, run_object, hosts, order, &setup)
1624
- @command = command
1625
- @run_object = run_object
1626
- @hosts = hosts
1627
- @order = order
1628
- @setup = setup
1629
-
1630
- @callbacks_queue = CallbacksQueue.new(order)
1631
-
1632
- @run_type = case @run_object
1633
- when Script
1634
- :run_script
1635
- when String
1636
- :run_command
1637
- when Localhost::BlockProxy
1638
- :run_block
1639
- end
1640
- end
1641
-
1642
- def banner
1643
- @run_object
1644
- end
1645
-
1646
- def and_then(&block)
1647
- @callbacks_queue << block
1648
- self
1649
- end
1650
-
1651
- def run
1652
- execution_result = @hosts.public_send(@run_type, @run_object, order: @order, &@setup)
1653
-
1654
- execution_result = @callbacks_queue.drain(execution_result)
1655
-
1656
- if execution_result.failed?
1657
- @command.on_failure(execution_result)
1658
- end
1659
-
1660
- execution_result
1661
- end
1662
-
1663
- class CallbacksQueue
1664
- def initialize(execution_order)
1665
- @queue = []
1666
- @executor_class = Executor.for(execution_order)
1667
- end
1668
-
1669
- def <<(callback)
1670
- @queue << callback
1671
- end
1672
-
1673
- def drain(execution_result)
1674
- drain_queue = @queue.dup
1675
-
1676
- # NOTE: It would be nice to incorporate the failure callback into the code here
1677
- until drain_queue.empty? || execution_result.failed?
1678
- callback = drain_queue.shift
1679
- executor = @executor_class.new(execution_result)
1680
-
1681
- execution_result = executor.run do |outcome, result|
1682
- callback_outcome = Outcome.new(outcome)
1683
-
1684
- begin
1685
- # Use `||=` in case `#value` is set in the callback
1686
- callback_outcome.value ||= callback.(outcome.host, outcome.value, callback_outcome)
1687
- rescue => error
1688
- callback_outcome.error = error
1689
- end
1690
-
1691
- result.update callback_outcome
1692
- end
1693
- end
1694
-
1695
- execution_result
1696
- end
1697
-
1698
- class Outcome
1699
- attr_reader :error
1700
- attr_reader :host
1701
- attr_reader :source_outcome
1702
- attr_accessor :value
1703
-
1704
- def initialize(outcome)
1705
- @source_outcome = outcome
1706
- @host = @source_outcome.host
1707
- @successful = true
1708
- end
1709
-
1710
- def resolve(value)
1711
- @value = value
1712
- end
1713
-
1714
- def fail!(message)
1715
- @successful = false
1716
-
1717
- raise CallbackFailedError.new(message)
1718
- end
1719
-
1720
- def error=(error)
1721
- @successful = false
1722
- @error = error
1723
- end
1724
-
1725
- def successful?
1726
- @successful
1727
- end
1728
-
1729
- def failed?
1730
- !successful?
1731
- end
1732
-
1733
- def failure_summary
1734
- error && error.full_message
1735
- end
1736
- end
1737
- end
1738
-
1739
- class CallbackFailedError < StandardError
1740
- end
1741
- end
1742
-
1743
1611
  class Result
1744
1612
  include Enumerable
1745
1613
  extend Forwardable
@@ -1924,9 +1792,8 @@ module Warg
1924
1792
  attr_reader :argv
1925
1793
  attr_reader :context
1926
1794
  attr_reader :hosts
1927
- attr_reader :operations
1928
1795
  attr_reader :parser
1929
- attr_reader :steps
1796
+ attr_reader :playlist
1930
1797
 
1931
1798
  def initialize(context)
1932
1799
  @context = context
@@ -1934,11 +1801,9 @@ module Warg
1934
1801
  @parser = @context.parser
1935
1802
  @hosts = @context.hosts
1936
1803
  @argv = @context.argv.dup
1804
+ @playlist = @context.playlist
1937
1805
 
1938
1806
  configure_parser!
1939
-
1940
- @context.queue!(self)
1941
- @steps = []
1942
1807
  end
1943
1808
 
1944
1809
  def name
@@ -1946,20 +1811,11 @@ module Warg
1946
1811
  end
1947
1812
 
1948
1813
  def call
1949
- setup
1814
+ run
1950
1815
  self
1951
1816
  end
1952
1817
 
1953
- def setup
1954
- end
1955
-
1956
1818
  def run
1957
- Warg.console.puts Console::SGR(command_name.console).with(text_color: :blue, effect: :bold)
1958
-
1959
- @steps.each do |deferred|
1960
- Warg.console.puts Console::SGR(" -> #{deferred.banner}").with(text_color: :magenta)
1961
- deferred.run
1962
- end
1963
1819
  end
1964
1820
 
1965
1821
  def command_name
@@ -1984,6 +1840,10 @@ module Warg
1984
1840
  Console::SGR(text)
1985
1841
  end
1986
1842
 
1843
+ def and_then(order: :parallel, &block)
1844
+ @playlist.queue Step.callback(self, @playlist.insert_at, order, block)
1845
+ end
1846
+
1987
1847
  private
1988
1848
 
1989
1849
  def configure_parser!
@@ -1993,21 +1853,21 @@ module Warg
1993
1853
  script_name ||= command_name.script
1994
1854
  script = Script.new(script_name, context)
1995
1855
 
1996
- append Executor::Deferred.new(self, script, on, order, &setup)
1856
+ queue Step.new(self, script, on, order, &setup)
1997
1857
  end
1998
1858
 
1999
1859
  def run_command(command, on: hosts, order: :parallel, &setup)
2000
- append Executor::Deferred.new(self, command, on, order, &setup)
1860
+ queue Step.new(self, command, on, order, &setup)
2001
1861
  end
2002
1862
 
2003
1863
  def on_localhost(banner, &block)
2004
- append LOCALHOST.defer(self, banner, &block)
1864
+ queue Step.local(self, banner, block)
2005
1865
  end
2006
1866
  alias locally on_localhost
2007
1867
 
2008
- def append(deferred)
2009
- @steps << deferred
2010
- deferred
1868
+ def queue(step)
1869
+ @playlist.queue(step)
1870
+ step
2011
1871
  end
2012
1872
  end
2013
1873
 
@@ -2025,6 +1885,141 @@ module Warg
2025
1885
  klass.extend(Chaining)
2026
1886
  end
2027
1887
  end
1888
+
1889
+ class Step
1890
+ def self.local(command, banner, block)
1891
+ new(command, BlockProxy.new(banner, block), LOCALHOST, :serial)
1892
+ end
1893
+
1894
+ def self.callback(command, last_step, order, block)
1895
+ new \
1896
+ command,
1897
+ Callback.new(last_step, block),
1898
+ last_step.hosts,
1899
+ order
1900
+ end
1901
+
1902
+ attr_reader :command
1903
+ attr_reader :hosts
1904
+ attr_accessor :next
1905
+ attr_accessor :previous
1906
+ attr_reader :result
1907
+
1908
+ def initialize(command, run_object, hosts, order, &setup)
1909
+ @command = command
1910
+ @run_object = run_object
1911
+ @hosts = hosts
1912
+ @order = order
1913
+ @setup = setup
1914
+ end
1915
+
1916
+ def banner
1917
+ @run_object
1918
+ end
1919
+
1920
+ def and_then(order: :parallel, &block)
1921
+ @command.and_then order: order, &block
1922
+ end
1923
+
1924
+ def run
1925
+ @result = case @run_object
1926
+ when String
1927
+ @hosts.run_command(@run_object, order: @order, &@setup)
1928
+ when Script
1929
+ @hosts.run_script(@run_object, order: @order, &@setup)
1930
+ when Callback
1931
+ @run_object.run(@order)
1932
+ when BlockProxy
1933
+ # NOTE: A `Proc` means `@hosts` is `LOCALHOST`
1934
+ Executor::Result.new.tap do |result|
1935
+ result.update LOCALHOST.run(&@run_object)
1936
+ end
1937
+ end
1938
+ end
1939
+
1940
+ class BlockProxy < Struct.new(:banner, :block)
1941
+ def to_s
1942
+ banner
1943
+ end
1944
+
1945
+ def to_proc
1946
+ block
1947
+ end
1948
+ end
1949
+
1950
+ class Callback
1951
+ def initialize(last_step, run_object)
1952
+ @last_step = last_step
1953
+ @run_object = run_object
1954
+ end
1955
+
1956
+ def run(order)
1957
+ Executor.for(order).new(@last_step.result).run do |last_outcome, result|
1958
+ callback_outcome = Outcome.new(last_outcome)
1959
+
1960
+ begin
1961
+ # Use `||=` in case `#value` is set in the callback
1962
+ callback_outcome.value ||= @run_object.(last_outcome.host, last_outcome.value, callback_outcome)
1963
+ rescue => error
1964
+ callback_outcome.error = error
1965
+ end
1966
+
1967
+ result.update callback_outcome
1968
+ end
1969
+ end
1970
+
1971
+ def to_s
1972
+ "(callback)"
1973
+ end
1974
+
1975
+ class Outcome
1976
+ attr_reader :error
1977
+ attr_reader :host
1978
+ attr_reader :last_outcome
1979
+ attr_accessor :value
1980
+
1981
+ def initialize(outcome)
1982
+ @last_outcome = outcome
1983
+ @host = @last_outcome.host
1984
+ @successful = true
1985
+ end
1986
+
1987
+ def resolve(value)
1988
+ @value = value
1989
+ end
1990
+
1991
+ def fail!(message)
1992
+ @successful = false
1993
+
1994
+ raise CallbackFailedError.new(message)
1995
+ end
1996
+
1997
+ def error=(error)
1998
+ @successful = false
1999
+ @error = error
2000
+ end
2001
+
2002
+ def successful?
2003
+ @successful
2004
+ end
2005
+
2006
+ def failed?
2007
+ !successful?
2008
+ end
2009
+
2010
+ def failure_reason
2011
+ error
2012
+ end
2013
+
2014
+ def failure_summary
2015
+ error && error.full_message
2016
+ end
2017
+ end
2018
+ end
2019
+
2020
+ class CallbackFailedError < StandardError
2021
+ end
2022
+ end
2028
2023
  end
2029
2024
 
2030
2025
  class ChainCommand
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: warg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eduardo Gutierrez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-16 00:00:00.000000000 Z
11
+ date: 2023-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bcrypt_pbkdf
@@ -54,98 +54,112 @@ dependencies:
54
54
  name: net-ssh
55
55
  requirement: !ruby/object:Gem::Requirement
56
56
  requirements:
57
- - - "~>"
57
+ - - ">="
58
58
  - !ruby/object:Gem::Version
59
59
  version: '6.0'
60
60
  type: :runtime
61
61
  prerelease: false
62
62
  version_requirements: !ruby/object:Gem::Requirement
63
63
  requirements:
64
- - - "~>"
64
+ - - ">="
65
65
  - !ruby/object:Gem::Version
66
66
  version: '6.0'
67
67
  - !ruby/object:Gem::Dependency
68
68
  name: net-scp
69
69
  requirement: !ruby/object:Gem::Requirement
70
70
  requirements:
71
- - - "~>"
71
+ - - ">="
72
72
  - !ruby/object:Gem::Version
73
73
  version: '3.0'
74
74
  type: :runtime
75
75
  prerelease: false
76
76
  version_requirements: !ruby/object:Gem::Requirement
77
77
  requirements:
78
- - - "~>"
78
+ - - ">="
79
79
  - !ruby/object:Gem::Version
80
80
  version: '3.0'
81
81
  - !ruby/object:Gem::Dependency
82
82
  name: m
83
83
  requirement: !ruby/object:Gem::Requirement
84
84
  requirements:
85
- - - "~>"
85
+ - - ">="
86
86
  - !ruby/object:Gem::Version
87
87
  version: '1.0'
88
88
  type: :development
89
89
  prerelease: false
90
90
  version_requirements: !ruby/object:Gem::Requirement
91
91
  requirements:
92
- - - "~>"
92
+ - - ">="
93
93
  - !ruby/object:Gem::Version
94
94
  version: '1.0'
95
95
  - !ruby/object:Gem::Dependency
96
96
  name: byebug
97
97
  requirement: !ruby/object:Gem::Requirement
98
98
  requirements:
99
- - - "~>"
99
+ - - ">="
100
100
  - !ruby/object:Gem::Version
101
101
  version: '11'
102
102
  type: :development
103
103
  prerelease: false
104
104
  version_requirements: !ruby/object:Gem::Requirement
105
105
  requirements:
106
- - - "~>"
106
+ - - ">="
107
107
  - !ruby/object:Gem::Version
108
108
  version: '11'
109
109
  - !ruby/object:Gem::Dependency
110
110
  name: pry
111
111
  requirement: !ruby/object:Gem::Requirement
112
112
  requirements:
113
- - - "~>"
113
+ - - ">="
114
114
  - !ruby/object:Gem::Version
115
115
  version: '0.13'
116
116
  type: :development
117
117
  prerelease: false
118
118
  version_requirements: !ruby/object:Gem::Requirement
119
119
  requirements:
120
- - - "~>"
120
+ - - ">="
121
121
  - !ruby/object:Gem::Version
122
122
  version: '0.13'
123
+ - !ruby/object:Gem::Dependency
124
+ name: pry-remote
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: '0.1'
130
+ type: :development
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0.1'
123
137
  - !ruby/object:Gem::Dependency
124
138
  name: minitest
125
139
  requirement: !ruby/object:Gem::Requirement
126
140
  requirements:
127
- - - "~>"
141
+ - - ">="
128
142
  - !ruby/object:Gem::Version
129
143
  version: 5.15.0
130
144
  type: :development
131
145
  prerelease: false
132
146
  version_requirements: !ruby/object:Gem::Requirement
133
147
  requirements:
134
- - - "~>"
148
+ - - ">="
135
149
  - !ruby/object:Gem::Version
136
150
  version: 5.15.0
137
151
  - !ruby/object:Gem::Dependency
138
152
  name: simplecov
139
153
  requirement: !ruby/object:Gem::Requirement
140
154
  requirements:
141
- - - "~>"
155
+ - - ">="
142
156
  - !ruby/object:Gem::Version
143
157
  version: 0.21.2
144
158
  type: :development
145
159
  prerelease: false
146
160
  version_requirements: !ruby/object:Gem::Requirement
147
161
  requirements:
148
- - - "~>"
162
+ - - ">="
149
163
  - !ruby/object:Gem::Version
150
164
  version: 0.21.2
151
165
  description: Running one-off commands, templated scripts, or managing output from