epc 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. data/CHANGELOG +1 -0
  2. data/Gemfile +22 -0
  3. data/Rakefile +67 -0
  4. data/Rakefile.gem +1 -0
  5. data/bin/epc +10 -0
  6. data/lib/epc.rb +126 -0
  7. data/lib/epc/client/base_client.rb +80 -0
  8. data/lib/epc/client/http_client.rb +19 -0
  9. data/lib/epc/client/json_client.rb +48 -0
  10. data/lib/epc/command/archive_project_command.rb +24 -0
  11. data/lib/epc/command/archive_solution_command.rb +21 -0
  12. data/lib/epc/command/attach_library_command.rb +82 -0
  13. data/lib/epc/command/attach_libraryset_command.rb +32 -0
  14. data/lib/epc/command/attach_runtime_command.rb +27 -0
  15. data/lib/epc/command/base_command.rb +451 -0
  16. data/lib/epc/command/bind_service_command.rb +35 -0
  17. data/lib/epc/command/build_command.rb +83 -0
  18. data/lib/epc/command/config/create_config_command.rb +55 -0
  19. data/lib/epc/command/copy_deployment_command.rb +21 -0
  20. data/lib/epc/command/create_command.rb +13 -0
  21. data/lib/epc/command/create_dependency_command.rb +43 -0
  22. data/lib/epc/command/define_service_command.rb +37 -0
  23. data/lib/epc/command/delete_config_command.rb +63 -0
  24. data/lib/epc/command/delete_dependency_command.rb +40 -0
  25. data/lib/epc/command/delete_group_command.rb +40 -0
  26. data/lib/epc/command/delete_library_command.rb +30 -0
  27. data/lib/epc/command/delete_librarylanguage_command.rb +40 -0
  28. data/lib/epc/command/delete_libraryset_command.rb +40 -0
  29. data/lib/epc/command/delete_project_command.rb +54 -0
  30. data/lib/epc/command/delete_role_command.rb +25 -0
  31. data/lib/epc/command/delete_serviceversion_command.rb +52 -0
  32. data/lib/epc/command/delete_solution_command.rb +39 -0
  33. data/lib/epc/command/delete_user_command.rb +31 -0
  34. data/lib/epc/command/deploy_command.rb +142 -0
  35. data/lib/epc/command/deployment/create_deployment_command.rb +82 -0
  36. data/lib/epc/command/detach_library_command.rb +35 -0
  37. data/lib/epc/command/detach_libraryset_command.rb +8 -0
  38. data/lib/epc/command/group/create_group_command.rb +21 -0
  39. data/lib/epc/command/info_command.rb +11 -0
  40. data/lib/epc/command/library/create_library_command.rb +45 -0
  41. data/lib/epc/command/librarylanguage/create_librarylanguage_command.rb +24 -0
  42. data/lib/epc/command/libraryset/create_libraryset_command.rb +54 -0
  43. data/lib/epc/command/list_approvals_command.rb +27 -0
  44. data/lib/epc/command/list_attachedlibraries_command.rb +42 -0
  45. data/lib/epc/command/list_boundservices_command.rb +40 -0
  46. data/lib/epc/command/list_config_command.rb +60 -0
  47. data/lib/epc/command/list_dependencies_command.rb +43 -0
  48. data/lib/epc/command/list_deployments_command.rb +68 -0
  49. data/lib/epc/command/list_groups_command.rb +19 -0
  50. data/lib/epc/command/list_libraries_command.rb +19 -0
  51. data/lib/epc/command/list_librarylanguages_command.rb +19 -0
  52. data/lib/epc/command/list_librarysets_command.rb +26 -0
  53. data/lib/epc/command/list_objectroles_command.rb +25 -0
  54. data/lib/epc/command/list_objecttypes_command.rb +20 -0
  55. data/lib/epc/command/list_permissiongroups_command.rb +20 -0
  56. data/lib/epc/command/list_projects_command.rb +36 -0
  57. data/lib/epc/command/list_projecttypes_command.rb +20 -0
  58. data/lib/epc/command/list_rolepermissions_command.rb +21 -0
  59. data/lib/epc/command/list_roles_command.rb +26 -0
  60. data/lib/epc/command/list_runtimes_command.rb +16 -0
  61. data/lib/epc/command/list_service_types_command.rb +19 -0
  62. data/lib/epc/command/list_servicedefinitions_command.rb +19 -0
  63. data/lib/epc/command/list_serviceversions_command.rb +21 -0
  64. data/lib/epc/command/list_solutions_command.rb +25 -0
  65. data/lib/epc/command/list_stages_command.rb +21 -0
  66. data/lib/epc/command/list_users_command.rb +26 -0
  67. data/lib/epc/command/list_versions_command.rb +39 -0
  68. data/lib/epc/command/login_command.rb +32 -0
  69. data/lib/epc/command/logout_command.rb +20 -0
  70. data/lib/epc/command/objectrole/create_objectrole_command.rb +19 -0
  71. data/lib/epc/command/project/create_project_command.rb +78 -0
  72. data/lib/epc/command/pull_command.rb +209 -0
  73. data/lib/epc/command/push_command.rb +194 -0
  74. data/lib/epc/command/refresh_solution_command.rb +71 -0
  75. data/lib/epc/command/renew_command.rb +19 -0
  76. data/lib/epc/command/request_passwordchange_command.rb +23 -0
  77. data/lib/epc/command/role/create_role_command.rb +17 -0
  78. data/lib/epc/command/serviceversion/create_serviceversion_command.rb +33 -0
  79. data/lib/epc/command/show_deployment_command.rb +57 -0
  80. data/lib/epc/command/show_group_command.rb +35 -0
  81. data/lib/epc/command/show_libraryset_command.rb +54 -0
  82. data/lib/epc/command/show_project_command.rb +74 -0
  83. data/lib/epc/command/show_projecttype_command.rb +18 -0
  84. data/lib/epc/command/show_role_command.rb +46 -0
  85. data/lib/epc/command/show_solution_command.rb +54 -0
  86. data/lib/epc/command/show_user_command.rb +42 -0
  87. data/lib/epc/command/solution/create_solution_command.rb +34 -0
  88. data/lib/epc/command/solution/list_solutions_command.rb +25 -0
  89. data/lib/epc/command/solution/update_solution_command.rb +43 -0
  90. data/lib/epc/command/submit_deployment_command.rb +19 -0
  91. data/lib/epc/command/target_command.rb +26 -0
  92. data/lib/epc/command/unarchive_project_command.rb +23 -0
  93. data/lib/epc/command/unarchive_solution_command.rb +21 -0
  94. data/lib/epc/command/unbind_service_command.rb +42 -0
  95. data/lib/epc/command/undefine_service_command.rb +33 -0
  96. data/lib/epc/command/undeploy_command.rb +106 -0
  97. data/lib/epc/command/update_config_command.rb +62 -0
  98. data/lib/epc/command/update_deploymentproject_command.rb +54 -0
  99. data/lib/epc/command/update_group_command.rb +43 -0
  100. data/lib/epc/command/update_librarylanguage_command.rb +28 -0
  101. data/lib/epc/command/update_libraryset_command.rb +80 -0
  102. data/lib/epc/command/update_project_command.rb +49 -0
  103. data/lib/epc/command/update_role_command.rb +47 -0
  104. data/lib/epc/command/update_rolepermissions_command.rb +83 -0
  105. data/lib/epc/command/update_solution_command.rb +45 -0
  106. data/lib/epc/command/update_user_command.rb +57 -0
  107. data/lib/epc/command/user/create_user_command.rb +27 -0
  108. data/lib/epc/command/vote_deployment_command.rb +29 -0
  109. data/lib/epc/config.rb +245 -0
  110. data/lib/epc/error/basic_error.rb +6 -0
  111. data/lib/epc/error/fatal_error.rb +6 -0
  112. data/lib/epc/error/input_error.rb +6 -0
  113. data/lib/epc/error/internal_error.rb +6 -0
  114. data/lib/epc/help.rb +292 -0
  115. data/lib/epc/persistent_attributes.rb +18 -0
  116. data/lib/epc/runner.rb +177 -0
  117. data/lib/epc/tabular_outputter.rb +161 -0
  118. data/lib/epc/version.rb +3 -0
  119. data/lib/fixnum.rb +9 -0
  120. data/lib/object.rb +13 -0
  121. data/test/command/archive_project_command_test.rb +41 -0
  122. data/test/command/archive_solution_command_test.rb +40 -0
  123. data/test/command/attach_library_command_test.rb +124 -0
  124. data/test/command/attach_libraryset_command_test.rb +49 -0
  125. data/test/command/attach_runtime_command_test.rb +44 -0
  126. data/test/command/base_command_test.rb +276 -0
  127. data/test/command/bind_service_command_test.rb +46 -0
  128. data/test/command/build_command_test.rb +103 -0
  129. data/test/command/copy_deployment_command_test.rb +38 -0
  130. data/test/command/create_config_command_test.rb +124 -0
  131. data/test/command/create_dependency_command_test.rb +55 -0
  132. data/test/command/create_deployment_command_test.rb +136 -0
  133. data/test/command/create_group_command_test.rb +34 -0
  134. data/test/command/create_library_command_test.rb +61 -0
  135. data/test/command/create_librarylanguage_command_test.rb +51 -0
  136. data/test/command/create_libraryset_command_test.rb +81 -0
  137. data/test/command/create_objectrole_command_test.rb +37 -0
  138. data/test/command/create_project_command_test.rb +102 -0
  139. data/test/command/create_role_command_test.rb +31 -0
  140. data/test/command/create_serviceversion_command_test.rb +60 -0
  141. data/test/command/create_solution_command_test.rb +70 -0
  142. data/test/command/create_user_command_test.rb +54 -0
  143. data/test/command/define_service_command_test.rb +55 -0
  144. data/test/command/delete_config_command_test.rb +82 -0
  145. data/test/command/delete_dependency_command_test.rb +50 -0
  146. data/test/command/delete_group_command_test.rb +56 -0
  147. data/test/command/delete_library_command_test.rb +43 -0
  148. data/test/command/delete_librarylanguage_command_test.rb +55 -0
  149. data/test/command/delete_libraryset_command_test.rb +55 -0
  150. data/test/command/delete_project_command_test.rb +76 -0
  151. data/test/command/delete_role_command_test.rb +41 -0
  152. data/test/command/delete_serviceversion_command_test.rb +53 -0
  153. data/test/command/delete_solution_command_test.rb +79 -0
  154. data/test/command/delete_user_command_test.rb +56 -0
  155. data/test/command/deploy_command_test.rb +185 -0
  156. data/test/command/detach_library_command_test.rb +53 -0
  157. data/test/command/info_command_test.rb +17 -0
  158. data/test/command/list_approvals_command_test.rb +41 -0
  159. data/test/command/list_boundservices_command_test.rb +46 -0
  160. data/test/command/list_config_command_test.rb +72 -0
  161. data/test/command/list_dependencies_command_test.rb +46 -0
  162. data/test/command/list_deployments_command_test.rb +112 -0
  163. data/test/command/list_deploymentstages_command_test.rb +44 -0
  164. data/test/command/list_libraries_command_test.rb +42 -0
  165. data/test/command/list_librarylanguages_command_test.rb +34 -0
  166. data/test/command/list_librarysets_command_test.rb +33 -0
  167. data/test/command/list_objectroles_command_test.rb +41 -0
  168. data/test/command/list_objecttypes_command_test.rb +25 -0
  169. data/test/command/list_permissiongroups_command_test.rb +25 -0
  170. data/test/command/list_projects_command_test.rb +63 -0
  171. data/test/command/list_projecttypes_command_test.rb +39 -0
  172. data/test/command/list_rolepermissions_command_test.rb +39 -0
  173. data/test/command/list_roles_command_test.rb +46 -0
  174. data/test/command/list_runtimes_command_test.rb +30 -0
  175. data/test/command/list_service_types_command_test.rb +44 -0
  176. data/test/command/list_servicedefinitions_command_test.rb +44 -0
  177. data/test/command/list_serviceversions_command_test.rb +47 -0
  178. data/test/command/list_solutions_command_test.rb +48 -0
  179. data/test/command/list_users_command_test.rb +33 -0
  180. data/test/command/login_command_test.rb +83 -0
  181. data/test/command/logout_command_test.rb +30 -0
  182. data/test/command/pull_command_test.rb +229 -0
  183. data/test/command/push_command_test.rb +246 -0
  184. data/test/command/refresh_solution_command_test.rb +35 -0
  185. data/test/command/renew_command_test.rb +43 -0
  186. data/test/command/request_passwordchange_command_test.rb +31 -0
  187. data/test/command/show_group_command_test.rb +50 -0
  188. data/test/command/show_libraryset_command_test.rb +51 -0
  189. data/test/command/show_project_command_test.rb +57 -0
  190. data/test/command/show_projecttype_command_test.rb +46 -0
  191. data/test/command/show_role_command_test.rb +37 -0
  192. data/test/command/show_solution_command_test.rb +59 -0
  193. data/test/command/show_user_command_test.rb +50 -0
  194. data/test/command/submit_deployment_command_test.rb +37 -0
  195. data/test/command/target_command_test.rb +58 -0
  196. data/test/command/unarchive_project_command_test.rb +45 -0
  197. data/test/command/unarchive_solution_command_test.rb +43 -0
  198. data/test/command/unbind_service_command_test.rb +48 -0
  199. data/test/command/undefine_service_command_test.rb +49 -0
  200. data/test/command/update_config_command_test.rb +74 -0
  201. data/test/command/update_deploymentproject_command_test.rb +77 -0
  202. data/test/command/update_group_command_test.rb +69 -0
  203. data/test/command/update_librarylanguage_command_test.rb +43 -0
  204. data/test/command/update_libraryset_command_test.rb +113 -0
  205. data/test/command/update_project_command_test.rb +56 -0
  206. data/test/command/update_role_command_test.rb +42 -0
  207. data/test/command/update_rolepermissions_command_test.rb +54 -0
  208. data/test/command/update_solution_command_test.rb +58 -0
  209. data/test/command/update_user_command_test.rb +76 -0
  210. data/test/command/vote_deployment_command_test.rb +33 -0
  211. data/test/config_test.rb +70 -0
  212. data/test/successful_test.rb +21 -0
  213. data/test/test_files/pom.xml +273 -0
  214. data/test/test_helper.rb +25 -0
  215. metadata +470 -0
@@ -0,0 +1,32 @@
1
+ module EPC::Command
2
+ class LoginCommand < BaseCommand
3
+
4
+ dont_require_login
5
+
6
+ def execute(email = nil)
7
+ if blank?(email)
8
+ say("You must supply an email address")
9
+ return 1
10
+ end
11
+
12
+ password = options[:password]
13
+ password = ask("Password: ") { |q| q.echo = '*' } unless password
14
+
15
+ begin
16
+ status, response, headers = client.post("#{EPC::Config::TOKENS_PATH}/retrieve", { :email => email, :password => password }, true)
17
+ if status.successful? && response
18
+ EPC::Config.store_caller_id(response[:caller_id])
19
+ EPC::Config.store_auth_token(response[:authentication_token])
20
+ EPC::Config.store_username(email)
21
+ say("Successfully logged into [#{target_url}]")
22
+ elsif response
23
+ say("Login failed [#{response[:message]}]. Please make sure you entered the correct email and password.")
24
+ end
25
+ return status
26
+ rescue Exception => ex
27
+ say("Login failed [#{ex}].")
28
+ return 1
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,20 @@
1
+ module EPC::Command
2
+ class LogoutCommand < BaseCommand
3
+ def execute
4
+
5
+ begin
6
+ if EPC::Config.remove_auth_token
7
+ EPC::Config.remove_username
8
+ say("Successfully logged out of [#{target_url}]")
9
+ return 0
10
+ else
11
+ say("Logout failed [#{response[:message]}]. Please try again later.")
12
+ return 1
13
+ end
14
+ rescue Exception => ex
15
+ say("Logout failed [#{ex}].")
16
+ return 1
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ module EPC::Command
2
+ class CreateObjectroleCommand < BaseCommand
3
+ def execute(*params)
4
+ obj_type, obj_id = params[0].split(":") rescue [nil, nil]
5
+ name = params[1]
6
+
7
+ raise FatalError, "Parameters incorrectly specified" if obj_type.blank? || obj_id.blank? || name.blank?
8
+
9
+ status, response, headers = client.post(EPC::Config::ROLES_PATH, {:name => name, :owner_type => obj_type, :owner_id => obj_id})
10
+
11
+ if status.successful?
12
+ say("Role [#{name}] created")
13
+ else
14
+ say("Request failed: [#{response[:message]}]")
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,78 @@
1
+ module EPC::Command
2
+ class CreateProjectCommand < BaseCommand
3
+ def execute(*params)
4
+
5
+ target_type, target_id = params.first.split(":") rescue [nil, nil]
6
+ project_name = params[1]
7
+ uri_name = params[2]
8
+
9
+ raise FatalError, "You have to specify a project name to run this command" if project_name.blank?
10
+ raise InputError, "Target type must be: [Solution]" if target_type.present? && target_type.downcase != "solution"
11
+
12
+ if numeric?(@options[:type])
13
+ type_id = @options[:type].to_i
14
+ elsif @options[:type].present?
15
+ type_id = get_resource_id(EPC::Config::PROJECT_TYPES_PATH, :name, @options[:type], :case_sensitivity => false)
16
+ end
17
+
18
+ if type_id.blank? || type_id == 0
19
+ choose do |menu|
20
+ menu.prompt = "Please choose the project type: "
21
+
22
+ status, response, headers = client.get(EPC::Config::PROJECT_TYPES_PATH)
23
+ if status.failure?
24
+ say("Request failed: [#{response[:message]}")
25
+ return status
26
+ end
27
+
28
+ if response.empty?
29
+ say("No project types defined yet")
30
+ return status
31
+ end
32
+
33
+ response.each do |type|
34
+ menu.choice(type[:name]) { type_id = type[:id]}
35
+ end
36
+
37
+ end
38
+ end
39
+
40
+ path = File.expand_path(".")
41
+
42
+ solution_id, solution_name = infer_solution_context(target_id, path, :get_solution_name => true)
43
+
44
+ raise InputError, "Request failed: [Solution not found]" if solution_name.nil?
45
+
46
+ uri_name = project_name if uri_name.nil?
47
+
48
+ proceed = ask_yn("You are creating the '#{project_name}' project as part of the '#{solution_name}' solution. Correct? [Yn]: ")
49
+ if proceed.upcase == 'N'
50
+ return 1
51
+ end
52
+
53
+ begin
54
+ status, response, headers = client.post("#{EPC::Config::PROJECTS_PATH}",
55
+ { :project_name => project_name, :solution_name => solution_name, :uri_name => uri_name, :project_type_id => type_id})
56
+ if status.successful?
57
+ if options[:nodir]
58
+ say("Successfully created the project with [#{target_url}]")
59
+ return status
60
+ end
61
+ result = mkdir(project_name)
62
+ if result == :ok
63
+ EPC::Config.write_project_metadata(response[:id], client)
64
+ say("Successfully created the project with [#{target_url}] and created your local directory.")
65
+ else
66
+ say("Successfully created the project with [#{target_url}], but FAILED to create your local directory.")
67
+ end
68
+ else
69
+ say("Project creation failed [#{response[:message]}].")
70
+ end
71
+ rescue Exception => ex
72
+ say("Project creation failed [#{ex}].")
73
+ return 1
74
+ end
75
+ return status
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,209 @@
1
+ require 'rubygems'
2
+ require 'fileutils'
3
+ require 'zip/zipfilesystem'
4
+
5
+ module EPC::Command
6
+ class PullCommand < BaseCommand
7
+ SLEEP_TIME = 1
8
+
9
+ # Numerators are in secs
10
+ TICKER_TICKS = 25/SLEEP_TIME
11
+ GIVEUP_TICKS = 120/SLEEP_TIME
12
+
13
+ def execute(solution_name = nil)
14
+ first_time_pull = false
15
+
16
+ path = File.expand_path(".")
17
+ create_dir = false
18
+
19
+ if numeric?(solution_name)
20
+ solution_name = get_resource_name(EPC::Config::SOLUTIONS_PATH, :id, solution_name)
21
+ end
22
+
23
+ if !EPC::Config.is_solution_dir?(path) && !EPC::Config.is_project_dir?(path)
24
+ if solution_name.nil?
25
+ raise FatalError, "Solution could not be inferred"
26
+ else
27
+ create_dir = true
28
+ first_time_pull = true
29
+ end
30
+ elsif EPC::Config.is_project_dir?(path)
31
+ path = File.join(path, "..")
32
+ end
33
+
34
+ return unless check_pull_directory(project_solution_path(path))
35
+
36
+ solution_name = EPC::Config.get_solution_value(project_solution_path(path), "name") if solution_name.nil?
37
+
38
+ proceed = ask_yn("You are pulling the '#{solution_name}' solution. Correct? [Yn]: ")
39
+ if proceed.upcase == 'N'
40
+ return 1
41
+ end
42
+
43
+
44
+ begin
45
+ status, id = create_pull(solution_name)
46
+ if status.successful?
47
+ say("Pulling - ")
48
+ shown, url = poll_for_pull_url(id)
49
+ if shown
50
+ tmpdir = Dir.tmpdir
51
+ pulled, zip_path = pull_zip(url, tmpdir)
52
+ if pulled
53
+ if create_dir
54
+ return 1 unless prep_solution_directory(path, solution_name)
55
+ path = File.join(path, solution_name)
56
+ end
57
+ unzip_solution(zip_path, path)
58
+ confirm_pull(id)
59
+ refresh_command = EPC::Command::RefreshSolutionCommand.new(client, @options)
60
+ refresh_command.options[:prompt_refresh] = false if first_time_pull
61
+ refresh_command.execute(path)
62
+ return 0
63
+ end
64
+ end
65
+ end
66
+ rescue Exception => ex
67
+ say("Pull failed [#{ex.to_s}].")
68
+ end
69
+ return 1
70
+ end
71
+
72
+ private
73
+
74
+ def create_pull(solution_name)
75
+ status, response, headers = client.post("#{EPC::Config::PULLS_PATH}", { :solution_name => solution_name })
76
+ if status.successful?
77
+ say("Successfully created a pull with [#{target_url}]")
78
+ return status, response[:id]
79
+ else
80
+ raise Exception, response[:message]
81
+ return status
82
+ end
83
+ end
84
+
85
+ def confirm_pull(id)
86
+ status, response, headers = client.put("#{EPC::Config::PULLS_PATH}/#{id}/confirm", { :pulled => 'yes' })
87
+ if status.successful?
88
+ say("Successfully confirmed the pull with [#{target_url}]")
89
+ true
90
+ else
91
+ say("Pull confirmation failed [#{response[:message]}].")
92
+ false
93
+ end
94
+ end
95
+
96
+ def sign_pull(id)
97
+ status, response, headers = client.put("#{EPC::Config::PULLS_PATH}/#{id}/sign")
98
+ if status.successful?
99
+ return status, nil, response[:signed_url]
100
+ else
101
+ return status, response[:error_code], nil
102
+ end
103
+ end
104
+
105
+ def prep_solution_directory(path, solution_name)
106
+ solution_id = get_resource_id(EPC::Config::SOLUTIONS_PATH, :name, solution_name)
107
+ if solution_id.nil?
108
+ say("Solution not found")
109
+ return false
110
+ end
111
+
112
+ begin
113
+ Dir.mkdir(File.join(path, solution_name))
114
+ rescue Exception => ex
115
+ say(ex.to_s)
116
+ return false
117
+ end
118
+
119
+ begin
120
+ File.open(File.join(path, solution_name, ".epc_solution"), 'w') do |f|
121
+ f.write({:id => solution_id, :name => solution_name}.to_json)
122
+ end
123
+ rescue Exception => ex
124
+ say(ex.to_s)
125
+ return false
126
+ end
127
+ return true
128
+ end
129
+
130
+ def poll_for_pull_url(id)
131
+ count = 0
132
+ failed = false
133
+
134
+ while count <= GIVEUP_TICKS
135
+ unless count > TICKER_TICKS
136
+ STDOUT.print('.')
137
+ STDOUT.flush
138
+ end
139
+ sleep(SLEEP_TIME)
140
+
141
+ status, code, url = sign_pull(id)
142
+ if status.successful? || (status == 404 && code == 801)
143
+ count += 1
144
+ next if url.nil? || url.empty?
145
+ break
146
+ else
147
+ say("Poller failed to get the pull URL. Aborting.")
148
+ failed = true
149
+ break
150
+ end
151
+ end
152
+
153
+
154
+ if url
155
+ [true, url]
156
+ elsif failed
157
+ [false, nil]
158
+ else
159
+ if count > GIVEUP_TICKS
160
+ say("\nServer is taking too long to update the pull URL. Please contact the AgileMethods support team.")
161
+ end
162
+ [false, nil]
163
+ end
164
+ end
165
+
166
+ def check_pull_directory(path)
167
+ unless File.exists?(path)
168
+ say("Pull path does not exist")
169
+ return false
170
+ end
171
+
172
+ unless File.directory?(path)
173
+ say("Pull path is not a directory")
174
+ return false
175
+ end
176
+ return true
177
+ end
178
+
179
+ def pull_zip(url, path)
180
+ status, response, headers = http_client.get(url)
181
+ if status.successful?
182
+ say("Successfully pulled the zip file from the build repository")
183
+
184
+ zip_path = File.join(path, "pulled#{rand(9999)}.zip")
185
+ open(zip_path, "wb") { |io| io.write(response) }
186
+ [true, zip_path]
187
+ else
188
+ say("Failed to pull the zip file from the build repository [status = #{status}]. Aborting pull command.")
189
+ [false, nil]
190
+ end
191
+ end
192
+
193
+ def unzip_solution(zip_path, solution_path)
194
+ Zip::ZipFile.foreach(zip_path) do |entry|
195
+ file_path = File.join(solution_path, entry.to_s)
196
+ FileUtils.mkdir_p File.dirname(file_path)
197
+ if entry.file?
198
+ FileUtils.rm(file_path) if File.exists?(file_path)
199
+ entry.extract(file_path)
200
+ end
201
+ end
202
+
203
+ say("Solution skeleton has been extracted to #{solution_path}")
204
+
205
+ ensure File.delete zip_path if File.exists? zip_path
206
+ end
207
+
208
+ end
209
+ end
@@ -0,0 +1,194 @@
1
+ require 'rubygems'
2
+ require 'digest/sha1'
3
+ require 'fileutils'
4
+ require 'find'
5
+ require 'pathname'
6
+ require 'zip/zipfilesystem'
7
+
8
+ module EPC::Command
9
+ class PushCommand < BaseCommand
10
+ ZIP_DIR_EXCLUDES = %w(target)
11
+ ZIP_FILE_EXCLUDES = %w(pom.xml)
12
+ ZIP_EXT_EXCLUDES = ['.class', '.jar']
13
+
14
+ def execute(project_name = nil)
15
+ path = "."
16
+ path = File.expand_path(path)
17
+
18
+
19
+ if @options[:no_poll].present? && @options[:timeout].present?
20
+ raise InputError, "You cannot specify both --nopoll and --timeout options at the same time"
21
+ end
22
+
23
+ @timeout = GIVEUP_TICKS
24
+ parse_timeout_value
25
+
26
+ solution_id, solution_name = infer_solution_context(nil, path)
27
+
28
+ raise FatalError, "Solution could not be inferred" if solution_id.nil?
29
+
30
+ if EPC::Config.is_solution_dir?(path)
31
+ if project_name.nil?
32
+ proceed = ask_yn("You are pushing the [#{solution_name}] solution. Correct: [Yn]? ")
33
+ paths = Dir.glob(path +"/*/").select{|dir| EPC::Config.is_project_dir?(dir)}
34
+ else
35
+ project_id, p_name = infer_project_context(project_name, path, solution_id, {:get_project_name => true})
36
+ raise FatalError, "Project not found. Please run this command with the correct project name." if !project_name.nil? && (p_name.nil? || p_name.empty?)
37
+ proceed = ask_yn("You are pushing the [#{p_name}] project belonging to the [#{solution_name}] solution. Correct: [Yn]? ")
38
+ paths = [path + "/#{project_name}"]
39
+ end
40
+ elsif EPC::Config.is_project_dir?(path)
41
+ project_id, project_name = infer_project_context(p_name, path, solution_id, false)
42
+ raise FatalError if project_id.nil?
43
+ proceed = ask_yn("You are pushing the [#{project_name}] project belonging to the [#{solution_name}] solution. Correct: [Yn]? ")
44
+ paths = [path]
45
+ else
46
+ say("This command must be run from a solution/project directory")
47
+ return 1
48
+ end
49
+
50
+ if (proceed.upcase == "N" rescue true )
51
+ return 1
52
+ end
53
+
54
+ raise FatalError, "Nothing to push" if paths.empty?
55
+
56
+ @versions = []
57
+ paths.each do |path|
58
+ project_id, project_name = infer_project_context(nil, path, solution_id, {:get_project_name => true})
59
+ say("\nPushing #{project_name}...")
60
+ begin
61
+ zip_path = zip_source(path)
62
+ return 1 unless zip_path
63
+ sha1 = sha1(zip_path)
64
+ status, url, signature, id = create_push(project_name, solution_name, sha1, @options[:note])
65
+ if status.successful?
66
+ pushed = push_zip(zip_path, url, signature)
67
+ resp = confirm_push(id)
68
+ if resp[:build_id].present? && !@options[:skip_build]
69
+ poll_for_build_status(resp[:build_id]) unless @options[:no_poll].present?
70
+ end
71
+ @versions << {project_name => resp[:project_version]} if pushed
72
+ else
73
+ return 1
74
+ end
75
+ rescue Exception => ex
76
+ say("Push failed [#{ex}].")
77
+ return 1
78
+ end
79
+ end
80
+ return 0
81
+ end
82
+
83
+ def execute_internal
84
+ code = execute
85
+ return code, @versions
86
+ end
87
+
88
+ private
89
+
90
+ def create_push(project_name, solution_name, sha1, note = nil)
91
+ status, response, headers = client.post("#{EPC::Config::PUSHES_PATH}",
92
+ { :project_name => project_name, :solution_name => solution_name, :sha1 => sha1, :note => note})
93
+ if status.successful?
94
+ say("Successfully created a push with [#{target_url}]")
95
+ return status, response[:url], response[:signature], response[:id]
96
+ else
97
+ raise BasicError, "Push creation failed [#{response[:message]}]. Aborting push command."
98
+ end
99
+ end
100
+
101
+ def confirm_push(id)
102
+ status, response, headers = client.put("#{EPC::Config::PUSHES_PATH}/#{id}/confirm", { :pushed => 'yes' })
103
+ if status.successful?
104
+ say("Successfully confirmed the push with [#{target_url}]")
105
+ response
106
+ else
107
+ say("Push confirmation failed [#{response[:message]}].")
108
+ nil
109
+ end
110
+ end
111
+
112
+ def zip_source(path)
113
+ if check_push_directory(path)
114
+ tmpdir = Dir.tmpdir
115
+ zip_path = File.join(tmpdir, "#{rand(9999)}pushed.zip")
116
+ FileUtils.rm_f(zip_path) if File.exists?(zip_path)
117
+ Zip::ZipFile.open(zip_path, Zip::ZipFile::CREATE) { |zf|
118
+ full_paths, relative_paths = recurse_project_directory(path)
119
+ full_paths.each_index do |i|
120
+ zf.add(relative_paths[i], full_paths[i])
121
+ end
122
+ }
123
+ end
124
+
125
+ zip_path
126
+ end
127
+
128
+ def recurse_project_directory(projdir)
129
+ full_paths = Array.new
130
+ relative_paths = Array.new
131
+ toplevel = Pathname(projdir)
132
+
133
+
134
+ Find.find(projdir) { |path|
135
+ if File.directory?(path)
136
+ if ZIP_DIR_EXCLUDES.include?(File.basename(path.downcase))
137
+ Find.prune # skip this dir
138
+ else
139
+ full_paths << path
140
+
141
+ current = Pathname.new(path)
142
+ relative_paths << current.relative_path_from(toplevel)
143
+ end
144
+ else
145
+ current = Pathname.new(path)
146
+ relative_path = current.relative_path_from(toplevel)
147
+
148
+ unless ZIP_FILE_EXCLUDES.include?(File.basename(relative_path.to_s.downcase)) ||
149
+ (ZIP_EXT_EXCLUDES.include?(File.extname(relative_path.to_s.downcase)) && relative_path.to_s !~ /^lib/)
150
+ full_paths << path
151
+ relative_paths << relative_path.to_s
152
+ end
153
+ end
154
+ }
155
+
156
+ return full_paths, relative_paths
157
+ end
158
+
159
+ def push_zip(zip_path, url, signature)
160
+ # create API returns a URL that includes protocol://host/solution_name/project_name/version
161
+
162
+ status, response, headers = http_client.post(url,
163
+ { :file => File.new(zip_path, "rb") }, nil, { 'X-AGILEMETHODS-SIGNATURE' => signature }, true)
164
+ if status.successful?
165
+ say("Successfully pushed the zip file to the build area")
166
+ true
167
+ else
168
+ raise BasicError, "Failed to push the zip file to the build area [status = #{status}]. Aborting push command."
169
+ end
170
+
171
+ ensure File.delete zip_path if File.exists? zip_path
172
+ end
173
+
174
+ def check_push_directory(path)
175
+ project_type = EPC::Config.get_project_value(path, "project_type")["name"] rescue ""
176
+ unless File.exists?(path)
177
+ say("#{path} does not exist")
178
+ return false
179
+ end
180
+
181
+ unless File.directory?(path)
182
+ say("#{path} is not a directory")
183
+ return false
184
+ end
185
+
186
+ if project_type == "Java Web Archive" || project_type == "Java Library"
187
+ src_path = File.join(path, "src")
188
+ raise BasicError, "#{path} does not include a src directory" if !File.exists?(src_path) && !File.directory?(src_path)
189
+ end
190
+
191
+ return true
192
+ end
193
+ end
194
+ end