gooddata 0.6.0 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +13 -5
- data/.rubocop.yml +23 -0
- data/.travis.yml +9 -4
- data/CLI.md +439 -0
- data/Gemfile +0 -1
- data/README.md +2 -2
- data/Rakefile +60 -8
- data/doc/templates/default/module/setup.rb +1 -1
- data/examples.rb +2 -0
- data/gooddata +2 -0
- data/gooddata.gemspec +12 -8
- data/lib/gooddata.rb +0 -2
- data/lib/gooddata/bricks/base_downloader.rb +52 -47
- data/lib/gooddata/bricks/brick.rb +20 -31
- data/lib/gooddata/bricks/bricks.rb +1 -1
- data/lib/gooddata/bricks/middleware/base_middleware.rb +9 -7
- data/lib/gooddata/bricks/middleware/bench_middleware.rb +12 -10
- data/lib/gooddata/bricks/middleware/bulk_salesforce_middleware.rb +28 -28
- data/lib/gooddata/bricks/middleware/fs_upload_middleware.rb +20 -16
- data/lib/gooddata/bricks/middleware/gooddata_middleware.rb +21 -19
- data/lib/gooddata/bricks/middleware/logger_middleware.rb +10 -8
- data/lib/gooddata/bricks/middleware/restforce_middleware.rb +36 -34
- data/lib/gooddata/bricks/middleware/stdout_middleware.rb +11 -9
- data/lib/gooddata/bricks/middleware/twitter_middleware.rb +14 -12
- data/lib/gooddata/bricks/pipeline.rb +28 -0
- data/lib/gooddata/bricks/utils.rb +10 -8
- data/lib/gooddata/cli/cli.rb +1 -6
- data/lib/gooddata/cli/commands/auth_cmd.rb +1 -1
- data/lib/gooddata/cli/commands/console_cmd.rb +7 -5
- data/lib/gooddata/cli/commands/domain_cmd.rb +45 -0
- data/lib/gooddata/cli/commands/process_cmd.rb +42 -5
- data/lib/gooddata/cli/commands/project_cmd.rb +96 -36
- data/lib/gooddata/cli/commands/projects_cmd.rb +21 -0
- data/lib/gooddata/cli/commands/role_cmd.rb +28 -0
- data/lib/gooddata/cli/commands/run_ruby_cmd.rb +5 -5
- data/lib/gooddata/cli/commands/scaffold_cmd.rb +1 -1
- data/lib/gooddata/cli/commands/{profile_cmd.rb → user_cmd.rb} +7 -9
- data/lib/gooddata/cli/shared.rb +3 -2
- data/lib/gooddata/client.rb +16 -304
- data/lib/gooddata/commands/api.rb +13 -5
- data/lib/gooddata/commands/auth.rb +47 -40
- data/lib/gooddata/commands/base.rb +4 -2
- data/lib/gooddata/commands/commands.rb +1 -1
- data/lib/gooddata/commands/datasets.rb +20 -7
- data/lib/gooddata/commands/domain.rb +23 -0
- data/lib/gooddata/commands/process.rb +23 -117
- data/lib/gooddata/commands/project.rb +147 -0
- data/lib/gooddata/commands/projects.rb +8 -102
- data/lib/gooddata/commands/role.rb +26 -0
- data/lib/gooddata/commands/runners.rb +41 -38
- data/lib/gooddata/commands/scaffold.rb +46 -43
- data/lib/gooddata/commands/user.rb +33 -0
- data/lib/gooddata/connection.rb +43 -353
- data/lib/gooddata/core/connection.rb +389 -0
- data/lib/gooddata/core/core.rb +5 -4
- data/lib/gooddata/core/logging.rb +48 -0
- data/lib/gooddata/core/nil_logger.rb +13 -0
- data/lib/gooddata/core/project.rb +70 -0
- data/lib/gooddata/core/rest.rb +120 -0
- data/lib/gooddata/core/threaded.rb +14 -0
- data/lib/gooddata/core/user.rb +19 -0
- data/lib/gooddata/data/data.rb +2 -1
- data/lib/gooddata/data/guesser.rb +16 -12
- data/lib/gooddata/exceptions/command_failed.rb +1 -1
- data/lib/gooddata/exceptions/exceptions.rb +2 -1
- data/lib/gooddata/exceptions/no_project_error.rb +11 -0
- data/lib/gooddata/exceptions/project_not_found.rb +1 -1
- data/lib/gooddata/extensions/big_decimal.rb +6 -2
- data/lib/gooddata/extract.rb +10 -8
- data/lib/gooddata/goodzilla/goodzilla.rb +61 -59
- data/lib/gooddata/helpers.rb +15 -9
- data/lib/gooddata/models/account_settings.rb +124 -0
- data/lib/gooddata/models/attributes/anchor.rb +37 -0
- data/lib/gooddata/models/attributes/attributes.rb +8 -0
- data/lib/gooddata/models/attributes/date_attribute.rb +25 -0
- data/lib/gooddata/models/attributes/time_attribute.rb +24 -0
- data/lib/gooddata/models/columns/attribute.rb +71 -0
- data/lib/gooddata/models/columns/columns.rb +8 -0
- data/lib/gooddata/models/columns/date_column.rb +63 -0
- data/lib/gooddata/models/columns/fact_model.rb +54 -0
- data/lib/gooddata/models/columns/label.rb +55 -0
- data/lib/gooddata/models/columns/reference.rb +57 -0
- data/lib/gooddata/models/dashboard_builder.rb +26 -0
- data/lib/gooddata/models/data_result.rb +10 -9
- data/lib/gooddata/models/domain.rb +131 -0
- data/lib/gooddata/models/empty_result.rb +5 -8
- data/lib/gooddata/models/facts/facts.rb +8 -0
- data/lib/gooddata/models/facts/time_fact.rb +20 -0
- data/lib/gooddata/models/folders/attribute_folder.rb +20 -0
- data/lib/gooddata/models/folders/fact_folder.rb +20 -0
- data/lib/gooddata/models/folders/folders.rb +8 -0
- data/lib/gooddata/models/invitation.rb +78 -0
- data/lib/gooddata/models/links.rb +6 -6
- data/lib/gooddata/models/md_object.rb +25 -0
- data/lib/gooddata/models/metadata.rb +160 -62
- data/lib/gooddata/models/metadata/attribute.rb +81 -0
- data/lib/gooddata/models/metadata/column.rb +61 -0
- data/lib/gooddata/models/{dashboard.rb → metadata/dashboard.rb} +12 -7
- data/lib/gooddata/models/{data_set.rb → metadata/data_set.rb} +5 -4
- data/lib/gooddata/models/metadata/date_dimension.rb +26 -0
- data/lib/gooddata/models/metadata/display_form.rb +61 -0
- data/lib/gooddata/models/metadata/fact.rb +36 -0
- data/lib/gooddata/models/metadata/folder.rb +24 -0
- data/lib/gooddata/models/metadata/metadata.rb +8 -0
- data/lib/gooddata/models/metadata/metric.rb +197 -0
- data/lib/gooddata/models/metadata/report.rb +115 -0
- data/lib/gooddata/models/{report_definition.rb → metadata/report_definition.rb} +16 -10
- data/lib/gooddata/models/metadata/schema.rb +227 -0
- data/lib/gooddata/models/model.rb +38 -1339
- data/lib/gooddata/models/models.rb +5 -2
- data/lib/gooddata/models/module_constants.rb +29 -0
- data/lib/gooddata/models/process.rb +142 -13
- data/lib/gooddata/models/profile.rb +4 -6
- data/lib/gooddata/models/project.rb +406 -136
- data/lib/gooddata/models/project_blueprint.rb +221 -0
- data/lib/gooddata/models/project_builder.rb +136 -0
- data/lib/gooddata/models/project_creator.rb +138 -0
- data/lib/gooddata/models/project_metadata.rb +11 -10
- data/lib/gooddata/models/project_role.rb +92 -0
- data/lib/gooddata/models/references/date_reference.rb +44 -0
- data/lib/gooddata/models/references/references.rb +8 -0
- data/lib/gooddata/models/references/time_reference.rb +13 -0
- data/lib/gooddata/models/report_data_result.rb +11 -11
- data/lib/gooddata/models/schedule.rb +284 -0
- data/lib/gooddata/models/schema_blueprint.rb +158 -0
- data/lib/gooddata/models/schema_builder.rb +81 -0
- data/lib/gooddata/models/tab_builder.rb +23 -0
- data/lib/gooddata/models/user.rb +165 -0
- data/lib/gooddata/version.rb +1 -1
- data/lib/templates/project/data/devs.csv +1 -1
- data/lib/templates/project/data/repos.csv +1 -1
- data/lib/templates/project/model/model.rb.erb +7 -11
- data/spec/bricks/bricks_spec.rb +2 -0
- data/spec/data/test-ci-data.csv +2 -0
- data/spec/data/test_project_model_spec.json +7 -27
- data/spec/helpers/blueprint_helper.rb +2 -0
- data/spec/helpers/cli_helper.rb +2 -0
- data/spec/helpers/connection_helper.rb +14 -1
- data/spec/helpers/project_helper.rb +16 -0
- data/spec/helpers/schema_helper.rb +16 -0
- data/spec/integration/command_projects_spec.rb +7 -7
- data/spec/integration/create_from_template_spec.rb +2 -2
- data/spec/integration/full_project_spec.rb +160 -7
- data/spec/integration/partial_md_export_import_spec.rb +3 -3
- data/spec/logging_in_logging_out_spec.rb +2 -1
- data/spec/spec_helper.rb +26 -4
- data/spec/unit/bricks/bricks_spec.rb +15 -7
- data/spec/unit/bricks/middleware/bench_middleware_spec.rb +2 -0
- data/spec/unit/bricks/middleware/bulk_salesforce_middleware_spec.rb +2 -0
- data/spec/unit/bricks/middleware/gooddata_middleware_spec.rb +2 -0
- data/spec/unit/bricks/middleware/logger_middleware_spec.rb +2 -0
- data/spec/unit/bricks/middleware/restforce_middleware_spec.rb +2 -0
- data/spec/unit/bricks/middleware/stdout_middleware_spec.rb +2 -0
- data/spec/unit/bricks/middleware/twitter_middleware_spec.rb +2 -0
- data/spec/unit/cli/cli_spec.rb +2 -0
- data/spec/unit/cli/commands/cmd_api_spec.rb +23 -15
- data/spec/unit/cli/commands/cmd_auth_spec.rb +8 -4
- data/spec/unit/cli/commands/cmd_domain_spec.rb +82 -0
- data/spec/unit/cli/commands/cmd_process_spec.rb +29 -13
- data/spec/unit/cli/commands/cmd_project_spec.rb +51 -30
- data/spec/unit/cli/commands/cmd_role_spec.rb +44 -0
- data/spec/unit/cli/commands/cmd_run_ruby_spec.rb +8 -4
- data/spec/unit/cli/commands/cmd_scaffold_spec.rb +48 -11
- data/spec/unit/cli/commands/cmd_user_spec.rb +29 -0
- data/spec/unit/commands/command_api_spec.rb +1 -1
- data/spec/unit/commands/command_auth_spec.rb +100 -18
- data/spec/unit/commands/command_dataset_spec.rb +4 -0
- data/spec/unit/commands/command_process_spec.rb +9 -4
- data/spec/unit/commands/command_projects_spec.rb +10 -6
- data/spec/unit/commands/command_scaffold_spec.rb +5 -1
- data/spec/unit/commands/command_user_spec.rb +22 -0
- data/spec/unit/core/connection_spec.rb +35 -6
- data/spec/unit/core/logging_spec.rb +65 -0
- data/spec/unit/core/nil_logger_spec.rb +9 -0
- data/spec/unit/core/project_spec.rb +51 -0
- data/spec/unit/core/rest_spec.rb +33 -0
- data/spec/unit/data/guesser_spec.rb +5 -0
- data/spec/unit/godzilla/goodzilla_spec.rb +2 -0
- data/spec/unit/models/account_settings_spec.rb +28 -0
- data/spec/unit/models/anchor_spec.rb +32 -0
- data/spec/unit/models/attribute_column_spec.rb +7 -0
- data/spec/unit/models/domain_spec.rb +45 -0
- data/spec/unit/models/invitation_spec.rb +13 -0
- data/spec/unit/models/md_object_spec.rb +47 -0
- data/spec/unit/models/metric.rb +92 -0
- data/spec/unit/{model → models}/model_spec.rb +9 -7
- data/spec/unit/models/project_blueprint_spec.rb +202 -0
- data/spec/unit/models/project_creator.rb +73 -0
- data/spec/unit/models/project_role_spec.rb +90 -0
- data/spec/unit/models/project_spec.rb +143 -0
- data/spec/unit/models/schedule_spec.rb +491 -0
- data/spec/unit/{model → models}/schema_builder_spec.rb +2 -0
- data/spec/unit/{model → models}/tools_spec.rb +13 -7
- data/spec/unit/models/user_spec.rb +16 -0
- data/test/test_upload.rb +2 -0
- metadata +189 -86
- data/lib/gooddata/commands/profile.rb +0 -11
- data/lib/gooddata/models/attribute.rb +0 -29
- data/lib/gooddata/models/display_form.rb +0 -9
- data/lib/gooddata/models/fact.rb +0 -19
- data/lib/gooddata/models/metric.rb +0 -99
- data/lib/gooddata/models/report.rb +0 -89
- data/spec/data/blueprint_valid.json +0 -37
- data/spec/unit/cli/commands/cmd_profile_spec.rb +0 -16
- data/spec/unit/commands/command_profile_spec.rb +0 -18
- data/spec/unit/core/core_spec.rb +0 -7
- data/spec/unit/model/blueprint_spec.rb +0 -132
- 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
|
-
|
37
|
+
fail(GoodData::CommandFailed, 'Specify the path you want to GET.') if path.nil?
|
38
38
|
result = GoodData.get path
|
39
|
-
|
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
|
-
|
49
|
+
fail(GoodData::CommandFailed, 'Specify the path you want to DELETE.') if path.nil?
|
46
50
|
result = GoodData.delete path
|
47
|
-
|
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
|
10
|
-
|
11
|
-
class
|
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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
19
|
-
|
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
|
-
|
26
|
-
|
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
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
39
|
-
|
40
|
-
|
46
|
+
# Ask for credentials and store them
|
47
|
+
def store(credentials_file_path = credentials_file)
|
48
|
+
credentials = ask_for_credentials
|
41
49
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
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
|
-
|
49
|
-
|
50
|
-
|
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
|
-
|
58
|
-
|
59
|
-
|
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
|
@@ -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
|
-
|
69
|
-
|
70
|
-
|
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
|
-
|
92
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
23
|
-
verbose = options[:verbose] || false
|
26
|
+
def delete(process_id, options = {})
|
24
27
|
GoodData.with_project(options[:project_id]) do
|
25
|
-
|
26
|
-
|
28
|
+
process = GoodData::Process[process_id]
|
29
|
+
process.delete
|
27
30
|
end
|
28
31
|
end
|
29
32
|
|
30
|
-
|
31
|
-
|
32
|
-
GoodData.with_project(options[:project_id]) do
|
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
|
-
|
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(
|
49
|
-
|
50
|
-
|
51
|
-
|
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 |
|
97
|
-
puts HighLine
|
98
|
-
|
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
|