amphibian 0.0.2 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Chris Kelly
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,6 @@
1
+ amphibian
2
+ =========
3
+
4
+ Amphibian is a ruby library for accessing and interacting with an Apache mod_proxy_balancer via the web GUI created by the balancer_manager directive.
5
+
6
+ This is a continuation of the work done by Nick Stielau. (amphibian.rubyforge.org)
File without changes
@@ -9,12 +9,9 @@ require 'open-uri'
9
9
  # Gems
10
10
  require 'rubygems'
11
11
  require 'hpricot'
12
+ require 'curb'
13
+ require 'nokogiri'
12
14
 
13
15
  # Files
14
16
  require 'amphibian/runner'
15
17
  require 'amphibian/balancerManagerDocument'
16
-
17
-
18
- module Amphibian
19
- VERSION = '0.0.2'
20
- end
@@ -1,35 +1,28 @@
1
1
  module Amphibian
2
2
  class BalancerManager
3
-
3
+
4
4
  def initialize(balancer_manager_url, dry_run = false)
5
5
  @balancer_manager_url = balancer_manager_url
6
6
  @dry_run = dry_run
7
-
8
- if !balancer_manager_url.match("127.0.0.1") && !dry_run
9
- @dry_run = true
10
- log_error
11
- log_error "Not running on localhost: Performing dry-run"
12
- log_error
13
- end
14
- end
15
-
7
+ end
8
+
16
9
  # Disables a host from the balancer.
17
10
  def disable_host(host)
18
11
  # TODO: Check Status
19
12
  toggle_host(host, 'Disable')
20
13
  end
21
-
14
+
22
15
  # Enables a host in the balancer
23
16
  def enable_host(host)
24
17
  # TODO: Check Status
25
18
  toggle_host(host, 'Enable')
26
19
  end
27
-
20
+
28
21
  # Returns an array of strings indicated the balancer members parsed out of the BalancerManager page.
29
22
  def hosts
30
- @hosts ||= (get_doc/'a').select{|a_tag| a_tag.inner_text =~ /^http:/}.map{|a_tag| a_tag.inner_text}
23
+ @hosts ||= (get_doc/'a').select{|a_tag| a_tag.inner_text =~ /^http[s]?:/}.map{|a_tag| a_tag.inner_text}
31
24
  end
32
-
25
+
33
26
  # Get an array of hosts that are in 'Ok' state
34
27
  #---
35
28
  # TODO: Optionally force refresh
@@ -39,7 +32,7 @@ module Amphibian
39
32
  hosts_with_status.select{|host,state| state == 'Ok'}.each{|host, state| hosts_array << host}
40
33
  hosts_array
41
34
  end
42
-
35
+
43
36
  # Get an array of hosts that are not in 'Ok' state
44
37
  #---
45
38
  # TODO: Optionally force refresh
@@ -49,45 +42,48 @@ module Amphibian
49
42
  hosts_with_status.select{|host,state| state != 'Ok'}.each{|host, state| hosts_array << host}
50
43
  hosts_array
51
44
  end
52
-
45
+
53
46
  # Returns the name of the balancer on the BalancerManager page.
54
47
  def balancer_name
55
- @balancer_name ||= (get_doc/'a').select{|a_tag| a_tag.inner_text =~ /^balancer:/}.map{|a_tag| a_tag.inner_text}[0].sub('balancer://', '')
48
+ @balancer_name ||= get_doc2().css('h3').to_s.scan(/\/\/([^"]*)</)[0][0]
49
+ end
50
+
51
+ def nonce
52
+ @nonce ||= get_doc2().css('a').first.to_s.scan(/nonce=([^"]*)">/)[0][0]
56
53
  end
57
-
58
54
  # Returns the url of the BalancerManager page.
59
55
  def balancer_manager_url
60
56
  @balancer_manager_url
61
57
  end
62
-
58
+
63
59
  # TODO: Optionally force refresh
64
60
  def host_enabled?(host)
65
61
  enabled_hosts.include?(host)
66
62
  end
67
63
 
68
- # TODO: Optionally force refresh
64
+ # TODO: Optionally force refresh
69
65
  def host_disabled?(host)
70
66
  !enabled_hosts.include?(host)
71
67
  end
72
-
68
+
73
69
  def dry_run?
74
70
  @dry_run
75
71
  end
76
72
 
77
73
  def hosts_with_status
78
74
  host_to_status = {}
79
- (get_doc/'a').select{|a_tag| a_tag.inner_text =~ /^http:/}.each do |a_tag|
75
+ (get_doc/'a').select{|a_tag| a_tag.inner_text =~ /^http[s]?:/}.each do |a_tag|
80
76
  host_to_status[a_tag.inner_text] = (a_tag.parent.parent.children[6].inner_text.strip)
81
77
  end
82
78
  host_to_status
83
79
  end
84
-
80
+
85
81
  private
86
82
 
87
83
  # Sets the state of the host to the specified state
88
84
  def toggle_host(host, state)
89
85
  log_error("#{state} is an invalid state") if state != "Enable" && state != "Disable"
90
- run "curl -s -o /dev/null #{@balancer_manager_url}\?b=#{balancer_name}\\&w=#{host}\\&dw=#{state}"
86
+ Curl.get("#{@balancer_manager_url}\?b=#{balancer_name}&w=#{host}&dw=#{state}&nonce=#{nonce}")
91
87
  # TODO: Check status
92
88
  end
93
89
 
@@ -116,6 +112,18 @@ private
116
112
  nil
117
113
  end
118
114
  end
115
+ def get_doc2
116
+ @doc ||= begin
117
+ Nokogiri::HTML(open(@balancer_manager_url))
118
+ rescue Exception => e
119
+ if e =~ /403/
120
+ log_error "Balancer Manager is getting a 403: Forbidden response. Make sure it is accessable from this location."
121
+ else
122
+ log_error "Error opening the balancer manager: #{e}"
123
+ end
124
+ nil
125
+ end
126
+ end
119
127
  end
120
128
  end
121
129
 
@@ -1,33 +1,26 @@
1
- require 'net/smtp'
2
-
3
1
  module Amphibian
4
2
  class Runner
5
3
  # TODO: log everything, and set log level, so we don't have to print anything
6
4
  # TODO: Email at the end
7
-
5
+
8
6
  def initialize(balancer_manager_url, test_page='/', test_regex=nil, dry_run=false)
9
7
  @balancer_manager_url = balancer_manager_url
10
8
  @test_page = test_page
11
9
  @test_regex = test_regex
12
10
  @dry_run = dry_run
13
11
  @errors = []
14
-
15
- if !balancer_manager_url.match("127.0.0.1") && !dry_run
16
- @dry_run = true
17
- log_error "Not running on localhost: Performing dry-run"
18
- end
19
-
12
+
20
13
  @balancer_manager = BalancerManager.new(@balancer_manager_url, @dry_run)
21
14
 
22
15
  @min_hosts = -1
23
16
  end
24
-
17
+
25
18
  def do_check
26
19
  check
27
20
  end
28
21
 
29
22
  private
30
-
23
+
31
24
  # Checks the balancer members, enabling/disabling each depending on the status.
32
25
  def check
33
26
  puts
@@ -45,7 +38,7 @@ private
45
38
  puts
46
39
 
47
40
  @live_hosts.each do |host, state|
48
- status = check_host(host, @test_page)
41
+ status = check_host(host, @test_page)
49
42
  puts " #{host} is #{status ? 'OK' : 'not responsive. Disabling via BalancerManager.'}"
50
43
  disable_host(host) if !status
51
44
  end
@@ -58,7 +51,7 @@ private
58
51
  @errors << error
59
52
  puts "ERROR: #{error}"
60
53
  end
61
-
54
+
62
55
  # Returns the BalancerManager object.
63
56
  def get_balancer_manager
64
57
  @balancer_manager
@@ -71,12 +64,12 @@ private
71
64
  status = Timeout::timeout(timeout) do
72
65
  Net::HTTP.start(URI.parse(host).host) do |http|
73
66
  response = http.get(path)
74
-
67
+
75
68
  if not response.code.match(/200/)
76
69
  log_error("Web Server down or not responding: #{response.code} #{response.message}")
77
70
  return false;
78
71
  end
79
-
72
+
80
73
  if @test_regex && ! response.body.match(@test_regex)
81
74
  log_error("The response did not contain the regex '#{@test_regex}'")
82
75
  return false
@@ -93,39 +86,19 @@ private
93
86
  log_error("An unknown error occured checking #{host}#{path}: #{e}")
94
87
  return false;
95
88
  end
96
-
89
+
97
90
  return true
98
91
  end
99
-
92
+
100
93
  # Disables a host from the balancer.
101
94
  def disable_host(host)
102
95
  if @live_hosts.size <= @min_hosts
103
96
  puts "Will not take #{host} down, alreay at lower limit #{@min_hosts}"
104
97
  return
105
98
  end
106
-
99
+
107
100
  #puts "Disabling host '#{host}'"
108
101
  get_balancer_manager.disable_host(host)
109
- send_email("Disabled #{host} from the balancer #{get_balancer_manager.balancer_name} at #{get_balancer_manager.balancer_manager_url}")
110
- end
111
-
112
- def send_email(message)
113
- begin
114
- Net::SMTP.start('127.0.0.1', 25) do |smtp|
115
- smtp.open_message_stream('dev@delvenetworks.com', ['nick@delvenetworks.com']) do |f|
116
- f.puts 'From: dev@delvenetworks.com'
117
- f.puts 'To: nick@delvenetworks.com'
118
- f.puts 'Subject: Apache mod_balancer host disabled'
119
- f.puts
120
- f.puts message
121
- f.puts
122
- f.puts "Errors:"
123
- f.puts @errors.join(",")
124
- end
125
- end
126
- rescue Exception => e
127
- log_error("Error sending email: #{e}")
128
- end
129
102
  end
130
103
  end
131
104
  end
metadata CHANGED
@@ -1,91 +1,94 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: amphibian
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ prerelease:
5
+ version: 0.0.4
5
6
  platform: ruby
6
7
  authors:
8
+ - Chris Kelly
7
9
  - Nick Stielau
8
10
  autorequire:
9
11
  bindir: bin
10
12
  cert_chain: []
11
13
 
12
- date: 2009-06-28 00:00:00 -07:00
13
- default_executable:
14
+ date: 2013-08-08 00:00:00 Z
14
15
  dependencies:
15
16
  - !ruby/object:Gem::Dependency
16
- name: newgem
17
- type: :development
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
17
+ name: curb
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
20
21
  requirements:
21
22
  - - ">="
22
23
  - !ruby/object:Gem::Version
23
- version: 1.4.1
24
- version:
24
+ version: "0"
25
+ type: :runtime
26
+ version_requirements: *id001
25
27
  - !ruby/object:Gem::Dependency
26
- name: hoe
27
- type: :development
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
28
+ name: nokogiri
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
30
32
  requirements:
31
33
  - - ">="
32
34
  - !ruby/object:Gem::Version
33
- version: 1.8.0
34
- version:
35
- description: Amphibian is a ruby library for accessing and interacting with an Apache mod_proxy_balancer via the web GUI created by the balancer_manager directive. Amhpbian works by scraping the balancer-manager page, and sending get requests with appropriate query strings to the balancer manager in order to enable and disable hosts.
36
- email:
37
- - nick.stielau@gmail.com
38
- executables:
39
- - check_balancer_members
35
+ version: "0"
36
+ type: :runtime
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: hpricot
40
+ prerelease: false
41
+ requirement: &id003 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id003
49
+ description: Amphibian is a ruby library for accessing and interacting with an Apache mod_proxy_balancer via the web GUI created by the balancer_manager directive.
50
+ email: chris@chris-kelly.net
51
+ executables: []
52
+
40
53
  extensions: []
41
54
 
42
- extra_rdoc_files:
43
- - History.txt
44
- - Manifest.txt
45
- - PostInstall.txt
46
- - README.rdoc
55
+ extra_rdoc_files: []
56
+
47
57
  files:
48
- - History.txt
49
- - Manifest.txt
50
- - PostInstall.txt
51
- - README.rdoc
52
- - Rakefile
53
- - bin/check_balancer_members
54
- - lib/amphibian.rb
55
58
  - lib/amphibian/balancerManagerDocument.rb
56
59
  - lib/amphibian/runner.rb
57
- - script/console
58
- - script/destroy
59
- - script/generate
60
+ - lib/amphibian.rb
61
+ - bin/check_balancer_members
62
+ - LICENSE
63
+ - README.md
60
64
  - test/test_amphibian.rb
61
65
  - test/test_helper.rb
62
- has_rdoc: true
63
- homepage:
64
- post_install_message: PostInstall.txt
65
- rdoc_options:
66
- - --main
67
- - README.rdoc
66
+ homepage: https://github.com/chkelly/amphibian
67
+ licenses:
68
+ - MIT
69
+ post_install_message:
70
+ rdoc_options: []
71
+
68
72
  require_paths:
69
73
  - lib
70
74
  required_ruby_version: !ruby/object:Gem::Requirement
75
+ none: false
71
76
  requirements:
72
77
  - - ">="
73
78
  - !ruby/object:Gem::Version
74
79
  version: "0"
75
- version:
76
80
  required_rubygems_version: !ruby/object:Gem::Requirement
81
+ none: false
77
82
  requirements:
78
83
  - - ">="
79
84
  - !ruby/object:Gem::Version
80
85
  version: "0"
81
- version:
82
86
  requirements: []
83
87
 
84
- rubyforge_project: amphibian
85
- rubygems_version: 1.3.1
88
+ rubyforge_project:
89
+ rubygems_version: 1.8.25
86
90
  signing_key:
87
- specification_version: 2
88
- summary: Amphibian is a ruby library for accessing and interacting with an Apache mod_proxy_balancer via the web GUI created by the balancer_manager directive
89
- test_files:
90
- - test/test_amphibian.rb
91
- - test/test_helper.rb
91
+ specification_version: 3
92
+ summary: Gem for managing apache mox_proxy_balancer
93
+ test_files: []
94
+
@@ -1,10 +0,0 @@
1
- == 0.0.1 2009-06-26
2
-
3
- * 1 major enhancement:
4
- * Initial release
5
-
6
- == 0.0.2 2009-06-28
7
-
8
- * 2 major enhancements:
9
- * adding 'check_balancer_members' executable
10
- * fixing output of 'BalancerManager#enabled_hosts' and 'BalancerManager#disabled_hosts'
@@ -1,14 +0,0 @@
1
- History.txt
2
- Manifest.txt
3
- PostInstall.txt
4
- README.rdoc
5
- Rakefile
6
- bin/check_balancer_members
7
- lib/amphibian.rb
8
- lib/amphibian/balancerManagerDocument.rb
9
- lib/amphibian/runner.rb
10
- script/console
11
- script/destroy
12
- script/generate
13
- test/test_amphibian.rb
14
- test/test_helper.rb
@@ -1,6 +0,0 @@
1
-
2
- For more information on amphibian, see http://amphibian.rubyforge.org
3
-
4
- woot!
5
-
6
-
@@ -1,66 +0,0 @@
1
- = amphibian
2
-
3
- == DESCRIPTION:
4
-
5
- Amphibian is a ruby library for accessing and interacting with an Apache mod_proxy_balancer via the web GUI created by the balancer_manager directive.
6
-
7
- Amhpbian works by scraping the balancer-manager page, and sending get requests with appropriate query strings to the balancer manager in order to enable and disable hosts.
8
-
9
- == FEATURES/PROBLEMS:
10
-
11
- Allows you to access the different balancers and members on the Apache mod_proxy_balancer balancer-manager handler page.
12
-
13
- Also, investigating controlling the load balancer via the web page, but use at your own risk.
14
-
15
-
16
- == SYNOPSIS:
17
-
18
- nick-stielaus-computer-3:amphibian nick$ irb
19
- >> require 'amphibian'
20
- => true
21
- >> a = "http://example.com/balancer-manager"
22
- => "http://example.com/balancer-manager"
23
- >> amp = Amphibian::BalancerManager.new(a)
24
- >> amp.hosts
25
- => ["http://127.0.0.1:10000", "http://127.0.0.1:10001", "http://127.0.0.1:10002"]
26
- >> amp.enabled_hosts
27
- => ["http://127.0.0.1:10001", "http://127.0.0.1:10002"]
28
- >> amp.disabled_hosts
29
- => ["http://127.0.0.1:10000"]
30
- >> amp.hosts_with_status
31
- => {"http://127.0.0.1:10000"=>"Dis", "http://127.0.0.1:10001"=>"Ok", "http://127.0.0.1:10002"=>"Ok"}
32
-
33
-
34
- == REQUIREMENTS:
35
-
36
- * Ruby stuff
37
- * Apache, mod_proxy, mod_proxy_balancer, and an accessible balancer-manager page.
38
-
39
- == INSTALL:
40
-
41
- * gem install amphibian
42
-
43
- == LICENSE:
44
-
45
- (The MIT License)
46
-
47
- Copyright (c) 2009 Nick Stielau
48
-
49
- Permission is hereby granted, free of charge, to any person obtaining
50
- a copy of this software and associated documentation files (the
51
- 'Software'), to deal in the Software without restriction, including
52
- without limitation the rights to use, copy, modify, merge, publish,
53
- distribute, sublicense, and/or sell copies of the Software, and to
54
- permit persons to whom the Software is furnished to do so, subject to
55
- the following conditions:
56
-
57
- The above copyright notice and this permission notice shall be
58
- included in all copies or substantial portions of the Software.
59
-
60
- THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
61
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
62
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
63
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
64
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
65
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
66
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile DELETED
@@ -1,42 +0,0 @@
1
- require 'rubygems' unless ENV['NO_RUBYGEMS']
2
- %w[rake rake/clean fileutils newgem rubigen].each { |f| require f }
3
- require File.dirname(__FILE__) + '/lib/amphibian'
4
-
5
- # Generate all the Rake tasks
6
- # Run 'rake -T' to see list of generated tasks (from gem root directory)
7
- $hoe = Hoe.new('amphibian', Amphibian::VERSION) do |p|
8
- p.developer('Nick Stielau', 'nick.stielau@gmail.com')
9
- p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
10
- p.post_install_message = 'PostInstall.txt'
11
- p.rubyforge_name = p.name
12
- p.bin_files = ["bin/check_balancer_members"]
13
-
14
- # p.extra_deps = [
15
- # ['activesupport','>= 2.0.2'],
16
- # ]
17
- p.extra_dev_deps = [
18
- ['newgem', ">= #{::Newgem::VERSION}"]
19
- ]
20
-
21
- p.clean_globs |= %w[**/.DS_Store tmp *.log]
22
- path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
23
- p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
24
- p.rsync_args = '-av --delete --ignore-errors'
25
- end
26
-
27
- desc "Upload current documentation to Rubyforge"
28
- task :upload_docs => [:redocs] do
29
- sh "scp -r doc/* nstielau@rubyforge.org:/var/www/gforge-projects/amphibian/doc/"
30
- end
31
-
32
- desc "Upload current documentation to Rubyforge"
33
- task :upload_site do
34
- #webgen && scp -r output/* nstielau@rubyforge.org:/var/www/gforge-projects/amphibian/
35
- sh "scp -r webgen_site/* nstielau@rubyforge.org:/var/www/gforge-projects/amphibian/"
36
- end
37
-
38
- require 'newgem/tasks' # load /tasks/*.rake
39
- Dir['tasks/**/*.rake'].each { |t| load t }
40
-
41
- # TODO - want other tests/tasks run by default? Add them to the list
42
- # task :default => [:spec, :features]
@@ -1,10 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # File: script/console
3
- irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
-
5
- libs = " -r irb/completion"
6
- # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
- # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
- libs << " -r #{File.dirname(__FILE__) + '/../lib/amphibian.rb'}"
9
- puts "Loading amphibian gem"
10
- exec "#{irb} #{libs} --simple-prompt"
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env ruby
2
- APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
-
4
- begin
5
- require 'rubigen'
6
- rescue LoadError
7
- require 'rubygems'
8
- require 'rubigen'
9
- end
10
- require 'rubigen/scripts/destroy'
11
-
12
- ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
- RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
- RubiGen::Scripts::Destroy.new.run(ARGV)
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env ruby
2
- APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
-
4
- begin
5
- require 'rubigen'
6
- rescue LoadError
7
- require 'rubygems'
8
- require 'rubigen'
9
- end
10
- require 'rubigen/scripts/generate'
11
-
12
- ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
- RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
- RubiGen::Scripts::Generate.new.run(ARGV)