gooddata 0.6.0 → 0.6.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.
- 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
|