cloudfactory 0.1.21 → 0.1.22
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.
- data/CHANGELOG.md +9 -0
- data/bin/cf +7 -1
- data/cf.gemspec +9 -6
- data/lib/cf/cli.rb +2 -1
- data/lib/cf/cli/line.rb +11 -11
- data/lib/cf/cli/line_yaml_validator.rb +151 -151
- data/lib/cf/cli/production.rb +69 -9
- data/lib/cf/run.rb +26 -12
- data/lib/cf/version.rb +1 -1
- data/spec/run_spec.rb +26 -1
- metadata +53 -53
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## 0.1.22 (2011-08-26)
|
2
|
+
|
3
|
+
* Fixed #317
|
4
|
+
* Fixed #156
|
5
|
+
* Fixed #328
|
6
|
+
* Store the account name and email ad while cf login
|
7
|
+
* For runs and lines listing, :page => 'all' added to return all the records #321
|
8
|
+
* Inserting units to existing production run #310
|
9
|
+
|
1
10
|
## 0.1.21 (2011-08-25)
|
2
11
|
|
3
12
|
* Line listing with pagination with custom flags
|
data/bin/cf
CHANGED
@@ -9,4 +9,10 @@ $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
|
|
9
9
|
|
10
10
|
require 'cf/cli'
|
11
11
|
|
12
|
-
|
12
|
+
begin
|
13
|
+
Cf::CLI.start
|
14
|
+
rescue ArgumentError
|
15
|
+
$stderr.puts "\n\tError during processing: #{$!.message}\n\n"
|
16
|
+
rescue Psych::SyntaxError
|
17
|
+
$stderr.puts "\n\tError during processing: #{$!.message}\n\n"
|
18
|
+
end
|
data/cf.gemspec
CHANGED
@@ -34,17 +34,20 @@ Gem::Specification.new do |s|
|
|
34
34
|
|
35
35
|
3. Generate your first assembly line...
|
36
36
|
> cf line generate <line-title>
|
37
|
-
|
38
|
-
4.
|
37
|
+
|
38
|
+
4. Go into generated line directory
|
39
|
+
> cd <line-title>
|
40
|
+
|
41
|
+
5. Edit the generated line.yml to design your perfect assembly line
|
39
42
|
See http://developers.cloudfactory.com/lines/yaml.html
|
40
|
-
|
41
|
-
|
43
|
+
|
44
|
+
6. Create your line in CloudFactory
|
42
45
|
> cf line create
|
43
46
|
|
44
|
-
|
47
|
+
7. Do a test production run in the sandbox first...
|
45
48
|
> cf production start TITLE -i=INPUT_DATA.CSV
|
46
49
|
|
47
|
-
|
50
|
+
8. Go live! Send your production run to real workers...
|
48
51
|
> cf production start TITLE -i=INPUT_DATA.CSV --live
|
49
52
|
|
50
53
|
------------------------------------------------------------------------------
|
data/lib/cf/cli.rb
CHANGED
@@ -17,10 +17,11 @@ require 'active_support/core_ext/object/blank'
|
|
17
17
|
|
18
18
|
cli_directory = File.expand_path("../cf/cli", File.dirname(__FILE__))
|
19
19
|
require "#{cli_directory}/config"
|
20
|
+
require "#{cli_directory}/line_yaml_validator"
|
20
21
|
require "#{cli_directory}/line"
|
21
22
|
require "#{cli_directory}/form"
|
22
23
|
require "#{cli_directory}/production"
|
23
|
-
|
24
|
+
|
24
25
|
|
25
26
|
if ENV['TEST']
|
26
27
|
require 'ruby-debug'
|
data/lib/cf/cli/line.rb
CHANGED
@@ -27,6 +27,8 @@ end
|
|
27
27
|
module Cf # :nodoc: all
|
28
28
|
class Line < Thor # :nodoc: all
|
29
29
|
include Cf::Config
|
30
|
+
include Cf::LineYamlValidator
|
31
|
+
|
30
32
|
desc "line generate LINE-TITLE", "generates a line template at <line-title>/line.yml"
|
31
33
|
method_option :force, :type => :boolean, :default => false, :aliases => "-f", :desc => "force to overwrite the files if the line already exists, default is false"
|
32
34
|
# method_option :with_custom_form, :type => :boolean, :default => false, :aliases => "-wcf", :desc => "generate the template with custom task form and the sample files, default is true"
|
@@ -68,9 +70,9 @@ module Cf # :nodoc: all
|
|
68
70
|
CF.account_name = CF::Account.info.name
|
69
71
|
line_title = options['line'].parameterize
|
70
72
|
end
|
71
|
-
|
72
|
-
|
73
|
-
line = Hashie::Mash.new(
|
73
|
+
|
74
|
+
resp_line = CF::Line.find(line_title)
|
75
|
+
line = Hashie::Mash.new(resp_line)
|
74
76
|
if line.title == line_title
|
75
77
|
if options.force
|
76
78
|
CF::Line.destroy(line_title, :forced => true)
|
@@ -78,12 +80,11 @@ module Cf # :nodoc: all
|
|
78
80
|
else
|
79
81
|
|
80
82
|
# Check whether this line has existing runs or not
|
81
|
-
|
82
|
-
|
83
|
+
resp_runs = CF::Run.all({:line_title => line_title})
|
84
|
+
|
85
|
+
if resp_runs.has_key?("runs") && resp_runs['runs'].present?
|
83
86
|
say("!!! Warning !!!\nThe following are the existing production runs based on this line.", :cyan)
|
84
|
-
|
85
|
-
existing_runs = Cf::Production.new
|
86
|
-
existing_runs.options = {"line" => line_title}
|
87
|
+
existing_runs = Cf::Production.new([],{'line' => line_title, 'all' => true})
|
87
88
|
existing_runs.list
|
88
89
|
|
89
90
|
delete_forcefully = agree("Do you still want to delete this line? [y/n] ")
|
@@ -126,8 +127,7 @@ module Cf # :nodoc: all
|
|
126
127
|
say "The line.yml file does not exist in this directory", :red
|
127
128
|
return
|
128
129
|
end
|
129
|
-
|
130
|
-
errors = LineYamlValidator.validate(yaml_source)
|
130
|
+
errors = validate(yaml_source)
|
131
131
|
|
132
132
|
if errors.present?
|
133
133
|
say("Invalid line.yml file. Correct its structure as per the errors shown below.", :red)
|
@@ -310,7 +310,7 @@ module Cf # :nodoc: all
|
|
310
310
|
say("You don't have any lines to list", :yellow) and return if lines.blank?
|
311
311
|
|
312
312
|
if resp_lines['total_pages']
|
313
|
-
say("Showing page #{current_page} of #{resp_lines['total_pages']}
|
313
|
+
say("Showing page #{current_page} of #{resp_lines['total_pages']}\tTotal lines: #{resp_lines['total_lines']}")
|
314
314
|
end
|
315
315
|
lines.sort! { |a, b| a['title'] <=> b['title'] }
|
316
316
|
lines_table = table do |t|
|
@@ -1,181 +1,182 @@
|
|
1
1
|
module Cf
|
2
|
-
|
2
|
+
module LineYamlValidator
|
3
3
|
|
4
|
-
def
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
def validate(yaml_path)
|
5
|
+
line_dump = YAML::load(File.read(yaml_path).strip)
|
6
|
+
errors = []
|
7
|
+
# Checking Department
|
8
|
+
if line_dump['department'].nil?
|
9
|
+
errors << "The line Department is missing!"
|
10
|
+
end
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
12
|
+
# Checking Input Formats
|
13
|
+
input_formats = line_dump['input_formats']
|
14
|
+
if input_formats.nil?
|
15
|
+
errors << "The Input Format is missing!"
|
16
|
+
else
|
17
|
+
if input_formats.class == Array
|
18
|
+
input_formats.each_with_index do |input_format, index|
|
19
|
+
name = input_format['name']
|
20
|
+
required = input_format['required']
|
21
|
+
valid_type = input_format['valid_type']
|
22
|
+
if name.nil?
|
23
|
+
errors << "Input Format name is missing in Block #{index+1}!"
|
24
|
+
end
|
24
25
|
end
|
25
26
|
end
|
26
27
|
end
|
27
|
-
end
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
29
|
+
# Checking Stations
|
30
|
+
stations = line_dump['stations']
|
31
|
+
if stations.nil?
|
32
|
+
errors << "Station is missing!"
|
33
|
+
else
|
34
|
+
if stations.class == Array
|
35
|
+
if stations.first['station'].nil?
|
36
|
+
errors << "Station Settings missing!"
|
37
|
+
else
|
38
|
+
stations.each_with_index do |station, i|
|
39
|
+
station_index = station['station']['station_index']
|
40
|
+
errors << "Station Index is missing in Block station #{i+1}!" if station_index.nil?
|
41
41
|
|
42
|
-
|
43
|
-
|
42
|
+
station_type = station['station']['station_type']
|
43
|
+
errors << "Station type is missing in Block station #{i+1}!" if station_type.nil?
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
end
|
55
|
-
# Checking Worker
|
56
|
-
worker = station['station']['worker']
|
57
|
-
if worker.class != Hash
|
58
|
-
errors << "Worker is missing in Block station #{i+1}!"
|
59
|
-
elsif worker.class == Hash
|
60
|
-
# Checking Worker type
|
61
|
-
worker.each_pair do |k, v|
|
62
|
-
errors << "Should not be an array" if v.class == Array && k != "skill_badges"
|
45
|
+
if station_type == "tournament"
|
46
|
+
jury_worker = station['station']['jury_worker']
|
47
|
+
if jury_worker.nil?
|
48
|
+
errors << "Jury worker setting is missing in Block station #{i+1}!"
|
49
|
+
elsif !jury_worker.nil?
|
50
|
+
reward = jury_worker['reward']
|
51
|
+
errors << "Reward for Jury worker is missing in block of Tournament Station #{i+1}!" if reward.nil?
|
52
|
+
errors << "Reward Must be greater than 0 in Block station #{i+1}!" if !reward.nil? && reward < 1
|
53
|
+
end
|
63
54
|
end
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
if
|
78
|
-
errors << "
|
79
|
-
|
80
|
-
|
81
|
-
|
55
|
+
# Checking Worker
|
56
|
+
worker = station['station']['worker']
|
57
|
+
if worker.class != Hash
|
58
|
+
errors << "Worker is missing in Block station #{i+1}!"
|
59
|
+
elsif worker.class == Hash
|
60
|
+
# Checking Worker type
|
61
|
+
worker.each_pair do |k, v|
|
62
|
+
errors << "Should not be an array" if v.class == Array && k != "skill_badges"
|
63
|
+
end
|
64
|
+
worker_type = worker['worker_type']
|
65
|
+
if worker_type.nil?
|
66
|
+
errors << "Worker Type is missing!"
|
67
|
+
else
|
68
|
+
if worker_type != "human"
|
69
|
+
errors << "Worker type is invalid in Block station #{i+1}!" if worker_type.split("_").last != "robot"
|
70
|
+
if worker_type.split("_").last == "robot"
|
71
|
+
settings = worker['settings']
|
72
|
+
errors << "Settings for the robot worker is missingin Block station #{i+1}!" if settings.nil?
|
73
|
+
end
|
74
|
+
elsif worker_type == "human"
|
75
|
+
# Checking number of workers if worker_type == "human"
|
76
|
+
num_workers = worker['num_workers']
|
77
|
+
if num_workers.nil?
|
78
|
+
errors << "Number of workers not specified in Block station #{i+1}!"
|
79
|
+
else
|
80
|
+
errors << "Number of workers must be greater than 0 in Block station #{i+1}!" if num_workers < 1
|
81
|
+
end
|
82
82
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
83
|
+
# Checking reward of workers if worker_type == "human"
|
84
|
+
reward = worker['reward']
|
85
|
+
if reward.nil?
|
86
|
+
errors << "Reward of workers not specified in Block station #{i+1}!"
|
87
|
+
else
|
88
|
+
errors << "Reward of workers must be greater than 0 in Block station #{i+1}!" if reward < 1
|
89
|
+
end
|
89
90
|
end
|
90
91
|
end
|
91
92
|
end
|
92
|
-
end
|
93
93
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
94
|
+
if station_type != "improve"
|
95
|
+
# Checking Stat_badge
|
96
|
+
stat_badge = station['station']['worker']['stat_badge']
|
97
|
+
if !stat_badge.nil?
|
98
|
+
errors << "Stat badge setting is invalid in Block station #{i+1}!" if stat_badge.class != Hash
|
99
|
+
end
|
100
100
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
101
|
+
# Checking skill_badge
|
102
|
+
skill_badges = station['station']['worker']['skill_badges']
|
103
|
+
if !skill_badges.nil?
|
104
|
+
errors << "Skill badge settings is invalid in Block station #{i+1}!" if skill_badges.class != Array
|
105
|
+
skill_badges.each_with_index do |badge, badge_index|
|
106
|
+
badge_title = badge['title']
|
107
|
+
badge_description = badge['description']
|
108
|
+
max_badges = badge['max_badges']
|
109
|
+
badge_test = badge['test']
|
110
|
+
test_input = badge_test['input'] if badge_test.class == Hash
|
111
|
+
expected_output = badge_test['expected_output'] if badge_test.class == Hash
|
112
|
+
errors << "Skill badge title is Missing in Block #{badge_index+1}!" if badge_title.nil?
|
113
|
+
errors << "Skill badge Description is Missing in Block #{badge_index+1}!" if badge_description.nil?
|
114
|
+
errors << "Skill badge max_badges must be greater than 1000 in Block #{badge_index+1}!" if max_badges < 1000 && !max_badges.nil?
|
115
|
+
errors << "Skill badge Test is Missing in Block #{badge_index+1}!" if badge_test.nil?
|
116
|
+
errors << "Skill badge Test is Invalid (must be Hash) in Block #{badge_index+1}!" if badge_test.class != Hash && !badge_test.nil?
|
117
|
+
errors << "Skill badge Test input is Missing in Block #{badge_index+1}!" if test_input.nil? && !badge_test.nil?
|
118
|
+
errors << "Skill badge Test input is Invalid (must be Hash) in Block #{badge_index+1}!" if test_input.class != Hash && !test_input.nil? && !badge_test.nil?
|
119
|
+
errors << "Skill badge Test expected_output is Missing in Block #{badge_index+1}!" if expected_output.nil? && !badge_test.nil?
|
120
|
+
errors << "Skill badge Test expected_output is Invalid (must be an array) in Block #{badge_index+1}!" if expected_output.class != Array && !expected_output.nil? && !badge_test.nil?
|
121
|
+
end
|
121
122
|
end
|
122
|
-
end
|
123
123
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
124
|
+
# Checking TaskForm
|
125
|
+
if worker_type == "human"
|
126
|
+
task_form = station['station']['task_form']
|
127
|
+
if task_form.nil?
|
128
|
+
custom_task_form = station['station']['custom_task_form']
|
129
|
+
if custom_task_form.nil?
|
130
|
+
errors << "Form is missing in Block station #{i+1}!"
|
131
|
+
elsif custom_task_form.class == Hash
|
132
|
+
form_title = custom_task_form['form_title']
|
133
|
+
errors << "Form Title is missing in Block station #{i+1}!" if form_title.nil?
|
134
134
|
|
135
|
-
|
136
|
-
|
135
|
+
instruction = custom_task_form['instruction']
|
136
|
+
errors << "Form Instruction is missing in Block station #{i+1}!" if instruction.nil?
|
137
137
|
|
138
|
-
|
138
|
+
errors << "station_#{i+1} folder is missing! Create station_#{i+1} folder in #{Dir.pwd}" if !File.exist?("#{Dir.pwd}/station_#{i+1}")
|
139
139
|
|
140
|
-
|
141
|
-
|
142
|
-
|
140
|
+
if File.exist?("#{Dir.pwd}/station_#{i+1}")
|
141
|
+
station_source = "#{Dir.pwd}/station_#{i+1}"
|
142
|
+
errors << "form.html is missing in folder #{Dir.pwd}/station_#{i+1} !" if !File.exist?("#{station_source}/form.html")
|
143
|
+
end
|
143
144
|
end
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
errors << "Form Title is missing in Block station #{i+1}!" if form_title.nil?
|
145
|
+
elsif task_form.class == Hash
|
146
|
+
form_title = task_form['form_title']
|
147
|
+
errors << "Form Title is missing in Block station #{i+1}!" if form_title.nil?
|
148
148
|
|
149
|
-
|
150
|
-
|
149
|
+
instruction = task_form['instruction']
|
150
|
+
errors << "Form Instruction is missing in Block station #{i+1}!" if instruction.nil?
|
151
151
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
152
|
+
# Checking Form Fields
|
153
|
+
form_fields = task_form['form_fields']
|
154
|
+
errors << "Form Field is missing in Block station #{i+1}!" if form_fields.nil?
|
155
|
+
if form_fields.class == Array
|
156
|
+
form_fields.each_with_index do |form_field, index|
|
157
|
+
field_label = form_field['label']
|
158
|
+
errors << "Label is missing in block #{index+1} of Form Field within Station #{i+1}!" if field_label.nil?
|
159
|
+
required = form_field['required']
|
160
|
+
field_type = form_field['field_type']
|
161
|
+
if !field_type.nil?
|
162
|
+
unless %w(short_answer long_answer radio_button check_box select_box date email number).include?(field_type)
|
163
|
+
errors << "Field Type of Form Field is invalid in Block #{index+1} of station Block #{i+1}!"
|
164
|
+
end
|
165
|
+
if field_type == "radio_button" || field_type == "select_box"
|
166
|
+
option_values = form_field['option_values']
|
167
|
+
if option_values.nil?
|
168
|
+
errors << "Option values is required for field_type => #{field_type} in block #{index+1} of Form Field within Station #{i+1} !"
|
169
|
+
elsif !option_values.nil?
|
170
|
+
if option_values.class != Array
|
171
|
+
errors << "Option values must be an array for field_type => #{field_type} in block #{index+1} of Form Field within Station #{i+1}!"
|
172
|
+
end
|
172
173
|
end
|
173
174
|
end
|
174
175
|
end
|
175
176
|
end
|
177
|
+
else
|
178
|
+
errors << "Form fields must be an array for Station #{i+1}!"
|
176
179
|
end
|
177
|
-
else
|
178
|
-
errors << "Form fields must be an array for Station #{i+1}!"
|
179
180
|
end
|
180
181
|
end
|
181
182
|
end
|
@@ -183,8 +184,7 @@ module Cf
|
|
183
184
|
end
|
184
185
|
end
|
185
186
|
end
|
186
|
-
|
187
|
-
return errors
|
187
|
+
return errors
|
188
188
|
end
|
189
189
|
end
|
190
190
|
end
|
data/lib/cf/cli/production.rb
CHANGED
@@ -134,26 +134,57 @@ module Cf # :nodoc: all
|
|
134
134
|
end
|
135
135
|
|
136
136
|
desc "production list", "list the production runs"
|
137
|
-
method_option :line, :type => :string, :aliases => "-l", :desc => "the title of the line"
|
137
|
+
method_option :line, :type => :string, :aliases => "-l", :desc => "the title of the line, if the line title is not given, it will show all the production runs under your account"
|
138
138
|
method_option :page, :type => :numeric, :aliases => "-p", :desc => "page number"
|
139
|
+
method_option :all, :type => :boolean, :default => false, :aliases => '-a', :desc => "list all the production runs"
|
139
140
|
def list
|
140
141
|
set_target_uri(false)
|
141
142
|
set_api_key
|
142
143
|
CF.account_name = CF::Account.info.name
|
144
|
+
param = {}
|
145
|
+
current_page = 1
|
146
|
+
|
143
147
|
if options['line'].present?
|
144
148
|
line_title = options['line'].parameterize
|
145
|
-
|
149
|
+
param.merge!({:line_title => line_title})
|
150
|
+
|
151
|
+
if options['all']
|
152
|
+
param.merge!({:page => "all"})
|
153
|
+
current_page = 1
|
154
|
+
end
|
155
|
+
|
156
|
+
if page = options['page'].presence
|
157
|
+
param.merge!({:page => page})
|
158
|
+
current_page = page
|
159
|
+
end
|
160
|
+
|
146
161
|
else
|
147
|
-
|
148
|
-
|
162
|
+
if options['all']
|
163
|
+
param = {:page => "all"}
|
164
|
+
current_page = 1
|
165
|
+
end
|
149
166
|
|
150
|
-
|
151
|
-
|
152
|
-
|
167
|
+
if page = options['page'].presence
|
168
|
+
param.merge!({:page => page})
|
169
|
+
current_page = page
|
153
170
|
end
|
154
171
|
end
|
155
172
|
|
156
|
-
|
173
|
+
resp_runs = CF::Run.all(param)
|
174
|
+
|
175
|
+
if resp_runs.has_key?('error')
|
176
|
+
say("#{resp_runs['error']}", :red) and exit(1)
|
177
|
+
end
|
178
|
+
|
179
|
+
if resp_runs.has_key?("runs") && resp_runs['runs'].blank?
|
180
|
+
say("\nRun list is empty.\n", :yellow) and return
|
181
|
+
end
|
182
|
+
|
183
|
+
if resp_runs['total_pages']
|
184
|
+
say("\nShowing page #{current_page} of #{resp_runs['total_pages']} (Total runs: #{resp_runs['total_runs']})")
|
185
|
+
end
|
186
|
+
runs = resp_runs['runs'].presence
|
187
|
+
runs.sort! {|a, b| a['title'] <=> b['title'] }
|
157
188
|
runs_table = table do |t|
|
158
189
|
t.headings = ["Run Title", 'URL']
|
159
190
|
runs.each do |run|
|
@@ -184,6 +215,35 @@ module Cf # :nodoc: all
|
|
184
215
|
# if result.status == "resumed"
|
185
216
|
say("Run with title \"#{result.title}\" is resumed!", :green)
|
186
217
|
# end
|
187
|
-
end
|
218
|
+
end
|
219
|
+
|
220
|
+
desc "production add_units", "add units to already existing production run"
|
221
|
+
method_option :run_title, :type => :string, :required => true, :aliases => "-t", :desc => "the title of the run to resume"
|
222
|
+
method_option :input_data, :type => :string, :required => true, :aliases => "-i", :desc => "the path of the input data file"
|
223
|
+
|
224
|
+
def add_units
|
225
|
+
set_target_uri(false)
|
226
|
+
set_api_key
|
227
|
+
CF.account_name = CF::Account.info.name
|
228
|
+
run_title = options[:run_title].parameterize
|
229
|
+
input_data = options[:input_data].presence
|
230
|
+
|
231
|
+
if input_data =~ /^\// #checking absolute input data path
|
232
|
+
input_data_file = input_data
|
233
|
+
else
|
234
|
+
unless File.exist?(input_data)
|
235
|
+
say("The input data file named #{input_data} doesn't exist", :red) and return
|
236
|
+
end
|
237
|
+
input_data_file = "#{Dir.pwd}/#{input_data}"
|
238
|
+
end
|
239
|
+
units = CF::Run.add_units({:run_title => run_title, :file => input_data_file})
|
240
|
+
if units['error'].present?
|
241
|
+
say("Error: #{units['error']['message']}", :red) and exit(1)
|
242
|
+
end
|
243
|
+
|
244
|
+
# if result.status == "resumed"
|
245
|
+
say("\"#{units['successfull']}\"!", :green)
|
246
|
+
# end
|
247
|
+
end
|
188
248
|
end
|
189
249
|
end
|
data/lib/cf/run.rb
CHANGED
@@ -89,18 +89,27 @@ module CF
|
|
89
89
|
def self.add_units(options={})
|
90
90
|
units = options[:units].presence
|
91
91
|
run_title = options[:run_title].presence
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
:body =>
|
92
|
+
file = options[:file].presence
|
93
|
+
if units
|
94
|
+
request =
|
96
95
|
{
|
97
|
-
:
|
98
|
-
|
96
|
+
:body =>
|
97
|
+
{
|
98
|
+
:api_key => CF.api_key,
|
99
|
+
:data => units
|
100
|
+
}
|
99
101
|
}
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
102
|
+
resp = HTTParty.post("#{CF.api_url}#{CF.api_version}/runs/#{CF.account_name}/#{run_title.downcase}/units.json",request)
|
103
|
+
@errors = resp['error']['message'] if resp.code != 200
|
104
|
+
return resp.parsed_response
|
105
|
+
elsif file
|
106
|
+
if File.exist?(file.to_s)
|
107
|
+
file_upload = File.new(file, 'rb')
|
108
|
+
resp = post("/runs/#{CF.account_name}/#{run_title.downcase}/units.json", {:file => file_upload})
|
109
|
+
@errors = resp.error.message if resp.code != 200
|
110
|
+
return resp.to_hash
|
111
|
+
end
|
112
|
+
end
|
104
113
|
end
|
105
114
|
# ==Returns Final Output of production Run
|
106
115
|
# ===Usage Example:
|
@@ -216,7 +225,12 @@ module CF
|
|
216
225
|
resp = get("/lines/#{CF.account_name}/#{line_title}/list_runs.json", :page => page)
|
217
226
|
end
|
218
227
|
end
|
219
|
-
|
228
|
+
|
229
|
+
if resp.code != 200
|
230
|
+
send_resp = {"error" => resp.error.message}
|
231
|
+
return send_resp
|
232
|
+
end
|
233
|
+
|
220
234
|
new_resp = []
|
221
235
|
if resp.code == 200
|
222
236
|
if resp.runs
|
@@ -226,7 +240,7 @@ module CF
|
|
226
240
|
end
|
227
241
|
end
|
228
242
|
end
|
229
|
-
send_resp = {"runs" => new_resp, "total_pages" => resp.total_pages}
|
243
|
+
send_resp = {"runs" => new_resp, "total_pages" => resp.total_pages, "total_runs" => resp.total_runs}
|
230
244
|
return send_resp
|
231
245
|
end
|
232
246
|
end
|
data/lib/cf/version.rb
CHANGED
data/spec/run_spec.rb
CHANGED
@@ -379,7 +379,8 @@ module CF
|
|
379
379
|
|
380
380
|
got_run = CF::Run.all
|
381
381
|
got_run['runs'].class.should eql(Array)
|
382
|
-
got_run['
|
382
|
+
got_run['runs'].first['progress'].should eql(100)
|
383
|
+
got_run['runs'].first['status'].should eql("active")
|
383
384
|
end
|
384
385
|
end
|
385
386
|
|
@@ -407,6 +408,8 @@ module CF
|
|
407
408
|
# WebMock.allow_net_connect!
|
408
409
|
run = CF::Run.all({:page => 1})
|
409
410
|
run['runs'].class.should eql(Array)
|
411
|
+
run['runs'].first['progress'].should eql(100)
|
412
|
+
run['runs'].first['status'].should eql("active")
|
410
413
|
end
|
411
414
|
end
|
412
415
|
|
@@ -481,6 +484,28 @@ module CF
|
|
481
484
|
end
|
482
485
|
end
|
483
486
|
|
487
|
+
it "should add units by passing file" do
|
488
|
+
VCR.use_cassette "run/block/adding_units_file", :record => :new_episodes do
|
489
|
+
# WebMock.allow_net_connect!
|
490
|
+
line = CF::Line.create("adding_units_file","Digitization") do |l|
|
491
|
+
CF::InputFormat.new({:line => l, :name => "Company", :required => true, :valid_type => "general"})
|
492
|
+
CF::InputFormat.new({:line => l, :name => "Website", :required => true, :valid_type => "url"})
|
493
|
+
CF::Station.create({:line => l, :type => "work"}) do |s|
|
494
|
+
CF::HumanWorker.new({:station => s, :number => 1, :reward => 20})
|
495
|
+
CF::TaskForm.create({:station => s, :title => "Enter text from a business card image", :instruction => "Describe"}) do |i|
|
496
|
+
CF::FormField.new({:form => i, :label => "First Name", :field_type => "short_answer", :required => "true"})
|
497
|
+
CF::FormField.new({:form => i, :label => "Middle Name", :field_type => "short_answer"})
|
498
|
+
CF::FormField.new({:form => i, :label => "Last Name", :field_type => "short_answer", :required => "true"})
|
499
|
+
end
|
500
|
+
end
|
501
|
+
end
|
502
|
+
run = CF::Run.create(line, "adding_units_file_run", [{"Company"=>"Sprout","Website"=>"sprout.com"}])
|
503
|
+
added_units = CF::Run.add_units({:run_title => "adding_units_file_run", :file => File.expand_path("../../fixtures/input_data/test.csv", __FILE__)})
|
504
|
+
added_units['successfull'].should eql("sucessfully added 1 units, failed :0")
|
505
|
+
run.title.should eql("adding_units_file_run")
|
506
|
+
end
|
507
|
+
end
|
508
|
+
|
484
509
|
it "should throw errors for invalid input while adding units" do
|
485
510
|
VCR.use_cassette "run/block/adding_units_errors", :record => :new_episodes do
|
486
511
|
# WebMock.allow_net_connect!
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloudfactory
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.22
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2011-08-25 00:00:00.000000000Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: i18n
|
16
|
-
requirement: &
|
16
|
+
requirement: &2161047200 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2161047200
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: activesupport
|
27
|
-
requirement: &
|
27
|
+
requirement: &2161046700 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '3.0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2161046700
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: hashie
|
38
|
-
requirement: &
|
38
|
+
requirement: &2161046200 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '1.0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *2161046200
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rest-client
|
49
|
-
requirement: &
|
49
|
+
requirement: &2161045820 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *2161045820
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: json
|
60
|
-
requirement: &
|
60
|
+
requirement: &2161045360 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *2161045360
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: thor
|
71
|
-
requirement: &
|
71
|
+
requirement: &2161044860 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ~>
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0.14'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *2161044860
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: highline
|
82
|
-
requirement: &
|
82
|
+
requirement: &2161044440 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :runtime
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *2161044440
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: httparty
|
93
|
-
requirement: &
|
93
|
+
requirement: &2161043900 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ~>
|
@@ -98,10 +98,10 @@ dependencies:
|
|
98
98
|
version: '0.7'
|
99
99
|
type: :runtime
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *2161043900
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: terminal-table
|
104
|
-
requirement: &
|
104
|
+
requirement: &2161043400 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ~>
|
@@ -109,10 +109,10 @@ dependencies:
|
|
109
109
|
version: '1.4'
|
110
110
|
type: :runtime
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *2161043400
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: millisami-csv-hash
|
115
|
-
requirement: &
|
115
|
+
requirement: &2161043020 !ruby/object:Gem::Requirement
|
116
116
|
none: false
|
117
117
|
requirements:
|
118
118
|
- - ! '>='
|
@@ -120,10 +120,10 @@ dependencies:
|
|
120
120
|
version: '0'
|
121
121
|
type: :runtime
|
122
122
|
prerelease: false
|
123
|
-
version_requirements: *
|
123
|
+
version_requirements: *2161043020
|
124
124
|
- !ruby/object:Gem::Dependency
|
125
125
|
name: awesome_print
|
126
|
-
requirement: &
|
126
|
+
requirement: &2161060720 !ruby/object:Gem::Requirement
|
127
127
|
none: false
|
128
128
|
requirements:
|
129
129
|
- - ! '>='
|
@@ -131,10 +131,10 @@ dependencies:
|
|
131
131
|
version: '0'
|
132
132
|
type: :runtime
|
133
133
|
prerelease: false
|
134
|
-
version_requirements: *
|
134
|
+
version_requirements: *2161060720
|
135
135
|
- !ruby/object:Gem::Dependency
|
136
136
|
name: ruby-debug19
|
137
|
-
requirement: &
|
137
|
+
requirement: &2161060300 !ruby/object:Gem::Requirement
|
138
138
|
none: false
|
139
139
|
requirements:
|
140
140
|
- - ! '>='
|
@@ -142,10 +142,10 @@ dependencies:
|
|
142
142
|
version: '0'
|
143
143
|
type: :development
|
144
144
|
prerelease: false
|
145
|
-
version_requirements: *
|
145
|
+
version_requirements: *2161060300
|
146
146
|
- !ruby/object:Gem::Dependency
|
147
147
|
name: aruba
|
148
|
-
requirement: &
|
148
|
+
requirement: &2161059880 !ruby/object:Gem::Requirement
|
149
149
|
none: false
|
150
150
|
requirements:
|
151
151
|
- - ! '>='
|
@@ -153,10 +153,10 @@ dependencies:
|
|
153
153
|
version: '0'
|
154
154
|
type: :development
|
155
155
|
prerelease: false
|
156
|
-
version_requirements: *
|
156
|
+
version_requirements: *2161059880
|
157
157
|
- !ruby/object:Gem::Dependency
|
158
158
|
name: rails
|
159
|
-
requirement: &
|
159
|
+
requirement: &2161059380 !ruby/object:Gem::Requirement
|
160
160
|
none: false
|
161
161
|
requirements:
|
162
162
|
- - ~>
|
@@ -164,10 +164,10 @@ dependencies:
|
|
164
164
|
version: 3.0.3
|
165
165
|
type: :development
|
166
166
|
prerelease: false
|
167
|
-
version_requirements: *
|
167
|
+
version_requirements: *2161059380
|
168
168
|
- !ruby/object:Gem::Dependency
|
169
169
|
name: bundler
|
170
|
-
requirement: &
|
170
|
+
requirement: &2161058880 !ruby/object:Gem::Requirement
|
171
171
|
none: false
|
172
172
|
requirements:
|
173
173
|
- - ~>
|
@@ -175,10 +175,10 @@ dependencies:
|
|
175
175
|
version: 1.0.0
|
176
176
|
type: :development
|
177
177
|
prerelease: false
|
178
|
-
version_requirements: *
|
178
|
+
version_requirements: *2161058880
|
179
179
|
- !ruby/object:Gem::Dependency
|
180
180
|
name: generator_spec
|
181
|
-
requirement: &
|
181
|
+
requirement: &2161058420 !ruby/object:Gem::Requirement
|
182
182
|
none: false
|
183
183
|
requirements:
|
184
184
|
- - ~>
|
@@ -186,10 +186,10 @@ dependencies:
|
|
186
186
|
version: 0.8.3
|
187
187
|
type: :development
|
188
188
|
prerelease: false
|
189
|
-
version_requirements: *
|
189
|
+
version_requirements: *2161058420
|
190
190
|
- !ruby/object:Gem::Dependency
|
191
191
|
name: rspec-rails
|
192
|
-
requirement: &
|
192
|
+
requirement: &2161058040 !ruby/object:Gem::Requirement
|
193
193
|
none: false
|
194
194
|
requirements:
|
195
195
|
- - ! '>='
|
@@ -197,10 +197,10 @@ dependencies:
|
|
197
197
|
version: '0'
|
198
198
|
type: :development
|
199
199
|
prerelease: false
|
200
|
-
version_requirements: *
|
200
|
+
version_requirements: *2161058040
|
201
201
|
- !ruby/object:Gem::Dependency
|
202
202
|
name: cucumber
|
203
|
-
requirement: &
|
203
|
+
requirement: &2161057580 !ruby/object:Gem::Requirement
|
204
204
|
none: false
|
205
205
|
requirements:
|
206
206
|
- - ! '>='
|
@@ -208,10 +208,10 @@ dependencies:
|
|
208
208
|
version: '0'
|
209
209
|
type: :development
|
210
210
|
prerelease: false
|
211
|
-
version_requirements: *
|
211
|
+
version_requirements: *2161057580
|
212
212
|
- !ruby/object:Gem::Dependency
|
213
213
|
name: rdoc
|
214
|
-
requirement: &
|
214
|
+
requirement: &2161057080 !ruby/object:Gem::Requirement
|
215
215
|
none: false
|
216
216
|
requirements:
|
217
217
|
- - ~>
|
@@ -219,10 +219,10 @@ dependencies:
|
|
219
219
|
version: 3.5.3
|
220
220
|
type: :development
|
221
221
|
prerelease: false
|
222
|
-
version_requirements: *
|
222
|
+
version_requirements: *2161057080
|
223
223
|
- !ruby/object:Gem::Dependency
|
224
224
|
name: vcr
|
225
|
-
requirement: &
|
225
|
+
requirement: &2161056660 !ruby/object:Gem::Requirement
|
226
226
|
none: false
|
227
227
|
requirements:
|
228
228
|
- - ! '>='
|
@@ -230,10 +230,10 @@ dependencies:
|
|
230
230
|
version: '0'
|
231
231
|
type: :development
|
232
232
|
prerelease: false
|
233
|
-
version_requirements: *
|
233
|
+
version_requirements: *2161056660
|
234
234
|
- !ruby/object:Gem::Dependency
|
235
235
|
name: rake
|
236
|
-
requirement: &
|
236
|
+
requirement: &2161056200 !ruby/object:Gem::Requirement
|
237
237
|
none: false
|
238
238
|
requirements:
|
239
239
|
- - ! '>='
|
@@ -241,10 +241,10 @@ dependencies:
|
|
241
241
|
version: '0'
|
242
242
|
type: :development
|
243
243
|
prerelease: false
|
244
|
-
version_requirements: *
|
244
|
+
version_requirements: *2161056200
|
245
245
|
- !ruby/object:Gem::Dependency
|
246
246
|
name: webmock
|
247
|
-
requirement: &
|
247
|
+
requirement: &2161055780 !ruby/object:Gem::Requirement
|
248
248
|
none: false
|
249
249
|
requirements:
|
250
250
|
- - ! '>='
|
@@ -252,10 +252,10 @@ dependencies:
|
|
252
252
|
version: '0'
|
253
253
|
type: :development
|
254
254
|
prerelease: false
|
255
|
-
version_requirements: *
|
255
|
+
version_requirements: *2161055780
|
256
256
|
- !ruby/object:Gem::Dependency
|
257
257
|
name: timecop
|
258
|
-
requirement: &
|
258
|
+
requirement: &2161055360 !ruby/object:Gem::Requirement
|
259
259
|
none: false
|
260
260
|
requirements:
|
261
261
|
- - ! '>='
|
@@ -263,7 +263,7 @@ dependencies:
|
|
263
263
|
version: '0'
|
264
264
|
type: :development
|
265
265
|
prerelease: false
|
266
|
-
version_requirements: *
|
266
|
+
version_requirements: *2161055360
|
267
267
|
description: A Ruby wrapper and CLI for to interact with Cloudfactory.com REST API
|
268
268
|
email:
|
269
269
|
- info@cloudfactory.com
|
@@ -369,12 +369,12 @@ post_install_message: ! " ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁
|
|
369
369
|
your API key\n http://cloudfactory.com/users/sign_up\n Get API key from welcome
|
370
370
|
email or http://cloudfactory.com/account#settings\n\n 2. Login with your credentials\n
|
371
371
|
\ > cf login\n \n 3. Generate your first assembly line...\n > cf line generate
|
372
|
-
<line-title>\n\n 4.
|
373
|
-
line\n See http://developers.cloudfactory.com/lines/yaml.html\n
|
374
|
-
line in CloudFactory\n > cf line create\n\n
|
375
|
-
sandbox first...\n > cf production start TITLE -i=INPUT_DATA.CSV\n\n
|
376
|
-
Send your production run to real workers...\n > cf production start
|
377
|
-
--live\n \n ------------------------------------------------------------------------------\n
|
372
|
+
<line-title>\n \n 4. Go into generated line directory\n > cd <line-title>\n \n
|
373
|
+
\ 5. Edit the generated line.yml to design your perfect assembly line\n See http://developers.cloudfactory.com/lines/yaml.html\n
|
374
|
+
\ \n 6. Create your line in CloudFactory\n > cf line create\n\n 7. Do a test
|
375
|
+
production run in the sandbox first...\n > cf production start TITLE -i=INPUT_DATA.CSV\n\n
|
376
|
+
\ 8. Go live! Send your production run to real workers...\n > cf production start
|
377
|
+
TITLE -i=INPUT_DATA.CSV --live\n \n ------------------------------------------------------------------------------\n
|
378
378
|
\n Follow @thecloudfactory on Twitter for announcements, updates, and news.\n https://twitter.com/thecloudfactory\n\n
|
379
379
|
\ Add your project or organization to the apps wiki!\n https://github.com/sprout/cloudfactory_ruby/wiki/Apps\n
|
380
380
|
\ \n ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁ ☁
|