gooddata 0.6.0 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (208) hide show
  1. checksums.yaml +13 -5
  2. data/.rubocop.yml +23 -0
  3. data/.travis.yml +9 -4
  4. data/CLI.md +439 -0
  5. data/Gemfile +0 -1
  6. data/README.md +2 -2
  7. data/Rakefile +60 -8
  8. data/doc/templates/default/module/setup.rb +1 -1
  9. data/examples.rb +2 -0
  10. data/gooddata +2 -0
  11. data/gooddata.gemspec +12 -8
  12. data/lib/gooddata.rb +0 -2
  13. data/lib/gooddata/bricks/base_downloader.rb +52 -47
  14. data/lib/gooddata/bricks/brick.rb +20 -31
  15. data/lib/gooddata/bricks/bricks.rb +1 -1
  16. data/lib/gooddata/bricks/middleware/base_middleware.rb +9 -7
  17. data/lib/gooddata/bricks/middleware/bench_middleware.rb +12 -10
  18. data/lib/gooddata/bricks/middleware/bulk_salesforce_middleware.rb +28 -28
  19. data/lib/gooddata/bricks/middleware/fs_upload_middleware.rb +20 -16
  20. data/lib/gooddata/bricks/middleware/gooddata_middleware.rb +21 -19
  21. data/lib/gooddata/bricks/middleware/logger_middleware.rb +10 -8
  22. data/lib/gooddata/bricks/middleware/restforce_middleware.rb +36 -34
  23. data/lib/gooddata/bricks/middleware/stdout_middleware.rb +11 -9
  24. data/lib/gooddata/bricks/middleware/twitter_middleware.rb +14 -12
  25. data/lib/gooddata/bricks/pipeline.rb +28 -0
  26. data/lib/gooddata/bricks/utils.rb +10 -8
  27. data/lib/gooddata/cli/cli.rb +1 -6
  28. data/lib/gooddata/cli/commands/auth_cmd.rb +1 -1
  29. data/lib/gooddata/cli/commands/console_cmd.rb +7 -5
  30. data/lib/gooddata/cli/commands/domain_cmd.rb +45 -0
  31. data/lib/gooddata/cli/commands/process_cmd.rb +42 -5
  32. data/lib/gooddata/cli/commands/project_cmd.rb +96 -36
  33. data/lib/gooddata/cli/commands/projects_cmd.rb +21 -0
  34. data/lib/gooddata/cli/commands/role_cmd.rb +28 -0
  35. data/lib/gooddata/cli/commands/run_ruby_cmd.rb +5 -5
  36. data/lib/gooddata/cli/commands/scaffold_cmd.rb +1 -1
  37. data/lib/gooddata/cli/commands/{profile_cmd.rb → user_cmd.rb} +7 -9
  38. data/lib/gooddata/cli/shared.rb +3 -2
  39. data/lib/gooddata/client.rb +16 -304
  40. data/lib/gooddata/commands/api.rb +13 -5
  41. data/lib/gooddata/commands/auth.rb +47 -40
  42. data/lib/gooddata/commands/base.rb +4 -2
  43. data/lib/gooddata/commands/commands.rb +1 -1
  44. data/lib/gooddata/commands/datasets.rb +20 -7
  45. data/lib/gooddata/commands/domain.rb +23 -0
  46. data/lib/gooddata/commands/process.rb +23 -117
  47. data/lib/gooddata/commands/project.rb +147 -0
  48. data/lib/gooddata/commands/projects.rb +8 -102
  49. data/lib/gooddata/commands/role.rb +26 -0
  50. data/lib/gooddata/commands/runners.rb +41 -38
  51. data/lib/gooddata/commands/scaffold.rb +46 -43
  52. data/lib/gooddata/commands/user.rb +33 -0
  53. data/lib/gooddata/connection.rb +43 -353
  54. data/lib/gooddata/core/connection.rb +389 -0
  55. data/lib/gooddata/core/core.rb +5 -4
  56. data/lib/gooddata/core/logging.rb +48 -0
  57. data/lib/gooddata/core/nil_logger.rb +13 -0
  58. data/lib/gooddata/core/project.rb +70 -0
  59. data/lib/gooddata/core/rest.rb +120 -0
  60. data/lib/gooddata/core/threaded.rb +14 -0
  61. data/lib/gooddata/core/user.rb +19 -0
  62. data/lib/gooddata/data/data.rb +2 -1
  63. data/lib/gooddata/data/guesser.rb +16 -12
  64. data/lib/gooddata/exceptions/command_failed.rb +1 -1
  65. data/lib/gooddata/exceptions/exceptions.rb +2 -1
  66. data/lib/gooddata/exceptions/no_project_error.rb +11 -0
  67. data/lib/gooddata/exceptions/project_not_found.rb +1 -1
  68. data/lib/gooddata/extensions/big_decimal.rb +6 -2
  69. data/lib/gooddata/extract.rb +10 -8
  70. data/lib/gooddata/goodzilla/goodzilla.rb +61 -59
  71. data/lib/gooddata/helpers.rb +15 -9
  72. data/lib/gooddata/models/account_settings.rb +124 -0
  73. data/lib/gooddata/models/attributes/anchor.rb +37 -0
  74. data/lib/gooddata/models/attributes/attributes.rb +8 -0
  75. data/lib/gooddata/models/attributes/date_attribute.rb +25 -0
  76. data/lib/gooddata/models/attributes/time_attribute.rb +24 -0
  77. data/lib/gooddata/models/columns/attribute.rb +71 -0
  78. data/lib/gooddata/models/columns/columns.rb +8 -0
  79. data/lib/gooddata/models/columns/date_column.rb +63 -0
  80. data/lib/gooddata/models/columns/fact_model.rb +54 -0
  81. data/lib/gooddata/models/columns/label.rb +55 -0
  82. data/lib/gooddata/models/columns/reference.rb +57 -0
  83. data/lib/gooddata/models/dashboard_builder.rb +26 -0
  84. data/lib/gooddata/models/data_result.rb +10 -9
  85. data/lib/gooddata/models/domain.rb +131 -0
  86. data/lib/gooddata/models/empty_result.rb +5 -8
  87. data/lib/gooddata/models/facts/facts.rb +8 -0
  88. data/lib/gooddata/models/facts/time_fact.rb +20 -0
  89. data/lib/gooddata/models/folders/attribute_folder.rb +20 -0
  90. data/lib/gooddata/models/folders/fact_folder.rb +20 -0
  91. data/lib/gooddata/models/folders/folders.rb +8 -0
  92. data/lib/gooddata/models/invitation.rb +78 -0
  93. data/lib/gooddata/models/links.rb +6 -6
  94. data/lib/gooddata/models/md_object.rb +25 -0
  95. data/lib/gooddata/models/metadata.rb +160 -62
  96. data/lib/gooddata/models/metadata/attribute.rb +81 -0
  97. data/lib/gooddata/models/metadata/column.rb +61 -0
  98. data/lib/gooddata/models/{dashboard.rb → metadata/dashboard.rb} +12 -7
  99. data/lib/gooddata/models/{data_set.rb → metadata/data_set.rb} +5 -4
  100. data/lib/gooddata/models/metadata/date_dimension.rb +26 -0
  101. data/lib/gooddata/models/metadata/display_form.rb +61 -0
  102. data/lib/gooddata/models/metadata/fact.rb +36 -0
  103. data/lib/gooddata/models/metadata/folder.rb +24 -0
  104. data/lib/gooddata/models/metadata/metadata.rb +8 -0
  105. data/lib/gooddata/models/metadata/metric.rb +197 -0
  106. data/lib/gooddata/models/metadata/report.rb +115 -0
  107. data/lib/gooddata/models/{report_definition.rb → metadata/report_definition.rb} +16 -10
  108. data/lib/gooddata/models/metadata/schema.rb +227 -0
  109. data/lib/gooddata/models/model.rb +38 -1339
  110. data/lib/gooddata/models/models.rb +5 -2
  111. data/lib/gooddata/models/module_constants.rb +29 -0
  112. data/lib/gooddata/models/process.rb +142 -13
  113. data/lib/gooddata/models/profile.rb +4 -6
  114. data/lib/gooddata/models/project.rb +406 -136
  115. data/lib/gooddata/models/project_blueprint.rb +221 -0
  116. data/lib/gooddata/models/project_builder.rb +136 -0
  117. data/lib/gooddata/models/project_creator.rb +138 -0
  118. data/lib/gooddata/models/project_metadata.rb +11 -10
  119. data/lib/gooddata/models/project_role.rb +92 -0
  120. data/lib/gooddata/models/references/date_reference.rb +44 -0
  121. data/lib/gooddata/models/references/references.rb +8 -0
  122. data/lib/gooddata/models/references/time_reference.rb +13 -0
  123. data/lib/gooddata/models/report_data_result.rb +11 -11
  124. data/lib/gooddata/models/schedule.rb +284 -0
  125. data/lib/gooddata/models/schema_blueprint.rb +158 -0
  126. data/lib/gooddata/models/schema_builder.rb +81 -0
  127. data/lib/gooddata/models/tab_builder.rb +23 -0
  128. data/lib/gooddata/models/user.rb +165 -0
  129. data/lib/gooddata/version.rb +1 -1
  130. data/lib/templates/project/data/devs.csv +1 -1
  131. data/lib/templates/project/data/repos.csv +1 -1
  132. data/lib/templates/project/model/model.rb.erb +7 -11
  133. data/spec/bricks/bricks_spec.rb +2 -0
  134. data/spec/data/test-ci-data.csv +2 -0
  135. data/spec/data/test_project_model_spec.json +7 -27
  136. data/spec/helpers/blueprint_helper.rb +2 -0
  137. data/spec/helpers/cli_helper.rb +2 -0
  138. data/spec/helpers/connection_helper.rb +14 -1
  139. data/spec/helpers/project_helper.rb +16 -0
  140. data/spec/helpers/schema_helper.rb +16 -0
  141. data/spec/integration/command_projects_spec.rb +7 -7
  142. data/spec/integration/create_from_template_spec.rb +2 -2
  143. data/spec/integration/full_project_spec.rb +160 -7
  144. data/spec/integration/partial_md_export_import_spec.rb +3 -3
  145. data/spec/logging_in_logging_out_spec.rb +2 -1
  146. data/spec/spec_helper.rb +26 -4
  147. data/spec/unit/bricks/bricks_spec.rb +15 -7
  148. data/spec/unit/bricks/middleware/bench_middleware_spec.rb +2 -0
  149. data/spec/unit/bricks/middleware/bulk_salesforce_middleware_spec.rb +2 -0
  150. data/spec/unit/bricks/middleware/gooddata_middleware_spec.rb +2 -0
  151. data/spec/unit/bricks/middleware/logger_middleware_spec.rb +2 -0
  152. data/spec/unit/bricks/middleware/restforce_middleware_spec.rb +2 -0
  153. data/spec/unit/bricks/middleware/stdout_middleware_spec.rb +2 -0
  154. data/spec/unit/bricks/middleware/twitter_middleware_spec.rb +2 -0
  155. data/spec/unit/cli/cli_spec.rb +2 -0
  156. data/spec/unit/cli/commands/cmd_api_spec.rb +23 -15
  157. data/spec/unit/cli/commands/cmd_auth_spec.rb +8 -4
  158. data/spec/unit/cli/commands/cmd_domain_spec.rb +82 -0
  159. data/spec/unit/cli/commands/cmd_process_spec.rb +29 -13
  160. data/spec/unit/cli/commands/cmd_project_spec.rb +51 -30
  161. data/spec/unit/cli/commands/cmd_role_spec.rb +44 -0
  162. data/spec/unit/cli/commands/cmd_run_ruby_spec.rb +8 -4
  163. data/spec/unit/cli/commands/cmd_scaffold_spec.rb +48 -11
  164. data/spec/unit/cli/commands/cmd_user_spec.rb +29 -0
  165. data/spec/unit/commands/command_api_spec.rb +1 -1
  166. data/spec/unit/commands/command_auth_spec.rb +100 -18
  167. data/spec/unit/commands/command_dataset_spec.rb +4 -0
  168. data/spec/unit/commands/command_process_spec.rb +9 -4
  169. data/spec/unit/commands/command_projects_spec.rb +10 -6
  170. data/spec/unit/commands/command_scaffold_spec.rb +5 -1
  171. data/spec/unit/commands/command_user_spec.rb +22 -0
  172. data/spec/unit/core/connection_spec.rb +35 -6
  173. data/spec/unit/core/logging_spec.rb +65 -0
  174. data/spec/unit/core/nil_logger_spec.rb +9 -0
  175. data/spec/unit/core/project_spec.rb +51 -0
  176. data/spec/unit/core/rest_spec.rb +33 -0
  177. data/spec/unit/data/guesser_spec.rb +5 -0
  178. data/spec/unit/godzilla/goodzilla_spec.rb +2 -0
  179. data/spec/unit/models/account_settings_spec.rb +28 -0
  180. data/spec/unit/models/anchor_spec.rb +32 -0
  181. data/spec/unit/models/attribute_column_spec.rb +7 -0
  182. data/spec/unit/models/domain_spec.rb +45 -0
  183. data/spec/unit/models/invitation_spec.rb +13 -0
  184. data/spec/unit/models/md_object_spec.rb +47 -0
  185. data/spec/unit/models/metric.rb +92 -0
  186. data/spec/unit/{model → models}/model_spec.rb +9 -7
  187. data/spec/unit/models/project_blueprint_spec.rb +202 -0
  188. data/spec/unit/models/project_creator.rb +73 -0
  189. data/spec/unit/models/project_role_spec.rb +90 -0
  190. data/spec/unit/models/project_spec.rb +143 -0
  191. data/spec/unit/models/schedule_spec.rb +491 -0
  192. data/spec/unit/{model → models}/schema_builder_spec.rb +2 -0
  193. data/spec/unit/{model → models}/tools_spec.rb +13 -7
  194. data/spec/unit/models/user_spec.rb +16 -0
  195. data/test/test_upload.rb +2 -0
  196. metadata +189 -86
  197. data/lib/gooddata/commands/profile.rb +0 -11
  198. data/lib/gooddata/models/attribute.rb +0 -29
  199. data/lib/gooddata/models/display_form.rb +0 -9
  200. data/lib/gooddata/models/fact.rb +0 -19
  201. data/lib/gooddata/models/metric.rb +0 -99
  202. data/lib/gooddata/models/report.rb +0 -89
  203. data/spec/data/blueprint_valid.json +0 -37
  204. data/spec/unit/cli/commands/cmd_profile_spec.rb +0 -16
  205. data/spec/unit/commands/command_profile_spec.rb +0 -18
  206. data/spec/unit/core/core_spec.rb +0 -7
  207. data/spec/unit/model/blueprint_spec.rb +0 -132
  208. data/spec/unit/model/project_blueprint_spec.rb +0 -44
@@ -34,19 +34,27 @@ module GoodData
34
34
  # Get resource
35
35
  # @param path Resource path
36
36
  def get(path)
37
- raise(GoodData::CommandFailed, 'Specify the path you want to GET.') if path.nil?
37
+ fail(GoodData::CommandFailed, 'Specify the path you want to GET.') if path.nil?
38
38
  result = GoodData.get path
39
- result rescue puts result
39
+ begin
40
+ result
41
+ rescue
42
+ puts result
43
+ end
40
44
  end
41
45
 
42
46
  # Delete resource
43
47
  # @param path Resource path
44
48
  def delete(path)
45
- raise(GoodData::CommandFailed, 'Specify the path you want to DELETE.') if path.nil?
49
+ fail(GoodData::CommandFailed, 'Specify the path you want to DELETE.') if path.nil?
46
50
  result = GoodData.delete path
47
- result rescue puts result
51
+ begin
52
+ result
53
+ rescue
54
+ puts result
55
+ end
48
56
  end
49
57
  end
50
58
  end
51
59
  end
52
- end
60
+ end
@@ -6,57 +6,64 @@ require 'multi_json'
6
6
  require_relative '../cli/terminal'
7
7
  require_relative '../helpers'
8
8
 
9
- module GoodData::Command
10
- class Auth
11
- class << self
9
+ module GoodData
10
+ module Command
11
+ class Auth
12
+ class << self
13
+ # Get path of .gooddata config
14
+ def credentials_file
15
+ "#{GoodData::Helpers.home_directory}/.gooddata"
16
+ end
12
17
 
13
- # Get path of .gooddata config
14
- def credentials_file
15
- "#{GoodData::Helpers.home_directory}/.gooddata"
16
- end
18
+ # Ask for credentials
19
+ def ask_for_credentials
20
+ puts 'Enter your GoodData credentials.'
21
+ user = GoodData::CLI.terminal.ask('Email')
22
+ password = GoodData::CLI.terminal.ask('Password') { |q| q.echo = 'x' }
23
+ auth_token = GoodData::CLI.terminal.ask('Authorization Token')
17
24
 
18
- # Ask for credentials
19
- def ask_for_credentials
20
- puts 'Enter your GoodData credentials.'
21
- user = GoodData::CLI.terminal.ask('Email')
22
- password = GoodData::CLI.terminal.ask('Password') { |q| q.echo = 'x' }
23
- auth_token = GoodData::CLI.terminal.ask('Authorization Token')
25
+ { :username => user, :password => password, :auth_token => auth_token }
26
+ end
24
27
 
25
- {:username => user, :password => password, :auth_token => auth_token}
26
- end
28
+ # Read credentials
29
+ def read_credentials(credentials_file_path = credentials_file)
30
+ if File.exist?(credentials_file_path)
31
+ config = File.read(credentials_file_path)
32
+ MultiJson.load(config, :symbolize_keys => true)
33
+ else
34
+ {}
35
+ end
36
+ end
27
37
 
28
- # Read credentials
29
- def read_credentials
30
- if File.exists?(credentials_file) then
31
- config = File.read(credentials_file)
32
- JSON.parser.new(config, :symbolize_names => true).parse
33
- else
34
- {}
38
+ # Writes credentials
39
+ def write_credentials(credentials, credentials_file_path = credentials_file)
40
+ File.open(credentials_file_path, 'w', 0600) do |f|
41
+ f.puts MultiJson.encode(credentials, :pretty => true)
42
+ end
43
+ credentials
35
44
  end
36
- end
37
45
 
38
- # Ask for credentials and store them
39
- def store
40
- credentials = ask_for_credentials
46
+ # Ask for credentials and store them
47
+ def store(credentials_file_path = credentials_file)
48
+ credentials = ask_for_credentials
41
49
 
42
- ovewrite = if File.exist?(credentials_file)
43
- GoodData::CLI.terminal.ask("Overwrite existing stored credentials (y/n)")
44
- else
45
- 'y'
46
- end
50
+ ovewrite = if File.exist?(credentials_file_path)
51
+ GoodData::CLI.terminal.ask('Overwrite existing stored credentials (y/n)')
52
+ else
53
+ 'y'
54
+ end
47
55
 
48
- if ovewrite == 'y'
49
- File.open(credentials_file, 'w', 0600) do |f|
50
- f.puts JSON.pretty_generate(credentials)
56
+ if ovewrite == 'y'
57
+ write_credentials(credentials, credentials_file_path)
58
+ else
59
+ puts 'Aborting...'
51
60
  end
52
- else
53
- puts 'Aborting...'
54
61
  end
55
- end
56
62
 
57
- # Delete stored credentials
58
- def unstore
59
- FileUtils.rm_f(credentials_file)
63
+ # Delete stored credentials
64
+ def unstore(credentials_file_path = credentials_file)
65
+ FileUtils.rm_f(credentials_file_path)
66
+ end
60
67
  end
61
68
  end
62
69
  end
@@ -1,6 +1,8 @@
1
1
  # encoding: UTF-8
2
2
 
3
- module GoodData::Command
4
- class Base
3
+ module GoodData
4
+ module Command
5
+ class Base
6
+ end
5
7
  end
6
8
  end
@@ -4,4 +4,4 @@ require 'pathname'
4
4
  base = Pathname(__FILE__).dirname.expand_path
5
5
  Dir.glob(base + '*.rb').each do |file|
6
6
  require file
7
- end
7
+ end
@@ -65,9 +65,18 @@ module GoodData
65
65
  # TODO: Review following connect replacement/reimplementation
66
66
  # connect
67
67
  with_project do |project_id|
68
- cfg_file = args.shift rescue nil
69
- raise(CommandFailed, "Usage: #{$0} <dataset config>") unless cfg_file
70
- config = JSON.load open(cfg_file) rescue raise(CommandFailed, "Error reading dataset config file '#{cfg_file}'")
68
+ begin
69
+ cfg_file = args.shift
70
+ rescue
71
+ raise(CommandFailed, 'Invalid arguments')
72
+ end
73
+
74
+ fail(CommandFailed, "Usage: #{$PROGRAM_NAME} <dataset config>") unless cfg_file
75
+ config = begin
76
+ JSON.load open(cfg_file)
77
+ rescue
78
+ raise(CommandFailed, "Error reading dataset config file '#{cfg_file}'")
79
+ end
71
80
  objects = Project[project_id].add_dataset config['title'], config['columns']
72
81
  puts "Dataset #{config['title']} added to the project, #{objects['uris'].length} metadata objects affected"
73
82
  end
@@ -88,8 +97,12 @@ module GoodData
88
97
  # connect
89
98
  with_project do |project_id|
90
99
  file, cfg_file = args
91
- raise(CommandFailed, "Usage: #{$0} datasets:load <file> <dataset config>") unless cfg_file
92
- config = JSON.load open(cfg_file) rescue raise(CommandFailed, "Error reading dataset config file '#{cfg_file}'")
100
+ fail(CommandFailed, "Usage: #{$PROGRAM_NAME} datasets:load <file> <dataset config>") unless cfg_file
101
+ begin
102
+ config = JSON.load open(cfg_file)
103
+ rescue
104
+ raise(CommandFailed, "Error reading dataset config file '#{cfg_file}'")
105
+ end
93
106
  schema = Model::Schema.new config
94
107
  Project[project_id].upload file, schema
95
108
  end
@@ -100,7 +113,7 @@ module GoodData
100
113
  def with_project
101
114
  unless @project_id
102
115
  @project_id = extract_option('--project')
103
- raise CommandFailed.new('Project not specified, use the --project switch') unless @project_id
116
+ fail(CommandFailed, 'Project not specified, use the --project switch') unless @project_id
104
117
  end
105
118
  yield @project_id
106
119
  end
@@ -124,7 +137,7 @@ module GoodData
124
137
  def create_dataset
125
138
  file = extract_option('--file-csv')
126
139
  return Extract::CsvFile.new(file) if file
127
- raise CommandFailed.new('Unknown data set. Please specify a data set using --file-csv option (more supported data sources to come!)')
140
+ fail(CommandFailed, 'Unknown data set. Please specify a data set using --file-csv option (more supported data sources to come!)')
128
141
  end
129
142
  end
130
143
  end
@@ -0,0 +1,23 @@
1
+ # encoding: UTF-8
2
+
3
+ require_relative '../exceptions/command_failed'
4
+ require_relative '../models/domain'
5
+
6
+ module GoodData
7
+ module Command
8
+ # Low level access to GoodData API
9
+ class Domain
10
+ attr_reader :name
11
+
12
+ class << self
13
+ def add_user(domain, login, password)
14
+ GoodData::Domain.add_user(domain, login, password)
15
+ end
16
+
17
+ def list_users(domain)
18
+ GoodData::Domain.users(domain)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,16 +1,20 @@
1
1
  # encoding: UTF-8
2
2
 
3
+ require 'pathname'
4
+
5
+ require_relative '../core/core'
6
+
3
7
  module GoodData
4
8
  module Command
5
9
  class Process
6
10
  class << self
7
- def list(options={})
11
+ def list(options = {})
8
12
  GoodData.with_project(options[:project_id]) do
9
- processes = GoodData::Process[:all]
13
+ GoodData::Process[:all]
10
14
  end
11
15
  end
12
16
 
13
- def get(options={})
17
+ def get(options = {})
14
18
  id = options[:process_id]
15
19
  fail 'Unspecified process id' if id.nil?
16
20
 
@@ -19,137 +23,39 @@ module GoodData
19
23
  end
20
24
  end
21
25
 
22
- def deploy(dir, options={})
23
- verbose = options[:verbose] || false
26
+ def delete(process_id, options = {})
24
27
  GoodData.with_project(options[:project_id]) do
25
- params = options[:params].nil? ? [] : [options[:params]]
26
- deploy_graph(dir, options.merge({:files_to_exclude => params}))
28
+ process = GoodData::Process[process_id]
29
+ process.delete
27
30
  end
28
31
  end
29
32
 
30
- def with_deploy(dir, options={}, &block)
31
- verbose = options[:verbose] || false
32
- GoodData.with_project(options[:project_id]) do |project|
33
+ # TODO: check files_to_exclude param. Does it do anything? It should check that in case of using CLI, it makes sure the files are not deployed
34
+ def deploy(dir, options = {})
35
+ GoodData.with_project(options[:project_id]) do
33
36
  params = options[:params].nil? ? [] : [options[:params]]
34
- if block
35
- begin
36
- res = deploy_graph(dir, options.merge({:files_to_exclude => params}))
37
- block.call(res)
38
- ensure
39
- self_link = res && res['process']['links']['self']
40
- GoodData.delete(self_link)
41
- end
42
- else
43
- deploy_graph(dir, options.merge({:files_to_exclude => params}))
44
- end
37
+ GoodData::Process.deploy(dir, options.merge(:files_to_exclude => params))
45
38
  end
46
39
  end
47
40
 
48
- def execute_process(link, dir, options={})
49
- dir = Pathname(dir)
50
- type = :ruby
51
- if type == :ruby
52
- result = GoodData.post(link, {
53
- :execution => {
54
- :graph => ('./main.rb').to_s,
55
- :params => options[:expanded_params]
56
- }
57
- })
58
- begin
59
- GoodData.poll(result, 'executionTask')
60
- rescue RestClient::RequestFailed => e
61
-
62
- ensure
63
- result = GoodData.get(result['executionTask']['links']['detail'])
64
- if result['executionDetail']['status'] == 'ERROR'
65
- fail "Runing process failed. You can look at a log here #{result["executionDetail"]["logFileName"]}"
66
- end
67
- end
68
- result
69
- else
70
- result = GoodData.post(link, {
71
- :execution => {
72
- :graph => dir + 'graphs/main.grf',
73
- :params => {}
74
- }
75
- })
76
- begin
77
- GoodData.poll(result, 'executionTask')
78
- rescue RestClient::RequestFailed => e
79
-
80
- ensure
81
- result = GoodData.get(result['executionTask']['links']['detail'])
82
- if result['executionDetail']['status'] == 'ERROR'
83
- fail "Runing process failed. You can look at a log here #{result["executionDetail"]["logFileName"]}"
84
- end
85
- end
86
- result
41
+ def execute_process(process_id, executable, options = {})
42
+ GoodData.with_project(options[:project_id]) do
43
+ process = GoodData::Process[process_id]
44
+ process.execute_process(executable, options)
87
45
  end
88
46
  end
89
47
 
90
- def run(dir, options={})
91
- email = options[:email]
48
+ def run(dir, executable, options = {})
92
49
  verbose = options[:v]
93
50
  dir = Pathname(dir)
94
51
  name = options[:name] || "Temporary deploy[#{dir}][#{options[:project_name]}]"
95
52
 
96
- with_deploy(dir, options.merge(:name => name)) do |deploy_response|
97
- puts HighLine::color('Executing', HighLine::BOLD) if verbose
98
- result = execute_process(deploy_response['process']['links']['executions'], dir, options)
99
- end
100
- end
101
-
102
- private
103
-
104
- def deploy_graph(dir, options={})
105
- dir = Pathname(dir) || fail('Directory is not specified')
106
- fail "\"#{dir}\" is not a directory" unless dir.directory?
107
- files_to_exclude = options[:files_to_exclude].map { |p| Pathname(p) }
108
-
109
- project_id = options[:project_id] || fail('Project Id has to be specified')
110
-
111
- type = options[:type] || 'GRAPH'
112
- deploy_name = options[:name]
113
- verbose = options[:verbose] || false
114
-
115
- puts HighLine::color("Deploying #{dir}", HighLine::BOLD) if verbose
116
- res = nil
117
-
118
- Tempfile.open('deploy-graph-archive') do |temp|
119
- Zip::OutputStream.open(temp.path) do |zio|
120
- FileUtils::cd(dir) do
121
-
122
- files_to_pack = Dir.glob('./**/*').reject { |f| files_to_exclude.include?(Pathname(dir) + f) }
123
- files_to_pack.each do |item|
124
- puts "including #{item}" if verbose
125
- unless File.directory?(item)
126
- zio.put_next_entry(item)
127
- zio.print IO.read(item)
128
- end
129
- end
130
- end
131
- end
132
-
133
- GoodData.upload_to_user_webdav(temp.path)
134
- process_id = options[:process]
135
-
136
- data = {
137
- :process => {
138
- :name => deploy_name,
139
- :path => "/uploads/#{File.basename(temp.path)}",
140
- :type => type
141
- }
142
- }
143
- res = if process_id.nil?
144
- GoodData.post("/gdc/projects/#{GoodData.project.pid}/dataload/processes", data)
145
- else
146
- GoodData.put("/gdc/projects/#{GoodData.project.pid}/dataload/processes/#{process_id}", data)
147
- end
53
+ GoodData::Process.with_deploy(dir, options.merge(:name => name)) do |process|
54
+ puts HighLine.color('Executing', HighLine::BOLD) if verbose
55
+ process.execute(executable, options)
148
56
  end
149
- puts HighLine::color("Deploy DONE #{dir}", HighLine::GREEN) if verbose
150
- res
151
57
  end
152
58
  end
153
59
  end
154
60
  end
155
- end
61
+ end
@@ -0,0 +1,147 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'pathname'
4
+
5
+ module GoodData
6
+ module Command
7
+ class Project
8
+ class << self
9
+ # Create new project based on options supplied
10
+ def create(options = {})
11
+ title = options[:title]
12
+ summary = options[:summary]
13
+ template = options[:template]
14
+ token = options[:token]
15
+
16
+ GoodData::Project.create(:title => title, :summary => summary, :template => template, :auth_token => token)
17
+ end
18
+
19
+ # Show existing project
20
+ def show(id)
21
+ GoodData::Project[id]
22
+ end
23
+
24
+ def invite(project_id, email, role, msg = GoodData::Project::DEFAULT_INVITE_MESSAGE)
25
+ msg = GoodData::Project::DEFAULT_INVITE_MESSAGE if msg.nil? || msg.empty?
26
+
27
+ project = GoodData::Project[project_id]
28
+ fail "Invalid project id '#{project_id}' specified" if project.nil?
29
+
30
+ project.invite(email, role, msg)
31
+ end
32
+
33
+ # Clone existing project
34
+ def clone(project_id, options)
35
+ with_data = options[:data] || true
36
+ with_users = options[:users] || false
37
+ export = {
38
+ :exportProject => {
39
+ :exportUsers => with_users ? 1 : 0,
40
+ :exportData => with_data ? 1 : 0
41
+ }
42
+ }
43
+
44
+ result = GoodData.post("/gdc/md/#{project_id}/maintenance/export", export)
45
+ export_token = result['exportArtifact']['token']
46
+ status_url = result['exportArtifact']['status']['uri']
47
+
48
+ state = GoodData.get(status_url)['taskState']['status']
49
+ while state == 'RUNNING'
50
+ sleep 5
51
+ result = GoodData.get(status_url)
52
+ state = result['taskState']['status']
53
+ end
54
+
55
+ old_project = GoodData::Project[project_id]
56
+ project_uri = create(options.merge(:title => "Clone of #{old_project.title}"))
57
+ new_project = GoodData::Project[project_uri]
58
+
59
+ import = {
60
+ :importProject => {
61
+ :token => export_token
62
+ }
63
+ }
64
+ result = GoodData.post("/gdc/md/#{new_project.obj_id}/maintenance/import", import)
65
+ status_url = result['uri']
66
+ state = GoodData.get(status_url)['taskState']['status']
67
+ while state == 'RUNNING'
68
+ sleep 5
69
+ result = GoodData.get(status_url)
70
+ state = result['taskState']['status']
71
+ end
72
+ true
73
+ end
74
+
75
+ # Delete existing project
76
+ def delete(project_id)
77
+ p = GoodData::Project[project_id]
78
+ p.delete
79
+ end
80
+
81
+ # Get Spec and ID (of project)
82
+ def get_spec_and_project_id(base_path)
83
+ goodfile_path = GoodData::Helpers.find_goodfile(Pathname(base_path))
84
+ fail 'Goodfile could not be located in any parent directory. Please make sure you are inside a gooddata project folder.' if goodfile_path.nil?
85
+ goodfile = JSON.parse(File.read(goodfile_path), :symbolize_names => true)
86
+ spec_path = goodfile[:model] || fail('You need to specify the path of the build spec')
87
+ fail "Model path provided in Goodfile \"#{spec_path}\" does not exist" unless File.exist?(spec_path) && !File.directory?(spec_path)
88
+
89
+ spec_path = Pathname(spec_path)
90
+
91
+ content = File.read(spec_path)
92
+ spec = if spec_path.extname == '.rb'
93
+ eval(content)
94
+ elsif spec_path.extname == '.json'
95
+ JSON.parse(spec_path, :symbolize_names => true)
96
+ end
97
+ [spec, goodfile[:project_id]]
98
+ end
99
+
100
+ def list_users(pid)
101
+ users = []
102
+ finished = false
103
+ offset = 0
104
+ # Limit set to 1000 to be safe
105
+ limit = 1000
106
+ until finished
107
+ result = GoodData.get('/gdc/projects/#{pid}/users?offset=#{offset}&limit=#{limit}')
108
+ result['users'].map do |u|
109
+ as = u['user']
110
+ users.push(
111
+ :login => as['content']['email'],
112
+ :uri => as['links']['self'],
113
+ :first_name => as['content']['firstname'],
114
+ :last_name => as['content']['lastname'],
115
+ :role => as['content']['userRoles'].first,
116
+ :status => as['content']['status']
117
+ )
118
+ end
119
+ if result['users'].count == limit
120
+ offset += limit
121
+ else
122
+ finished = true
123
+ end
124
+ end
125
+ users
126
+ end
127
+
128
+ # Update project
129
+ def update(options = {})
130
+ project = options[:project]
131
+ GoodData::Model::ProjectCreator.migrate(:spec => options[:spec], :project => project)
132
+ end
133
+
134
+ # Build project
135
+ def build(options = {})
136
+ GoodData::Model::ProjectCreator.migrate(:spec => options[:spec], :token => options[:token])
137
+ end
138
+
139
+ def validate(project_id)
140
+ GoodData.with_project(project_id) do |p|
141
+ p.validate
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end