grid 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (10) hide show
  1. data/Gemfile +5 -3
  2. data/Gemfile.lock +40 -0
  3. data/LICENSE.txt +22 -17
  4. data/README.rdoc +191 -7
  5. data/Rakefile +5 -2
  6. data/VERSION +1 -1
  7. data/bin/grid +57 -0
  8. data/grid.gemspec +100 -0
  9. data/lib/grid.rb +209 -0
  10. metadata +148 -19
data/Gemfile CHANGED
@@ -1,10 +1,12 @@
1
1
  source "http://rubygems.org"
2
2
  # Add dependencies required to use your gem here.
3
- # Example:
4
- # gem "activesupport", ">= 2.3.5"
3
+ gem "watirgrid"
4
+ gem "json"
5
+ gem "rest-client"
6
+ gem "awesome_print"
7
+ gem "highline"
5
8
 
6
9
  # Add dependencies to develop your gem here.
7
- # Include everything needed to run rake, tests, features, etc.
8
10
  group :development do
9
11
  gem "rspec", "~> 2.3.0"
10
12
  gem "bundler", "~> 1.0.0"
data/Gemfile.lock ADDED
@@ -0,0 +1,40 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ awesome_print (0.3.2)
5
+ diff-lcs (1.1.2)
6
+ git (1.2.5)
7
+ highline (1.6.1)
8
+ jeweler (1.5.2)
9
+ bundler (~> 1.0.0)
10
+ git (>= 1.2.5)
11
+ rake
12
+ json (1.5.1)
13
+ mime-types (1.16)
14
+ rake (0.8.7)
15
+ rcov (0.9.9)
16
+ rest-client (1.6.1)
17
+ mime-types (>= 1.16)
18
+ rspec (2.3.0)
19
+ rspec-core (~> 2.3.0)
20
+ rspec-expectations (~> 2.3.0)
21
+ rspec-mocks (~> 2.3.0)
22
+ rspec-core (2.3.1)
23
+ rspec-expectations (2.3.0)
24
+ diff-lcs (~> 1.1.2)
25
+ rspec-mocks (2.3.0)
26
+ watirgrid (1.0.4)
27
+
28
+ PLATFORMS
29
+ ruby
30
+
31
+ DEPENDENCIES
32
+ awesome_print
33
+ bundler (~> 1.0.0)
34
+ highline
35
+ jeweler (~> 1.5.2)
36
+ json
37
+ rcov
38
+ rest-client
39
+ rspec (~> 2.3.0)
40
+ watirgrid
data/LICENSE.txt CHANGED
@@ -1,20 +1,25 @@
1
- Copyright (c) 2011 Tim Koopmans
1
+ Copyright (c) 2009-2011 Altentee. All rights reserved.
2
2
 
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
3
+ Redistribution and use in source and binary forms, with or without modification, are
4
+ permitted provided that the following conditions are met:
10
5
 
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
6
+ 1. Redistributions of source code must retain the above copyright notice, this list of
7
+ conditions and the following disclaimer.
13
8
 
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
9
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list
10
+ of conditions and the following disclaimer in the documentation and/or other materials
11
+ provided with the distribution.
12
+
13
+ THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY EXPRESS OR IMPLIED
14
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
15
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
16
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
18
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
21
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22
+
23
+ The views and conclusions contained in the software and documentation are those of the
24
+ authors and should not be interpreted as representing official policies, either expressed
25
+ or implied, of Altentee.
data/README.rdoc CHANGED
@@ -1,9 +1,195 @@
1
- = grid
1
+ = Grid
2
2
 
3
- Description goes here.
3
+ This is a utility gem for use with Gridinit.com.
4
+
5
+ == About
6
+ Gridinit.com is a RESTful API for distributed testing. It currently supports Watir test cases with plans to also support Selenium in the near future. Gridinit allows for the simple command and control of grid resources. You can control the grid using the included RESTful API, or you can use this gem which is another abstraction of the API from the command line.
7
+
8
+ A Grid consists of loosely coupled, distributed "nodes". Nodes are an alias for remote browsers. Nodes can be grouped into "intranodes", which is a collection of similar nodes defined by their browser type, quantity and location.
9
+
10
+ One Grid can have many Intranodes, with each Intranode consisting of many Nodes!
11
+
12
+ == Getting Started
13
+ To install Grid:
14
+ gem install grid
15
+
16
+ You will need an account on Gridinit.com before you proceed. You can also purchase credits on Gridinit, which are necessary to consume resources on the cloud. After you have created an account and purchased credits (note: first 50 credits are free) you can run the following from any command line / terminal.
17
+
18
+ === The Grid Command Line
19
+ Usage: grid [options] command
20
+
21
+ Commands:
22
+ list - List all grids
23
+ show - Show specified grids
24
+ create - Create a new grid
25
+ add - Add intranode to specified grid ID
26
+ delete - Delete intranode from specified grid ID
27
+ start - Start specified grid ID
28
+ stop - Stop specified grid ID
29
+ restart - Restart specified grid ID
30
+ status - Update status of specified grid ID
31
+
32
+ Options:
33
+ -g, --grid ID Specify the Grid ID to use
34
+ -t, --token TOKEN Specify the token to authenticate with
35
+ -e, --email EMAIL Specify the email to authenticate with, if not using token
36
+ -p, --password PASSWORD Specify the password to authenticate with, if not using token
37
+ -u, --uri URI Optional URI of the Gridinit API, default http://gridin.it/api/v0
38
+ -h, --help Show this message
39
+
40
+ === Step 1. Create a new Grid
41
+ *Create* a new grid with the create command. Following is an example using your email address and password as parameters. You will then be prompted for the name, description, number, type and location of nodes which are the remote providers (browsers).
42
+
43
+ grid -e your@email.com -p yourpassword create
44
+
45
+ D, [2011-04-17 11:49:06 #43304] DEBUG -- : Current token: yKan0JEfPSEbwsgeSRIYSg
46
+ Grid name: |Grid|
47
+ Grid description: |Grid created Sun Apr 17 11:49:07 +1000 2011|
48
+ Number of nodes: |5|
49
+ Location of nodes: |us-east|
50
+ Node type: |webdriver|
51
+ D, [2011-04-17 11:49:10 #43304] DEBUG -- : Creating grid ...
52
+ D, [2011-04-17 11:49:10 #43304] DEBUG -- : Creating intranode ...
53
+ D, [2011-04-17 11:49:10 #43304] DEBUG -- : Listing grid ...
54
+ {
55
+ "grid" => {
56
+ "name" => "Grid",
57
+ "created_at" => "2011-04-17T11:49:10+10:00",
58
+ "updated_at" => "2011-04-17T11:49:10+10:00",
59
+ "id" => 1,
60
+ "user_id" => 1,
61
+ "credits_used" => 0,
62
+ "nodes" => 5,
63
+ "description" => "Grid created Sun Apr 17 11:49:07 +1000 2011",
64
+ "intranodes" => [
65
+ [0] {
66
+ "intranode" => {
67
+ "grid_id" => 1,
68
+ "created_at" => "2011-04-17T11:49:10+10:00",
69
+ "location" => "us-east",
70
+ "updated_at" => "2011-04-17T11:49:10+10:00",
71
+ "id" => 1,
72
+ "credits_used" => 0,
73
+ "user_id" => 1,
74
+ "nodes" => 5,
75
+ "controller_uri" => nil,
76
+ "status" => "stopped",
77
+ "active" => true,
78
+ "browser_type" => "webdriver"
79
+ }
80
+ }
81
+ ],
82
+ "active" => true
83
+ }
84
+ }
85
+
86
+ === Step 2. Start the Grid
87
+ Once you have created a grid, you can use the start command to start up the remote browsers.
88
+ grid -e your@email.com -p yourpassword start
89
+
90
+ D, [2011-04-17 11:49:21 #43313] DEBUG -- : Current token: dm3uw4yKY6jqknCvzGKBHQ
91
+ Grid ID: 1
92
+ D, [2011-04-17 11:49:22 #43313] DEBUG -- : Starting grid ...
93
+ D, [2011-04-17 11:49:31 #43313] DEBUG -- : Listing grid ...
94
+ {
95
+ "grid" => {
96
+ "name" => "Grid",
97
+ "created_at" => "2011-04-17T11:49:10+10:00",
98
+ "updated_at" => "2011-04-17T11:49:10+10:00",
99
+ "id" => 1,
100
+ "user_id" => 1,
101
+ "credits_used" => 0,
102
+ "nodes" => 5,
103
+ "description" => "Grid created Sun Apr 17 11:49:07 +1000 2011",
104
+ "intranodes" => [
105
+ [0] {
106
+ "intranode" => {
107
+ "grid_id" => 1,
108
+ "created_at" => "2011-04-17T11:49:10+10:00",
109
+ "location" => "us-east",
110
+ "updated_at" => "2011-04-17T11:49:31+10:00",
111
+ "id" => 1,
112
+ "credits_used" => 0,
113
+ "user_id" => 1,
114
+ "nodes" => 5,
115
+ "controller_uri" => nil,
116
+ "status" => "starting",
117
+ "active" => true,
118
+ "browser_type" => "webdriver"
119
+ }
120
+ }
121
+ ],
122
+ "active" => true
123
+ }
124
+ }
125
+ === Step 3. Refresh the status of the Grid
126
+ After starting the grid, you can refresh its status to confirm all grid => intranodes have a "running" status. Typically it takes between 30 - 60s to start up all the remote browsers on the grid. You can refresh the status with the status command.
127
+
128
+ grid -e your@email.com -p yourpassword start
129
+
130
+ D, [2011-04-17 11:49:44 #43339] DEBUG -- : Current token: xTbnoM6LVSjjLjQSB4GLtA
131
+ Grid ID: 1
132
+ D, [2011-04-17 11:49:45 #43339] DEBUG -- : Updating status of grid ...
133
+ D, [2011-04-17 11:49:49 #43339] DEBUG -- : Listing grid ...
134
+ {
135
+ "grid" => {
136
+ "name" => "Grid",
137
+ "created_at" => "2011-04-17T11:49:10+10:00",
138
+ "updated_at" => "2011-04-17T11:49:47+10:00",
139
+ "id" => 1,
140
+ "user_id" => 1,
141
+ "credits_used" => 5,
142
+ "nodes" => 5,
143
+ "description" => "Grid created Sun Apr 17 11:49:07 +1000 2011",
144
+ "intranodes" => [
145
+ [0] {
146
+ "intranode" => {
147
+ "grid_id" => 1,
148
+ "created_at" => "2011-04-17T11:49:10+10:00",
149
+ "location" => "us-east",
150
+ "updated_at" => "2011-04-17T11:49:49+10:00",
151
+ "id" => 1,
152
+ "credits_used" => 5,
153
+ "user_id" => 1,
154
+ "nodes" => 5,
155
+ "controller_uri" => "druby://ec2-50-17-120-217.compute-1.amazonaws.com:11235",
156
+ "status" => "{\"running\":5}",
157
+ "active" => true,
158
+ "browser_type" => "webdriver"
159
+ }
160
+ }
161
+ ],
162
+ "active" => true
163
+ }
164
+ }
165
+
166
+ Take note of the intranode *status* which in this examples indicates that there are 5 nodes "running" on the first intranode in your grid.
167
+ Also take note of the *controller_uri* as this will be what you connect to when you distribute your tests. In this example the *controller_uri* is "druby://ec2-50-17-120-217.compute-1.amazonaws.com:11235"
168
+
169
+ === Step 4. Distribute your tests on the Grid
170
+ Very little modification is needed to your existing test scripts. Essentially you will "top and tail" your test scripts with a Grid.control method as follows
171
+
172
+ *Old Code*
173
+ require 'watir-webdriver'
174
+ browser = Watir::Browser.new :firefox
175
+ browser.goto("http://www.google.com")
176
+ browser.text_field(:name, 'q').set("watirgrid")
177
+ browser.button(:name, "btnI").click
178
+
179
+ *New Code*
180
+ require 'grid'
181
+ Grid.control(
182
+ :controller_uri => 'druby://ec2-50-17-120-217.compute-1.amazonaws.com:11235') do |browser, id|
183
+ puts "My remote browser id is #{id}"
184
+ browser.goto("http://www.google.com")
185
+ browser.text_field(:name, 'q').set("watirgrid")
186
+ browser.button(:name, "btnI").click
187
+ end
188
+
189
+ In this example, we required the 'grid' gem and controlled a Grid object with the "control" method. This method requires the *:controller_uri* parameter obtained from step 3 and is passed a block of your existing watir code. The same method will yield an individual browser object (same as a Watir browser object) as well as a thread ID which you can use to help identify which node your code is executed on.
190
+
191
+ == Contributing to the Grid
4
192
 
5
- == Contributing to grid
6
-
7
193
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
8
194
  * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
9
195
  * Fork the project
@@ -14,6 +200,4 @@ Description goes here.
14
200
 
15
201
  == Copyright
16
202
 
17
- Copyright (c) 2011 Tim Koopmans. See LICENSE.txt for
18
- further details.
19
-
203
+ Copyright (c) 2011 Tim Koopmans. See LICENSE.txt for details.
data/Rakefile CHANGED
@@ -19,8 +19,11 @@ Jeweler::Tasks.new do |gem|
19
19
  gem.email = "tim.koops@gmail.com"
20
20
  gem.authors = ["Tim Koopmans"]
21
21
  gem.add_runtime_dependency 'watirgrid'
22
- gem.add_runtime_dependency 'rest_client'
23
- # gem.add_development_dependency 'rspec', '> 1.2.3'
22
+ gem.add_runtime_dependency 'rest-client'
23
+ gem.add_runtime_dependency 'json'
24
+ gem.add_runtime_dependency 'highline'
25
+ gem.add_runtime_dependency 'awesome_print'
26
+ gem.add_development_dependency 'rspec'
24
27
  end
25
28
  Jeweler::RubygemsDotOrgTasks.new
26
29
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
data/bin/grid ADDED
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'grid'
4
+ require 'optparse'
5
+
6
+ options = {}
7
+ OptionParser.new do |opts|
8
+ opts.banner = "Usage: grid [options] command"
9
+ opts.separator ""
10
+ opts.separator "Commands:"
11
+ opts.separator " list - List all grids"
12
+ opts.separator " show - Show specified grids"
13
+ opts.separator " create - Create a new grid"
14
+ opts.separator " add - Add intranode to specified grid ID"
15
+ opts.separator " delete - Delete intranode from specified grid ID"
16
+ opts.separator " start - Start specified grid ID"
17
+ opts.separator " stop - Stop specified grid ID"
18
+ opts.separator " restart - Restart specified grid ID"
19
+ opts.separator " status - Update status of specified grid ID"
20
+ opts.separator ""
21
+ opts.separator "Options:"
22
+ opts.on("-g", "--grid ID", String,
23
+ "Specify the Grid ID to use") do |g|
24
+ options[:grid_id] = g || nil
25
+ end
26
+ opts.on("-t", "--token TOKEN", String,
27
+ "Specify the token to authenticate with") do |t|
28
+ options[:token] = t || nil
29
+ end
30
+ opts.on("-e", "--email EMAIL", String,
31
+ "Specify the email to authenticate with, if not using token") do |e|
32
+ options[:email] = e || nil
33
+ end
34
+ opts.on("-p", "--password PASSWORD", String,
35
+ "Specify the password to authenticate with, if not using token") do |p|
36
+ options[:password] = p || nil
37
+ end
38
+ opts.on("-u", "--uri URI", String,
39
+ "Optional URI of the Gridinit API, default http://gridin.it/api/v0") do |u|
40
+ options[:uri] = u || nil
41
+ end
42
+
43
+ opts.on_tail("-h", "--help", "Show this message") do
44
+ puts opts
45
+ exit
46
+ end
47
+ end.parse!
48
+
49
+ helper = Grid::Helper.new(
50
+ :grid_id => options[:grid_id],
51
+ :token => options[:token],
52
+ :email => options[:email],
53
+ :password => options[:password],
54
+ :uri => options[:uri],
55
+ :args => ARGV
56
+ )
57
+ helper.send(ARGV[0])
data/grid.gemspec ADDED
@@ -0,0 +1,100 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{grid}
8
+ s.version = "0.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Tim Koopmans"]
12
+ s.date = %q{2011-04-17}
13
+ s.default_executable = %q{grid}
14
+ s.description = %q{Gridinit command line utilities to help you use the Gridinit API}
15
+ s.email = %q{tim.koops@gmail.com}
16
+ s.executables = ["grid"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE.txt",
19
+ "README.rdoc"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ ".rspec",
24
+ "Gemfile",
25
+ "Gemfile.lock",
26
+ "LICENSE.txt",
27
+ "README.rdoc",
28
+ "Rakefile",
29
+ "VERSION",
30
+ "bin/grid",
31
+ "grid.gemspec",
32
+ "lib/grid.rb",
33
+ "spec/grid_spec.rb",
34
+ "spec/spec_helper.rb"
35
+ ]
36
+ s.homepage = %q{http://github.com/90kts/grid}
37
+ s.licenses = ["MIT"]
38
+ s.require_paths = ["lib"]
39
+ s.rubygems_version = %q{1.4.2}
40
+ s.summary = %q{Gridinit command line utilities}
41
+ s.test_files = [
42
+ "spec/grid_spec.rb",
43
+ "spec/spec_helper.rb"
44
+ ]
45
+
46
+ if s.respond_to? :specification_version then
47
+ s.specification_version = 3
48
+
49
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
50
+ s.add_runtime_dependency(%q<watirgrid>, [">= 0"])
51
+ s.add_runtime_dependency(%q<json>, [">= 0"])
52
+ s.add_runtime_dependency(%q<rest-client>, [">= 0"])
53
+ s.add_runtime_dependency(%q<awesome_print>, [">= 0"])
54
+ s.add_runtime_dependency(%q<highline>, [">= 0"])
55
+ s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
56
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
57
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
58
+ s.add_development_dependency(%q<rcov>, [">= 0"])
59
+ s.add_runtime_dependency(%q<watirgrid>, [">= 0"])
60
+ s.add_runtime_dependency(%q<rest-client>, [">= 0"])
61
+ s.add_runtime_dependency(%q<json>, [">= 0"])
62
+ s.add_runtime_dependency(%q<highline>, [">= 0"])
63
+ s.add_runtime_dependency(%q<awesome_print>, [">= 0"])
64
+ s.add_development_dependency(%q<rspec>, [">= 0"])
65
+ else
66
+ s.add_dependency(%q<watirgrid>, [">= 0"])
67
+ s.add_dependency(%q<json>, [">= 0"])
68
+ s.add_dependency(%q<rest-client>, [">= 0"])
69
+ s.add_dependency(%q<awesome_print>, [">= 0"])
70
+ s.add_dependency(%q<highline>, [">= 0"])
71
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
72
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
73
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
74
+ s.add_dependency(%q<rcov>, [">= 0"])
75
+ s.add_dependency(%q<watirgrid>, [">= 0"])
76
+ s.add_dependency(%q<rest-client>, [">= 0"])
77
+ s.add_dependency(%q<json>, [">= 0"])
78
+ s.add_dependency(%q<highline>, [">= 0"])
79
+ s.add_dependency(%q<awesome_print>, [">= 0"])
80
+ s.add_dependency(%q<rspec>, [">= 0"])
81
+ end
82
+ else
83
+ s.add_dependency(%q<watirgrid>, [">= 0"])
84
+ s.add_dependency(%q<json>, [">= 0"])
85
+ s.add_dependency(%q<rest-client>, [">= 0"])
86
+ s.add_dependency(%q<awesome_print>, [">= 0"])
87
+ s.add_dependency(%q<highline>, [">= 0"])
88
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
89
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
90
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
91
+ s.add_dependency(%q<rcov>, [">= 0"])
92
+ s.add_dependency(%q<watirgrid>, [">= 0"])
93
+ s.add_dependency(%q<rest-client>, [">= 0"])
94
+ s.add_dependency(%q<json>, [">= 0"])
95
+ s.add_dependency(%q<highline>, [">= 0"])
96
+ s.add_dependency(%q<awesome_print>, [">= 0"])
97
+ s.add_dependency(%q<rspec>, [">= 0"])
98
+ end
99
+ end
100
+
data/lib/grid.rb CHANGED
@@ -0,0 +1,209 @@
1
+ #!/usr/bin/env ruby
2
+ # grid.rb
3
+ # Grid Helper
4
+
5
+ require 'ap'
6
+ require 'watirgrid'
7
+ require 'json'
8
+ require 'rest_client'
9
+ require 'highline/import'
10
+
11
+ class Grid
12
+
13
+ ##
14
+ # This is a helper method to control a grid based on watir.
15
+ # It involves some general block thuggery and could
16
+ # honestly benefit from some brutal refactoring...
17
+ def self.control(params = {}, &block)
18
+ log = Logger.new(STDOUT, 'daily')
19
+ log.level = params[:loglevel] || Logger::DEBUG
20
+ grid = Watir::Grid.new(params)
21
+ grid.start(:take_all => true)
22
+ log.debug("Grid size : #{grid.size}")
23
+ log.debug("Grid rampup : #{rampup(grid.size, params)} secs")
24
+ threads = []
25
+ grid.browsers.each_with_index do |browser, index|
26
+ sleep rampup(grid.size, params)
27
+ threads << Thread.new do
28
+ start = ::Time.now
29
+ log.debug("Browser #{index+1}##{Thread.current.object_id} start : #{::Time.now}")
30
+ log.debug("Browser #{index+1}##{Thread.current.object_id} architecture : #{browser[:architecture]}")
31
+ log.debug("Browser #{index+1}##{Thread.current.object_id} type : #{browser[:browser_type]}")
32
+ log.debug("Browser #{index+1}##{Thread.current.object_id} hostname : #{browser[:hostname]}")
33
+ @browser = browser[:object].new_browser
34
+ yield @browser, "#{index+1}##{Thread.current.object_id}"
35
+ log.debug("Browser #{index+1}##{Thread.current.object_id} stop : #{::Time.now}")
36
+ log.debug("Browser #{index+1}##{Thread.current.object_id} elapsed : #{(::Time.now - start).to_i} secs")
37
+ end
38
+ end
39
+ threads.each {|thread| thread.join}
40
+ grid.release_tuples
41
+ end
42
+
43
+ class Helper
44
+ def initialize(params = {})
45
+ @grid_id = params[:grid_id]
46
+ @uri = params[:uri] || "http://gridin.it/api/v0"
47
+ logfile = STDOUT
48
+ @log = Logger.new(logfile, 'daily')
49
+ @log.level = Logger::DEBUG
50
+ @log.datetime_format = "%Y-%m-%d %H:%M:%S "
51
+ @token = get_token(params)
52
+ @log.debug("Current token: #{@token}")
53
+ end
54
+
55
+ def get_password(prompt='Password: ', mask='*')
56
+ ask(prompt) { |q| q.echo = mask }
57
+ end
58
+
59
+ def get_token(params)
60
+ if params[:token]
61
+ params[:token]
62
+ else
63
+ HighLine.track_eof = false
64
+ @email = params[:email] || ask('Email: ')
65
+ @password = params[:password] || get_password
66
+ response = RestClient.post "#{@uri}/token.json" , {
67
+ :email => @email, :password => @password
68
+ }
69
+ (JSON.parse(response))["token"]
70
+ end
71
+ end
72
+
73
+ def list
74
+ @log.debug("Listing grids ...")
75
+ begin
76
+ response = RestClient.get "#{@uri}/grid.json" , {
77
+ :token => @token
78
+ }
79
+ ap JSON.parse(response)
80
+ rescue => e
81
+ @log.error("#{e}")
82
+ end
83
+ end
84
+
85
+ def show
86
+ @grid_id = ask("Grid ID: ") unless @grid_id
87
+ @log.debug("Listing grid ...")
88
+ begin
89
+ response = RestClient.get "#{@uri}/grid/#{@grid_id}.json" , {
90
+ :token => @token
91
+ }
92
+ ap JSON.parse(response)
93
+ rescue => e
94
+ @log.error("#{e}")
95
+ end
96
+ end
97
+
98
+ def create_grid(name, description)
99
+ begin
100
+ @log.debug("Creating grid ...")
101
+ response = RestClient.post "#{@uri}/grid.json" , {
102
+ :token => @token,
103
+ :name => name,
104
+ :description => description
105
+ }
106
+ (JSON.parse(response)).first[1]["id"]
107
+ rescue => e
108
+ @log.error("#{e}")
109
+ end
110
+ end
111
+
112
+ def create_intranode(grid_id, browser_type, location, nodes)
113
+ begin
114
+ @log.debug("Creating intranode ...")
115
+ response = RestClient.post "#{@uri}/grid/#{grid_id.to_s}/intranode.json", {
116
+ :token => @token,
117
+ :browser_type => browser_type,
118
+ :location => location,
119
+ :nodes => nodes
120
+ }
121
+ rescue => e
122
+ @log.error("#{e}")
123
+ end
124
+ end
125
+
126
+ def delete_intranode
127
+ begin
128
+ @log.debug("Deleting intranode ...")
129
+ response = RestClient.delete "#{@uri}/grid/intranode/#{@intranode_id}.json", {
130
+ :token => @token
131
+ }
132
+ rescue => e
133
+ @log.error("#{e}")
134
+ end
135
+ end
136
+
137
+ def create
138
+ name = ask("Grid name: ") { |q| q.default = "Grid" }
139
+ description = ask("Grid description: ") { |q| q.default = "Grid created #{Time.now}" }
140
+ nodes = ask("Number of nodes: ") { |q| q.default = 5 }
141
+ location = ask("Location of nodes: ") { |q| q.default = "us-east" }
142
+ browser_type = ask("Node type: ") { |q| q.default = "webdriver" }
143
+ @grid_id = create_grid(name, description)
144
+ create_intranode(@grid_id, browser_type, location, nodes)
145
+ show
146
+ end
147
+
148
+ def add
149
+ @grid_id = ask("Grid ID: ") unless @grid_id
150
+ nodes = ask("Number of nodes: ") { |q| q.default = 5 }
151
+ location = ask("Location of nodes: ") { |q| q.default = "us-east" }
152
+ browser_type = ask("Node type: ") { |q| q.default = "webdriver" }
153
+ create_intranode(@grid_id, browser_type, location, nodes)
154
+ show
155
+ end
156
+
157
+ def delete
158
+ @grid_id = ask("Grid ID: ") unless @grid_id
159
+ @intranode_id= ask("Intranode ID: ") unless @intranode_id
160
+ delete_intranode
161
+ show
162
+ end
163
+
164
+ def start
165
+ @grid_id = ask("Grid ID: ") unless @grid_id
166
+ @log.debug("Starting grid ...")
167
+ begin
168
+ response = RestClient.put "#{@uri}/grid/#{@grid_id.to_s}/start.json", {:token => @token}
169
+ rescue => e
170
+ @log.error("#{e}")
171
+ end
172
+ show
173
+ end
174
+
175
+ def stop
176
+ @grid_id = ask("Grid ID: ") unless @grid_id
177
+ @log.debug("Stopping grid ...")
178
+ begin
179
+ response = RestClient.put "#{@uri}/grid/#{@grid_id.to_s}/stop.json", {:token => @token}
180
+ rescue => e
181
+ @log.error("#{e}")
182
+ end
183
+ show
184
+ end
185
+
186
+ def restart
187
+ @grid_id = ask("Grid ID: ") unless @grid_id
188
+ @log.debug("Restarting grid ...")
189
+ begin
190
+ response = RestClient.put "#{@uri}/grid/#{@grid_id.to_s}/restart.json", {:token => @token}
191
+ rescue => e
192
+ @log.error("#{e}")
193
+ end
194
+ show
195
+ end
196
+
197
+ def status
198
+ @grid_id = ask("Grid ID: ") unless @grid_id
199
+ @log.debug("Updating status of grid ...")
200
+ begin
201
+ response = RestClient.put "#{@uri}/grid/#{@grid_id.to_s}/status.json", {:token => @token}
202
+ rescue => e
203
+ @log.error("#{e}")
204
+ end
205
+ show
206
+ end
207
+
208
+ end
209
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grid
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 1
8
+ - 2
9
9
  - 0
10
- version: 0.1.0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Tim Koopmans
@@ -15,11 +15,81 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-04-16 00:00:00 +10:00
19
- default_executable:
18
+ date: 2011-04-17 00:00:00 +10:00
19
+ default_executable: grid
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  version_requirements: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ hash: 3
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ prerelease: false
32
+ requirement: *id001
33
+ type: :runtime
34
+ name: watirgrid
35
+ - !ruby/object:Gem::Dependency
36
+ version_requirements: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ hash: 3
42
+ segments:
43
+ - 0
44
+ version: "0"
45
+ prerelease: false
46
+ requirement: *id002
47
+ type: :runtime
48
+ name: json
49
+ - !ruby/object:Gem::Dependency
50
+ version_requirements: &id003 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ hash: 3
56
+ segments:
57
+ - 0
58
+ version: "0"
59
+ prerelease: false
60
+ requirement: *id003
61
+ type: :runtime
62
+ name: rest-client
63
+ - !ruby/object:Gem::Dependency
64
+ version_requirements: &id004 !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ hash: 3
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ prerelease: false
74
+ requirement: *id004
75
+ type: :runtime
76
+ name: awesome_print
77
+ - !ruby/object:Gem::Dependency
78
+ version_requirements: &id005 !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ hash: 3
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ prerelease: false
88
+ requirement: *id005
89
+ type: :runtime
90
+ name: highline
91
+ - !ruby/object:Gem::Dependency
92
+ version_requirements: &id006 !ruby/object:Gem::Requirement
23
93
  none: false
24
94
  requirements:
25
95
  - - ~>
@@ -31,11 +101,11 @@ dependencies:
31
101
  - 0
32
102
  version: 2.3.0
33
103
  prerelease: false
34
- requirement: *id001
104
+ requirement: *id006
35
105
  type: :development
36
106
  name: rspec
37
107
  - !ruby/object:Gem::Dependency
38
- version_requirements: &id002 !ruby/object:Gem::Requirement
108
+ version_requirements: &id007 !ruby/object:Gem::Requirement
39
109
  none: false
40
110
  requirements:
41
111
  - - ~>
@@ -47,11 +117,11 @@ dependencies:
47
117
  - 0
48
118
  version: 1.0.0
49
119
  prerelease: false
50
- requirement: *id002
120
+ requirement: *id007
51
121
  type: :development
52
122
  name: bundler
53
123
  - !ruby/object:Gem::Dependency
54
- version_requirements: &id003 !ruby/object:Gem::Requirement
124
+ version_requirements: &id008 !ruby/object:Gem::Requirement
55
125
  none: false
56
126
  requirements:
57
127
  - - ~>
@@ -63,11 +133,11 @@ dependencies:
63
133
  - 2
64
134
  version: 1.5.2
65
135
  prerelease: false
66
- requirement: *id003
136
+ requirement: *id008
67
137
  type: :development
68
138
  name: jeweler
69
139
  - !ruby/object:Gem::Dependency
70
- version_requirements: &id004 !ruby/object:Gem::Requirement
140
+ version_requirements: &id009 !ruby/object:Gem::Requirement
71
141
  none: false
72
142
  requirements:
73
143
  - - ">="
@@ -77,11 +147,11 @@ dependencies:
77
147
  - 0
78
148
  version: "0"
79
149
  prerelease: false
80
- requirement: *id004
150
+ requirement: *id009
81
151
  type: :development
82
152
  name: rcov
83
153
  - !ruby/object:Gem::Dependency
84
- version_requirements: &id005 !ruby/object:Gem::Requirement
154
+ version_requirements: &id010 !ruby/object:Gem::Requirement
85
155
  none: false
86
156
  requirements:
87
157
  - - ">="
@@ -91,11 +161,11 @@ dependencies:
91
161
  - 0
92
162
  version: "0"
93
163
  prerelease: false
94
- requirement: *id005
164
+ requirement: *id010
95
165
  type: :runtime
96
166
  name: watirgrid
97
167
  - !ruby/object:Gem::Dependency
98
- version_requirements: &id006 !ruby/object:Gem::Requirement
168
+ version_requirements: &id011 !ruby/object:Gem::Requirement
99
169
  none: false
100
170
  requirements:
101
171
  - - ">="
@@ -105,13 +175,69 @@ dependencies:
105
175
  - 0
106
176
  version: "0"
107
177
  prerelease: false
108
- requirement: *id006
178
+ requirement: *id011
179
+ type: :runtime
180
+ name: rest-client
181
+ - !ruby/object:Gem::Dependency
182
+ version_requirements: &id012 !ruby/object:Gem::Requirement
183
+ none: false
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ hash: 3
188
+ segments:
189
+ - 0
190
+ version: "0"
191
+ prerelease: false
192
+ requirement: *id012
193
+ type: :runtime
194
+ name: json
195
+ - !ruby/object:Gem::Dependency
196
+ version_requirements: &id013 !ruby/object:Gem::Requirement
197
+ none: false
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ hash: 3
202
+ segments:
203
+ - 0
204
+ version: "0"
205
+ prerelease: false
206
+ requirement: *id013
109
207
  type: :runtime
110
- name: rest_client
208
+ name: highline
209
+ - !ruby/object:Gem::Dependency
210
+ version_requirements: &id014 !ruby/object:Gem::Requirement
211
+ none: false
212
+ requirements:
213
+ - - ">="
214
+ - !ruby/object:Gem::Version
215
+ hash: 3
216
+ segments:
217
+ - 0
218
+ version: "0"
219
+ prerelease: false
220
+ requirement: *id014
221
+ type: :runtime
222
+ name: awesome_print
223
+ - !ruby/object:Gem::Dependency
224
+ version_requirements: &id015 !ruby/object:Gem::Requirement
225
+ none: false
226
+ requirements:
227
+ - - ">="
228
+ - !ruby/object:Gem::Version
229
+ hash: 3
230
+ segments:
231
+ - 0
232
+ version: "0"
233
+ prerelease: false
234
+ requirement: *id015
235
+ type: :development
236
+ name: rspec
111
237
  description: Gridinit command line utilities to help you use the Gridinit API
112
238
  email: tim.koops@gmail.com
113
- executables: []
114
-
239
+ executables:
240
+ - grid
115
241
  extensions: []
116
242
 
117
243
  extra_rdoc_files:
@@ -121,10 +247,13 @@ files:
121
247
  - .document
122
248
  - .rspec
123
249
  - Gemfile
250
+ - Gemfile.lock
124
251
  - LICENSE.txt
125
252
  - README.rdoc
126
253
  - Rakefile
127
254
  - VERSION
255
+ - bin/grid
256
+ - grid.gemspec
128
257
  - lib/grid.rb
129
258
  - spec/grid_spec.rb
130
259
  - spec/spec_helper.rb