rudy 0.8.1 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. data/CHANGES.txt +21 -8
  2. data/README.rdoc +43 -1
  3. data/Rudyfile +28 -27
  4. data/bin/rudy +8 -15
  5. data/lib/rudy.rb +2 -2
  6. data/lib/rudy/cli/routines.rb +4 -20
  7. data/lib/rudy/config.rb +1 -0
  8. data/lib/rudy/config/objects.rb +29 -33
  9. data/lib/rudy/huxtable.rb +9 -1
  10. data/lib/rudy/routines.rb +113 -96
  11. data/lib/rudy/routines/helper.rb +3 -3
  12. data/lib/rudy/routines/helpers/dependshelper.rb +1 -1
  13. data/lib/rudy/routines/helpers/diskhelper.rb +3 -3
  14. data/lib/rudy/routines/helpers/scripthelper.rb +41 -39
  15. data/lib/rudy/routines/helpers/userhelper.rb +5 -5
  16. data/lib/rudy/routines/passthrough.rb +11 -11
  17. data/lib/rudy/routines/startup.rb +1 -1
  18. data/rudy.gemspec +4 -37
  19. metadata +5 -38
  20. data/examples/README.md +0 -10
  21. data/examples/debian-sinatra-passenger/commands.rb +0 -19
  22. data/examples/debian-sinatra-passenger/machines.rb +0 -32
  23. data/examples/debian-sinatra-passenger/routines.rb +0 -30
  24. data/examples/debian-sinatra-thin/commands.rb +0 -17
  25. data/examples/debian-sinatra-thin/machines.rb +0 -35
  26. data/examples/debian-sinatra-thin/routines.rb +0 -72
  27. data/lib/rudy/routines/helpers/scmhelper.rb +0 -39
  28. data/lib/rudy/routines/release.rb +0 -48
  29. data/lib/rudy/scm.rb +0 -75
  30. data/lib/rudy/scm/git.rb +0 -217
  31. data/lib/rudy/scm/svn.rb +0 -110
  32. data/test/01_mixins/10_hash_test.rb +0 -25
  33. data/test/10_config/00_setup_test.rb +0 -20
  34. data/test/10_config/30_machines_test.rb +0 -69
  35. data/test/15_scm/00_setup_test.rb +0 -20
  36. data/test/15_scm/20_git_test.rb +0 -61
  37. data/test/20_sdb/00_setup_test.rb +0 -16
  38. data/test/20_sdb/10_domains_test.rb +0 -115
  39. data/test/25_ec2/00_setup_test.rb +0 -29
  40. data/test/25_ec2/10_keypairs_test.rb +0 -41
  41. data/test/25_ec2/20_groups_test.rb +0 -131
  42. data/test/25_ec2/30_addresses_test.rb +0 -38
  43. data/test/25_ec2/40_volumes_test.rb +0 -49
  44. data/test/25_ec2/50_snapshots_test.rb +0 -74
  45. data/test/26_ec2_instances/00_setup_test.rb +0 -28
  46. data/test/26_ec2_instances/10_instances_test.rb +0 -83
  47. data/test/26_ec2_instances/50_images_test.rb +0 -13
  48. data/test/30_sdb_metadata/00_setup_test.rb +0 -21
  49. data/test/30_sdb_metadata/10_disks_test.rb +0 -109
  50. data/test/30_sdb_metadata/20_backups_test.rb +0 -102
  51. data/test/coverage.txt +0 -51
  52. data/test/helper.rb +0 -36
@@ -1,7 +1,7 @@
1
1
 
2
2
  module Rudy; module Routines;
3
3
  module UserHelper
4
- include Rudy::Routines::HelperBase # TODO: use execute_rbox_command
4
+ include Rudy::Routines::HelperBase # TODO: use trap_rbox_errors
5
5
  extend self
6
6
 
7
7
  def adduser?(routine)
@@ -13,22 +13,22 @@ module Rudy; module Routines;
13
13
  # explicitly so we do it for linux too for fun.
14
14
  homedir = rbox.guess_user_home(routine.adduser.to_s)
15
15
  args = [:m, :d, homedir, :s, '/bin/bash', routine.adduser.to_s]
16
- puts command_separator(rbox.preview_command(:useradd, args), rbox.user)
16
+ puts command_separator(rbox.preview_command(:useradd, args), rbox.user, rbox.host)
17
17
 
18
18
  # NOTE: We'll may to use platform specific code here.
19
19
  # Linux has adduser and useradd commands:
20
20
  # adduser can prompt for info which we don't want.
21
21
  # useradd does not prompt (on Debian/Ubuntu at least).
22
22
  # We need to specify bash b/c the default is /bin/sh
23
- execute_rbox_command { rbox.useradd(args) }
23
+ trap_rbox_errors { rbox.useradd(args) }
24
24
  end
25
25
 
26
26
  def authorize?(routine)
27
27
  (!routine.authorize.nil? && !routine.authorize.to_s.empty?)
28
28
  end
29
29
  def authorize(routine, machine, rbox)
30
- puts command_separator(:authorize_keys_remote, rbox.user)
31
- execute_rbox_command { rbox.authorize_keys_remote(routine.authorize) }
30
+ puts command_separator(:authorize_keys_remote, rbox.user, rbox.host)
31
+ trap_rbox_errors { rbox.authorize_keys_remote(routine.authorize) }
32
32
  end
33
33
 
34
34
 
@@ -4,18 +4,17 @@ module Rudy; module Routines;
4
4
  class Passthrough < Rudy::Routines::Base
5
5
 
6
6
  def init(*args)
7
- @routine_name = args.first
8
- @routine = fetch_routine_config(@routine_name)
7
+ @routine = fetch_routine_config(@cmdname)
9
8
  end
10
9
 
11
10
  # * +each_mach+ is an optional block which is executed between
12
11
  # disk creation and the after scripts. The will receives two
13
12
  # arguments: instances of Rudy::Machine and Rye::Box.
14
13
  def execute(&each_mach)
15
- routine_separator(@routine_name)
14
+ routine_separator(@cmdname)
16
15
  machines = []
17
16
  generic_machine_runner(:list) do |machine,rbox|
18
- puts $/ #, "[routine: #{@routine_name}]"
17
+ puts $/ #, "[routine: #{@cmdname}]"
19
18
  machines << machine
20
19
  end
21
20
  machines
@@ -23,14 +22,15 @@ module Rudy; module Routines;
23
22
 
24
23
  # Called by generic_machine_runner
25
24
  def raise_early_exceptions
26
- raise Rudy::Error, "No routine name" unless @routine_name
27
- raise NoRoutine, @routine_name unless @routine
28
- rmach = Rudy::Machines.new
29
- raise Rudy::PrivateKeyNotFound, root_keypairpath unless has_keypair?(:root)
25
+ raise Rudy::Error, "No routine name" unless @cmdname
26
+ raise NoRoutine, @cmdname unless @routine
27
+ # TODO: enable this for EC2 groups only
28
+ #raise Rudy::PrivateKeyNotFound, root_keypairpath unless has_keypair?(:root)
30
29
  raise MachineGroupNotDefined, current_machine_group unless known_machine_group?
31
- if !@@global.offline && !rmach.running?
32
- raise MachineGroupNotRunning, current_machine_group
33
- end
30
+ ##rmach = Rudy::Machines.new
31
+ ##if !@@global.offline && !rmach.running?
32
+ ## raise MachineGroupNotRunning, current_machine_group
33
+ ##end
34
34
  end
35
35
 
36
36
  end
@@ -4,7 +4,7 @@ module Rudy; module Routines;
4
4
  class Startup < Rudy::Routines::Base
5
5
 
6
6
  def init(*args)
7
- @routine = fetch_routine_config(:startup)
7
+ @routine = fetch_routine_config(:startup) # NOTE: could use @cmdname here
8
8
  end
9
9
 
10
10
  # * +each_mach+ is an optional block which is executed between
data/rudy.gemspec CHANGED
@@ -1,22 +1,22 @@
1
1
  @spec = Gem::Specification.new do |s|
2
2
  s.name = "rudy"
3
3
  s.rubyforge_project = 'rudy'
4
- s.version = "0.8.1"
4
+ s.version = "0.8.2"
5
5
  s.summary = "Rudy: Not your grandparents' EC2 deployment tool."
6
6
  s.description = s.summary
7
7
  s.author = "Delano Mandelbaum"
8
8
  s.email = "delano@solutious.com"
9
9
  s.homepage = "http://github.com/solutious/rudy"
10
10
 
11
- s.extra_rdoc_files = %w[README.rdoc Rudyfile LICENSE.txt CHANGES.txt ]
11
+ s.extra_rdoc_files = %w[README.rdoc Rudyfile LICENSE.txt CHANGES.txt]
12
12
  s.has_rdoc = true
13
13
  s.rdoc_options = ["--line-numbers", "--title", s.summary, "--main", "README.rdoc"]
14
14
  s.require_paths = %w[lib]
15
15
  s.rubygems_version = '1.1.1'
16
16
 
17
17
  s.add_dependency 'drydock', '>= 0.6.3'
18
- s.add_dependency 'caesars', '>= 0.6.6'
19
- s.add_dependency 'rye', '>= 0.6.5'
18
+ s.add_dependency 'caesars', '>= 0.6.8'
19
+ s.add_dependency 'rye', '>= 0.7.2'
20
20
  s.add_dependency 'sysinfo', '>= 0.5.1'
21
21
  s.add_dependency 'storable', '>= 0.5.2'
22
22
  s.add_dependency 'annoy', '>= 0.5.0'
@@ -49,13 +49,6 @@
49
49
  bin/rudy-ec2
50
50
  bin/rudy-s3
51
51
  bin/rudy-sdb
52
- examples/README.md
53
- examples/debian-sinatra-passenger/commands.rb
54
- examples/debian-sinatra-passenger/machines.rb
55
- examples/debian-sinatra-passenger/routines.rb
56
- examples/debian-sinatra-thin/commands.rb
57
- examples/debian-sinatra-thin/machines.rb
58
- examples/debian-sinatra-thin/routines.rb
59
52
  lib/rudy.rb
60
53
  lib/rudy/aws.rb
61
54
  lib/rudy/aws/ec2.rb
@@ -106,44 +99,18 @@
106
99
  lib/rudy/routines/helper.rb
107
100
  lib/rudy/routines/helpers/dependshelper.rb
108
101
  lib/rudy/routines/helpers/diskhelper.rb
109
- lib/rudy/routines/helpers/scmhelper.rb
110
102
  lib/rudy/routines/helpers/scripthelper.rb
111
103
  lib/rudy/routines/helpers/userhelper.rb
112
104
  lib/rudy/routines/passthrough.rb
113
105
  lib/rudy/routines/reboot.rb
114
- lib/rudy/routines/release.rb
115
106
  lib/rudy/routines/shutdown.rb
116
107
  lib/rudy/routines/startup.rb
117
- lib/rudy/scm.rb
118
- lib/rudy/scm/git.rb
119
- lib/rudy/scm/svn.rb
120
108
  lib/rudy/utils.rb
121
109
  rudy.gemspec
122
110
  support/mailtest
123
111
  support/randomize-root-password
124
112
  support/rudy-ec2-startup
125
113
  support/update-ec2-ami-tools
126
- test/01_mixins/10_hash_test.rb
127
- test/10_config/00_setup_test.rb
128
- test/10_config/30_machines_test.rb
129
- test/15_scm/00_setup_test.rb
130
- test/15_scm/20_git_test.rb
131
- test/20_sdb/00_setup_test.rb
132
- test/20_sdb/10_domains_test.rb
133
- test/25_ec2/00_setup_test.rb
134
- test/25_ec2/10_keypairs_test.rb
135
- test/25_ec2/20_groups_test.rb
136
- test/25_ec2/30_addresses_test.rb
137
- test/25_ec2/40_volumes_test.rb
138
- test/25_ec2/50_snapshots_test.rb
139
- test/26_ec2_instances/00_setup_test.rb
140
- test/26_ec2_instances/10_instances_test.rb
141
- test/26_ec2_instances/50_images_test.rb
142
- test/30_sdb_metadata/00_setup_test.rb
143
- test/30_sdb_metadata/10_disks_test.rb
144
- test/30_sdb_metadata/20_backups_test.rb
145
- test/coverage.txt
146
- test/helper.rb
147
114
  )
148
115
 
149
116
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rudy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Delano Mandelbaum
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-05-18 00:00:00 -04:00
12
+ date: 2009-06-01 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -30,7 +30,7 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.6.6
33
+ version: 0.6.8
34
34
  version:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: rye
@@ -40,7 +40,7 @@ dependencies:
40
40
  requirements:
41
41
  - - ">="
42
42
  - !ruby/object:Gem::Version
43
- version: 0.6.5
43
+ version: 0.7.2
44
44
  version:
45
45
  - !ruby/object:Gem::Dependency
46
46
  name: sysinfo
@@ -147,13 +147,6 @@ files:
147
147
  - bin/rudy-ec2
148
148
  - bin/rudy-s3
149
149
  - bin/rudy-sdb
150
- - examples/README.md
151
- - examples/debian-sinatra-passenger/commands.rb
152
- - examples/debian-sinatra-passenger/machines.rb
153
- - examples/debian-sinatra-passenger/routines.rb
154
- - examples/debian-sinatra-thin/commands.rb
155
- - examples/debian-sinatra-thin/machines.rb
156
- - examples/debian-sinatra-thin/routines.rb
157
150
  - lib/rudy.rb
158
151
  - lib/rudy/aws.rb
159
152
  - lib/rudy/aws/ec2.rb
@@ -204,44 +197,18 @@ files:
204
197
  - lib/rudy/routines/helper.rb
205
198
  - lib/rudy/routines/helpers/dependshelper.rb
206
199
  - lib/rudy/routines/helpers/diskhelper.rb
207
- - lib/rudy/routines/helpers/scmhelper.rb
208
200
  - lib/rudy/routines/helpers/scripthelper.rb
209
201
  - lib/rudy/routines/helpers/userhelper.rb
210
202
  - lib/rudy/routines/passthrough.rb
211
203
  - lib/rudy/routines/reboot.rb
212
- - lib/rudy/routines/release.rb
213
204
  - lib/rudy/routines/shutdown.rb
214
205
  - lib/rudy/routines/startup.rb
215
- - lib/rudy/scm.rb
216
- - lib/rudy/scm/git.rb
217
- - lib/rudy/scm/svn.rb
218
206
  - lib/rudy/utils.rb
219
207
  - rudy.gemspec
220
208
  - support/mailtest
221
209
  - support/randomize-root-password
222
210
  - support/rudy-ec2-startup
223
211
  - support/update-ec2-ami-tools
224
- - test/01_mixins/10_hash_test.rb
225
- - test/10_config/00_setup_test.rb
226
- - test/10_config/30_machines_test.rb
227
- - test/15_scm/00_setup_test.rb
228
- - test/15_scm/20_git_test.rb
229
- - test/20_sdb/00_setup_test.rb
230
- - test/20_sdb/10_domains_test.rb
231
- - test/25_ec2/00_setup_test.rb
232
- - test/25_ec2/10_keypairs_test.rb
233
- - test/25_ec2/20_groups_test.rb
234
- - test/25_ec2/30_addresses_test.rb
235
- - test/25_ec2/40_volumes_test.rb
236
- - test/25_ec2/50_snapshots_test.rb
237
- - test/26_ec2_instances/00_setup_test.rb
238
- - test/26_ec2_instances/10_instances_test.rb
239
- - test/26_ec2_instances/50_images_test.rb
240
- - test/30_sdb_metadata/00_setup_test.rb
241
- - test/30_sdb_metadata/10_disks_test.rb
242
- - test/30_sdb_metadata/20_backups_test.rb
243
- - test/coverage.txt
244
- - test/helper.rb
245
212
  has_rdoc: true
246
213
  homepage: http://github.com/solutious/rudy
247
214
  licenses: []
@@ -270,7 +237,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
270
237
  requirements: []
271
238
 
272
239
  rubyforge_project: rudy
273
- rubygems_version: 1.3.2
240
+ rubygems_version: 1.3.3
274
241
  signing_key:
275
242
  specification_version: 3
276
243
  summary: "Rudy: Not your grandparents' EC2 deployment tool."
data/examples/README.md DELETED
@@ -1,10 +0,0 @@
1
- # Rudy Configuration Examples
2
-
3
- *NOTE: The examples are a work in progress*
4
-
5
- ## Contributions
6
-
7
- I'm very open to contributions! Rudy supports all Linux-based platforms (with partial Solaris support) and software (rails, sinatra, MySQL, PostgreSQL, etc...) so it's possible to write examples for pretty much anything. If you're interested in writing new examples, I'll gladly accept them and include them here (with credit of course!).
8
-
9
-
10
-
@@ -1,19 +0,0 @@
1
- # ----------------------------------------------------------- COMMANDS --------
2
- # The commands block defines shell commands that can be used in routines. The
3
- # ones defined here are added to the default list defined by Rye::Cmd (Rudy
4
- # executes all SSH commands via Rye).
5
- #
6
- # Usage:
7
- #
8
- # allow COMMAND-NAME
9
- # allow COMMAND-NAME, '/path/2/COMMAND'
10
- # allow COMMAND-NAME, '/path/2/COMMAND', 'default argument', 'another arg'
11
- #
12
- commands do
13
- allow :apt_get, "apt-get", :y, :q
14
- allow :gem_install, "/usr/bin/gem", "install", :n, '/usr/bin', :y, :V, "--no-rdoc", "--no-ri"
15
- allow :gem_sources, "/usr/bin/gem", "sources"
16
- allow :passenger_install_apache2, "passenger-install-apache2-module", '--auto'
17
- allow :passenger_install_nginx, "passenger-install-nginx-module", '--auto', '--autodownload'
18
- allow :apache2ctl
19
- end
@@ -1,32 +0,0 @@
1
-
2
- # --------------------------------------------------------- MACHINES --------
3
- # The machines block describes the "physical" characteristics
4
- # of your environments.
5
- machines do
6
-
7
- # We've defined an environment called "stage" with one role: "app".
8
- # The configuration inside the env block is available to all its
9
- # roles. The configuration inside the role blocks is available only
10
- # to machines in that specific role.
11
- env :dev, :stage, :prod do
12
- ami "ami-e348af8a" # Debian 5.0 32-bit, Alestic
13
- size 'm1.small'
14
-
15
- role :app do
16
- # You can define disks for the stage-app machines. Rudy uses
17
- # this configuration when it executes a routine (see below).
18
- disks do
19
- path "/rudy/disk1" do
20
- size 10
21
- device "/dev/sdr"
22
- fstype 'ext3'
23
- end
24
- end
25
-
26
- end
27
-
28
- end
29
-
30
- end
31
-
32
-
@@ -1,30 +0,0 @@
1
-
2
- routines do
3
-
4
- sysupdate do
5
- script :root do
6
- apt_get "update"
7
- apt_get "install", "build-essential", "git-core"
8
- apt_get "install", "sqlite3", "libsqlite3-dev"
9
- apt_get "install", "ruby1.8-dev", "rubygems"
10
- apt_get "install", "nginx"
11
- apt_get "install", "apache2-mpm-prefork", "apache2-prefork-dev", "libapr1-dev"
12
- apt_get "install", "libfcgi-dev", "libfcgi-ruby1.8"
13
- gem_sources :a, "http://gems.github.com"
14
- end
15
- end
16
-
17
- installdeps do
18
- script :root do
19
- gem_install "test-spec", "rspec", "camping", "fcgi", "memcache-client"
20
- gem_install "rake", "passenger"
21
- passenger_install_apache2
22
- passenger_install_nginx
23
- gem_install "rack", :v, "0.9.1" # 0.9.1 required by sinatra
24
- gem_install "sinatra"
25
- end
26
- end
27
-
28
-
29
-
30
- end
@@ -1,17 +0,0 @@
1
- # ----------------------------------------------------------- COMMANDS --------
2
- # The commands block defines shell commands that can be used in routines. The
3
- # ones defined here are added to the default list defined by Rye::Cmd (Rudy
4
- # executes all SSH commands via Rye).
5
- #
6
- # Usage:
7
- #
8
- # allow COMMAND-NAME
9
- # allow COMMAND-NAME, '/path/2/COMMAND'
10
- # allow COMMAND-NAME, '/path/2/COMMAND', 'default argument', 'another arg'
11
- #
12
- commands do
13
- allow :apt_get, "apt-get", :y, :q
14
- allow :gem_install, "/usr/bin/gem", "install", :n, '/usr/bin', :y, :V, "--no-rdoc", "--no-ri"
15
- allow :gem_sources, "/usr/bin/gem", "sources"
16
- allow :thin, "/usr/local/bin/thin", :d, :R, './config.ru', :l, './thin.log', :P, './thin.pid'
17
- end
@@ -1,35 +0,0 @@
1
- # THIS EXAMPLE IS INCOMPLETE -- 2009-05-03
2
-
3
- # --------------------------------------------------------- MACHINES --------
4
- # The machines block describes the "physical" characteristics
5
- # of your environments.
6
- machines do
7
-
8
- # We've defined an environment called "stage" with one role: "app".
9
- # The configuration inside the env block is available to all its
10
- # roles. The configuration inside the role blocks is available only
11
- # to machines in that specific role.
12
- env :dev, :stage, :prod do
13
- ami "ami-e348af8a" # Debian 5.0 32-bit, Alestic
14
- size 'm1.small'
15
-
16
- role :app do
17
- #positions 2
18
-
19
- # You can define disks for the stage-app machines. Rudy uses
20
- # this configuration when it executes a routine (see below).
21
- disks do
22
- path "/rudy/disk1" do
23
- size 10
24
- device "/dev/sdr"
25
- fstype 'ext2'
26
- end
27
- end
28
-
29
- end
30
-
31
- end
32
-
33
- end
34
-
35
-
@@ -1,72 +0,0 @@
1
- # THIS EXAMPLE IS INCOMPLETE -- 2009-05-03
2
-
3
- # Rudy -- debian-sinatra-thin
4
- #
5
- # Notes:
6
- # * Change :rudy to the name of your user remote deployment user
7
- #
8
- sinatra_home = "/rudy/disk1/sinatra"
9
- routines do
10
-
11
- sysupdate do
12
- script :root do
13
- apt_get "update"
14
- apt_get "install", "build-essential", "git-core"
15
- apt_get "install", "sqlite3", "libsqlite3-dev"
16
- apt_get "install", "ruby1.8-dev", "rubygems"
17
- apt_get "install", "apache2-prefork-dev", "libapr1-dev"
18
- apt_get "install", "libfcgi-dev", "libfcgi-ruby1.8"
19
- gem_sources :a, "http://gems.github.com"
20
- end
21
- end
22
-
23
- installdeps do
24
- script :root do
25
- gem_install "test-spec", "rspec", "camping", "fcgi", "memcache-client"
26
- gem_install "mongrel"
27
- gem_install 'ruby-openid', :v, "2.0.4" # thin requires 2.0.x
28
- gem_install "rack", :v, "0.9.1"
29
- gem_install "macournoyer-thin" # need 1.1.0 which works with rack 0.9.1
30
- gem_install "sinatra"
31
- end
32
- end
33
-
34
- environment :dev, :stage do
35
-
36
- startup do
37
- adduser :rudy
38
- authorize :rudy
39
- disks do
40
- create "/rudy/disk1"
41
- end
42
- end
43
- shutdown do
44
- disks do
45
- destroy "/rudy/disk1"
46
- end
47
- end
48
-
49
- restart do
50
- after :rudy do
51
- thin :c, sinatra_home, "restart"
52
- end
53
- end
54
- start do
55
- after :rudy do
56
- thin :c, sinatra_home, "start"
57
- end
58
- end
59
- stop do
60
- after :rudy do
61
- thin :c, sinatra_home, "stop"
62
- end
63
- end
64
-
65
-
66
- end
67
-
68
- end
69
-
70
-
71
-
72
-