Class: GoodData::Project
- Inherits:
-
Rest::Resource
- Object
- Rest::Object
- Rest::Resource
- GoodData::Project
- Includes:
- Mixin::Author, Mixin::Contributor, Mixin::UriGetter
- Defined in:
- lib/gooddata/models/project.rb
Constant Summary collapse
- USER_ACCOUNT_PATH =
'/gdc/account/profile/'
- USERSPROJECTS_PATH =
USER_ACCOUNT_PATH + '%s/projects'
- PROJECTS_PATH =
'/gdc/projects'
- PROJECT_PATH =
'/gdc/projects/%s'
- SLIS_PATH =
'/ldm/singleloadinterface'
- DEFAULT_INVITE_MESSAGE =
'Join us!'
- DEFAULT_ENVIRONMENT =
'PRODUCTION'
- EMPTY_OBJECT =
{ 'project' => { 'meta' => { 'summary' => 'No summary' }, 'content' => { 'guidedNavigation' => 1, 'driver' => 'Pg', 'environment' => GoodData::Helpers::AuthHelper.read_environment } } }
Instance Attribute Summary collapse
-
#connection ⇒ Object
Returns the value of attribute connection.
-
#json ⇒ Object
Returns the value of attribute json.
Attributes inherited from Rest::Object
Class Method Summary collapse
-
.[](id, opts = { client: GoodData.connection }) ⇒ Object
Returns a Project object identified by given string The following identifiers are accepted - /gdc/md/
- /gdc/projects/ - . -
.all(opts = { client: GoodData.connection }, limit = nil, offset = nil) ⇒ Object
Returns an array of all projects accessible by current user.
-
.clone_with_etl(project, options = {}) ⇒ GoodData::Project
Clones project along with etl and schedules.
- .collect_process_aliases(process_data, client, aliases) ⇒ Object
-
.create(opts = { client: GoodData.connection }, &block) ⇒ Object
Create a project from a given attributes Expected keys: - :title (mandatory) - :summary - :template (default /projects/blank).
- .create_from_blueprint(blueprint, options = {}) ⇒ Object
- .create_object(data = {}) ⇒ Object
- .find(opts = { client: GoodData.connection }) ⇒ Object
- .get_data_source_alias(data_source_id, client, aliases) ⇒ Object
- .get_dataset_mapping(from_project) ⇒ Object
- .project_id_or_path?(id) ⇒ Boolean
- .replace_data_source_ids(data_sources, client, aliases) ⇒ Object
- .replace_process_data_source_ids(process_data, client, aliases) ⇒ Object
- .transfer_color_palette(from_project, to_project) ⇒ Object
-
.transfer_etl(client, from_project, to_project) ⇒ Object
Clones project along with etl and schedules.
- .transfer_output_stage(from_project, to_project, options) ⇒ Object
- .transfer_processes(from_project, to_project, options = {}) ⇒ Object
-
.transfer_schedules(from_project, to_project) ⇒ Object
Clones project along with etl and schedules.
- .transfer_tagged_stuff(from_project, to_project, tag) ⇒ Object
- .transfer_user_groups(from_project, to_project) ⇒ Object
- .update_dataset_mapping(model_mapping_json, to_project) ⇒ Object
-
.user_csv_import(row) ⇒ Object
Takes one CSV line and creates hash from data extracted.
-
.verify_data_source_alias(ds_alias, client) ⇒ String
Verify whether the data source exists in the domain using its alias.
Instance Method Summary collapse
- #add ⇒ Object
- #add_dashboard(dashboard) ⇒ Object (also: #create_dashboard)
- #add_data_permissions(filters, options = {}) ⇒ Object
-
#add_metric(metric, options = {}) ⇒ GoodData::Report
(also: #create_metric, #add_measure, #create_measure)
Creates a metric in a project.
-
#add_report(options = {}) ⇒ GoodData::Report
(also: #create_report)
Creates new instance of report in context of project.
-
#add_report_definition(json) ⇒ GoodData::ReportDefinition
(also: #create_report_definition)
Creates new instance of report definition in context of project This report definition can be used for creating of GoodData::Report.
- #add_user_group(data) ⇒ Object (also: #create_group)
- #add_variable_permissions(filters, var, options = {}) ⇒ Object
-
#am_i_admin? ⇒ Boolean
Returns an indication whether current user is admin in this project.
- #attribute_by_identifier(identifier) ⇒ Object
- #attribute_by_title(title) ⇒ Object
-
#attributes(id = :all) ⇒ GoodData::Attribute | Array<GoodData::Attribute>
Helper for getting attributes of a project.
- #attributes_by_identifier(identifier) ⇒ Object
- #attributes_by_title(title) ⇒ Object
-
#blueprint(options = {}) ⇒ GoodData::ProjectRole
Gets project blueprint from the server.
-
#browser_uri(options = {}) ⇒ String
Returns web interface URI of project.
- #check_groups(specified_groups, user_groups_cache = nil, options = {}) ⇒ Object
-
#clone(options = {}) ⇒ GoodData::Project
Clones project.
- #compute_metric(expression) ⇒ Object (also: #compute_measure)
- #compute_report(spec = {}) ⇒ Object
- #computed_attributes(id = :all) ⇒ Object
- #create_custom_color_palette(colors) ⇒ Object
- #create_output_stage(ads, opts = {}) ⇒ Object
- #create_schedule(process, date, executable, options = {}) ⇒ Object
- #create_variable(data) ⇒ Object
- #current_color_palette ⇒ Object
-
#dashboards(id = :all) ⇒ GoodData::Dashboard | Array<GoodData::Dashboard>
Helper for getting dashboards of a project.
- #data_permissions(id = :all) ⇒ Object (also: #user_filters)
- #dataset_mapping ⇒ Object
-
#datasets(id = :all) ⇒ Array<GoodData::Dataset> | GoodData::Dataset
Gives you list of datasets.
-
#delete ⇒ Object
Deletes project.
-
#delete_all_data(options = {}) ⇒ Array
Helper for getting rid of all data in the project.
-
#delete_dashboards ⇒ Object
Deletes dashboards for project.
-
#deleted? ⇒ Boolean
Returns true if project is in deleted state.
- #deploy_process(path, options = {}) ⇒ Object
- #dimensions(id = :all) ⇒ Object
- #disable_users(list, options = {}) ⇒ Object
- #download_file(file, where) ⇒ Object
- #driver ⇒ Object
- #environment ⇒ Object
-
#execute_dml(dml, options = {}) ⇒ Hash
Executes DML expression.
-
#execute_maql(maql, options = {}) ⇒ Hash
Executes MAQL expression and waits for it to be finished.
-
#export_clone(options = {}) ⇒ String
Export a clone from a project to be later imported.
- #fact_by_title(title) ⇒ Object
-
#facts(id = :all) ⇒ GoodData::Fact | Array<GoodData::Fact>
Helper for getting facts of a project.
- #facts_by_title(title) ⇒ Object
- #find_attribute_element_value(uri) ⇒ Object
- #find_by_tag(tags) ⇒ Object
- #folders(id = :all) ⇒ Object
-
#fuzzy_get_user(name, user_list = users) ⇒ GoodDta::Membership
Gets user by its email, full_name, login or uri.
-
#get_role(role_name, role_list = roles) ⇒ GoodData::ProjectRole
Gets project role.
-
#get_role_by_identifier(role_name, role_list = roles) ⇒ GoodData::ProjectRole
Gets project role by its identifier.
-
#get_role_by_summary(role_summary, role_list = roles) ⇒ GoodData::ProjectRole
Gets project role byt its summary.
-
#get_role_by_title(role_title, role_list = roles) ⇒ GoodData::ProjectRole
Gets project role by its name.
-
#get_user(slug, user_list = users) ⇒ GoodDta::Membership
(also: #member)
Gets user by its login or uri in various shapes It does not find by other information because that is not unique.
-
#import_clone(export_token, options = {}) ⇒ Project
Imports a clone into current project.
-
#import_users(new_users, options = {}) ⇒ Object
Imports users.
- #info ⇒ Object
-
#initialize(json) ⇒ Project
constructor
Initializes object instance from raw wire JSON.
-
#invitations ⇒ Array<GoodData::Invitation>
Returns invitations to project.
-
#invite(email, role, msg = DEFAULT_INVITE_MESSAGE) ⇒ Object
Invites new user to project.
-
#labels(id = :all, opts = {}) ⇒ GoodData::Fact | Array<GoodData::Fact>
Helper for getting labels of a project.
-
#links ⇒ Hash
Returns project related links.
-
#maql_diff(options = {}) ⇒ Hash
get maql diff from another project or blueprint to current project.
- #md ⇒ Object
-
#member?(profile, list = members) ⇒ Boolean
Checks if the profile is member of project.
- #members?(profiles, list = members) ⇒ Boolean
-
#metadata(key = :all) ⇒ Hash
Get data from project specific metadata storage.
- #metric_by_title(title) ⇒ Object (also: #measure_by_title)
-
#metrics(id = :all, opts = { :full => true }) ⇒ Array<GoodData::Metric>
(also: #measures)
Helper for getting metrics of a project.
- #metrics_by_title(title) ⇒ Object (also: #measures_by_title)
-
#obj_id ⇒ String
(also: #pid)
Gets raw resource ID.
-
#objects(id, opts = {}) ⇒ Array<GoodData::MdObject>
Helper for getting objects of a project.
-
#objects_export(objs, options = {}) ⇒ String
Transfer objects from one project to another.
-
#objects_import(token, options = {}) ⇒ Boolean
Import objects from import token.
-
#partial_md_export(objects, options = {}) ⇒ Boolean | Array<Hash>
(also: #transfer_objects)
Transfer objects from one project to another.
-
#processes(id = :all) ⇒ GoodData::Report | Array<GoodData::Report>
Helper for getting processes of a project.
-
#project? ⇒ Boolean
Checks if this object instance is project.
-
#project_webdav_path ⇒ String
Get WebDav directory for project data.
- #public? ⇒ Boolean
-
#reload! ⇒ Object
Forces project to reload.
- #remove_users(list) ⇒ Object
-
#replace_from_mapping(mapping, opts = {}) ⇒ Object
Method used for walking through objects in project and trying to replace all occurences of some object for another object.
-
#report_definitions(id = :all, options = {}) ⇒ GoodData::ReportDefinition | Array<GoodData::ReportDefinition>
Helper for getting report definitions of a project.
-
#reports(id = :all) ⇒ GoodData::Report | Array<GoodData::Report>
Helper for getting reports of a project.
- #reset_color_palette ⇒ Object
- #resolve_roles(login, desired_roles, options = {}) ⇒ Object
-
#roles ⇒ Array<GoodData::ProjectRole>
Gets the list or project roles.
-
#save ⇒ Object
Saves project.
-
#schedule_mail(options = GoodData::ScheduledMail::DEFAULT_OPTS) ⇒ Object
Schedules an email with dashboard or report content.
- #scheduled_mails(options = { :full => false }) ⇒ Object
-
#schedules(id = :all) ⇒ GoodData::Schedule | Array<GoodData::Schedule>
Schedule instance or list.
-
#set_metadata(key, val) ⇒ String
Set data for specific key in project specific metadata storage.
-
#set_user_roles(login, desired_roles, options = {}) ⇒ Object
(also: #add_user)
Update user.
-
#set_users_roles(list, options = {}) ⇒ Object
(also: #add_users, #create_users)
Update list of users.
-
#slis ⇒ GoodData::Metadata
Gets SLIs data.
-
#state ⇒ String
Gets project state.
-
#title=(a_title) ⇒ String
Gets project title.
- #token ⇒ Object
- #transfer_color_palette(target) ⇒ Object
- #transfer_etl(target) ⇒ Object
- #transfer_processes(target) ⇒ Object
- #transfer_schedules(target) ⇒ Object
- #transfer_tagged_stuff(target, tag) ⇒ Object
- #update_dataset_mapping(model_mapping_json) ⇒ Object
-
#update_from_blueprint(blueprint, options = {}) ⇒ Object
Applies blueprint to the project.
- #upgrade_custom_v2(message, options = {}) ⇒ Object
-
#upload(data, blueprint, dataset_name, options = {}) ⇒ Object
Uploads file to project.
- #upload_file(file, options = {}) ⇒ Object
- #upload_multiple(data, blueprint, options = {}) ⇒ Object
- #uri ⇒ Object
- #user_groups(id = :all, options = {}) ⇒ Object
-
#user_has_role?(user, role_name) ⇒ Boolean
Checks whether user has particular role in given proejct.
-
#users(opts = {}) ⇒ Array<GoodData::User>
(also: #members)
List of users in project.
-
#validate(filters = %w(ldm pdm metric_filter invalid_objects), options = {}) ⇒ Object
Run validation on project Valid settins for validation are (default all): ldm - Checks the consistency of LDM objects.
- #variables(id = :all, options = { client: client, project: self }) ⇒ Object
- #whitelist_users(new_users, users_list, whitelist, mode = :exclude) ⇒ Object
Methods included from Mixin::Contributor
Methods included from Mixin::Author
Methods inherited from Rest::Object
client, default_client, #saved?
Methods included from Mixin::DataPropertyReader
Methods included from Mixin::DataPropertyWriter
Methods included from Mixin::MetaPropertyReader
Methods included from Mixin::MetaPropertyWriter
Methods included from Mixin::MetaGetter
Methods included from Mixin::DataGetter
Methods included from Mixin::RootKeyGetter
Methods included from Mixin::ContentGetter
Constructor Details
#initialize(json) ⇒ Project
Initializes object instance from raw wire JSON
1132 1133 1134 1135 1136 |
# File 'lib/gooddata/models/project.rb', line 1132 def initialize(json) super @json = json @log_formatter = GoodData::ProjectLogFormatter.new(self) end |
Instance Attribute Details
#connection ⇒ Object
Returns the value of attribute connection.
62 63 64 |
# File 'lib/gooddata/models/project.rb', line 62 def connection @connection end |
#json ⇒ Object
Returns the value of attribute json.
62 63 64 |
# File 'lib/gooddata/models/project.rb', line 62 def json @json end |
Class Method Details
.[](id, opts = { client: GoodData.connection }) ⇒ Object
Returns a Project object identified by given string The following identifiers are accepted
- /gdc/md/
- /gdc/projects/
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/gooddata/models/project.rb', line 82 def [](id, opts = { client: GoodData.connection }) return id if id.instance_of?(GoodData::Project) || id.respond_to?(:project?) && id.project? if id == :all Project.all({ client: GoodData.connection }.merge(opts)) else fail(ArgumentError, 'wrong type of argument. Should be either project ID or path') unless project_id_or_path?(id) id = id.match(/[a-zA-Z\d]+$/)[0] if id =~ %r{/} c = GoodData.get_client(opts) response = c.get(PROJECT_PATH % id) c.factory.create(Project, response) end end |
.all(opts = { client: GoodData.connection }, limit = nil, offset = nil) ⇒ Object
Returns an array of all projects accessible by current user
71 72 73 74 |
# File 'lib/gooddata/models/project.rb', line 71 def all(opts = { client: GoodData.connection }, limit = nil, offset = nil) c = GoodData.get_client(opts) c.user.projects(limit, offset) end |
.clone_with_etl(project, options = {}) ⇒ GoodData::Project
Clones project along with etl and schedules
107 108 109 110 111 |
# File 'lib/gooddata/models/project.rb', line 107 def clone_with_etl(project, = {}) a_clone = project.clone() GoodData::Project.transfer_etl(project.client, project, a_clone) a_clone end |
.collect_process_aliases(process_data, client, aliases) ⇒ Object
342 343 344 345 346 347 348 349 350 351 352 |
# File 'lib/gooddata/models/project.rb', line 342 def collect_process_aliases(process_data, client, aliases) data_sources = process_data.dig('process', 'dataSources') unless data_sources.blank? data_sources.map do |data_source| get_data_source_alias(data_source['id'], client, aliases) end end component = process_data.dig('process', 'component') get_data_source_alias(component['configLocation']['dataSourceConfig']['id'], client, aliases) if component&.dig('configLocation', 'dataSourceConfig') aliases end |
.create(opts = { client: GoodData.connection }, &block) ⇒ Object
Create a project from a given attributes Expected keys:
- :title (mandatory)
- :summary
- :template (default /projects/blank)
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/gooddata/models/project.rb', line 136 def create(opts = { client: GoodData.connection }, &block) GoodData.logger.info "Creating project #{opts[:title]}" auth_token = opts[:auth_token] || opts[:token] if auth_token.nil? || auth_token.empty? opts = { auth_token: Helpers::AuthHelper.read_token }.merge(opts) auth_token = opts[:auth_token] end fail ArgumentError, 'You have to provide your token for creating projects as :auth_token or :token parameter' if auth_token.nil? || auth_token.empty? project = create_object(opts) project.save # until it is enabled or deleted, recur. This should still end if there # is a exception thrown out from RESTClient. This sometimes happens from # WebApp when request is too long while project.state.to_s != 'enabled' if project.deleted? # if project is switched to deleted state, fail. This is usually problem of creating a template which is invalid. fail 'Project was marked as deleted during creation. This usually means you were trying to create from template and it failed.' end sleep(3) project.reload! end if block GoodData.with_project(project) do |p| block.call(p) end end sleep 3 project end |
.create_from_blueprint(blueprint, options = {}) ⇒ Object
177 178 179 |
# File 'lib/gooddata/models/project.rb', line 177 def create_from_blueprint(blueprint, = {}) GoodData::Model::ProjectCreator.migrate(.merge(spec: blueprint, client: client)) end |
.create_object(data = {}) ⇒ Object
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/gooddata/models/project.rb', line 113 def create_object(data = {}) c = GoodData.get_client(data) new_data = GoodData::Helpers.deep_dup(EMPTY_OBJECT).tap do |d| d['project']['meta']['title'] = data[:title] d['project']['meta']['summary'] = data[:summary] if data[:summary] d['project']['meta']['projectTemplate'] = data[:template] if data[:template] d['project']['content']['guidedNavigation'] = data[:guided_navigation] if data[:guided_navigation] token = data[:auth_token] || data[:token] d['project']['content']['authorizationToken'] = token if token d['project']['content']['driver'] = data[:driver] if data[:driver] d['project']['content']['environment'] = data[:environment] if data[:environment] end c.create(Project, new_data) end |
.find(opts = { client: GoodData.connection }) ⇒ Object
169 170 171 172 173 174 175 |
# File 'lib/gooddata/models/project.rb', line 169 def find(opts = { client: GoodData.connection }) c = GoodData.get_client(opts) user = c.user user.projects['projects'].map do |project| c.create(GoodData::Project, project) end end |
.get_data_source_alias(data_source_id, client, aliases) ⇒ Object
354 355 356 357 358 359 360 361 362 363 364 365 |
# File 'lib/gooddata/models/project.rb', line 354 def get_data_source_alias(data_source_id, client, aliases) unless aliases[data_source_id] data_source = GoodData::DataSource.from_id(data_source_id, client: client) if data_source&.alias aliases[data_source_id] = { :type => data_source.type, :alias => data_source.alias } end end aliases[data_source_id] end |
.get_dataset_mapping(from_project) ⇒ Object
259 260 261 |
# File 'lib/gooddata/models/project.rb', line 259 def get_dataset_mapping(from_project) GoodData::DatasetMapping.get(:client => from_project.client, :project => from_project) end |
.project_id_or_path?(id) ⇒ Boolean
98 99 100 |
# File 'lib/gooddata/models/project.rb', line 98 def project_id_or_path?(id) id.to_s =~ %r{^(\/gdc\/(projects|md)\/)?[a-zA-Z\d]+$} end |
.replace_data_source_ids(data_sources, client, aliases) ⇒ Object
377 378 379 380 381 382 383 384 385 386 |
# File 'lib/gooddata/models/project.rb', line 377 def replace_data_source_ids(data_sources, client, aliases) array_data_sources = [] if data_sources && !data_sources.empty? data_sources.map do |data_source| new_id = verify_data_source_alias(aliases[data_source[:id]], client) array_data_sources.push(:id => new_id) end end array_data_sources end |
.replace_process_data_source_ids(process_data, client, aliases) ⇒ Object
367 368 369 370 371 372 373 374 375 |
# File 'lib/gooddata/models/project.rb', line 367 def replace_process_data_source_ids(process_data, client, aliases) component = process_data.dig(:process, :component) if component&.dig(:configLocation, :dataSourceConfig) the_alias = aliases[component[:configLocation][:dataSourceConfig][:id]] process_data[:process][:component][:configLocation][:dataSourceConfig][:id] = verify_data_source_alias(the_alias, client) end process_data[:process][:dataSources] = replace_data_source_ids(process_data[:process][:dataSources], client, aliases) process_data end |
.transfer_color_palette(from_project, to_project) ⇒ Object
595 596 597 598 |
# File 'lib/gooddata/models/project.rb', line 595 def transfer_color_palette(from_project, to_project) colors = from_project.current_color_palette to_project.create_custom_color_palette(colors) unless colors.empty? end |
.transfer_etl(client, from_project, to_project) ⇒ Object
Clones project along with etl and schedules.
Object to be cloned from. Can be either segment in which case we take the master, client in which case we take its project, string in which case we treat is as an project object or directly project
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
# File 'lib/gooddata/models/project.rb', line 237 def transfer_etl(client, from_project, to_project) from_project = case from_project when GoodData::Client from_project.project when GoodData::Segment from_project.master_project else client.projects(from_project) end to_project = case to_project when GoodData::Client to_project.project when GoodData::Segment to_project.master_project else client.projects(to_project) end transfer_processes(from_project, to_project) transfer_schedules(from_project, to_project) end |
.transfer_output_stage(from_project, to_project, options) ⇒ Object
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/gooddata/models/project.rb', line 198 def transfer_output_stage(from_project, to_project, ) from_prj_output_stage = from_project.add.output_stage output_stage_prefix = [:ads_output_stage_prefix] || from_prj_output_stage.output_stage_prefix output_stage_uri = [:ads_output_stage_uri] || from_prj_output_stage.schema if from_project.processes.any? { |p| p.type == :dataload } if to_project.processes.any? { |p| p.type == :dataload } to_project.add.output_stage.schema = output_stage_uri to_project.add.output_stage.output_stage_prefix = output_stage_prefix to_project.add.output_stage.save else from_server = from_project.client.connection.server.url to_server = to_project.client.connection.server.url if from_server != to_server && [:ads_output_stage_uri].nil? raise "Cannot transfer output stage from #{from_server} to #{to_server}. " \ 'It is not possible to transfer output stages between ' \ 'different domains. Please specify an address of an output ' \ 'stage that is in the same domain as the target project ' \ 'using the "ads_output_stage_uri" parameter.' end to_project.add.output_stage = GoodData::AdsOutputStage.create( client: to_project.client, ads: output_stage_uri, client_id: from_prj_output_stage.client_id, output_stage_prefix: output_stage_prefix, project: to_project ) end end end |
.transfer_processes(from_project, to_project, options = {}) ⇒ Object
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 |
# File 'lib/gooddata/models/project.rb', line 279 def transfer_processes(from_project, to_project, = {}) = GoodData::Helpers.symbolize_keys() aliases = {} to_project_processes = to_project.processes additional_hidden_params = [:additional_hidden_params] || {} result = from_project.processes.uniq(&:name).map do |process| fail "The process name #{process.name} must be unique in transferred project #{to_project}" if to_project_processes.count { |p| p.name == process.name } > 1 next if process.type == :dataload || process.add_v2_component? collect_process_aliases(process.data, from_project.client, aliases) to_process = to_project_processes.find { |p| p.name == process.name } data_sources = GoodData::Helpers.symbolize_keys_recursively!(process.data_sources) data_sources = replace_data_source_ids(data_sources, to_project.client, aliases) to_process = if process.path to_process.delete if to_process Process.deploy_from_appstore(process.path, name: process.name, client: to_project.client, project: to_project, data_sources: data_sources) elsif process.component to_process.delete if to_process process_hash = GoodData::Helpers::DeepMergeableHash[GoodData::Helpers.symbolize_keys(process.to_hash)].deep_merge(additional_hidden_params) process_hash = replace_process_data_source_ids(process_hash, to_project.client, aliases) Process.deploy_component(process_hash, project: to_project, client: to_project.client) else Dir.mktmpdir('etl_transfer') do |dir| dir = Pathname(dir) filename = dir + 'process.zip' File.open(filename, 'w') do |f| f << process.download end if to_process to_process.deploy(filename, type: process.type, name: process.name, data_sources: data_sources) else to_project.deploy_process(filename, type: process.type, name: process.name, data_sources: data_sources) end end end { from: from_project.pid, to: to_project.pid, name: process.name, status: to_process ? 'successful' : 'failed' } end transfer_output_stage(from_project, to_project, ) result << { from: from_project.pid, to: to_project.pid, name: 'Automated Data Distribution', status: 'successful' } res = (from_project.processes + to_project.processes).map { |p| [p, p.name, p.type] } res.group_by { |x| [x[1], x[2]] } .select { |_, procs| procs.length == 1 && procs[2] != :dataload } .reject { |_, procs| procs.first.first.add_v2_component? } .flat_map { |_, procs| procs.select { |p| p[0].project.pid == to_project.pid }.map { |p| p[0] } } .peach(&:delete) result.compact end |
.transfer_schedules(from_project, to_project) ⇒ Object
Clones project along with etl and schedules.
Object to be cloned from. Can be either segment in which case we take the master, client in which case we take its project, string in which case we treat is as an project object or directly project.
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 |
# File 'lib/gooddata/models/project.rb', line 446 def transfer_schedules(from_project, to_project) to_project_processes = to_project.processes.sort_by(&:name) from_project_processes = from_project.processes.sort_by(&:name) from_project_processes.reject!(&:add_v2_component?) GoodData.logger.debug("Processes in from project #{from_project.pid}: #{from_project_processes.map(&:name).join(', ')}") GoodData.logger.debug("Processes in to project #{to_project.pid}: #{to_project_processes.map(&:name).join(', ')}") cache = to_project_processes .zip(from_project_processes) .flat_map do |remote, local| local.schedules.map do |schedule| [remote, local, schedule] end end remote_schedules = to_project.schedules remote_stuff = remote_schedules.map do |s| v = s.to_hash after_schedule = remote_schedules.find { |s2| s.trigger_id == s2.obj_id } v[:after] = s.trigger_id && after_schedule && after_schedule.name v[:remote_schedule] = s v[:params] = v[:params].except("EXECUTABLE", "PROCESS_ID") v.compact end local_schedules = from_project.schedules local_stuff = local_schedules.map do |s| v = s.to_hash after_schedule = local_schedules.find { |s2| s.trigger_id == s2.obj_id } after_process_schedule = from_project_processes.find { |p| after_schedule && p.obj_id == after_schedule.process_id } v[:after] = s.trigger_id && after_process_schedule && after_schedule && after_schedule.name v[:trigger_execution_status] = s.trigger_execution_status v[:remote_schedule] = s v[:params] = v[:params].except("EXECUTABLE", "PROCESS_ID") v.compact end diff = GoodData::Helpers.diff(remote_stuff, local_stuff, key: :name, fields: [:name, :cron, :after, :params, :hidden_params, :reschedule, :state]) stack = diff[:added].map do |x| [:added, x] end stack += diff[:changed].map do |x| [:changed, x] end schedule_cache = remote_schedules.reduce({}) do |a, e| a[e.name] = e a end results = [] loop do # rubocop:disable Metrics/BlockLength break if stack.empty? state, changed_schedule = stack.shift if state == :added schedule_spec = changed_schedule if schedule_spec[:after] && !schedule_cache[schedule_spec[:after]] stack << [state, schedule_spec] next end remote_process, process_spec = cache.find do |_remote, local, schedule| (schedule_spec[:process_id] == local.process_id) && (schedule.name == schedule_spec[:name]) end next unless remote_process || process_spec GoodData.logger.info("Creating schedule #{schedule_spec[:name]} for process #{remote_process.name}") executable = nil if process_spec.type != :dataload executable = schedule_spec[:executable] || (process_spec.type == :ruby ? 'main.rb' : 'main.grf') end params = schedule_parameters(schedule_spec) created_schedule = remote_process.create_schedule(schedule_spec[:cron] || schedule_cache[schedule_spec[:after]], executable, params) schedule_cache[created_schedule.name] = created_schedule results << { state: :added, process: remote_process, schedule: created_schedule } else schedule_spec = changed_schedule[:new_obj] if schedule_spec[:after] && !schedule_cache[schedule_spec[:after]] stack << [state, schedule_spec] next end remote_process, process_spec = cache.find do |i| i[2].name == schedule_spec[:name] end schedule = changed_schedule[:old_obj][:remote_schedule] GoodData.logger.info("Updating schedule #{schedule_spec[:name]} for process #{remote_process.name}") schedule.params = (schedule_spec[:params] || {}) schedule.cron = schedule_spec[:cron] if schedule_spec[:cron] schedule.after = schedule_cache[schedule_spec[:after]] if schedule_spec[:after] schedule.trigger_execution_status = schedule_cache[schedule_spec[:trigger_execution_status]] if schedule_spec[:after] schedule.hidden_params = schedule_spec[:hidden_params] || {} if process_spec.type != :dataload schedule.executable = schedule_spec[:executable] || (process_spec.type == :ruby ? 'main.rb' : 'main.grf') end schedule.reschedule = schedule_spec[:reschedule] schedule.name = schedule_spec[:name] schedule.state = schedule_spec[:state] schedule.save schedule_cache[schedule.name] = schedule results << { state: :changed, process: remote_process, schedule: schedule } end end diff[:removed].each do |removed_schedule| GoodData.logger.info("Removing schedule #{removed_schedule[:name]}") removed_schedule[:remote_schedule].delete results << { state: :removed, process: removed_schedule.process, schedule: removed_schedule } end results end |
.transfer_tagged_stuff(from_project, to_project, tag) ⇒ Object
582 583 584 585 586 587 588 589 590 591 592 593 |
# File 'lib/gooddata/models/project.rb', line 582 def transfer_tagged_stuff(from_project, to_project, tag) GoodData.logger.info("Transferring tagged stuff - #{tag}") objects = from_project.find_by_tag(tag) if objects.any? GoodData.logger.info("\n#{JSON.pretty_generate(objects)}") from_project.partial_md_export(objects, project: to_project) else GoodData.logger.info('No tagged objects to transfer') end end |
.transfer_user_groups(from_project, to_project) ⇒ Object
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 |
# File 'lib/gooddata/models/project.rb', line 410 def transfer_user_groups(from_project, to_project) from_project.user_groups.map do |ug| # migrate groups new_group = to_project.user_groups.select { |group| group.name == ug.name }.first new_group_status = new_group ? 'modified' : 'created' new_group ||= UserGroup.create(:name => ug.name, :description => ug.description, :project => to_project) new_group.project = to_project new_group.description = ug.description new_group.save # migrate dashboard "grantees" dashboards = from_project.dashboards dashboards.each do |dashboard| new_dashboard = to_project.dashboards.select { |dash| dash.title == dashboard.title }.first next unless new_dashboard grantee = dashboard.grantees['granteeURIs']['items'].select { |item| item['aclEntryURI']['grantee'].split('/').last == ug.links['self'].split('/').last }.first next unless grantee = grantee['aclEntryURI']['permission'] new_dashboard.grant(:member => new_group, :permission => ) end { from: from_project.pid, to: to_project.pid, user_group: new_group.name, status: new_group_status } end end |
.update_dataset_mapping(model_mapping_json, to_project) ⇒ Object
263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/gooddata/models/project.rb', line 263 def update_dataset_mapping(model_mapping_json, to_project) dataset_mapping = GoodData::DatasetMapping.new(model_mapping_json) res = dataset_mapping.save(:client => to_project.client, :project => to_project) status = res&.dig('datasetMappings', 'items').nil? ? "Failed" : "OK" count = "OK".eql?(status) ? res['datasetMappings']['items'].length : 0 { to: to_project.pid, count: count, status: status } end |
.user_csv_import(row) ⇒ Object
Takes one CSV line and creates hash from data extracted
184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/gooddata/models/project.rb', line 184 def user_csv_import(row) { 'user' => { 'content' => { 'email' => row[0], 'login' => row[1], 'firstname' => row[2], 'lastname' => row[3] }, 'meta' => {} } } end |
.verify_data_source_alias(ds_alias, client) ⇒ String
Verify whether the data source exists in the domain using its alias
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 |
# File 'lib/gooddata/models/project.rb', line 393 def verify_data_source_alias(ds_alias, client) domain = client.connection.server.url fail "The data source alias is empty, check your data source configuration." unless ds_alias uri = "/gdc/dataload/dataSources/internal/availableAlias?alias=#{ds_alias[:alias]}" res = client.get(uri) fail "Unable to get information about the Data Source '#{ds_alias[:alias]}' in the domain '#{domain}'" unless res fail "Unable to find the #{ds_alias[:type]} Data Source '#{ds_alias[:alias]}' in the domain '#{domain}'" if res['availableAlias']['available'] ds_type = res['availableAlias']['existingDataSource']['type'] if ds_type && ds_type != ds_alias[:type] fail "Wrong Data Source type - the '#{ds_type}' type is expected but the Data Source '#{ds_alias[:alias]}' in the domain '#{domain}' has the '#{ds_alias[:type]}' type" else res['availableAlias']['existingDataSource']['id'] end end |
Instance Method Details
#add ⇒ Object
2033 2034 2035 2036 |
# File 'lib/gooddata/models/project.rb', line 2033 def add @add ||= GoodData::AutomatedDataDistribution.new(self) @add end |
#add_dashboard(dashboard) ⇒ Object Also known as: create_dashboard
614 615 616 |
# File 'lib/gooddata/models/project.rb', line 614 def add_dashboard(dashboard) GoodData::Dashboard.create(dashboard, :client => client, :project => self) end |
#add_data_permissions(filters, options = {}) ⇒ Object
1949 1950 1951 1952 |
# File 'lib/gooddata/models/project.rb', line 1949 def (filters, = {}) GoodData.logger.info("Synchronizing #{filters.count} filters in project #{pid}") GoodData::UserFilterBuilder.execute_mufs(filters, { client: client, project: self }.merge()) end |
#add_metric(metric, options = {}) ⇒ GoodData::Report Also known as: create_metric, add_measure, create_measure
Creates a metric in a project
636 637 638 639 640 641 642 643 |
# File 'lib/gooddata/models/project.rb', line 636 def add_metric(metric, = {}) default = { client: client, project: self } if metric.is_a?(String) GoodData::Metric.xcreate(metric, .merge(default)) else GoodData::Metric.xcreate([:expression], metric.merge(.merge(default))) end end |
#add_report(options = {}) ⇒ GoodData::Report Also known as: create_report
Creates new instance of report in context of project
654 655 656 657 |
# File 'lib/gooddata/models/project.rb', line 654 def add_report( = {}) report = GoodData::Report.create(.merge(client: client, project: self)) report.save end |
#add_report_definition(json) ⇒ GoodData::ReportDefinition Also known as: create_report_definition
Creates new instance of report definition in context of project This report definition can be used for creating of GoodData::Report
666 667 668 669 670 671 |
# File 'lib/gooddata/models/project.rb', line 666 def add_report_definition(json) rd = GoodData::ReportDefinition.new(json) rd.client = client rd.project = self rd.save end |
#add_user_group(data) ⇒ Object Also known as: create_group
620 621 622 623 624 625 626 627 628 |
# File 'lib/gooddata/models/project.rb', line 620 def add_user_group(data) g = GoodData::UserGroup.create(data.merge(project: self)) begin g.save rescue RestClient::Conflict user_groups(data[:name]) end end |
#add_variable_permissions(filters, var, options = {}) ⇒ Object
1954 1955 1956 |
# File 'lib/gooddata/models/project.rb', line 1954 def (filters, var, = {}) GoodData::UserFilterBuilder.execute_variables(filters, var, { client: client, project: self }.merge()) end |
#am_i_admin? ⇒ Boolean
Returns an indication whether current user is admin in this project
678 679 680 |
# File 'lib/gooddata/models/project.rb', line 678 def am_i_admin? user_has_role?(client.user, 'admin') end |
#attribute_by_identifier(identifier) ⇒ Object
699 700 701 |
# File 'lib/gooddata/models/project.rb', line 699 def attribute_by_identifier(identifier) GoodData::Attribute.find_first_by_identifier(identifier, project: self, client: client) end |
#attribute_by_title(title) ⇒ Object
707 708 709 |
# File 'lib/gooddata/models/project.rb', line 707 def attribute_by_title(title) GoodData::Attribute.find_first_by_title(title, project: self, client: client) end |
#attributes(id = :all) ⇒ GoodData::Attribute | Array<GoodData::Attribute>
Helper for getting attributes of a project
686 687 688 |
# File 'lib/gooddata/models/project.rb', line 686 def attributes(id = :all) GoodData::Attribute[id, project: self, client: client] end |
#attributes_by_identifier(identifier) ⇒ Object
703 704 705 |
# File 'lib/gooddata/models/project.rb', line 703 def attributes_by_identifier(identifier) GoodData::Attribute.find_by_identifier(identifier, project: self, client: client) end |
#attributes_by_title(title) ⇒ Object
711 712 713 |
# File 'lib/gooddata/models/project.rb', line 711 def attributes_by_title(title) GoodData::Attribute.find_by_title(title, project: self, client: client) end |
#blueprint(options = {}) ⇒ GoodData::ProjectRole
Gets project blueprint from the server
718 719 720 721 722 723 724 725 726 727 |
# File 'lib/gooddata/models/project.rb', line 718 def blueprint( = {}) = { include_ca: true }.merge() result = client.get("/gdc/projects/#{pid}/model/view", params: { includeDeprecated: true, includeGrain: true, includeCA: [:include_ca] }) polling_url = result['asyncTask']['link']['poll'] model = client.poll_on_code(polling_url, ) bp = GoodData::Model::FromWire.from_wire(model, ) bp.title = title bp end |
#browser_uri(options = {}) ⇒ String
Returns web interface URI of project
732 733 734 735 736 737 738 739 740 |
# File 'lib/gooddata/models/project.rb', line 732 def browser_uri( = {}) grey = [:grey] server = client.connection.server_url if grey "#{server}#{uri}" else "#{server}/#s=#{uri}" end end |
#check_groups(specified_groups, user_groups_cache = nil, options = {}) ⇒ Object
1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 |
# File 'lib/gooddata/models/project.rb', line 1859 def check_groups(specified_groups, user_groups_cache = nil, = {}) current_user_groups = user_groups if user_groups_cache.nil? || user_groups_cache.empty? groups = current_user_groups.map(&:name) missing_groups = [] change_groups = {} specified_groups.each do |group| found_group = groups.find { |name| name.casecmp(group).zero? } if found_group.nil? missing_groups << group else # Change groups when they have similar group name with difference of case sensitivity if found_group != group change_groups[group] = found_group GoodData.logger.warn("Group with name #{group} is existed in project with name #{found_group}.") end end end if [:create_non_existing_user_groups] missing_groups.each do |g| GoodData.logger.info("Creating group #{g}") create_group(name: g, description: g) end else unless missing_groups.empty? fail 'All groups have to be specified before you try to import ' \ 'users. Groups that are currently in project are ' \ "#{groups.join(',')} and you asked for #{missing_groups.join(',')}" end end [current_user_groups, change_groups] end |
#clone(options = {}) ⇒ GoodData::Project
Clones project
749 750 751 752 753 754 755 756 757 758 759 760 761 762 |
# File 'lib/gooddata/models/project.rb', line 749 def clone( = {}) a_title = [:title] || "Clone of #{title}" begin # Create the project first so we know that it is passing. # What most likely is wrong is the token and the export actaully takes majority of the time new_project = GoodData::Project.create(.merge(:title => a_title, :client => client, :driver => content[:driver])) export_token = export_clone() new_project.import_clone(export_token) rescue new_project.delete if new_project raise end end |
#compute_metric(expression) ⇒ Object Also known as: compute_measure
851 852 853 |
# File 'lib/gooddata/models/project.rb', line 851 def compute_metric(expression) GoodData::Metric.xexecute(expression, client: client, project: self) end |
#compute_report(spec = {}) ⇒ Object
847 848 849 |
# File 'lib/gooddata/models/project.rb', line 847 def compute_report(spec = {}) GoodData::ReportDefinition.execute(spec.merge(client: client, project: self)) end |
#computed_attributes(id = :all) ⇒ Object
690 691 692 693 694 695 696 697 |
# File 'lib/gooddata/models/project.rb', line 690 def computed_attributes(id = :all) attrs = attributes(id) if attrs.is_a?(GoodData::Attribute) attrs.computed_attribute? ? attrs : nil else attrs.select(&:computed_attribute?) end end |
#create_custom_color_palette(colors) ⇒ Object
2074 2075 2076 |
# File 'lib/gooddata/models/project.rb', line 2074 def create_custom_color_palette(colors) GoodData::StyleSetting.create(colors, client: client, project: self) end |
#create_output_stage(ads, opts = {}) ⇒ Object
2062 2063 2064 |
# File 'lib/gooddata/models/project.rb', line 2062 def create_output_stage(ads, opts = {}) add.create_output_stage(ads, opts) end |
#create_schedule(process, date, executable, options = {}) ⇒ Object
857 858 859 860 |
# File 'lib/gooddata/models/project.rb', line 857 def create_schedule(process, date, executable, = {}) s = GoodData::Schedule.create(process, date, executable, .merge(client: client, project: self)) s.save end |
#create_variable(data) ⇒ Object
862 863 864 |
# File 'lib/gooddata/models/project.rb', line 862 def create_variable(data) GoodData::Variable.create(data, client: client, project: self) end |
#current_color_palette ⇒ Object
2070 2071 2072 |
# File 'lib/gooddata/models/project.rb', line 2070 def current_color_palette GoodData::StyleSetting.current(client: client, project: self) end |
#dashboards(id = :all) ⇒ GoodData::Dashboard | Array<GoodData::Dashboard>
Helper for getting dashboards of a project
870 871 872 |
# File 'lib/gooddata/models/project.rb', line 870 def dashboards(id = :all) GoodData::Dashboard[id, project: self, client: client] end |
#data_permissions(id = :all) ⇒ Object Also known as: user_filters
874 875 876 |
# File 'lib/gooddata/models/project.rb', line 874 def (id = :all) GoodData::MandatoryUserFilter[id, client: client, project: self] end |
#dataset_mapping ⇒ Object
2042 2043 2044 |
# File 'lib/gooddata/models/project.rb', line 2042 def dataset_mapping GoodData::Project.get_dataset_mapping(self) end |
#datasets(id = :all) ⇒ Array<GoodData::Dataset> | GoodData::Dataset
Gives you list of datasets. These are not blueprint datasets but model datasets coming from meta data server.
769 770 771 |
# File 'lib/gooddata/models/project.rb', line 769 def datasets(id = :all) GoodData::Dataset[id, project: self, client: client] end |
#delete ⇒ Object
Deletes project
880 881 882 883 |
# File 'lib/gooddata/models/project.rb', line 880 def delete fail "Project '#{title}' with id #{uri} is already deleted" if deleted? client.delete(uri) end |
#delete_all_data(options = {}) ⇒ Array
Helper for getting rid of all data in the project
896 897 898 899 900 901 902 903 904 905 |
# File 'lib/gooddata/models/project.rb', line 896 def delete_all_data( = {}) return false unless [:force] begin datasets.reject(&:date_dimension?).pmap(&:delete_data) rescue MaqlExecutionError => e # This is here so that we do not throw out exceptions on synchornizing date dimensions # Currently there is no reliable way how to tell it is a date dimension fail e unless GoodData::Helpers.(e.data['wTaskStatus']['messages']) == ["Internal error [handle_exception, hide_internal]."] end end |
#delete_dashboards ⇒ Object
Deletes dashboards for project
908 909 910 |
# File 'lib/gooddata/models/project.rb', line 908 def delete_dashboards Dashboard.all.map { |data| Dashboard[data['link']] }.each(&:delete) end |
#deleted? ⇒ Boolean
Returns true if project is in deleted state
888 889 890 |
# File 'lib/gooddata/models/project.rb', line 888 def deleted? state == :deleted end |
#deploy_process(path, options = {}) ⇒ Object
912 913 914 |
# File 'lib/gooddata/models/project.rb', line 912 def deploy_process(path, = {}) GoodData::Process.deploy(path, .merge(client: client, project: self)) end |
#dimensions(id = :all) ⇒ Object
773 774 775 |
# File 'lib/gooddata/models/project.rb', line 773 def dimensions(id = :all) GoodData::Dimension[id, client: client, project: self] end |
#disable_users(list, options = {}) ⇒ Object
1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 |
# File 'lib/gooddata/models/project.rb', line 1830 def disable_users(list, = {}) list = list.map(&:to_hash) url = "#{uri}/users" payloads = list.map do |u| uri, = resolve_roles(u, [], ) generate_user_payload(uri, 'DISABLED') end payloads.each_slice(100).mapcat do |payload| result = client.post(url, 'users' => payload) result['projectUsersUpdateResult'].mapcat { |k, v| v.map { |x| { type: k.to_sym, user: x } } } end end |
#download_file(file, where) ⇒ Object
1055 1056 1057 |
# File 'lib/gooddata/models/project.rb', line 1055 def download_file(file, where) GoodData.download_from_project_webdav(file, where, project: self) end |
#driver ⇒ Object
1059 1060 1061 |
# File 'lib/gooddata/models/project.rb', line 1059 def driver content['driver'] end |
#environment ⇒ Object
1063 1064 1065 |
# File 'lib/gooddata/models/project.rb', line 1063 def environment content['environment'] end |
#execute_dml(dml, options = {}) ⇒ Hash
Executes DML expression. See (https://developer.gooddata.com/article/deleting-records-from-datasets) for some examples and explanations
921 922 923 924 925 926 927 928 929 |
# File 'lib/gooddata/models/project.rb', line 921 def execute_dml(dml, = {}) uri = "/gdc/md/#{pid}/dml/manage" result = client.post(uri, manage: { maql: dml }) polling_uri = result['uri'] client.poll_on_response(polling_uri, ) do |body| body && body['taskState'] && body['taskState']['status'] == 'WAIT' end end |
#execute_maql(maql, options = {}) ⇒ Hash
Executes MAQL expression and waits for it to be finished.
935 936 937 938 939 940 941 942 943 944 945 946 947 948 |
# File 'lib/gooddata/models/project.rb', line 935 def execute_maql(maql, = {}) ldm_links = client.get(md[GoodData::Model::LDM_CTG]) ldm_uri = Links.new(ldm_links)[GoodData::Model::LDM_MANAGE_CTG] response = client.post(ldm_uri, manage: { maql: maql }) polling_uri = response['entries'].first['link'] result = client.poll_on_response(polling_uri, ) do |body| body && body['wTaskStatus'] && body['wTaskStatus']['status'] == 'RUNNING' end if result['wTaskStatus']['status'] == 'ERROR' fail MaqlExecutionError.new("Executionof MAQL '#{maql}' failed in project '#{pid}'", result) end result end |
#export_clone(options = {}) ⇒ String
Export a clone from a project to be later imported. If you do not want to do anything special and you do not need fine grained controle use clone method which does all the heavy lifting for you.
788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 |
# File 'lib/gooddata/models/project.rb', line 788 def export_clone( = {}) with_data = [:data].nil? ? true : [:data] with_users = [:users].nil? ? false : [:users] export = { :exportProject => { :exportUsers => with_users ? 1 : 0, :exportData => with_data ? 1 : 0 } } export[:exportProject][:authorizedUsers] = [:authorized_users] if [:authorized_users] if [:exclude_schedules] exclude_notifications = [:exclude_schedules] ? 1 : 0 export[:exportProject][:excludeSchedules] = exclude_notifications end if [:cross_data_center_export] cross_data_center = [:cross_data_center_export] ? 1 : 0 export[:exportProject][:crossDataCenterExport] = cross_data_center end result = client.post("/gdc/md/#{obj_id}/maintenance/export", export) status_url = result['exportArtifact']['status']['uri'] polling_result = client.poll_on_response(status_url) do |body| body['taskState']['status'] == 'RUNNING' end ensure_clone_task_ok(polling_result, GoodData::ExportCloneError) result['exportArtifact']['token'] end |
#fact_by_title(title) ⇒ Object
958 959 960 |
# File 'lib/gooddata/models/project.rb', line 958 def fact_by_title(title) GoodData::Fact.find_first_by_title(title, project: self, client: client) end |
#facts(id = :all) ⇒ GoodData::Fact | Array<GoodData::Fact>
Helper for getting facts of a project
954 955 956 |
# File 'lib/gooddata/models/project.rb', line 954 def facts(id = :all) GoodData::Fact[id, project: self, client: client] end |
#facts_by_title(title) ⇒ Object
962 963 964 |
# File 'lib/gooddata/models/project.rb', line 962 def facts_by_title(title) GoodData::Fact.find_by_title(title, project: self, client: client) end |
#find_attribute_element_value(uri) ⇒ Object
966 967 968 |
# File 'lib/gooddata/models/project.rb', line 966 def find_attribute_element_value(uri) GoodData::Attribute.find_element_value(uri, client: client, project: self) end |
#find_by_tag(tags) ⇒ Object
1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 |
# File 'lib/gooddata/models/project.rb', line 1078 def find_by_tag() = .split(',').map(&:strip) unless .is_a?(Array) objects = .map do |tag| url = "/gdc/md/#{pid}/tags/#{tag}" res = client.get(url) ((res || {})['entries'] || []).map do |entry| entry['link'] end end objects.flatten! objects.uniq! objects end |
#folders(id = :all) ⇒ Object
818 819 820 |
# File 'lib/gooddata/models/project.rb', line 818 def folders(id = :all) GoodData::Folder[id, project: self, client: client] end |
#fuzzy_get_user(name, user_list = users) ⇒ GoodDta::Membership
Gets user by its email, full_name, login or uri.
1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 |
# File 'lib/gooddata/models/project.rb', line 1102 def fuzzy_get_user(name, user_list = users) return name if name.instance_of?(GoodData::Membership) return member(name) if name.instance_of?(GoodData::Profile) name = name.is_a?(Hash) ? name[:login] || name[:uri] : name return nil unless name name.downcase! user_list.select do |user| user.uri.downcase == name || user.login.downcase == name || user.email.downcase == name end nil end |
#get_role(role_name, role_list = roles) ⇒ GoodData::ProjectRole
Gets project role
1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 |
# File 'lib/gooddata/models/project.rb', line 1015 def get_role(role_name, role_list = roles) return role_name if role_name.is_a? GoodData::ProjectRole role_name.downcase! role_list.each do |role| return role if role.uri == role_name || role.identifier.downcase == role_name || role.identifier.downcase.gsub(/role$/, '') == role_name || role.title.downcase == role_name || role.summary.downcase == role_name end nil end |
#get_role_by_identifier(role_name, role_list = roles) ⇒ GoodData::ProjectRole
Gets project role by its identifier
980 981 982 983 984 985 986 987 |
# File 'lib/gooddata/models/project.rb', line 980 def get_role_by_identifier(role_name, role_list = roles) role_name = role_name.downcase.gsub(/role$/, '') role_list.each do |role| tmp_role_name = role.identifier.downcase.gsub(/role$/, '') return role if tmp_role_name == role_name end nil end |
#get_role_by_summary(role_summary, role_list = roles) ⇒ GoodData::ProjectRole
Gets project role byt its summary
993 994 995 996 997 998 |
# File 'lib/gooddata/models/project.rb', line 993 def get_role_by_summary(role_summary, role_list = roles) role_list.each do |role| return role if role.summary.downcase == role_summary.downcase end nil end |
#get_role_by_title(role_title, role_list = roles) ⇒ GoodData::ProjectRole
Gets project role by its name
1004 1005 1006 1007 1008 1009 |
# File 'lib/gooddata/models/project.rb', line 1004 def get_role_by_title(role_title, role_list = roles) role_list.each do |role| return role if role.title.downcase == role_title.downcase end nil end |
#get_user(slug, user_list = users) ⇒ GoodDta::Membership Also known as: member
Gets user by its login or uri in various shapes It does not find by other information because that is not unique. If you want to search by name or email please use fuzzy_get_user.
1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 |
# File 'lib/gooddata/models/project.rb', line 1036 def get_user(slug, user_list = users) search_crit = if slug.respond_to?(:login) slug.login || slug.uri elsif slug.is_a?(Hash) slug[:login] || slug[:uri] else slug end return nil unless search_crit user_list.find do |user| user.uri == search_crit.downcase || user.login.downcase == search_crit.downcase end end |
#import_clone(export_token, options = {}) ⇒ Project
Imports a clone into current project. The project has to be freshly created.
831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 |
# File 'lib/gooddata/models/project.rb', line 831 def import_clone(export_token, = {}) import = { :importProject => { :token => export_token } } result = client.post("/gdc/md/#{obj_id}/maintenance/import", import) status_url = result['uri'] polling_result = client.poll_on_response(status_url, ) do |body| body['taskState']['status'] == 'RUNNING' end ensure_clone_task_ok(polling_result, GoodData::ImportCloneError) self end |
#import_users(new_users, options = {}) ⇒ Object
Imports users
1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 |
# File 'lib/gooddata/models/project.rb', line 1700 def import_users(new_users, = {}) role_list = roles users_list = users GoodData.logger.warn("Importing users to project (#{pid})") new_users = new_users.map { |x| ((x.is_a?(Hash) && x[:user] && x[:user].to_hash.merge(role: x[:role])) || x.to_hash).tap { |u| u[:login].downcase! } } # First check that if groups are provided we have them set up user_groups_cache, change_groups = check_groups(new_users.map(&:to_hash).flat_map { |u| u[:user_group] || [] }.uniq, [:user_groups_cache], ) unless change_groups.empty? new_users.each do |user| user[:user_group].map! { |e| change_groups[e].nil? ? e : change_groups[e] } end end whitelisted_new_users, whitelisted_users = whitelist_users(new_users.map(&:to_hash), users_list, [:whitelists]) # conform the role on list of new users so we can diff them with the users coming from the project diffable_new_with_default_role = whitelisted_new_users.map do |u| u[:role] = Array(u[:role] || u[:roles] || 'readOnlyUser') u end intermediate_new = diffable_new_with_default_role.map do |u| u[:role] = u[:role].map do |r| role = get_role(r, role_list) role ? role.uri : r end u[:role_title] = u[:role].map do |r| role = get_role(r, role_list) role ? role.title : r end if u[:role].all?(&:nil?) u[:type] = :error u[:reason] = 'Invalid role(s) specified' else u[:type] = :ok end u[:status] = 'ENABLED' u end intermediate_new_by_type = intermediate_new.group_by { |i| i[:type] } diffable_new = intermediate_new_by_type[:ok] || [] # Diff users. Only login and role is important for the diff diff = GoodData::Helpers.diff(whitelisted_users, diffable_new, key: :login, fields: [:login, :role, :status]) diff_results = diff.flat_map do |operation, users| if operation == :changed users.map { |u| u[:new_obj].merge(operation: operation) } else users.map { |u| u.merge(operation: operation) } end end diff_results = diff_results.map do |u| u[:login_uri] = USER_ACCOUNT_PATH + u[:login] u end return diff_results if [:dry_run] # Create new users results = [] GoodData.logger.warn("Creating #{diff[:added].count} users in project (#{pid})") to_create = diff[:added].map { |x| { user: x, role: x[:role] } } created_users_result = create_users(to_create, roles: role_list, project_users: whitelisted_users) @log_formatter.log_created_users(created_users_result, diff[:added]) results.concat(created_users_result) send_mail_to_new_users(diff[:added], [:email_options]) if [:email_options] && ![:email_options].empty? && !diff[:added].empty? # # Update existing users GoodData.logger.warn("Updating #{diff[:changed].count} users in project (#{pid})") to_update = diff[:changed].map { |x| { user: x[:new_obj], role: x[:new_obj][:role] || x[:new_obj][:roles] } } updated_users_result = set_users_roles(to_update, roles: role_list, project_users: whitelisted_users) @log_formatter.log_updated_users(updated_users_result, diff[:changed], role_list) results.concat(updated_users_result) unless [:do_not_touch_users_that_are_not_mentioned] # Remove old users to_disable = diff[:removed].reject { |user| user[:status] == 'DISABLED' || user[:status] == :disabled } GoodData.logger.warn("Disabling #{to_disable.count} users from project (#{pid})") disabled_users_result = disable_users(to_disable, roles: role_list, project_users: whitelisted_users) @log_formatter.log_disabled_users(disabled_users_result) results.concat(disabled_users_result) # Remove old users completely if [:remove_users_from_project] to_remove = (to_disable + users(disabled: true).to_a).map(&:to_hash).uniq do |user| user[:uri] end GoodData.logger.warn("Removing #{to_remove.count} users from project (#{pid})") removed_users_result = remove_users(to_remove) @log_formatter.log_removed_users(removed_users_result) results.concat(removed_users_result) end end # reassign to groups mappings = new_users.map(&:to_hash).flat_map do |user| groups = user[:user_group] || [] groups.map { |g| [user[:login], g] } end unless mappings.empty? users_lookup = users.reduce({}) do |a, e| a[e.login] = e a end mappings.group_by { |_, g| g }.each do |g, mapping| remote_users = mapping.map { |user, _| user }.map { |login| users_lookup[login] && users_lookup[login].uri }.reject(&:nil?) GoodData.logger.info("Assigning users #{remote_users} to group #{g}") next if remote_users.empty? existing_group = user_groups(g) if existing_group.nil? GoodData.logger.warn("Group #{g} not found!!!") else existing_group.set_members(remote_users) end end mentioned_groups = mappings.map(&:last).uniq groups_to_cleanup = user_groups_cache.reject { |g| mentioned_groups.include?(g.name) } # clean all groups not mentioned with exception of whitelisted users groups_to_cleanup.each do |g| g.set_members(whitelist_users(g.members.map(&:to_hash), [], [:whitelists], :include).first.map { |x| x[:uri] }) end end GoodData::Helpers.join(results, diff_results, [:user], [:login_uri]) end |
#info ⇒ Object
1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 |
# File 'lib/gooddata/models/project.rb', line 1400 def info results = blueprint.datasets.pmap do |ds| [ds, ds.count(self)] end GoodData.logger.info(title) GoodData.logger.info(GoodData::Helpers.underline(title)) GoodData.logger.info("\nDatasets - #{results.count}\n") results.each do |x| dataset, count = x dataset.title.tap do |t| GoodData.logger.info(t) GoodData.logger.info(GoodData::Helpers.underline(t)) GoodData.logger.info("Size - #{count} rows") GoodData.logger.info("#{dataset.attributes_and_anchors.count} attributes, #{dataset.facts.count} facts, #{dataset.references.count} references\n") end end nil end |
#invitations ⇒ Array<GoodData::Invitation>
Returns invitations to project
1179 1180 1181 1182 1183 1184 |
# File 'lib/gooddata/models/project.rb', line 1179 def invitations invitations = client.get @json['project']['links']['invitations'] invitations['invitations'].pmap do |invitation| client.create GoodData::Invitation, invitation end end |
#invite(email, role, msg = DEFAULT_INVITE_MESSAGE) ⇒ Object
Invites new user to project
TODO: Return invite object
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 |
# File 'lib/gooddata/models/project.rb', line 1145 def invite(email, role, msg = DEFAULT_INVITE_MESSAGE) GoodData.logger.info("Inviting #{email}, role: #{role}") role_url = nil if role.index('/gdc/').nil? tmp = get_role(role) role_url = tmp.uri if tmp else role_url = role if role_url.nil? end data = { :invitations => [ { :invitation => { :content => { :email => email, :role => role_url, :action => { :setMessage => msg } } } } ] } url = "/gdc/projects/#{pid}/invitations" client.post(url, data) end |
#labels(id = :all, opts = {}) ⇒ GoodData::Fact | Array<GoodData::Fact>
Helper for getting labels of a project
GoodData::Label[id] + it supports :all as welll
1198 1199 1200 1201 1202 1203 1204 |
# File 'lib/gooddata/models/project.rb', line 1198 def labels(id = :all, opts = {}) if id == :all attributes.pmapcat(&:labels).uniq else GoodData::Label[id, opts.merge(project: self, client: client)] end end |
#links ⇒ Hash
Returns project related links
1189 1190 1191 |
# File 'lib/gooddata/models/project.rb', line 1189 def links data['links'] end |
#maql_diff(options = {}) ⇒ Hash
get maql diff from another project or blueprint to current project
2089 2090 2091 2092 2093 2094 2095 2096 |
# File 'lib/gooddata/models/project.rb', line 2089 def maql_diff( = {}) fail "No :project or :blueprint specified" unless [:blueprint] || [:project] bp = [:blueprint] || [:project].blueprint uri = "/gdc/projects/#{pid}/model/diff" params = Hash[([:params] || []).map { |i| [i, true] }] result = client.post(uri, bp.to_wire, params: params) client.poll_on_code(result['asyncTask']['link']['poll']) end |
#md ⇒ Object
1206 1207 1208 |
# File 'lib/gooddata/models/project.rb', line 1206 def md @md ||= client.create(Links, client.get(data['links']['metadata'])) end |
#member?(profile, list = members) ⇒ Boolean
Checks if the profile is member of project
1252 1253 1254 |
# File 'lib/gooddata/models/project.rb', line 1252 def member?(profile, list = members) !member(profile, list).nil? end |
#members?(profiles, list = members) ⇒ Boolean
1256 1257 1258 |
# File 'lib/gooddata/models/project.rb', line 1256 def members?(profiles, list = members) profiles.map { |p| member?(p, list) } end |
#metadata(key = :all) ⇒ Hash
Get data from project specific metadata storage
1214 1215 1216 |
# File 'lib/gooddata/models/project.rb', line 1214 def (key = :all) GoodData::ProjectMetadata[key, client: client, project: self] end |
#metric_by_title(title) ⇒ Object Also known as: measure_by_title
1235 1236 1237 |
# File 'lib/gooddata/models/project.rb', line 1235 def metric_by_title(title) GoodData::Metric.find_first_by_title(title, project: self, client: client) end |
#metrics(id = :all, opts = { :full => true }) ⇒ Array<GoodData::Metric> Also known as: measures
Helper for getting metrics of a project
1229 1230 1231 |
# File 'lib/gooddata/models/project.rb', line 1229 def metrics(id = :all, opts = { :full => true }) GoodData::Metric[id, opts.merge(project: self, client: client)] end |
#metrics_by_title(title) ⇒ Object Also known as: measures_by_title
1241 1242 1243 |
# File 'lib/gooddata/models/project.rb', line 1241 def metrics_by_title(title) GoodData::Metric.find_by_title(title, project: self, client: client) end |
#obj_id ⇒ String Also known as: pid
Gets raw resource ID
1263 1264 1265 |
# File 'lib/gooddata/models/project.rb', line 1263 def obj_id uri.split('/').last end |
#objects(id, opts = {}) ⇒ Array<GoodData::MdObject>
Helper for getting objects of a project
1272 1273 1274 |
# File 'lib/gooddata/models/project.rb', line 1272 def objects(id, opts = {}) GoodData::MdObject[id, opts.merge(project: self, client: client)] end |
#objects_export(objs, options = {}) ⇒ String
Transfer objects from one project to another
1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 |
# File 'lib/gooddata/models/project.rb', line 1283 def objects_export(objs, = {}) fail 'Nothing to migrate. You have to pass list of objects, ids or uris that you would like to migrate' if objs.nil? objs = Array(objs).map { |o| o.respond_to?(:uri) ? o.uri : o } if objs.empty? GoodData.logger.warn 'Nothing to migrate.' return end export_payload = { :partialMDExport => { :uris => objs, :exportAttributeProperties => '1', :crossDataCenterExport => '1' } } result = client.post("#{md['maintenance']}/partialmdexport", export_payload) polling_url = result['partialMDArtifact']['status']['uri'] token = result['partialMDArtifact']['token'] polling_result = client.poll_on_response(polling_url, ) do |body| body['wTaskStatus'] && body['wTaskStatus']['status'] == 'RUNNING' end if polling_result['wTaskStatus'] && polling_result['wTaskStatus']['status'] == 'ERROR' = GoodData::Helpers.(polling_result['wTaskStatus']['messages']).join(' ') fail ObjectsExportError, "Exporting objects failed with messages. #{}" end token end |
#objects_import(token, options = {}) ⇒ Boolean
Import objects from import token. If you do not need specifically this method what you are probably looking for is transfer_objects. This is a lower level method.
1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 |
# File 'lib/gooddata/models/project.rb', line 1319 def objects_import(token, = {}) fail 'You need to provide a token for object import' if token.blank? import_payload = { :partialMDImport => { :token => token, :overwriteNewer => '1', :updateLDMObjects => '1', :importAttributeProperties => '1' } } result = client.post("#{md['maintenance']}/partialmdimport", import_payload) polling_url = result['uri'] polling_result = client.poll_on_response(polling_url, ) do |body| body['wTaskStatus'] && body['wTaskStatus']['status'] == 'RUNNING' end if polling_result['wTaskStatus']['status'] == 'ERROR' = GoodData::Helpers.(polling_result['wTaskStatus']['messages']).join(' ') fail ObjectsImportError, "Importing objects failed with messages. #{}" end true end |
#partial_md_export(objects, options = {}) ⇒ Boolean | Array<Hash> Also known as: transfer_objects
Transfer objects from one project to another
if you passed only one project. If you provided an array returns list of hashes signifying sucees or failure. Take note that in case of list of projects it does not throw exception.
1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 |
# File 'lib/gooddata/models/project.rb', line 1356 def partial_md_export(objects, = {}) projects = [:project] batch_size = [:batch_size] || 10 token = objects_export(objects) return if token.nil? if projects.is_a?(Array) projects.each_slice(batch_size).flat_map do |batch| batch.pmap do |proj| target_project = client.projects(proj) target_project.objects_import(token, ) { project: target_project, result: true } end end else target_project = client.projects(projects) target_project.objects_import(token, ) [{ project: target_project, result: true }] end end |
#processes(id = :all) ⇒ GoodData::Report | Array<GoodData::Report>
Helper for getting processes of a project
1389 1390 1391 |
# File 'lib/gooddata/models/project.rb', line 1389 def processes(id = :all) GoodData::Process[id, project: self, client: client] end |
#project? ⇒ Boolean
Checks if this object instance is project
1396 1397 1398 |
# File 'lib/gooddata/models/project.rb', line 1396 def project? true end |
#project_webdav_path ⇒ String
Get WebDav directory for project data
972 973 974 |
# File 'lib/gooddata/models/project.rb', line 972 def project_webdav_path client.project_webdav_path(:project => self) end |
#public? ⇒ Boolean
1067 1068 1069 |
# File 'lib/gooddata/models/project.rb', line 1067 def public? content['isPublic'] end |
#reload! ⇒ Object
Forces project to reload
1420 1421 1422 1423 1424 1425 1426 |
# File 'lib/gooddata/models/project.rb', line 1420 def reload! if saved? response = client.get(uri) @json = response end self end |
#remove_users(list) ⇒ Object
1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 |
# File 'lib/gooddata/models/project.rb', line 1844 def remove_users(list) list = list.map(&:to_hash) list.pmapcat do |u| u_id = GoodData::Helpers.last_uri_part(u[:uri]) url = "#{uri}/users/#{u_id}" begin client.delete(url) [{ type: :successful, operation: :user_deleted_from_project, user: u }] rescue => e [{ type: :failed, message: e., user: u }] end end end |
#replace_from_mapping(mapping, opts = {}) ⇒ Object
Method used for walking through objects in project and trying to replace all occurences of some object for another object. This is typically used as a means for exchanging Date dimensions.
1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 |
# File 'lib/gooddata/models/project.rb', line 1433 def replace_from_mapping(mapping, opts = {}) default = { :purge => false, :dry_run => false } opts = default.merge(opts) dry_run = opts[:dry_run] if opts[:purge] GoodData.logger.info 'Purging old project definitions' reports.peach(&:purge_report_of_unused_definitions!) end fail ArgumentError, 'No mapping specified' if mapping.blank? rds = report_definitions { # data_permissions: data_permissions, variables: variables, dashboards: dashboards, metrics: metrics, report_definitions: rds }.each do |key, collection| GoodData.logger.info("Replacing #{key}") collection.peach do |item| new_item = item.replace(mapping) if new_item.json != item.json if dry_run GoodData.logger.info "Would save #{new_item.uri}. Running in dry run mode" else GoodData.logger.info "Saving #{new_item.uri}" new_item.save end else GoodData.logger.info "Ignore #{item.uri}" end end end GoodData.logger.info 'Replacing hidden metrics' local_metrics = mapping.map { |a, _| a }.pmapcat { |a| a.usedby('metric') }.select { |m| m['deprecated'] == '1' }.map { |m| m['link'] }.uniq GoodData.logger.info("Found #{local_metrics.count} metrics") local_metrics.pmap { |m| metrics(m) }.peach do |item| new_item = item.replace(mapping) if new_item.json != item.json if dry_run GoodData.logger.info "Would save #{new_item.uri}. Running in dry run mode" else GoodData.logger.info "Saving #{new_item.uri}" new_item.save end else GoodData.logger.info "Ignore #{item.uri}" end end GoodData.logger.info 'Replacing dashboard saved views' contexts = mapping.map { |a, _| a }.pmapcat { |a| a.usedby('executionContext') }.map { |a| GoodData::MdObject[a['link'], client: client, project: self] } GoodData.logger.info("Found #{contexts.count} dashboard saved views") contexts.peach do |item| new_item = GoodData::MdObject.replace_quoted(item, mapping) if new_item.json != item.json if dry_run GoodData.logger.info "Would save #{new_item.uri}. Running in dry run mode" else GoodData.logger.info "Saving #{new_item.uri}" new_item.save end else GoodData.logger.info "Ignore #{item.uri}" end end GoodData.logger.info 'Replacing variable values' variables.each do |var| var.values.peach do |val| val.replace(mapping).save unless dry_run end end { visualizations: MdObject.query('visualizationObject', MdObject, client: client, project: self), visualization_widgets: MdObject.query('visualizationWidget', MdObject, client: client, project: self), kpis: MdObject.query('kpi', MdObject, client: client, project: self) }.each do |key, collection| GoodData.logger.info "Replacing #{key}" collection.each do |item| new_item = MdObject.replace_quoted(item, mapping) if new_item.json != item.json if dry_run GoodData.logger.info "Would save #{new_item.uri}. Running in dry run mode" else GoodData.logger.info "Saving #{new_item.uri}" new_item.save end else GoodData.logger.info "Ignore #{item.uri}" end end end nil end |
#report_definitions(id = :all, options = {}) ⇒ GoodData::ReportDefinition | Array<GoodData::ReportDefinition>
Helper for getting report definitions of a project
1548 1549 1550 |
# File 'lib/gooddata/models/project.rb', line 1548 def report_definitions(id = :all, = {}) GoodData::ReportDefinition[id, .merge(project: self, client: client)] end |
#reports(id = :all) ⇒ GoodData::Report | Array<GoodData::Report>
Helper for getting reports of a project
1540 1541 1542 |
# File 'lib/gooddata/models/project.rb', line 1540 def reports(id = :all) GoodData::Report[id, project: self, client: client] end |
#reset_color_palette ⇒ Object
2078 2079 2080 |
# File 'lib/gooddata/models/project.rb', line 2078 def reset_color_palette GoodData::StyleSetting.reset(client: client, project: self) end |
#resolve_roles(login, desired_roles, options = {}) ⇒ Object
1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 |
# File 'lib/gooddata/models/project.rb', line 1992 def resolve_roles(login, desired_roles, = {}) user = if login.is_a?(String) && login.include?('@') USER_ACCOUNT_PATH + login elsif login.is_a?(String) login elsif login.is_a?(Hash) && login[:login] USER_ACCOUNT_PATH + login[:login] elsif login.is_a?(Hash) && login[:uri] login[:uri] elsif login.respond_to?(:uri) && login.uri login.uri elsif login.respond_to?(:login) && login.login USER_ACCOUNT_PATH + login.login else fail "Unsupported user specification #{login}" end role_list = [:roles] || roles desired_roles = Array(desired_roles) roles = desired_roles.map do |role_name| role = get_role(role_name, role_list) fail ArgumentError, "Invalid role '#{role_name}' specified for user '#{GoodData::Helpers.last_uri_part(user)}'" if role.nil? role.uri end [user, roles] end |
#roles ⇒ Array<GoodData::ProjectRole>
Gets the list or project roles
1555 1556 1557 1558 1559 1560 1561 |
# File 'lib/gooddata/models/project.rb', line 1555 def roles url = "/gdc/internal/projects/#{pid}/roles" res = client.get url res['internalProjectRoles']['roles'].map do |r| client.create(GoodData::ProjectRole, r, project: self) end end |
#save ⇒ Object
Saves project
1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 |
# File 'lib/gooddata/models/project.rb', line 1564 def save data_to_send = GoodData::Helpers.deep_dup(raw_data) data_to_send['project']['content'].delete('cluster') data_to_send['project']['content'].delete('isPublic') data_to_send['project']['content'].delete('state') response = if uri client.post(PROJECT_PATH % pid, data_to_send) client.get uri else result = client.post(PROJECTS_PATH, data_to_send) client.get result['uri'] end @json = response self end |
#schedule_mail(options = GoodData::ScheduledMail::DEFAULT_OPTS) ⇒ Object
Schedules an email with dashboard or report content
1581 1582 1583 |
# File 'lib/gooddata/models/project.rb', line 1581 def schedule_mail( = GoodData::ScheduledMail::DEFAULT_OPTS) GoodData::ScheduledMail.create(.merge(client: client, project: self)) end |
#scheduled_mails(options = { :full => false }) ⇒ Object
1585 1586 1587 |
# File 'lib/gooddata/models/project.rb', line 1585 def scheduled_mails( = { :full => false }) GoodData::ScheduledMail[:all, .merge(project: self, client: client)] end |
#schedules(id = :all) ⇒ GoodData::Schedule | Array<GoodData::Schedule>
Returns schedule instance or list.
1591 1592 1593 |
# File 'lib/gooddata/models/project.rb', line 1591 def schedules(id = :all) GoodData::Schedule[id, project: self, client: client] end |
#set_metadata(key, val) ⇒ String
Set data for specific key in project specific metadata storage
1222 1223 1224 |
# File 'lib/gooddata/models/project.rb', line 1222 def (key, val) GoodData::ProjectMetadata.[]=(key, { client: client, project: self }, val) end |
#set_user_roles(login, desired_roles, options = {}) ⇒ Object Also known as: add_user
Update user
1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 |
# File 'lib/gooddata/models/project.rb', line 1896 def set_user_roles(login, desired_roles, = {}) user_uri, roles = resolve_roles(login, desired_roles, ) url = "#{uri}/users" payload = generate_user_payload(user_uri, 'ENABLED', roles) res = client.post(url, payload) failure = GoodData::Helpers.get_path(res, %w(projectUsersUpdateResult failed)) fail ArgumentError, "User #{user_uri} could not be added. #{failure.first['message']}" unless failure.blank? res end |
#set_users_roles(list, options = {}) ⇒ Object Also known as: add_users, create_users
Update list of users
1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 |
# File 'lib/gooddata/models/project.rb', line 1912 def set_users_roles(list, = {}) return [] if list.empty? role_list = [:roles] || roles project_users = [:project_users] || users intermediate_users = list.flat_map do |user_hash| user = user_hash[:user] || user_hash[:login] desired_roles = user_hash[:role] || user_hash[:roles] || 'readOnlyUser' begin login, roles = resolve_roles(user, desired_roles, .merge(project_users: project_users, roles: role_list)) [{ :type => :successful, user: login, roles: roles }] rescue => e [{ :type => :failed, :reason => e., user: user, roles: desired_roles }] end end # User can fail pre sending to API during resolving roles. We add only users that passed that step. users_by_type = intermediate_users.group_by { |u| u[:type] } users_to_add = users_by_type[:successful] || [] payloads = users_to_add.map { |u| generate_user_payload(u[:user], 'ENABLED', u[:roles]) } results = payloads.each_slice(100).map do |payload| client.post("#{uri}/users", 'users' => payload) end # this ugly line turns the hash of errors into list of errors with types so we can process them easily typed_results = results.flat_map do |x| x['projectUsersUpdateResult'].flat_map do |k, v| v.map { |v2| v2.is_a?(String) ? { type: k.to_sym, user: v2 } : GoodData::Helpers.symbolize_keys(v2).merge(type: k.to_sym) } end end # we have to concat errors from role resolution and API result typed_results + (users_by_type[:failed] || []) end |
#slis ⇒ GoodData::Metadata
Gets SLIs data
1598 1599 1600 1601 1602 1603 |
# File 'lib/gooddata/models/project.rb', line 1598 def slis link = "#{data['links']['metadata']}#{SLIS_PATH}" # FIXME: Review what to do with passed extra argument Metadata.new client.get(link) end |
#state ⇒ String
Gets project state
1608 1609 1610 |
# File 'lib/gooddata/models/project.rb', line 1608 def state data['content']['state'].downcase.to_sym if data['content'] && data['content']['state'] end |
#title=(a_title) ⇒ String
Gets project title
1617 1618 1619 |
# File 'lib/gooddata/models/project.rb', line 1617 def title=(a_title) data['meta']['title'] = a_title if data['meta'] end |
#token ⇒ Object
1071 1072 1073 |
# File 'lib/gooddata/models/project.rb', line 1071 def token content['authorizationToken'] end |
#transfer_color_palette(target) ⇒ Object
2066 2067 2068 |
# File 'lib/gooddata/models/project.rb', line 2066 def transfer_color_palette(target) GoodData::Project.transfer_color_palette(self, target) end |
#transfer_etl(target) ⇒ Object
2038 2039 2040 |
# File 'lib/gooddata/models/project.rb', line 2038 def transfer_etl(target) GoodData::Project.transfer_etl(client, self, target) end |
#transfer_processes(target) ⇒ Object
2050 2051 2052 |
# File 'lib/gooddata/models/project.rb', line 2050 def transfer_processes(target) GoodData::Project.transfer_processes(self, target) end |
#transfer_schedules(target) ⇒ Object
2054 2055 2056 |
# File 'lib/gooddata/models/project.rb', line 2054 def transfer_schedules(target) GoodData::Project.transfer_schedules(self, target) end |
#transfer_tagged_stuff(target, tag) ⇒ Object
2058 2059 2060 |
# File 'lib/gooddata/models/project.rb', line 2058 def transfer_tagged_stuff(target, tag) GoodData::Project.transfer_tagged_stuff(self, target, tag) end |
#update_dataset_mapping(model_mapping_json) ⇒ Object
2046 2047 2048 |
# File 'lib/gooddata/models/project.rb', line 2046 def update_dataset_mapping(model_mapping_json) GoodData::Project.update_dataset_mapping(model_mapping_json, self) end |
#update_from_blueprint(blueprint, options = {}) ⇒ Object
Applies blueprint to the project.
1988 1989 1990 |
# File 'lib/gooddata/models/project.rb', line 1988 def update_from_blueprint(blueprint, = {}) GoodData::Model::ProjectCreator.migrate(.merge(spec: blueprint, token: [:auth_token], client: client, project: self)) end |
#upgrade_custom_v2(message, options = {}) ⇒ Object
2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 |
# File 'lib/gooddata/models/project.rb', line 2019 def upgrade_custom_v2(, = {}) uri = "/gdc/md/#{pid}/datedimension/upgrade" poll_result = client&.post(uri, ) return poll_result['wTaskStatus']['status'] if poll_result['wTaskStatus'] && poll_result['wTaskStatus']['status'] polling_uri = poll_result['asyncTask']['link']['poll'] result = client&.poll_on_response(polling_uri, ) do |body| body && body['wTaskStatus'] && body['wTaskStatus']['status'] == 'RUNNING' end result['wTaskStatus']['status'] == 'OK' ? 'OK' : 'FAIL' end |
#upload(data, blueprint, dataset_name, options = {}) ⇒ Object
Uploads file to project
1625 1626 1627 |
# File 'lib/gooddata/models/project.rb', line 1625 def upload(data, blueprint, dataset_name, = {}) GoodData::Model.upload_data(data, blueprint, dataset_name, .merge(client: client, project: self)) end |
#upload_file(file, options = {}) ⇒ Object
1051 1052 1053 |
# File 'lib/gooddata/models/project.rb', line 1051 def upload_file(file, = {}) GoodData.upload_to_project_webdav(file, .merge(project: self)) end |
#upload_multiple(data, blueprint, options = {}) ⇒ Object
1629 1630 1631 |
# File 'lib/gooddata/models/project.rb', line 1629 def upload_multiple(data, blueprint, = {}) GoodData::Model.upload_multiple_data(data, blueprint, .merge(client: client, project: self)) end |
#uri ⇒ Object
1633 1634 1635 |
# File 'lib/gooddata/models/project.rb', line 1633 def uri data['links']['self'] if data && data['links'] && data['links']['self'] end |
#user_groups(id = :all, options = {}) ⇒ Object
822 823 824 |
# File 'lib/gooddata/models/project.rb', line 822 def user_groups(id = :all, = {}) GoodData::UserGroup[id, .merge(project: self)] end |
#user_has_role?(user, role_name) ⇒ Boolean
Checks whether user has particular role in given proejct
1121 1122 1123 1124 1125 1126 1127 |
# File 'lib/gooddata/models/project.rb', line 1121 def user_has_role?(user, role_name) member = get_user(user) role = get_role(role_name) member.roles.include?(role) rescue false end |
#users(opts = {}) ⇒ Array<GoodData::User> Also known as: members
List of users in project
1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 |
# File 'lib/gooddata/models/project.rb', line 1641 def users(opts = {}) client = client(opts) all_users = [] offset = opts[:offset] || 0 limit = opts[:limit] || 1_000 loop do tmp = client.get("/gdc/projects/#{pid}/users", params: { offset: offset, limit: limit }) tmp['users'].each do |user_data| user = client.create(GoodData::Membership, user_data, project: self) if opts[:all] all_users << user elsif opts[:disabled] all_users << user if user&.disabled? else all_users << user if user&.enabled? end end break if tmp['users'].count < limit offset += limit end all_users end |
#validate(filters = %w(ldm pdm metric_filter invalid_objects), options = {}) ⇒ Object
Run validation on project Valid settins for validation are (default all): ldm - Checks the consistency of LDM objects. pdm Checks LDM to PDM mapping consistency, also checks PDM reference integrity. metric_filter - Checks metadata for inconsistent metric filters. invalid_objects - Checks metadata for invalid/corrupted objects. asyncTask response
1965 1966 1967 1968 1969 1970 1971 |
# File 'lib/gooddata/models/project.rb', line 1965 def validate(filters = %w(ldm pdm metric_filter invalid_objects), = {}) response = client.post "#{md['validate-project']}", 'validateProject' => filters polling_link = response['asyncTask']['link']['poll'] client.poll_on_response(polling_link, ) do |body| body['wTaskStatus'] && body['wTaskStatus']['status'] == 'RUNNING' end end |
#variables(id = :all, options = { client: client, project: self }) ⇒ Object
1973 1974 1975 |
# File 'lib/gooddata/models/project.rb', line 1973 def variables(id = :all, = { client: client, project: self }) GoodData::Variable[id, ] end |
#whitelist_users(new_users, users_list, whitelist, mode = :exclude) ⇒ Object
1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 |
# File 'lib/gooddata/models/project.rb', line 1669 def whitelist_users(new_users, users_list, whitelist, mode = :exclude) return [new_users, users_list] unless whitelist new_whitelist_proc = proc do |user| whitelist.any? do |wl| if wl.is_a?(Regexp) user[:login] =~ wl else user[:login] && user[:login] == wl end end end whitelist_proc = proc do |user| whitelist.any? do |wl| if wl.is_a?(Regexp) user.login =~ wl else user.login && user.login == wl end end end if mode == :include [new_users.select(&new_whitelist_proc), users_list.select(&whitelist_proc)] elsif mode == :exclude [new_users.reject(&new_whitelist_proc), users_list.reject(&whitelist_proc)] end end |