gooddata 0.6.49 → 0.6.50

Sign up to get free protection for your applications and to get access to all the features.
Files changed (390) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -4
  3. data/CLI.md +0 -4
  4. data/DEPENDENCIES.md +0 -8
  5. data/Dockerfile.jruby +19 -0
  6. data/Dockerfile.ruby +19 -0
  7. data/LICENSE +2 -2
  8. data/LICENSE.rb +1 -1
  9. data/Rakefile +1 -1
  10. data/gooddata.gemspec +29 -28
  11. data/lib/gooddata.rb +2 -1
  12. data/lib/gooddata/app/app.rb +1 -1
  13. data/lib/gooddata/bricks/base_downloader.rb +1 -1
  14. data/lib/gooddata/bricks/brick.rb +3 -4
  15. data/lib/gooddata/bricks/bricks.rb +3 -1
  16. data/lib/gooddata/bricks/middleware/aws_middleware.rb +6 -8
  17. data/lib/gooddata/bricks/middleware/base_middleware.rb +2 -1
  18. data/lib/gooddata/bricks/middleware/bench_middleware.rb +2 -1
  19. data/lib/gooddata/bricks/middleware/bulk_salesforce_middleware.rb +3 -3
  20. data/lib/gooddata/bricks/middleware/decode_params_middleware.rb +3 -2
  21. data/lib/gooddata/bricks/middleware/dwh_middleware.rb +28 -0
  22. data/lib/gooddata/bricks/middleware/fs_download_middleware.rb +2 -2
  23. data/lib/gooddata/bricks/middleware/fs_upload_middleware.rb +2 -2
  24. data/lib/gooddata/bricks/middleware/gooddata_middleware.rb +84 -21
  25. data/lib/gooddata/bricks/middleware/logger_middleware.rb +1 -1
  26. data/lib/gooddata/bricks/middleware/middleware.rb +1 -1
  27. data/lib/gooddata/bricks/middleware/params_inspect_middleware.rb +21 -0
  28. data/lib/gooddata/bricks/middleware/restforce_middleware.rb +26 -26
  29. data/lib/gooddata/bricks/middleware/stdout_middleware.rb +1 -1
  30. data/lib/gooddata/bricks/middleware/twitter_middleware.rb +1 -1
  31. data/lib/gooddata/bricks/middleware/undot_params_middleware.rb +1 -1
  32. data/lib/gooddata/bricks/pipeline.rb +6 -13
  33. data/lib/gooddata/bricks/utils.rb +3 -3
  34. data/lib/gooddata/cli/cli.rb +1 -1
  35. data/lib/gooddata/cli/commands/auth_cmd.rb +1 -1
  36. data/lib/gooddata/cli/commands/domain_cmd.rb +1 -1
  37. data/lib/gooddata/cli/commands/project_cmd.rb +1 -18
  38. data/lib/gooddata/cli/hooks.rb +1 -2
  39. data/lib/gooddata/cli/shared.rb +1 -1
  40. data/lib/gooddata/cli/terminal.rb +1 -1
  41. data/lib/gooddata/client.rb +1 -1
  42. data/lib/gooddata/commands/api.rb +1 -1
  43. data/lib/gooddata/commands/auth.rb +1 -1
  44. data/lib/gooddata/commands/base.rb +1 -1
  45. data/lib/gooddata/commands/commands.rb +1 -1
  46. data/lib/gooddata/commands/datasets.rb +1 -1
  47. data/lib/gooddata/commands/datawarehouse.rb +1 -1
  48. data/lib/gooddata/commands/domain.rb +1 -1
  49. data/lib/gooddata/commands/process.rb +1 -1
  50. data/lib/gooddata/commands/project.rb +2 -31
  51. data/lib/gooddata/commands/projects.rb +1 -1
  52. data/lib/gooddata/commands/role.rb +1 -1
  53. data/lib/gooddata/commands/runners.rb +1 -1
  54. data/lib/gooddata/commands/scaffold.rb +1 -1
  55. data/lib/gooddata/commands/user.rb +1 -1
  56. data/lib/gooddata/connection.rb +1 -1
  57. data/lib/gooddata/core/core.rb +1 -1
  58. data/lib/gooddata/core/logging.rb +1 -1
  59. data/lib/gooddata/core/nil_logger.rb +1 -1
  60. data/lib/gooddata/core/project.rb +1 -1
  61. data/lib/gooddata/core/rest.rb +1 -1
  62. data/lib/gooddata/core/user.rb +1 -1
  63. data/lib/gooddata/data/data.rb +1 -1
  64. data/lib/gooddata/data/guesser.rb +1 -1
  65. data/lib/gooddata/exceptions/attr_element_not_found.rb +1 -1
  66. data/lib/gooddata/exceptions/command_failed.rb +1 -1
  67. data/lib/gooddata/exceptions/exceptions.rb +1 -1
  68. data/lib/gooddata/exceptions/execution_limit_exceeded.rb +1 -1
  69. data/lib/gooddata/exceptions/export_clone.rb +4 -0
  70. data/lib/gooddata/exceptions/filter_maqlization.rb +1 -1
  71. data/lib/gooddata/exceptions/import_clone.rb +4 -0
  72. data/lib/gooddata/exceptions/malformed_user.rb +1 -1
  73. data/lib/gooddata/exceptions/maql_execution.rb +1 -1
  74. data/lib/gooddata/exceptions/no_project_error.rb +1 -1
  75. data/lib/gooddata/exceptions/object_migration.rb +1 -1
  76. data/lib/gooddata/exceptions/project_not_found.rb +1 -1
  77. data/lib/gooddata/exceptions/segment_not_empty.rb +1 -1
  78. data/lib/gooddata/exceptions/uncomputable_report.rb +1 -1
  79. data/lib/gooddata/exceptions/user_in_different_domain.rb +1 -1
  80. data/lib/gooddata/exceptions/validation_error.rb +1 -1
  81. data/lib/gooddata/extensions/big_decimal.rb +1 -1
  82. data/lib/gooddata/extensions/class.rb +11 -0
  83. data/lib/gooddata/extensions/enumerable.rb +1 -1
  84. data/lib/gooddata/extensions/extensions.rb +1 -1
  85. data/lib/gooddata/extensions/false.rb +9 -1
  86. data/lib/gooddata/extensions/hash.rb +12 -1
  87. data/lib/gooddata/extensions/integer.rb +5 -0
  88. data/lib/gooddata/extensions/nil.rb +5 -1
  89. data/lib/gooddata/extensions/numeric.rb +1 -1
  90. data/lib/gooddata/extensions/object.rb +5 -1
  91. data/lib/gooddata/extensions/symbol.rb +1 -1
  92. data/lib/gooddata/extensions/true.rb +9 -1
  93. data/lib/gooddata/extract.rb +1 -1
  94. data/lib/gooddata/goodzilla/goodzilla.rb +1 -1
  95. data/lib/gooddata/helpers/auth_helpers.rb +1 -1
  96. data/lib/gooddata/helpers/csv_helper.rb +1 -1
  97. data/lib/gooddata/helpers/data_helper.rb +19 -10
  98. data/lib/gooddata/helpers/erb_helper.rb +23 -0
  99. data/lib/gooddata/helpers/global_helpers.rb +5 -73
  100. data/lib/gooddata/helpers/global_helpers_params.rb +73 -7
  101. data/lib/gooddata/helpers/helpers.rb +1 -1
  102. data/lib/gooddata/lcm/actions/actions.rb +12 -0
  103. data/lib/gooddata/lcm/actions/associate_clients.rb +46 -0
  104. data/lib/gooddata/lcm/actions/base_action.rb +23 -0
  105. data/lib/gooddata/lcm/actions/collect_clients.rb +89 -0
  106. data/lib/gooddata/lcm/actions/collect_segment_clients.rb +103 -0
  107. data/lib/gooddata/lcm/actions/collect_segments.rb +59 -0
  108. data/lib/gooddata/lcm/actions/create_segment_masters.rb +167 -0
  109. data/lib/gooddata/lcm/actions/ensure_release_table.rb +56 -0
  110. data/lib/gooddata/lcm/actions/ensure_segments.rb +35 -0
  111. data/lib/gooddata/lcm/actions/ensure_technical_users_domain.rb +66 -0
  112. data/lib/gooddata/lcm/actions/ensure_technical_users_project.rb +68 -0
  113. data/lib/gooddata/lcm/actions/ensure_titles.rb +54 -0
  114. data/lib/gooddata/lcm/actions/hello_world.rb +44 -0
  115. data/lib/gooddata/lcm/actions/print_actions.rb +61 -0
  116. data/lib/gooddata/lcm/actions/print_modes.rb +72 -0
  117. data/lib/gooddata/lcm/actions/print_types.rb +55 -0
  118. data/lib/gooddata/lcm/actions/provision_clients.rb +80 -0
  119. data/lib/gooddata/lcm/actions/purge_clients.rb +78 -0
  120. data/lib/gooddata/lcm/actions/segments_filter.rb +50 -0
  121. data/lib/gooddata/lcm/actions/synchronize_attribute_drillpaths.rb +60 -0
  122. data/lib/gooddata/lcm/actions/synchronize_clients.rb +87 -0
  123. data/lib/gooddata/lcm/actions/synchronize_color_palette.rb +59 -0
  124. data/lib/gooddata/lcm/actions/synchronize_label_types.rb +61 -0
  125. data/lib/gooddata/lcm/actions/synchronize_ldm.rb +64 -0
  126. data/lib/gooddata/lcm/actions/synchronize_meta.rb +55 -0
  127. data/lib/gooddata/lcm/actions/synchronize_new_segments.rb +55 -0
  128. data/lib/gooddata/lcm/actions/synchronize_processes.rb +66 -0
  129. data/lib/gooddata/lcm/actions/synchronize_schedules.rb +81 -0
  130. data/lib/gooddata/lcm/actions/update_release_table.rb +80 -0
  131. data/lib/gooddata/lcm/data/create_lcm_release.sql.erb +5 -0
  132. data/lib/gooddata/lcm/data/insert_into_lcm_release.sql.erb +11 -0
  133. data/lib/gooddata/lcm/data/select_from_lcm_release.sql.erb +8 -0
  134. data/lib/gooddata/lcm/data/update_lcm_release.sql.erb +7 -0
  135. data/lib/gooddata/lcm/dsl/dsl.rb +50 -0
  136. data/lib/gooddata/lcm/dsl/params_dsl.rb +61 -0
  137. data/lib/gooddata/lcm/dsl/type_dsl.rb +61 -0
  138. data/lib/gooddata/lcm/helpers/check_helper.rb +37 -0
  139. data/lib/gooddata/lcm/helpers/helpers.rb +12 -0
  140. data/lib/gooddata/lcm/lcm.rb +161 -20
  141. data/lib/gooddata/lcm/lcm2.rb +260 -0
  142. data/lib/gooddata/lcm/types/base_type.rb +29 -0
  143. data/lib/gooddata/lcm/types/class/ads_client.rb +35 -0
  144. data/lib/gooddata/lcm/types/class/class.rb +21 -0
  145. data/lib/gooddata/lcm/types/class/gd_client.rb +35 -0
  146. data/lib/gooddata/lcm/types/class/types.rb +12 -0
  147. data/lib/gooddata/lcm/types/complex/complex.rb +33 -0
  148. data/lib/gooddata/lcm/types/complex/release_query.rb +35 -0
  149. data/lib/gooddata/lcm/types/complex/segment.rb +37 -0
  150. data/lib/gooddata/lcm/types/complex/synchronization_info.rb +32 -0
  151. data/lib/gooddata/lcm/types/complex/tokens.rb +31 -0
  152. data/lib/gooddata/lcm/types/complex/types.rb +12 -0
  153. data/lib/gooddata/lcm/types/complex/update_preference.rb +32 -0
  154. data/lib/gooddata/lcm/types/param.rb +16 -0
  155. data/lib/gooddata/lcm/types/scalar/bool.rb +22 -0
  156. data/lib/gooddata/lcm/types/scalar/hash.rb +22 -0
  157. data/lib/gooddata/lcm/types/scalar/integer.rb +22 -0
  158. data/lib/gooddata/lcm/types/scalar/object.rb +22 -0
  159. data/lib/gooddata/lcm/types/scalar/string.rb +22 -0
  160. data/lib/gooddata/lcm/types/scalar/types.rb +12 -0
  161. data/lib/gooddata/lcm/types/special/array.rb +35 -0
  162. data/lib/gooddata/lcm/types/special/enum.rb +17 -0
  163. data/lib/gooddata/lcm/types/special/types.rb +12 -0
  164. data/lib/gooddata/lcm/types/types.rb +12 -0
  165. data/lib/gooddata/mixins/author.rb +1 -1
  166. data/lib/gooddata/mixins/content_getter.rb +1 -1
  167. data/lib/gooddata/mixins/content_property_reader.rb +1 -1
  168. data/lib/gooddata/mixins/content_property_writer.rb +1 -1
  169. data/lib/gooddata/mixins/contributor.rb +1 -1
  170. data/lib/gooddata/mixins/data_getter.rb +1 -1
  171. data/lib/gooddata/mixins/data_property_reader.rb +1 -1
  172. data/lib/gooddata/mixins/data_property_writer.rb +1 -1
  173. data/lib/gooddata/mixins/inspector.rb +1 -1
  174. data/lib/gooddata/mixins/is_attribute.rb +1 -1
  175. data/lib/gooddata/mixins/is_dimension.rb +1 -1
  176. data/lib/gooddata/mixins/is_fact.rb +1 -1
  177. data/lib/gooddata/mixins/is_label.rb +1 -1
  178. data/lib/gooddata/mixins/links.rb +1 -1
  179. data/lib/gooddata/mixins/md_finders.rb +1 -1
  180. data/lib/gooddata/mixins/md_grantees.rb +1 -1
  181. data/lib/gooddata/mixins/md_id_to_uri.rb +9 -3
  182. data/lib/gooddata/mixins/md_json.rb +1 -1
  183. data/lib/gooddata/mixins/md_lock.rb +1 -1
  184. data/lib/gooddata/mixins/md_object_id.rb +1 -1
  185. data/lib/gooddata/mixins/md_object_indexer.rb +1 -1
  186. data/lib/gooddata/mixins/md_object_query.rb +1 -1
  187. data/lib/gooddata/mixins/md_relations.rb +1 -1
  188. data/lib/gooddata/mixins/meta_getter.rb +1 -1
  189. data/lib/gooddata/mixins/meta_property_reader.rb +1 -1
  190. data/lib/gooddata/mixins/meta_property_writer.rb +1 -1
  191. data/lib/gooddata/mixins/mixins.rb +1 -1
  192. data/lib/gooddata/mixins/not_attribute.rb +1 -1
  193. data/lib/gooddata/mixins/not_exportable.rb +1 -1
  194. data/lib/gooddata/mixins/not_fact.rb +1 -1
  195. data/lib/gooddata/mixins/not_group.rb +1 -1
  196. data/lib/gooddata/mixins/not_label.rb +1 -1
  197. data/lib/gooddata/mixins/not_metric.rb +1 -1
  198. data/lib/gooddata/mixins/obj_id.rb +1 -1
  199. data/lib/gooddata/mixins/rest_getters.rb +1 -1
  200. data/lib/gooddata/mixins/rest_resource.rb +1 -1
  201. data/lib/gooddata/mixins/root_key_getter.rb +1 -1
  202. data/lib/gooddata/mixins/root_key_setter.rb +1 -1
  203. data/lib/gooddata/mixins/timestamps.rb +1 -1
  204. data/lib/gooddata/models/ads_output_stage.rb +85 -0
  205. data/lib/gooddata/models/automated_data_distribution.rb +36 -0
  206. data/lib/gooddata/models/blueprint/anchor_field.rb +4 -3
  207. data/lib/gooddata/models/blueprint/attribute_field.rb +18 -2
  208. data/lib/gooddata/models/blueprint/blueprint.rb +1 -1
  209. data/lib/gooddata/models/blueprint/blueprint_field.rb +1 -1
  210. data/lib/gooddata/models/blueprint/dashboard_builder.rb +1 -1
  211. data/lib/gooddata/models/blueprint/dataset_blueprint.rb +6 -1
  212. data/lib/gooddata/models/blueprint/date_dimension.rb +1 -1
  213. data/lib/gooddata/models/blueprint/fact_field.rb +1 -1
  214. data/lib/gooddata/models/blueprint/label_field.rb +5 -1
  215. data/lib/gooddata/models/blueprint/project_blueprint.rb +1 -1
  216. data/lib/gooddata/models/blueprint/project_builder.rb +1 -1
  217. data/lib/gooddata/models/blueprint/reference_field.rb +1 -1
  218. data/lib/gooddata/models/blueprint/schema_blueprint.rb +1 -1
  219. data/lib/gooddata/models/blueprint/schema_builder.rb +1 -1
  220. data/lib/gooddata/models/blueprint/to_manifest.rb +7 -3
  221. data/lib/gooddata/models/blueprint/to_wire.rb +12 -1
  222. data/lib/gooddata/models/channel_configuration.rb +112 -0
  223. data/lib/gooddata/models/client.rb +42 -6
  224. data/lib/gooddata/models/client_synchronization_result.rb +1 -1
  225. data/lib/gooddata/models/client_synchronization_result_details.rb +1 -1
  226. data/lib/gooddata/models/datawarehouse.rb +25 -3
  227. data/lib/gooddata/models/domain.rb +29 -4
  228. data/lib/gooddata/models/execution.rb +1 -1
  229. data/lib/gooddata/models/execution_detail.rb +1 -1
  230. data/lib/gooddata/models/from_wire.rb +8 -1
  231. data/lib/gooddata/models/invitation.rb +1 -1
  232. data/lib/gooddata/models/links.rb +1 -1
  233. data/lib/gooddata/models/membership.rb +1 -1
  234. data/lib/gooddata/models/metadata.rb +3 -2
  235. data/lib/gooddata/models/metadata/attribute.rb +7 -1
  236. data/lib/gooddata/models/metadata/dashboard.rb +3 -3
  237. data/lib/gooddata/models/metadata/dashboard/dashboard_item.rb +1 -1
  238. data/lib/gooddata/models/metadata/dashboard/filter_apply_item.rb +2 -2
  239. data/lib/gooddata/models/metadata/dashboard/filter_item.rb +2 -2
  240. data/lib/gooddata/models/metadata/dashboard/geo_chart_item.rb +2 -2
  241. data/lib/gooddata/models/metadata/dashboard/headline_item.rb +2 -2
  242. data/lib/gooddata/models/metadata/dashboard/iframe_item.rb +2 -2
  243. data/lib/gooddata/models/metadata/dashboard/report_item.rb +2 -2
  244. data/lib/gooddata/models/metadata/dashboard/text_item.rb +2 -2
  245. data/lib/gooddata/models/metadata/dashboard_tab.rb +2 -2
  246. data/lib/gooddata/models/metadata/dataset.rb +1 -1
  247. data/lib/gooddata/models/metadata/dimension.rb +1 -1
  248. data/lib/gooddata/models/metadata/fact.rb +1 -1
  249. data/lib/gooddata/models/metadata/folder.rb +1 -1
  250. data/lib/gooddata/models/metadata/label.rb +1 -1
  251. data/lib/gooddata/models/metadata/metadata.rb +1 -1
  252. data/lib/gooddata/models/metadata/metric.rb +1 -1
  253. data/lib/gooddata/models/metadata/report.rb +1 -1
  254. data/lib/gooddata/models/metadata/report_definition.rb +1 -1
  255. data/lib/gooddata/models/metadata/scheduled_mail.rb +2 -2
  256. data/lib/gooddata/models/metadata/scheduled_mail/dashboard_attachment.rb +1 -1
  257. data/lib/gooddata/models/metadata/scheduled_mail/report_attachment.rb +1 -1
  258. data/lib/gooddata/models/metadata/variable.rb +1 -1
  259. data/lib/gooddata/models/model.rb +1 -1
  260. data/lib/gooddata/models/models.rb +1 -1
  261. data/lib/gooddata/models/module_constants.rb +1 -1
  262. data/lib/gooddata/models/notification_rule.rb +113 -0
  263. data/lib/gooddata/models/process.rb +10 -3
  264. data/lib/gooddata/models/profile.rb +9 -1
  265. data/lib/gooddata/models/project.rb +248 -50
  266. data/lib/gooddata/models/project_creator.rb +2 -2
  267. data/lib/gooddata/models/project_metadata.rb +1 -1
  268. data/lib/gooddata/models/project_role.rb +1 -1
  269. data/lib/gooddata/models/report_data_result.rb +1 -1
  270. data/lib/gooddata/models/schedule.rb +49 -13
  271. data/lib/gooddata/models/segment.rb +3 -3
  272. data/lib/gooddata/models/style_setting.rb +71 -0
  273. data/lib/gooddata/models/subscription.rb +181 -0
  274. data/lib/gooddata/models/tab_builder.rb +1 -1
  275. data/lib/gooddata/models/user_filters/mandatory_user_filter.rb +1 -1
  276. data/lib/gooddata/models/user_filters/user_filter.rb +1 -1
  277. data/lib/gooddata/models/user_filters/user_filter_builder.rb +11 -5
  278. data/lib/gooddata/models/user_filters/user_filters.rb +1 -1
  279. data/lib/gooddata/models/user_filters/variable_user_filter.rb +1 -1
  280. data/lib/gooddata/models/user_group.rb +19 -12
  281. data/lib/gooddata/rest/client.rb +9 -1
  282. data/lib/gooddata/rest/connection.rb +18 -9
  283. data/lib/gooddata/rest/object.rb +1 -1
  284. data/lib/gooddata/rest/object_factory.rb +1 -1
  285. data/lib/gooddata/rest/resource.rb +1 -1
  286. data/lib/gooddata/rest/rest.rb +1 -1
  287. data/lib/gooddata/version.rb +2 -2
  288. data/spec/.rubocop.yml +16 -0
  289. data/spec/bricks/bricks_spec.rb +13 -15
  290. data/spec/data/blueprints/attribute_sort_order_blueprint.json +72 -0
  291. data/spec/data/gooddata_version_process/gooddata_version.rb +1 -1
  292. data/spec/data/hello_world_process/hello_world.rb +2 -2
  293. data/spec/data/ruby_params_process/ruby_params.rb +1 -1
  294. data/spec/data/ruby_process/process.rb +2 -2
  295. data/spec/data/wire_models/attribute_sort_by_model.json +73 -0
  296. data/spec/environment/default.rb +14 -13
  297. data/spec/environment/develop.rb +26 -11
  298. data/spec/environment/environment.rb +2 -1
  299. data/spec/environment/hotfix.rb +15 -7
  300. data/spec/environment/production.rb +6 -14
  301. data/spec/environment/staging.rb +9 -10
  302. data/spec/helpers/blueprint_helper.rb +11 -10
  303. data/spec/helpers/cli_helper.rb +26 -24
  304. data/spec/helpers/connection_helper.rb +28 -26
  305. data/spec/helpers/crypto_helper.rb +8 -6
  306. data/spec/helpers/csv_helper.rb +7 -5
  307. data/spec/helpers/process_helper.rb +13 -11
  308. data/spec/helpers/project_helper.rb +36 -34
  309. data/spec/helpers/schedule_helper.rb +13 -11
  310. data/spec/helpers/spec_helper.rb +8 -6
  311. data/spec/integration/ads_output_stage_spec.rb +55 -0
  312. data/spec/integration/blueprint_updates_spec.rb +22 -16
  313. data/spec/integration/blueprint_with_grain_spec.rb +5 -3
  314. data/spec/integration/channel_configuration_spec.rb +67 -0
  315. data/spec/integration/clients_spec.rb +31 -22
  316. data/spec/integration/command_datawarehouse_spec.rb +4 -4
  317. data/spec/integration/command_projects_spec.rb +6 -6
  318. data/spec/integration/create_from_template_spec.rb +4 -3
  319. data/spec/integration/create_project_spec.rb +7 -4
  320. data/spec/integration/date_dim_switch_spec.rb +25 -28
  321. data/spec/integration/deprecated_load_spec.rb +11 -9
  322. data/spec/integration/full_process_schedule_spec.rb +82 -13
  323. data/spec/integration/full_project_spec.rb +67 -45
  324. data/spec/integration/lcm_spec.rb +41 -0
  325. data/spec/integration/over_to_user_filters_spec.rb +14 -10
  326. data/spec/integration/partial_md_export_import_spec.rb +3 -4
  327. data/spec/integration/project_spec.rb +101 -42
  328. data/spec/integration/rest_spec.rb +5 -4
  329. data/spec/integration/schedule_spec.rb +28 -39
  330. data/spec/integration/segments_spec.rb +42 -31
  331. data/spec/integration/subscription_spec.rb +63 -0
  332. data/spec/integration/user_filters_spec.rb +49 -39
  333. data/spec/integration/user_group_spec.rb +25 -5
  334. data/spec/integration/variables_spec.rb +34 -32
  335. data/spec/logging_in_logging_out_spec.rb +6 -8
  336. data/spec/spec_helper.rb +3 -3
  337. data/spec/unit/bricks/bricks_spec.rb +3 -4
  338. data/spec/unit/bricks/middleware/aws_middelware_spec.rb +8 -15
  339. data/spec/unit/bricks/middleware/bench_middleware_spec.rb +2 -2
  340. data/spec/unit/bricks/middleware/bulk_salesforce_middleware_spec.rb +2 -2
  341. data/spec/unit/bricks/middleware/gooddata_middleware_spec.rb +2 -2
  342. data/spec/unit/bricks/middleware/logger_middleware_spec.rb +2 -2
  343. data/spec/unit/bricks/middleware/restforce_middleware_spec.rb +3 -3
  344. data/spec/unit/bricks/middleware/stdout_middleware_spec.rb +3 -3
  345. data/spec/unit/bricks/middleware/twitter_middleware_spec.rb +3 -3
  346. data/spec/unit/cli/cli_spec.rb +3 -3
  347. data/spec/unit/cli/commands/cmd_auth_spec.rb +2 -2
  348. data/spec/unit/commands/command_projects_spec.rb +3 -3
  349. data/spec/unit/core/connection_spec.rb +3 -4
  350. data/spec/unit/core/logging_spec.rb +2 -5
  351. data/spec/unit/core/nil_logger_spec.rb +2 -2
  352. data/spec/unit/core/project_spec.rb +4 -4
  353. data/spec/unit/extensions/hash_spec.rb +3 -4
  354. data/spec/unit/godzilla/goodzilla_spec.rb +22 -26
  355. data/spec/unit/helpers/csv_helper_spec.rb +3 -3
  356. data/spec/unit/helpers/data_helper_spec.rb +6 -18
  357. data/spec/unit/helpers/global_helpers_spec.rb +112 -28
  358. data/spec/unit/helpers_spec.rb +139 -2
  359. data/spec/unit/models/blueprint/attribute_sort_by_spec.rb +20 -0
  360. data/spec/unit/models/blueprint/attributes_spec.rb +1 -2
  361. data/spec/unit/models/blueprint/dataset_spec.rb +2 -3
  362. data/spec/unit/models/blueprint/labels_spec.rb +1 -2
  363. data/spec/unit/models/blueprint/project_blueprint_spec.rb +34 -35
  364. data/spec/unit/models/blueprint/reference_spec.rb +1 -2
  365. data/spec/unit/models/blueprint/schema_builder_spec.rb +5 -7
  366. data/spec/unit/models/blueprint/to_wire_spec.rb +76 -55
  367. data/spec/unit/models/domain_spec.rb +4 -5
  368. data/spec/unit/models/execution_spec.rb +16 -15
  369. data/spec/unit/models/from_wire_spec.rb +24 -19
  370. data/spec/unit/models/invitation_spec.rb +1 -1
  371. data/spec/unit/models/membership_spec.rb +36 -41
  372. data/spec/unit/models/metadata_spec.rb +20 -18
  373. data/spec/unit/models/metric_spec.rb +67 -55
  374. data/spec/unit/models/model_spec.rb +32 -37
  375. data/spec/unit/models/params_spec.rb +1 -1
  376. data/spec/unit/models/profile_spec.rb +40 -45
  377. data/spec/unit/models/project_creator_spec.rb +27 -29
  378. data/spec/unit/models/project_role_spec.rb +1 -1
  379. data/spec/unit/models/project_spec.rb +65 -2
  380. data/spec/unit/models/report_result_data_spec.rb +7 -12
  381. data/spec/unit/models/schedule_spec.rb +71 -35
  382. data/spec/unit/models/to_manifest_spec.rb +69 -4
  383. data/spec/unit/models/unit_project_spec.rb +12 -12
  384. data/spec/unit/models/user_filters_spec.rb +40 -40
  385. data/spec/unit/models/variable_spec.rb +108 -93
  386. data/spec/unit/rest/polling_spec.rb +7 -7
  387. data/spec/unit/rest/resource_spec.rb +2 -2
  388. metadata +145 -228
  389. data/spec/environment/release.rb +0 -21
  390. data/spec/environment/staging_3.rb +0 -36
@@ -1,6 +1,6 @@
1
1
  # encoding: UTF-8
2
2
  #
3
- # Copyright (c) 2010-2015 GoodData Corporation. All rights reserved.
3
+ # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
4
4
  # This source code is licensed under the BSD-style license found in the
5
5
  # LICENSE file in the root directory of this source tree.
6
6
 
@@ -1,6 +1,6 @@
1
1
  # encoding: UTF-8
2
2
  #
3
- # Copyright (c) 2010-2015 GoodData Corporation. All rights reserved.
3
+ # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
4
4
  # This source code is licensed under the BSD-style license found in the
5
5
  # LICENSE file in the root directory of this source tree.
6
6
 
@@ -1,6 +1,6 @@
1
1
  # encoding: UTF-8
2
2
  #
3
- # Copyright (c) 2010-2015 GoodData Corporation. All rights reserved.
3
+ # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
4
4
  # This source code is licensed under the BSD-style license found in the
5
5
  # LICENSE file in the root directory of this source tree.
6
6
 
@@ -1,6 +1,6 @@
1
1
  # encoding: UTF-8
2
2
  #
3
- # Copyright (c) 2010-2015 GoodData Corporation. All rights reserved.
3
+ # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
4
4
  # This source code is licensed under the BSD-style license found in the
5
5
  # LICENSE file in the root directory of this source tree.
6
6
 
@@ -0,0 +1,113 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ module GoodData
8
+ class NotificationRule < Rest::Resource
9
+ NOTIFICATION_RULES_PATH = '/gdc/projects/%s/dataload/processes/%s/notificationRules'
10
+
11
+ EMPTY_OBJECT = {
12
+ 'notificationRule' => {
13
+ 'email' => '',
14
+ 'subject' => '',
15
+ 'body' => '',
16
+ 'events' => []
17
+ }
18
+ }
19
+
20
+ attr_accessor :email, :subject, :body, :events, :process
21
+ attr_reader :subscription, :channels
22
+
23
+ class << self
24
+ def [](id = :all, opts = { client: GoodData.connection })
25
+ c = GoodData.get_client(opts)
26
+ pid = (opts[:project].respond_to?(:pid) && opts[:project].pid) || opts[:project]
27
+ process_id = (opts[:process].respond_to?(:process_id) && opts[:process].process_id) || opts[:process]
28
+ uri = NOTIFICATION_RULES_PATH % [pid, process_id]
29
+ if id == :all
30
+ data = c.get uri
31
+ data['notificationRules']['items'].map { |notification_data| c.create(NotificationRule, notification_data) }
32
+ else
33
+ c.create(NotificationRule, c.get("#{uri}/#{id}"))
34
+ end
35
+ end
36
+
37
+ def all(opts = { client: GoodData.connection })
38
+ NotificationRule[:all, opts]
39
+ end
40
+
41
+ def create(opts = { client: GoodData.connection })
42
+ [:email, :events, :project, :process].each { |key| fail "No #{key.inspect} specified" unless opts[key] }
43
+
44
+ pid = (opts[:project].respond_to?(:pid) && opts[:project].pid) || opts[:project]
45
+ process_id = (opts[:process].respond_to?(:process_id) && opts[:process].process_id) || opts[:process]
46
+ events = (opts[:events].respond_to?(:each) && opts[:events]) || [opts[:events]]
47
+
48
+ notification_rule = create_object({ subject: 'Email subject', body: 'Email body' }.merge(opts).merge(project: pid, process: process_id, events: events))
49
+ notification_rule.save
50
+ notification_rule
51
+ end
52
+
53
+ def create_object(data = {})
54
+ c = GoodData.get_client(data)
55
+
56
+ new_data = GoodData::Helpers.deep_dup(EMPTY_OBJECT).tap do |d|
57
+ d['notificationRule']['email'] = data[:email]
58
+ d['notificationRule']['subject'] = data[:subject]
59
+ d['notificationRule']['body'] = data[:body]
60
+ d['notificationRule']['events'] = data[:events]
61
+ end
62
+
63
+ c.create(NotificationRule, new_data, data)
64
+ end
65
+ end
66
+
67
+ def initialize(json)
68
+ super
69
+ @json = json
70
+
71
+ @email = data['email']
72
+ @subject = data['subject']
73
+ @body = data['body']
74
+ @events = data['events']
75
+ end
76
+
77
+ def uri
78
+ data['links']['self'] if data && data['links'] && data['links']['self']
79
+ end
80
+
81
+ def obj_id
82
+ uri.split('/').last
83
+ end
84
+
85
+ alias_method :notification_rule_id, :obj_id
86
+
87
+ def save
88
+ response = if uri
89
+ data_to_send = GoodData::Helpers.deep_dup(EMPTY_OBJECT).tap do |d|
90
+ d['notificationRule']['email'] = email
91
+ d['notificationRule']['subject'] = subject
92
+ d['notificationRule']['body'] = body
93
+ d['notificationRule']['events'] = (events.respond_to?(:each) && events) || events
94
+ end
95
+ client.put(uri, data_to_send)
96
+ else
97
+ client.post(NOTIFICATION_RULES_PATH % [project, process], raw_data)
98
+ end
99
+ @json = client.get response['notificationRule']['links']['self']
100
+ @subscription = data['links']['subscription']
101
+ @channels = data['links']['channels']
102
+ end
103
+
104
+ def ==(other)
105
+ return false unless [:email, :subject, :body, :events].all? { |m| other.respond_to?(m) }
106
+ @email == other.email && @subject == other.subject && @body == other.body && @events == other.events
107
+ end
108
+
109
+ def delete
110
+ client.delete uri
111
+ end
112
+ end
113
+ end
@@ -1,10 +1,9 @@
1
1
  # encoding: UTF-8
2
2
  #
3
- # Copyright (c) 2010-2015 GoodData Corporation. All rights reserved.
3
+ # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
4
4
  # This source code is licensed under the BSD-style license found in the
5
5
  # LICENSE file in the root directory of this source tree.
6
6
 
7
- require 'pry'
8
7
  require 'zip'
9
8
  require 'uri'
10
9
 
@@ -27,7 +26,7 @@ module GoodData
27
26
  class << self
28
27
  def [](id, options = {})
29
28
  project = options[:project]
30
- c = client(options)
29
+ c = options[:client] || (project && project.client)
31
30
 
32
31
  if id == :all && project
33
32
  uri = "/gdc/projects/#{project.pid}/dataload/processes"
@@ -355,5 +354,13 @@ module GoodData
355
354
  :hiddenParams => GoodData::Helpers.encode_hidden_params(hidden_params)
356
355
  })
357
356
  end
357
+
358
+ def notification_rules
359
+ NotificationRule.all(project: project, process: self, client: client)
360
+ end
361
+
362
+ def create_notification_rule(opts = {})
363
+ NotificationRule.create(opts.merge(project: project, process: self, client: client))
364
+ end
358
365
  end
359
366
  end
@@ -1,6 +1,6 @@
1
1
  # encoding: UTF-8
2
2
  #
3
- # Copyright (c) 2010-2015 GoodData Corporation. All rights reserved.
3
+ # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
4
4
  # This source code is licensed under the BSD-style license found in the
5
5
  # LICENSE file in the root directory of this source tree.
6
6
 
@@ -422,5 +422,13 @@ module GoodData
422
422
  end
423
423
  tmp
424
424
  end
425
+
426
+ def create_channel
427
+ GoodData::ChannelConfiguration.create(to: email, title: email, client: client)
428
+ end
429
+
430
+ def channels
431
+ GoodData::ChannelConfiguration.all(client: client)
432
+ end
425
433
  end
426
434
  end
@@ -1,6 +1,6 @@
1
1
  # encoding: UTF-8
2
2
  #
3
- # Copyright (c) 2010-2015 GoodData Corporation. All rights reserved.
3
+ # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
4
4
  # This source code is licensed under the BSD-style license found in the
5
5
  # LICENSE file in the root directory of this source tree.
6
6
 
@@ -62,7 +62,7 @@ module GoodData
62
62
  # Returns an array of all projects accessible by
63
63
  # current user
64
64
  def all(opts = { client: GoodData.connection })
65
- c = client(opts)
65
+ c = GoodData.get_client(opts)
66
66
  c.user.projects
67
67
  end
68
68
 
@@ -84,9 +84,7 @@ module GoodData
84
84
 
85
85
  id = id.match(/[a-zA-Z\d]+$/)[0] if id =~ %r{/}
86
86
 
87
- c = client(opts)
88
- fail ArgumentError, 'No :client specified' if c.nil?
89
-
87
+ c = GoodData.get_client(opts)
90
88
  response = c.get(PROJECT_PATH % id)
91
89
  c.factory.create(Project, response)
92
90
  end
@@ -104,7 +102,7 @@ module GoodData
104
102
  end
105
103
 
106
104
  def create_object(data = {})
107
- c = client(data)
105
+ c = GoodData.get_client(data)
108
106
  new_data = GoodData::Helpers.deep_dup(EMPTY_OBJECT).tap do |d|
109
107
  d['project']['meta']['title'] = data[:title]
110
108
  d['project']['meta']['summary'] = data[:summary] if data[:summary]
@@ -126,15 +124,15 @@ module GoodData
126
124
  # - :summary
127
125
  # - :template (default /projects/blank)
128
126
  #
129
- def create(opts = { :client => GoodData.connection }, &block)
127
+ def create(opts = { client: GoodData.connection }, &block)
130
128
  GoodData.logger.info "Creating project #{opts[:title]}"
131
129
 
132
- c = client(opts)
133
- fail ArgumentError, 'No :client specified' if c.nil?
134
-
135
- opts = { :auth_token => Helpers::AuthHelper.read_token }.merge(opts)
136
130
  auth_token = opts[:auth_token] || opts[:token]
137
- fail ArgumentError, 'You have to provide your token for creating projects as :auth_token parameter' if auth_token.nil? || auth_token.empty?
131
+ if auth_token.nil? || auth_token.empty?
132
+ opts = { auth_token: Helpers::AuthHelper.read_token }.merge(opts)
133
+ auth_token = opts[:auth_token]
134
+ end
135
+ fail ArgumentError, 'You have to provide your token for creating projects as :auth_token or :token parameter' if auth_token.nil? || auth_token.empty?
138
136
 
139
137
  project = create_object(opts)
140
138
  project.save
@@ -157,15 +155,16 @@ module GoodData
157
155
  project
158
156
  end
159
157
 
160
- def find(_opts = {}, client = GoodData::Rest::Client.client)
161
- user = client.user
158
+ def find(opts = { client: GoodData.connection })
159
+ c = GoodData.get_client(opts)
160
+ user = c.user
162
161
  user.projects['projects'].map do |project|
163
- client.create(GoodData::Project, project)
162
+ c.create(GoodData::Project, project)
164
163
  end
165
164
  end
166
165
 
167
166
  def create_from_blueprint(blueprint, options = {})
168
- GoodData::Model::ProjectCreator.migrate(options.merge(spec: blueprint, client: GoodData.connection))
167
+ GoodData::Model::ProjectCreator.migrate(options.merge(spec: blueprint, client: client))
169
168
  end
170
169
 
171
170
  # Takes one CSV line and creates hash from data extracted
@@ -212,13 +211,15 @@ module GoodData
212
211
  end
213
212
 
214
213
  def transfer_processes(from_project, to_project)
215
- from_project.processes.each do |process|
216
- to_process = to_project.processes.find { |p| p.name == process.name }
214
+ to_project_processes = to_project.processes
215
+ from_project.processes.uniq(&:name).each do |process|
216
+ fail "The process name #{process.name} must be unique in transfered project #{to_project}" if to_project_processes.count { |p| p.name == process.name } > 1
217
+ to_process = to_project_processes.find { |p| p.name == process.name }
217
218
 
218
219
  if process.path
219
220
  to_process.delete if to_process
220
221
  GoodData::Process.deploy_from_appstore(process.path, name: process.name, client: to_project.client, project: to_project)
221
- else
222
+ elsif process.type != :dataload
222
223
  Dir.mktmpdir('etl_transfer') do |dir|
223
224
  dir = Pathname(dir)
224
225
  filename = dir + 'process.zip'
@@ -230,9 +231,20 @@ module GoodData
230
231
  end
231
232
  end
232
233
  end
234
+
235
+ if from_project.processes.any? { |p| p.type == :dataload }
236
+ if to_project_processes.any? { |p| p.type == :dataload }
237
+ to_project.add.output_stage.schema = from_project.add.output_stage.schema
238
+ to_project.add.output_stage.output_stage_prefix = from_project.add.output_stage.output_stage_prefix
239
+ to_project.add.output_stage.save
240
+ else
241
+ from_prj_output_stage = from_project.add.output_stage
242
+ to_project.add.output_stage = GoodData::AdsOutputStage.create(client: to_project.client, ads: from_prj_output_stage.schema, client_id: from_prj_output_stage.client_id, output_stage_prefix: from_prj_output_stage.output_stage_prefix, project: to_project)
243
+ end
244
+ end
233
245
  res = (from_project.processes + to_project.processes).map { |p| [p, p.name, p.type] }
234
246
  res.group_by { |x| [x[1], x[2]] }
235
- .select { |_, procs| procs.length == 1 }
247
+ .select { |_, procs| procs.length == 1 && procs[2] != :dataload }
236
248
  .flat_map { |_, procs| procs.select { |p| p[0].project.pid == to_project.pid }.map { |p| p[0] } }
237
249
  .peach(&:delete)
238
250
  end
@@ -242,7 +254,14 @@ module GoodData
242
254
  # @param client [GoodData::Rest::Client] GoodData client to be used for connection
243
255
  # @param from_project [GoodData::Project | GoodData::Segment | GoodData:Client | String] 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
244
256
  def transfer_schedules(from_project, to_project)
245
- cache = to_project.processes.sort_by(&:name).zip(from_project.processes.sort_by(&:name)).flat_map { |remote, local| local.schedules.map { |schedule| [remote, local, schedule] } }
257
+ cache = to_project
258
+ .processes.sort_by(&:name)
259
+ .zip(from_project.processes.sort_by(&:name))
260
+ .flat_map do |remote, local|
261
+ local.schedules.map do |schedule|
262
+ [remote, local, schedule]
263
+ end
264
+ end
246
265
 
247
266
  remote_schedules = to_project.schedules
248
267
  remote_stuff = remote_schedules.map do |s|
@@ -265,13 +284,21 @@ module GoodData
265
284
  end
266
285
 
267
286
  diff = GoodData::Helpers.diff(remote_stuff, local_stuff, key: :name, fields: [:name, :cron, :after, :params, :hidden_params, :reschedule])
268
- stack = diff[:added].map { |x| [:added, x] } + diff[:changed].map { |x| [:changed, x] }
287
+ stack = diff[:added].map do |x|
288
+ [:added, x]
289
+ end
290
+
291
+ stack += diff[:changed].map do |x|
292
+ [:changed, x]
293
+ end
294
+
269
295
  schedule_cache = remote_schedules.reduce({}) do |a, e|
270
296
  a[e.name] = e
271
297
  a
272
298
  end
273
- messages = []
274
- loop do
299
+
300
+ results = []
301
+ loop do # rubocop:disable Metrics/BlockLength
275
302
  break if stack.empty?
276
303
  state, changed_schedule = stack.shift
277
304
  if state == :added
@@ -280,44 +307,74 @@ module GoodData
280
307
  stack << [state, schedule_spec]
281
308
  next
282
309
  end
283
- remote_process, process_spec = cache.find { |_remote, _local, schedule| schedule.name == schedule_spec[:name] }
284
- messages << { message: "Creating schedule #{schedule_spec[:name]} for process #{remote_process.name}" }
285
- executable = schedule_spec[:executable] || (process_spec["process_type"] == 'ruby' ? 'main.rb' : 'main.grf')
286
- params = {
287
- params: schedule_spec[:params].merge('PROJECT_ID' => to_project.pid),
288
- hidden_params: schedule_spec[:hidden_params],
289
- name: schedule_spec[:name],
290
- reschedule: schedule_spec[:reschedule]
291
- }
310
+ remote_process, process_spec = cache.find do |_remote, local, schedule|
311
+ (schedule_spec[:process_id] == local.process_id) && (schedule.name == schedule_spec[:name])
312
+ end
313
+
314
+ GoodData.logger.info("Creating schedule #{schedule_spec[:name]} for process #{remote_process.name}")
315
+
316
+ executable = nil
317
+ if process_spec.type != :dataload
318
+ executable = schedule_spec[:executable] || (process_spec.type == :ruby ? 'main.rb' : 'main.grf')
319
+ end
320
+ params = schedule_parameters(to_project.pid, schedule_spec)
292
321
  created_schedule = remote_process.create_schedule(schedule_spec[:cron] || schedule_cache[schedule_spec[:after]], executable, params)
293
322
  schedule_cache[created_schedule.name] = created_schedule
323
+
324
+ results << {
325
+ state: :added,
326
+ process: remote_process,
327
+ schedule: created_schedule
328
+ }
294
329
  else
295
330
  schedule_spec = changed_schedule[:new_obj]
296
331
  if schedule_spec[:after] && !schedule_cache[schedule_spec[:after]]
297
332
  stack << [state, schedule_spec]
298
333
  next
299
334
  end
300
- remote_process, process_spec = cache.find { |i| i[2].name == schedule_spec[:name] }
335
+
336
+ remote_process, process_spec = cache.find do |i|
337
+ i[2].name == schedule_spec[:name]
338
+ end
339
+
301
340
  schedule = changed_schedule[:old_obj][:remote_schedule]
302
- messages << { message: "Updating schedule #{schedule_spec[:name]} for process #{remote_process.name}" }
341
+
342
+ GoodData.logger.info("Updating schedule #{schedule_spec[:name]} for process #{remote_process.name}")
343
+
303
344
  schedule.params = (schedule_spec[:params] || {})
304
345
  schedule.cron = schedule_spec[:cron] if schedule_spec[:cron]
305
346
  schedule.after = schedule_cache[schedule_spec[:after]] if schedule_spec[:after]
306
347
  schedule.hidden_params = schedule_spec[:hidden_params] || {}
307
- schedule.executable = schedule_spec[:executable] || (process_spec["process_type"] == 'ruby' ? 'main.rb' : 'main.grf')
348
+ if process_spec.type != :dataload
349
+ schedule.executable = schedule_spec[:executable] || (process_spec.type == :ruby ? 'main.rb' : 'main.grf')
350
+ end
351
+
308
352
  schedule.reschedule = schedule_spec[:reschedule]
309
353
  schedule.name = schedule_spec[:name]
310
354
  schedule.save
311
355
  schedule_cache[schedule.name] = schedule
356
+
357
+ results << {
358
+ state: :changed,
359
+ process: remote_process,
360
+ schedule: schedule
361
+ }
312
362
  end
313
363
  end
314
364
 
315
365
  diff[:removed].each do |removed_schedule|
316
- messages << { message: "Removing schedule #{removed_schedule[:name]}" }
366
+ GoodData.logger.info("Removing schedule #{removed_schedule[:name]}")
367
+
317
368
  removed_schedule[:remote_schedule].delete
369
+
370
+ results << {
371
+ state: :removed,
372
+ process: removed_schedule.process,
373
+ schedule: removed_schedule
374
+ }
318
375
  end
319
- messages
320
- # messages.map {|m| m.merge({custom_project_id: custom_project_id})}
376
+
377
+ results
321
378
  end
322
379
 
323
380
  def transfer_tagged_stuff(from_project, to_project, tag)
@@ -325,9 +382,28 @@ module GoodData
325
382
 
326
383
  objects = from_project.find_by_tag(tag)
327
384
 
328
- puts JSON.pretty_generate(objects)
385
+ if objects.any?
386
+ puts JSON.pretty_generate(objects)
387
+ from_project.partial_md_export(objects, project: to_project)
388
+ else
389
+ GoodData.logger.info('No tagged objects to transfer')
390
+ end
391
+ end
392
+
393
+ def transfer_color_palette(from_project, to_project)
394
+ colors = from_project.current_color_palette
395
+ to_project.create_custom_color_palette(colors) unless colors.empty?
396
+ end
397
+
398
+ private
329
399
 
330
- from_project.partial_md_export(objects, project: to_project)
400
+ def schedule_parameters(id, schedule_spec)
401
+ {
402
+ params: schedule_spec[:params].merge('PROJECT_ID' => id),
403
+ hidden_params: schedule_spec[:hidden_params],
404
+ name: schedule_spec[:name],
405
+ reschedule: schedule_spec[:reschedule]
406
+ }
331
407
  end
332
408
  end
333
409
 
@@ -453,7 +529,7 @@ module GoodData
453
529
  # @param options [Hash] Export options
454
530
  # @option options [Boolean] :data Clone project with data
455
531
  # @option options [Boolean] :users Clone project with users
456
- # @option options [String] :authorized_users Comma separated logins of authorized users. Users that can use the export
532
+ # @option options [Boolean] :exclude_schedules Specifies whether to include scheduled emails
457
533
  # @return [GoodData::Project] Newly created project
458
534
  def clone(options = {})
459
535
  a_title = options[:title] || "Clone of #{title}"
@@ -491,6 +567,8 @@ module GoodData
491
567
  # @option options [Boolean] :data Clone project with data
492
568
  # @option options [Boolean] :users Clone project with users
493
569
  # @option options [String] :authorized_users Comma separated logins of authorized users. Users that can use the export
570
+ # @option options [Boolean] :exclude_schedules Specifies whether to include scheduled notifications in the export
571
+ # @option options [Boolean] :cross_data_center_export Specifies whether export can be used in any data center
494
572
  # @return [String] token of the export
495
573
  def export_clone(options = {})
496
574
  with_data = options[:data].nil? ? true : options[:data]
@@ -503,12 +581,22 @@ module GoodData
503
581
  }
504
582
  }
505
583
  export[:exportProject][:authorizedUsers] = options[:authorized_users] if options[:authorized_users]
584
+ if options[:exclude_schedules]
585
+ exclude_notifications = options[:exclude_schedules] ? 1 : 0
586
+ export[:exportProject][:excludeSchedules] = exclude_notifications
587
+ end
588
+ if options[:cross_data_center_export]
589
+ cross_data_center = options[:cross_data_center_export] ? 1 : 0
590
+ export[:exportProject][:crossDataCenterExport] = cross_data_center
591
+ end
506
592
 
507
593
  result = client.post("/gdc/md/#{obj_id}/maintenance/export", export)
508
594
  status_url = result['exportArtifact']['status']['uri']
509
- client.poll_on_response(status_url) do |body|
595
+ polling_result = client.poll_on_response(status_url) do |body|
510
596
  body['taskState']['status'] == 'RUNNING'
511
597
  end
598
+
599
+ ensure_clone_task_ok(polling_result, GoodData::ExportCloneError)
512
600
  result['exportArtifact']['token']
513
601
  end
514
602
 
@@ -534,9 +622,10 @@ module GoodData
534
622
 
535
623
  result = client.post("/gdc/md/#{obj_id}/maintenance/import", import)
536
624
  status_url = result['uri']
537
- client.poll_on_response(status_url, options) do |body|
625
+ polling_result = client.poll_on_response(status_url, options) do |body|
538
626
  body['taskState']['status'] == 'RUNNING'
539
627
  end
628
+ ensure_clone_task_ok(polling_result, GoodData::ImportCloneError)
540
629
  self
541
630
  end
542
631
 
@@ -751,8 +840,20 @@ module GoodData
751
840
  GoodData.download_from_project_webdav(file, where, project: self)
752
841
  end
753
842
 
843
+ def driver
844
+ content['driver']
845
+ end
846
+
754
847
  def environment
755
- json['project']['content']['environment']
848
+ content['environment']
849
+ end
850
+
851
+ def public?
852
+ content['isPublic']
853
+ end
854
+
855
+ def token
856
+ content['authorizationToken']
756
857
  end
757
858
 
758
859
  # Gets user by its email, full_name, login or uri
@@ -828,7 +929,7 @@ module GoodData
828
929
  puts "Inviting #{email}, role: #{role}"
829
930
 
830
931
  role_url = nil
831
- if role.index('/gdc/').nonzero?
932
+ if role.index('/gdc/').nil?
832
933
  tmp = get_role(role)
833
934
  role_url = tmp.uri if tmp
834
935
  else
@@ -1307,7 +1408,14 @@ module GoodData
1307
1408
  tmp = client.get("/gdc/projects/#{pid}/users", params: { offset: offset, limit: limit })
1308
1409
  tmp['users'].each do |user_data|
1309
1410
  user = client.create(GoodData::Membership, user_data, project: self)
1310
- y << user if opts[:all] || user && user.enabled?
1411
+
1412
+ if opts[:all]
1413
+ y << user
1414
+ elsif opts[:disabled]
1415
+ y << user if user && user.disabled?
1416
+ else
1417
+ y << user if user && user.enabled?
1418
+ end
1311
1419
  end
1312
1420
  break if tmp['users'].count < limit
1313
1421
  offset += limit
@@ -1321,11 +1429,23 @@ module GoodData
1321
1429
  return [new_users, users_list] unless whitelist
1322
1430
 
1323
1431
  new_whitelist_proc = proc do |user|
1324
- whitelist.any? { |wl| wl.is_a?(Regexp) ? user[:login] =~ wl : (user[:login] && user[:login].include?(wl)) }
1432
+ whitelist.any? do |wl|
1433
+ if wl.is_a?(Regexp)
1434
+ user[:login] =~ wl
1435
+ else
1436
+ user[:login] && user[:login] == wl
1437
+ end
1438
+ end
1325
1439
  end
1326
1440
 
1327
1441
  whitelist_proc = proc do |user|
1328
- whitelist.any? { |wl| wl.is_a?(Regexp) ? user.login =~ wl : (user.login && user.login.include?(wl)) }
1442
+ whitelist.any? do |wl|
1443
+ if wl.is_a?(Regexp)
1444
+ user.login =~ wl
1445
+ else
1446
+ user.login && user.login == wl
1447
+ end
1448
+ end
1329
1449
  end
1330
1450
 
1331
1451
  if mode == :include
@@ -1408,9 +1528,18 @@ module GoodData
1408
1528
 
1409
1529
  # Remove old users
1410
1530
  to_remove = diff[:removed].reject { |user| user[:status] == 'DISABLED' || user[:status] == :disabled }
1411
- GoodData.logger.warn("Removing #{to_remove.count} users from project (#{pid})")
1531
+ GoodData.logger.warn("Disabling #{to_remove.count} users from project (#{pid})")
1412
1532
  results.concat(disable_users(to_remove, roles: role_list, project_users: whitelisted_users))
1413
1533
 
1534
+ # Remove old users completely
1535
+ if options[:remove_users_from_project]
1536
+ to_remove = (to_remove + users(disabled: true).to_a).map(&:to_hash).uniq do |user|
1537
+ user[:uri]
1538
+ end
1539
+ GoodData.logger.warn("Removing #{to_remove.count} users from project (#{pid})")
1540
+ results.concat(remove_users(to_remove))
1541
+ end
1542
+
1414
1543
  # reassign to groups
1415
1544
  mappings = new_users.map(&:to_hash).flat_map do |user|
1416
1545
  groups = user[:user_group] || []
@@ -1450,6 +1579,21 @@ module GoodData
1450
1579
  end
1451
1580
  end
1452
1581
 
1582
+ def remove_users(list)
1583
+ list = list.map(&:to_hash)
1584
+
1585
+ list.pmapcat do |u|
1586
+ u_id = GoodData::Helpers.last_uri_part(u[:uri])
1587
+ url = "#{uri}/users/#{u_id}"
1588
+ begin
1589
+ client.delete(url)
1590
+ [{ type: :successful, operation: :user_deleted_from_project, user: u }]
1591
+ rescue => e
1592
+ [{ type: :failed, message: e.message }]
1593
+ end
1594
+ end
1595
+ end
1596
+
1453
1597
  def check_groups(specified_groups)
1454
1598
  groups = user_groups.map(&:name)
1455
1599
  missing_groups = specified_groups - groups
@@ -1567,6 +1711,47 @@ module GoodData
1567
1711
  [user, roles]
1568
1712
  end
1569
1713
 
1714
+ def add
1715
+ @add ||= GoodData::AutomatedDataDistribution.new(self)
1716
+ @add
1717
+ end
1718
+
1719
+ def transfer_etl(target)
1720
+ GoodData::Project.transfer_etl(client, self, target)
1721
+ end
1722
+
1723
+ def transfer_processes(target)
1724
+ GoodData::Project.transfer_processes(self, target)
1725
+ end
1726
+
1727
+ def transfer_schedules(target)
1728
+ GoodData::Project.transfer_schedules(self, target)
1729
+ end
1730
+
1731
+ def transfer_tagged_stuff(target, tag)
1732
+ GoodData::Project.transfer_tagged_stuff(self, target, tag)
1733
+ end
1734
+
1735
+ def create_output_stage(ads, opts = {})
1736
+ add.create_output_stage(ads, opts)
1737
+ end
1738
+
1739
+ def transfer_color_palette(target)
1740
+ GoodData::Project.transfer_color_palette(self, target)
1741
+ end
1742
+
1743
+ def current_color_palette
1744
+ GoodData::StyleSetting.current(client: client, project: self)
1745
+ end
1746
+
1747
+ def create_custom_color_palette(colors)
1748
+ GoodData::StyleSetting.create(colors, client: client, project: self)
1749
+ end
1750
+
1751
+ def reset_color_palette
1752
+ GoodData::StyleSetting.reset(client: client, project: self)
1753
+ end
1754
+
1570
1755
  private
1571
1756
 
1572
1757
  def generate_user_payload(user_uri, status = 'ENABLED', roles_uri = nil)
@@ -1583,5 +1768,18 @@ module GoodData
1583
1768
  payload['user']['content']['userRoles'] = roles_uri if roles_uri
1584
1769
  payload
1585
1770
  end
1771
+
1772
+ # Checks state of an export/import task.
1773
+ # @param response [Hash] Response from API
1774
+ # @param clone_task_error [Error] Error to raise when state is not OK
1775
+ def ensure_clone_task_ok(response, clone_task_error)
1776
+ if response['taskState'].nil?
1777
+ fail clone_task_error, "Clone task failed with unknown response: #{response}"
1778
+ elsif response['taskState']['status'] != 'OK'
1779
+ messages = response['taskState']['messages'] || []
1780
+ interpolated_messages = GoodData::Helpers.interpolate_error_messages(messages).join(' ')
1781
+ fail clone_task_error, "Clone task failed. #{interpolated_messages}"
1782
+ end
1783
+ end
1586
1784
  end
1587
1785
  end