cloudfactory 0.5.6 → 0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +3 -0
- data/lib/cf/badge.rb +109 -22
- data/lib/cf/cli.rb +11 -5
- data/lib/cf/cli/badge.rb +234 -0
- data/lib/cf/cli/badge_yaml_validator.rb +25 -0
- data/lib/cf/cli/line.rb +23 -42
- data/lib/cf/cli/templates/sample-line/badge.yml +21 -0
- data/lib/cf/cli/templates/sample-line/line.yml.erb +2 -0
- data/lib/cf/help.txt +13 -0
- data/lib/cf/human_worker.rb +13 -65
- data/lib/cf/station.rb +12 -58
- data/lib/cf/version.rb +1 -1
- data/spec/badges_spec.rb +237 -337
- data/spec/custom_task_form_spec.rb +2 -2
- data/spec/human_worker_spec.rb +131 -5
- data/spec/line_spec.rb +7 -5
- data/spec/task_form_spec.rb +1 -18
- data/spec/text_appending_robot_spec.rb +4 -5
- metadata +55 -52
data/CHANGELOG.md
CHANGED
data/lib/cf/badge.rb
CHANGED
@@ -13,45 +13,132 @@ module CF
|
|
13
13
|
attr_accessor :description
|
14
14
|
|
15
15
|
# number of badge provided to the worker
|
16
|
-
attr_accessor :
|
16
|
+
attr_accessor :max_badge_assignments
|
17
|
+
|
18
|
+
attr_accessor :allow_retake_after
|
17
19
|
|
18
20
|
# Contains error message
|
19
21
|
attr_accessor :errors
|
20
22
|
|
21
23
|
def initialize(options={})
|
22
24
|
options.symbolize_keys!
|
23
|
-
if
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
#if the form is provided as a file then explicitly add title and raw_html for the form
|
26
|
+
if options[:form] && options[:form].class != Hash && File.exist?(options[:form])
|
27
|
+
file_type = IO.popen(["file", "--brief", "--mime-type", options[:form]], in: :close, err: :close).read.chomp
|
28
|
+
if file_type == "text/html"
|
29
|
+
options[:form] = {:title => "#{options[:name]}_form",:_type => "CustomTaskForm", :raw_html => File.read(options[:form])}
|
30
|
+
else
|
31
|
+
@errors = ["Wrong type of file for the form."]
|
32
|
+
return @errors
|
33
|
+
exit(1)
|
31
34
|
end
|
32
|
-
options[:test_attributes][:form_attributes].merge!({:_type =>"TaskForm"}) if form[:type] == "TaskForm"
|
33
35
|
end
|
36
|
+
|
37
|
+
#known_answers of the badge get customize because to if unique identifier doesn't present then array of hashs returns the last hash for Httparty and get all key value merge into one in rest client/ rack
|
38
|
+
options[:known_answers] = self.class.customize_known_answers(options[:known_answers], options[:name]) if options[:known_answers].present?
|
39
|
+
|
34
40
|
@settings = options
|
35
|
-
@
|
36
|
-
@
|
37
|
-
|
38
|
-
|
41
|
+
@name = options[:name]
|
42
|
+
@description = options[:description]
|
43
|
+
@allow_retake_after = options[:allow_retake_after]
|
44
|
+
|
45
|
+
request =
|
46
|
+
{
|
47
|
+
:body =>
|
39
48
|
{
|
40
|
-
:
|
41
|
-
|
42
|
-
:api_key => CF.api_key,
|
43
|
-
:badge => options
|
44
|
-
}
|
49
|
+
:api_key => CF.api_key,
|
50
|
+
:badge => options
|
45
51
|
}
|
52
|
+
}
|
46
53
|
|
47
|
-
|
48
|
-
|
49
|
-
|
54
|
+
resp = HTTParty.post("#{CF.api_url}#{CF.api_version}/accounts/#{CF.account_name}/badges.json",request)
|
55
|
+
begin
|
56
|
+
self.errors = resp["error"]["message"] if resp.code != 200
|
57
|
+
return resp
|
58
|
+
rescue
|
59
|
+
self.errors = ["Unexpected error found. Confirm that you are in correct path and try again."]
|
50
60
|
end
|
51
61
|
end
|
52
62
|
|
53
63
|
def self.create(*args)
|
54
64
|
Badge.new(args.first)
|
55
65
|
end
|
66
|
+
|
67
|
+
def self.update(badge_name, update_params)
|
68
|
+
badge_name = badge_name.parameterize
|
69
|
+
update_params.symbolize_keys!
|
70
|
+
if update_params[:form] && update_params[:form].class != Hash && File.exist?(update_params[:form])
|
71
|
+
file_type = IO.popen(["file", "--brief", "--mime-type", update_params[:form]], in: :close, err: :close).read.chomp
|
72
|
+
if file_type == "text/html"
|
73
|
+
update_params[:form] = {:title => "#{update_params[:name]}_form",:_type => "CustomTaskForm", :raw_html => File.read(update_params[:form])}
|
74
|
+
else
|
75
|
+
return
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
update_params[:known_answers] = customize_known_answers(update_params[:known_answers], update_params[:name]) if update_params[:known_answers].present?
|
80
|
+
|
81
|
+
request =
|
82
|
+
{
|
83
|
+
:body =>
|
84
|
+
{
|
85
|
+
:api_key => CF.api_key,
|
86
|
+
:badge => update_params
|
87
|
+
}
|
88
|
+
}
|
89
|
+
resp = HTTParty.put("#{CF.api_url}#{CF.api_version}/accounts/#{CF.account_name}/badges/#{badge_name}.json",request)
|
90
|
+
return resp
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.destroy(*args)
|
94
|
+
name = args[0].parameterize
|
95
|
+
options = args[1].nil? ? {} : args[1]
|
96
|
+
decendents = check_for_decendents(name)
|
97
|
+
if decendents
|
98
|
+
response = delete("/accounts/#{CF.account_name}/badges/#{name}.json") if options.force
|
99
|
+
else
|
100
|
+
response = delete("/accounts/#{CF.account_name}/badges/#{name}.json")
|
101
|
+
end
|
102
|
+
@errors = response['error']['message'] if response['code'] != 200
|
103
|
+
return response
|
104
|
+
end
|
105
|
+
|
106
|
+
#list all badges with in the account if name is not provided else it will return list all values of the given badge
|
107
|
+
def self.list(name = nil)
|
108
|
+
response = get("/accounts/#{CF.account_name}/badges.json", :name => name)
|
109
|
+
@errors = response['error']['message'] if response['code'] != 200
|
110
|
+
return response
|
111
|
+
end
|
112
|
+
|
113
|
+
protected
|
114
|
+
|
115
|
+
#insert name to the goldstandard/known_answer if name is not provided
|
116
|
+
def self.customize_known_answers(known_answers, badge_name)
|
117
|
+
index = 1
|
118
|
+
known_answers.each do |known_answer|
|
119
|
+
unless known_answer["name"].present?
|
120
|
+
known_answer.merge!("name" => "#{badge_name}_answer_#{index}")
|
121
|
+
index +=1
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
#list the decendents for the badges like worker_associated, line_associated, number of tasks associated with the badge
|
128
|
+
def self.check_for_decendents(name)
|
129
|
+
response = get("/accounts/#{CF.account_name}/badges.json", :name => name)
|
130
|
+
@errors = response["error"]["message"] unless response["code"] == 200
|
131
|
+
unless @errors
|
132
|
+
lines = response["badges"].first["line_associated"]
|
133
|
+
workers = response["badges"].first["workers"]
|
134
|
+
tasks = response["badges"].first["num_of_tasks"]
|
135
|
+
#if the lines of worker count is greater then 0 then return true else return lines and worker count
|
136
|
+
if lines > 0 || workers > 0
|
137
|
+
{:lines_count => lines, :workers_count => workers, :tasks => tasks }
|
138
|
+
else
|
139
|
+
false
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
56
143
|
end
|
57
144
|
end
|
data/lib/cf/cli.rb
CHANGED
@@ -17,12 +17,15 @@ 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}/badge_yaml_validator"
|
21
|
+
require "#{cli_directory}/badge"
|
20
22
|
require "#{cli_directory}/line_yaml_validator"
|
21
23
|
require "#{cli_directory}/line"
|
22
24
|
require "#{cli_directory}/form"
|
23
25
|
require "#{cli_directory}/production"
|
24
26
|
|
25
27
|
|
28
|
+
|
26
29
|
if ENV['TEST']
|
27
30
|
require 'pry'
|
28
31
|
end
|
@@ -33,9 +36,9 @@ module Cf # :nodoc: all
|
|
33
36
|
include Cf::Config
|
34
37
|
|
35
38
|
def help(*args)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
+
File.open(File.expand_path(File.dirname(__FILE__)+"/help.txt")).each_line{ |s|
|
40
|
+
say s
|
41
|
+
}
|
39
42
|
end
|
40
43
|
|
41
44
|
map "-v" => :version
|
@@ -59,7 +62,7 @@ module Cf # :nodoc: all
|
|
59
62
|
|
60
63
|
no_tasks do
|
61
64
|
def ask_password(message)
|
62
|
-
::HighLine.new.ask(message) do |q|
|
65
|
+
::HighLine.new.ask(message) do |q|
|
63
66
|
q.echo = '*'
|
64
67
|
end
|
65
68
|
end
|
@@ -103,6 +106,9 @@ module Cf # :nodoc: all
|
|
103
106
|
# later it can be replaced with hacked millisami-thor version of the thor library with run-time dependency via Bundler
|
104
107
|
subcommand "production", Cf::Production
|
105
108
|
|
109
|
+
desc "badge", "Commands to manage Badges. For more info cf badge help"
|
110
|
+
subcommand "badge", Cf::Badge
|
111
|
+
|
106
112
|
desc "output <run-title>", "Get the output of run. For more info, cf output help"
|
107
113
|
method_option :run_title, :type => :string, :required => true, :aliases => "-t", :desc => "the index of the station"
|
108
114
|
method_option :station_index, :type => :numeric, :aliases => "-s", :desc => "the index of the station"
|
@@ -128,7 +134,7 @@ module Cf # :nodoc: all
|
|
128
134
|
output = CF::Run.final_output(run_title)
|
129
135
|
end
|
130
136
|
if !output.empty?
|
131
|
-
output.each
|
137
|
+
output.each
|
132
138
|
csv_str = CSVHash(output,output.first.keys)
|
133
139
|
csv_str = csv_str.gsub("\"\"", '"')
|
134
140
|
FileUtils.mkdir("#{line_source}/output") unless Dir.exist?("#{line_source}/output") if RUBY_VERSION > "1.9"
|
data/lib/cf/cli/badge.rb
ADDED
@@ -0,0 +1,234 @@
|
|
1
|
+
require 'thor/group'
|
2
|
+
|
3
|
+
module Cf # :nodoc: all
|
4
|
+
class NewBadge < Thor::Group # :nodoc: all
|
5
|
+
include Thor::Actions
|
6
|
+
include Cf::Config
|
7
|
+
source_root File.expand_path('../templates', __FILE__)
|
8
|
+
|
9
|
+
def generate
|
10
|
+
badge_destination = "#{Dir.pwd}/badges"
|
11
|
+
FileUtils.mkdir(badge_destination)
|
12
|
+
copy_file("sample-line/badge.yml", "#{badge_destination}/badge.yml")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module Cf # :nodoc: all
|
18
|
+
class Badge < Thor
|
19
|
+
include Cf::Config
|
20
|
+
include Cf::BadgeYamlValidator
|
21
|
+
|
22
|
+
|
23
|
+
desc "badge generate", "Generate a new badge template at badges/badge.yml"
|
24
|
+
method_option :force, :type => :boolean, :default => false, :aliases => "-f", :desc => "force to overwrite the files if already exists, default is false"
|
25
|
+
def generate
|
26
|
+
yaml_destination = "#{Dir.pwd}/badges/badge.yml"
|
27
|
+
FileUtils.rm_rf("#{Dir.pwd}/badges", :verbose => true) if options.force?
|
28
|
+
if File.exist?(yaml_destination)
|
29
|
+
say "Skipping #{yaml_destination} because it already exists.", :red
|
30
|
+
else
|
31
|
+
say "Generating a new badge template #{yaml_destination}", :green
|
32
|
+
Cf::NewBadge.start()
|
33
|
+
say "Badge template generated successfully.", :green
|
34
|
+
say "Modify the #{yaml_destination} file and create badge with: cf badge create", :yellow
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
desc "badge create", "Create badges that are in badge.yml"
|
41
|
+
def create
|
42
|
+
badge_source = "#{Dir.pwd}/badges"
|
43
|
+
yaml_source = "#{badge_source}/badge.yml"
|
44
|
+
|
45
|
+
unless File.exist?(yaml_source)
|
46
|
+
say "The badge.yml file does not exist in this directory.", :red
|
47
|
+
return
|
48
|
+
end
|
49
|
+
errors = validate(yaml_source)
|
50
|
+
unless errors.present?
|
51
|
+
set_target_uri(false)
|
52
|
+
set_api_key(yaml_source)
|
53
|
+
CF.account_name = CF::Account.info['name']
|
54
|
+
|
55
|
+
badge_dump = YAML::load(File.read(yaml_source).strip)
|
56
|
+
badge_dump["badge"].each do |badge_hash|
|
57
|
+
name = badge_hash["name"]
|
58
|
+
do_exist = CF::Badge.list(name.parameterize)
|
59
|
+
if do_exist && do_exist["code"]==200
|
60
|
+
say "A badge named #{name} already exists.", :yellow
|
61
|
+
override = agree("Do you want to override ? [y/n] ")
|
62
|
+
override == true ? badge_hash.merge!(:confirmed => true) : ((say "Badge creation aborted!", :red) and exit(1))
|
63
|
+
end
|
64
|
+
say "Creating badge '#{name}'"
|
65
|
+
badge = CF::Badge.new(badge_hash)
|
66
|
+
if badge.errors.present?
|
67
|
+
say "Errors: \n", :red
|
68
|
+
badge.errors.each do |error|
|
69
|
+
say(error, :red)
|
70
|
+
end
|
71
|
+
exit(1)
|
72
|
+
else
|
73
|
+
say "A new badge named '#{name}' created sucessfully!"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
else
|
77
|
+
say "Following errors has been encountered in your badge.yml file: #{errors}" , :red
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
desc "badge update <badge_name>", "Updates the given badge within your account. Use 'cf badge update' to update all badges in badge.yml"
|
84
|
+
def update(badge_name = nil)
|
85
|
+
badge_source = "#{Dir.pwd}/badges"
|
86
|
+
yaml_source = "#{badge_source}/badge.yml"
|
87
|
+
|
88
|
+
unless File.exist?(yaml_source)
|
89
|
+
say "The badge.yml file does not exist in this directory", :red
|
90
|
+
return
|
91
|
+
end
|
92
|
+
errors = validate(yaml_source)
|
93
|
+
unless errors.present?
|
94
|
+
set_target_uri(false)
|
95
|
+
set_api_key(yaml_source)
|
96
|
+
CF.account_name = CF::Account.info['name']
|
97
|
+
|
98
|
+
badge_dump = YAML::load(File.read(yaml_source).strip)
|
99
|
+
|
100
|
+
badges = badge_dump["badge"]
|
101
|
+
|
102
|
+
#check whether the given badge_name is present in badge.yml file and if present then take the given badge_hash for update
|
103
|
+
if badge_name
|
104
|
+
selected_badge = badges.select {|f| f["name"].parameterize == badge_name.parameterize }
|
105
|
+
if selected_badge.present?
|
106
|
+
badges = selected_badge
|
107
|
+
else
|
108
|
+
say "Could not find badge named '#{badge_name}' in your badge.yml file", :red
|
109
|
+
exit(1)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
badges.each do |badge_hash|
|
114
|
+
previous_name = badge_hash["name"]["from"] || badge_hash["name"]
|
115
|
+
badge_hash["name"] = badge_hash["name"]["to"] || badge_hash["name"]
|
116
|
+
do_exist = CF::Badge.list(previous_name.parameterize)
|
117
|
+
#check whetether the badge do exist and has its decendents if do then retain_current_worker_badge = true so that worker and lines associated get retain if the badge get updated other wise the badge act as a new badge
|
118
|
+
if do_exist && do_exist["code"]==200
|
119
|
+
descendents = CF::Badge.check_for_decendents(previous_name.parameterize)
|
120
|
+
if descendents
|
121
|
+
say("\n!!! Warning !!!\n The badge '#{previous_name}' has the following number of tasks, lines and workers asscociated with it.\n", :yellow)
|
122
|
+
badge_table = table do |t|
|
123
|
+
t.headings = [ 'Tasks', 'Lines', 'Workers']
|
124
|
+
t << [ descendents[:tasks], descendents[:lines_count], descendents[:workers_count]]
|
125
|
+
end
|
126
|
+
say(badge_table)
|
127
|
+
say("\n!!! Warning !!!\n Retaining the workers will keep the workers associated with the badge.\n", :yellow)
|
128
|
+
update_forcefully = agree("Do you want to retain the workers? [y/n] ")
|
129
|
+
badge_hash.merge!(:retain_workers => false) if update_forcefully == false
|
130
|
+
end
|
131
|
+
|
132
|
+
#now update the badge
|
133
|
+
say "Updating badge named '#{previous_name}'"
|
134
|
+
badge = CF::Badge.update(previous_name,badge_hash)
|
135
|
+
if badge && badge.code == 200
|
136
|
+
say "A badge named '#{previous_name}' updated sucessfully!"
|
137
|
+
else
|
138
|
+
if badge.code == 422
|
139
|
+
say badge["error"]["message"]
|
140
|
+
else
|
141
|
+
say "A badge named '#{previous_name}' can not be updated", :red
|
142
|
+
end
|
143
|
+
exit(1)
|
144
|
+
end
|
145
|
+
else
|
146
|
+
say "A badge named '#{previous_name}' does not exist!", :red
|
147
|
+
exit(1)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
else
|
151
|
+
say "Following errors has been encountered in your badge.yml file: #{errors}" , :red
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
|
156
|
+
|
157
|
+
desc "badge delete <badge name>", "Delete the given badge within your account"
|
158
|
+
method_option :force, :type => :boolean, :aliases => "-f", :default => false, :desc => "force delete the badge"
|
159
|
+
def delete(name = nil)
|
160
|
+
#set badge basic credentials
|
161
|
+
line_source = Dir.pwd
|
162
|
+
yaml_source = "#{line_source}/line.yml"
|
163
|
+
set_target_uri(false)
|
164
|
+
set_api_key(yaml_source)
|
165
|
+
set_target_uri(false)
|
166
|
+
CF.account_name = CF::Account.info['name']
|
167
|
+
|
168
|
+
#list all badges if name is not present else list the specific badge
|
169
|
+
if name
|
170
|
+
badge_decendents = CF::Badge.check_for_decendents(name)
|
171
|
+
if badge_decendents
|
172
|
+
say("\n!!! Warning !!!\n The badge #{name} has following number of tasks, lines and workers asscociated with it.\n", :yellow)
|
173
|
+
badge_table = table do |t|
|
174
|
+
t.headings = [ 'Tasks', 'Lines', 'Workers']
|
175
|
+
t << [ badge_decendents[:tasks], badge_decendents[:lines_count], badge_decendents[:workers_count]]
|
176
|
+
end
|
177
|
+
say(badge_table)
|
178
|
+
|
179
|
+
delete_forcefully = agree("Do you still want to delete this badge? [y/n] ")
|
180
|
+
if delete_forcefully
|
181
|
+
badge_resp = CF::Badge.destroy(name,options.merge(:force => true))
|
182
|
+
else
|
183
|
+
say "Badge deletion aborted!", :yellow
|
184
|
+
exit(1)
|
185
|
+
end
|
186
|
+
else
|
187
|
+
say "Deleting badge named '#{name}'"
|
188
|
+
badge_resp = CF::Badge.destroy(name)
|
189
|
+
end
|
190
|
+
badge_resp["code"] == 200 ? (say "A badge named #{name} deleted sucessfully!", :green) : (say badge_resp["error"]["message"], :red)
|
191
|
+
else
|
192
|
+
say "Name of the badge for deletion is missing.", :red
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
|
197
|
+
|
198
|
+
desc "badge list ", "List all badges asscociated with your account. Use 'cf badge list <badge_name>' for single badge"
|
199
|
+
def list(name = nil)
|
200
|
+
#set badge basic credentials
|
201
|
+
line_source = Dir.pwd
|
202
|
+
yaml_source = "#{line_source}/line.yml"
|
203
|
+
set_target_uri(false)
|
204
|
+
set_api_key(yaml_source)
|
205
|
+
set_target_uri(false)
|
206
|
+
CF.account_name = CF::Account.info['name']
|
207
|
+
|
208
|
+
#list all badges if name is not present else list the specific badge
|
209
|
+
if name
|
210
|
+
badge_resp = CF::Badge.list(name)
|
211
|
+
else
|
212
|
+
badge_resp = CF::Badge.list
|
213
|
+
end
|
214
|
+
|
215
|
+
#show list of badges in the tabular view
|
216
|
+
if badges = badge_resp["badges"]
|
217
|
+
say "Listing badges within your account" , :green
|
218
|
+
badges.sort! { |a, b| a['name'] <=> b['name'] }
|
219
|
+
badge_table = table do |t|
|
220
|
+
t.headings = ["Name", 'Number oF Tasks', 'Lines Associates', 'Workers', 'description']
|
221
|
+
badges.each do |badge|
|
222
|
+
badge = Hashie::Mash.new(badge)
|
223
|
+
t << [badge.name, badge.num_of_tasks, badge.line_associated, badge.workers, badge.description]
|
224
|
+
end
|
225
|
+
end
|
226
|
+
say(badge_table)
|
227
|
+
else
|
228
|
+
say badge_resp["error"]["message"], :red
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
|
233
|
+
end
|
234
|
+
end
|