gooddata 1.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (517) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.editorconfig +12 -0
  4. data/.flayignore +6 -0
  5. data/.gitignore +38 -0
  6. data/.pronto.yml +3 -0
  7. data/.rspec +5 -0
  8. data/.rubocop.yml +101 -0
  9. data/.travis.yml +9 -0
  10. data/.yardopts +22 -0
  11. data/CHANGELOG.md +272 -0
  12. data/CLI.md +435 -0
  13. data/CONTRIBUTING.md +38 -0
  14. data/DEPENDENCIES.md +880 -0
  15. data/Dockerfile.jruby +17 -0
  16. data/Dockerfile.ruby +19 -0
  17. data/Gemfile +4 -0
  18. data/Guardfile +5 -0
  19. data/LICENSE +22 -0
  20. data/LICENSE.rb +5 -0
  21. data/README.md +78 -0
  22. data/Rakefile +204 -0
  23. data/TODO.md +32 -0
  24. data/authors.sh +4 -0
  25. data/bin/gooddata +7 -0
  26. data/ci.rake +47 -0
  27. data/dependency_decisions.yml +104 -0
  28. data/docker-compose.yml +34 -0
  29. data/gooddata +9 -0
  30. data/gooddata.gemspec +72 -0
  31. data/lib/gooddata.rb +34 -0
  32. data/lib/gooddata/app/app.rb +16 -0
  33. data/lib/gooddata/bricks/base_downloader.rb +86 -0
  34. data/lib/gooddata/bricks/brick.rb +37 -0
  35. data/lib/gooddata/bricks/bricks.rb +17 -0
  36. data/lib/gooddata/bricks/middleware/aws_middleware.rb +41 -0
  37. data/lib/gooddata/bricks/middleware/base_middleware.rb +57 -0
  38. data/lib/gooddata/bricks/middleware/bench_middleware.rb +25 -0
  39. data/lib/gooddata/bricks/middleware/bulk_salesforce_middleware.rb +37 -0
  40. data/lib/gooddata/bricks/middleware/decode_params_middleware.rb +21 -0
  41. data/lib/gooddata/bricks/middleware/dwh_middleware.rb +41 -0
  42. data/lib/gooddata/bricks/middleware/fs_download_middleware.rb +48 -0
  43. data/lib/gooddata/bricks/middleware/fs_upload_middleware.rb +36 -0
  44. data/lib/gooddata/bricks/middleware/gooddata_middleware.rb +112 -0
  45. data/lib/gooddata/bricks/middleware/logger_middleware.rb +33 -0
  46. data/lib/gooddata/bricks/middleware/middleware.rb +12 -0
  47. data/lib/gooddata/bricks/middleware/restforce_middleware.rb +58 -0
  48. data/lib/gooddata/bricks/middleware/stdout_middleware.rb +23 -0
  49. data/lib/gooddata/bricks/middleware/twitter_middleware.rb +29 -0
  50. data/lib/gooddata/bricks/middleware/undot_params_middleware.rb +37 -0
  51. data/lib/gooddata/bricks/pipeline.rb +25 -0
  52. data/lib/gooddata/bricks/utils.rb +18 -0
  53. data/lib/gooddata/cli/cli.rb +27 -0
  54. data/lib/gooddata/cli/commands/auth_cmd.rb +29 -0
  55. data/lib/gooddata/cli/commands/domain_cmd.rb +28 -0
  56. data/lib/gooddata/cli/commands/project_cmd.rb +28 -0
  57. data/lib/gooddata/cli/hooks.rb +56 -0
  58. data/lib/gooddata/cli/shared.rb +66 -0
  59. data/lib/gooddata/cli/terminal.rb +20 -0
  60. data/lib/gooddata/client.rb +67 -0
  61. data/lib/gooddata/commands/api.rb +64 -0
  62. data/lib/gooddata/commands/auth.rb +107 -0
  63. data/lib/gooddata/commands/base.rb +12 -0
  64. data/lib/gooddata/commands/commands.rb +12 -0
  65. data/lib/gooddata/commands/datasets.rb +148 -0
  66. data/lib/gooddata/commands/datawarehouse.rb +20 -0
  67. data/lib/gooddata/commands/domain.rb +40 -0
  68. data/lib/gooddata/commands/process.rb +67 -0
  69. data/lib/gooddata/commands/project.rb +144 -0
  70. data/lib/gooddata/commands/projects.rb +20 -0
  71. data/lib/gooddata/commands/role.rb +36 -0
  72. data/lib/gooddata/commands/runners.rb +47 -0
  73. data/lib/gooddata/commands/scaffold.rb +69 -0
  74. data/lib/gooddata/commands/user.rb +39 -0
  75. data/lib/gooddata/connection.rb +127 -0
  76. data/lib/gooddata/core/core.rb +12 -0
  77. data/lib/gooddata/core/logging.rb +105 -0
  78. data/lib/gooddata/core/nil_logger.rb +32 -0
  79. data/lib/gooddata/core/project.rb +74 -0
  80. data/lib/gooddata/core/rest.rb +149 -0
  81. data/lib/gooddata/core/user.rb +20 -0
  82. data/lib/gooddata/data/data.rb +12 -0
  83. data/lib/gooddata/data/guesser.rb +122 -0
  84. data/lib/gooddata/exceptions/attr_element_not_found.rb +16 -0
  85. data/lib/gooddata/exceptions/command_failed.rb +11 -0
  86. data/lib/gooddata/exceptions/exceptions.rb +12 -0
  87. data/lib/gooddata/exceptions/execution_limit_exceeded.rb +13 -0
  88. data/lib/gooddata/exceptions/export_clone.rb +4 -0
  89. data/lib/gooddata/exceptions/filter_maqlization.rb +16 -0
  90. data/lib/gooddata/exceptions/import_clone.rb +4 -0
  91. data/lib/gooddata/exceptions/malformed_user.rb +15 -0
  92. data/lib/gooddata/exceptions/maql_execution.rb +16 -0
  93. data/lib/gooddata/exceptions/no_project_error.rb +19 -0
  94. data/lib/gooddata/exceptions/object_migration.rb +32 -0
  95. data/lib/gooddata/exceptions/project_not_found.rb +13 -0
  96. data/lib/gooddata/exceptions/segment_not_empty.rb +18 -0
  97. data/lib/gooddata/exceptions/uncomputable_report.rb +13 -0
  98. data/lib/gooddata/exceptions/user_in_different_domain.rb +15 -0
  99. data/lib/gooddata/exceptions/validation_error.rb +16 -0
  100. data/lib/gooddata/extensions/big_decimal.rb +17 -0
  101. data/lib/gooddata/extensions/class.rb +11 -0
  102. data/lib/gooddata/extensions/enumerable.rb +39 -0
  103. data/lib/gooddata/extensions/extensions.rb +10 -0
  104. data/lib/gooddata/extensions/false.rb +23 -0
  105. data/lib/gooddata/extensions/hash.rb +49 -0
  106. data/lib/gooddata/extensions/integer.rb +5 -0
  107. data/lib/gooddata/extensions/nil.rb +19 -0
  108. data/lib/gooddata/extensions/numeric.rb +15 -0
  109. data/lib/gooddata/extensions/object.rb +31 -0
  110. data/lib/gooddata/extensions/string.rb +7 -0
  111. data/lib/gooddata/extensions/symbol.rb +15 -0
  112. data/lib/gooddata/extensions/true.rb +23 -0
  113. data/lib/gooddata/extract.rb +21 -0
  114. data/lib/gooddata/goodzilla/goodzilla.rb +160 -0
  115. data/lib/gooddata/helpers/auth_helpers.rb +75 -0
  116. data/lib/gooddata/helpers/csv_helper.rb +61 -0
  117. data/lib/gooddata/helpers/data_helper.rb +129 -0
  118. data/lib/gooddata/helpers/erb_helper.rb +23 -0
  119. data/lib/gooddata/helpers/global_helpers.rb +266 -0
  120. data/lib/gooddata/helpers/global_helpers_params.rb +292 -0
  121. data/lib/gooddata/helpers/helpers.rb +10 -0
  122. data/lib/gooddata/lcm/actions/actions.rb +12 -0
  123. data/lib/gooddata/lcm/actions/apply_custom_maql.rb +80 -0
  124. data/lib/gooddata/lcm/actions/associate_clients.rb +87 -0
  125. data/lib/gooddata/lcm/actions/base_action.rb +23 -0
  126. data/lib/gooddata/lcm/actions/collect_ca_metrics.rb +53 -0
  127. data/lib/gooddata/lcm/actions/collect_client_projects.rb +78 -0
  128. data/lib/gooddata/lcm/actions/collect_clients.rb +128 -0
  129. data/lib/gooddata/lcm/actions/collect_data_product.rb +57 -0
  130. data/lib/gooddata/lcm/actions/collect_dynamic_schedule_params.rb +62 -0
  131. data/lib/gooddata/lcm/actions/collect_ldm_objects.rb +56 -0
  132. data/lib/gooddata/lcm/actions/collect_meta.rb +88 -0
  133. data/lib/gooddata/lcm/actions/collect_segment_clients.rb +113 -0
  134. data/lib/gooddata/lcm/actions/collect_segments.rb +72 -0
  135. data/lib/gooddata/lcm/actions/collect_tagged_objects.rb +80 -0
  136. data/lib/gooddata/lcm/actions/collect_users_brick_users.rb +46 -0
  137. data/lib/gooddata/lcm/actions/create_segment_masters.rb +160 -0
  138. data/lib/gooddata/lcm/actions/ensure_data_product.rb +53 -0
  139. data/lib/gooddata/lcm/actions/ensure_release_table.rb +53 -0
  140. data/lib/gooddata/lcm/actions/ensure_segments.rb +32 -0
  141. data/lib/gooddata/lcm/actions/ensure_technical_users_domain.rb +70 -0
  142. data/lib/gooddata/lcm/actions/ensure_technical_users_project.rb +83 -0
  143. data/lib/gooddata/lcm/actions/execute_schedules.rb +128 -0
  144. data/lib/gooddata/lcm/actions/hello_world.rb +41 -0
  145. data/lib/gooddata/lcm/actions/import_object_collections.rb +60 -0
  146. data/lib/gooddata/lcm/actions/print_actions.rb +58 -0
  147. data/lib/gooddata/lcm/actions/print_modes.rb +69 -0
  148. data/lib/gooddata/lcm/actions/print_types.rb +52 -0
  149. data/lib/gooddata/lcm/actions/provision_clients.rb +89 -0
  150. data/lib/gooddata/lcm/actions/purge_clients.rb +58 -0
  151. data/lib/gooddata/lcm/actions/rename_existing_client_projects.rb +70 -0
  152. data/lib/gooddata/lcm/actions/segments_filter.rb +50 -0
  153. data/lib/gooddata/lcm/actions/synchronize_attribute_drillpaths.rb +64 -0
  154. data/lib/gooddata/lcm/actions/synchronize_cas.rb +72 -0
  155. data/lib/gooddata/lcm/actions/synchronize_clients.rb +94 -0
  156. data/lib/gooddata/lcm/actions/synchronize_color_palette.rb +67 -0
  157. data/lib/gooddata/lcm/actions/synchronize_etls_in_segment.rb +155 -0
  158. data/lib/gooddata/lcm/actions/synchronize_label_types.rb +64 -0
  159. data/lib/gooddata/lcm/actions/synchronize_ldm.rb +82 -0
  160. data/lib/gooddata/lcm/actions/synchronize_meta.rb +52 -0
  161. data/lib/gooddata/lcm/actions/synchronize_new_segments.rb +61 -0
  162. data/lib/gooddata/lcm/actions/synchronize_processes.rb +66 -0
  163. data/lib/gooddata/lcm/actions/synchronize_schedules.rb +91 -0
  164. data/lib/gooddata/lcm/actions/synchronize_tag_objects.rb +64 -0
  165. data/lib/gooddata/lcm/actions/synchronize_user_filters.rb +210 -0
  166. data/lib/gooddata/lcm/actions/synchronize_user_groups.rb +53 -0
  167. data/lib/gooddata/lcm/actions/synchronize_users.rb +336 -0
  168. data/lib/gooddata/lcm/actions/update_release_table.rb +77 -0
  169. data/lib/gooddata/lcm/data/create_lcm_release.sql.erb +6 -0
  170. data/lib/gooddata/lcm/data/insert_into_lcm_release.sql.erb +11 -0
  171. data/lib/gooddata/lcm/data/select_from_lcm_release.sql.erb +8 -0
  172. data/lib/gooddata/lcm/data/update_lcm_release.sql.erb +7 -0
  173. data/lib/gooddata/lcm/dsl/dsl.rb +50 -0
  174. data/lib/gooddata/lcm/dsl/params_dsl.rb +61 -0
  175. data/lib/gooddata/lcm/dsl/type_dsl.rb +62 -0
  176. data/lib/gooddata/lcm/helpers/check_helper.rb +41 -0
  177. data/lib/gooddata/lcm/helpers/helpers.rb +12 -0
  178. data/lib/gooddata/lcm/helpers/tags_helper.rb +36 -0
  179. data/lib/gooddata/lcm/lcm.rb +325 -0
  180. data/lib/gooddata/lcm/lcm2.rb +400 -0
  181. data/lib/gooddata/lcm/types/base_type.rb +29 -0
  182. data/lib/gooddata/lcm/types/class/ads_client.rb +35 -0
  183. data/lib/gooddata/lcm/types/class/class.rb +21 -0
  184. data/lib/gooddata/lcm/types/class/gd_client.rb +35 -0
  185. data/lib/gooddata/lcm/types/class/types.rb +12 -0
  186. data/lib/gooddata/lcm/types/complex/complex.rb +33 -0
  187. data/lib/gooddata/lcm/types/complex/release_query.rb +35 -0
  188. data/lib/gooddata/lcm/types/complex/segment.rb +40 -0
  189. data/lib/gooddata/lcm/types/complex/synchronization_info.rb +35 -0
  190. data/lib/gooddata/lcm/types/complex/tokens.rb +31 -0
  191. data/lib/gooddata/lcm/types/complex/types.rb +12 -0
  192. data/lib/gooddata/lcm/types/complex/update_preference.rb +38 -0
  193. data/lib/gooddata/lcm/types/complex/users_brick_config.rb +32 -0
  194. data/lib/gooddata/lcm/types/param.rb +16 -0
  195. data/lib/gooddata/lcm/types/scalar/bool.rb +22 -0
  196. data/lib/gooddata/lcm/types/scalar/hash.rb +22 -0
  197. data/lib/gooddata/lcm/types/scalar/integer.rb +22 -0
  198. data/lib/gooddata/lcm/types/scalar/object.rb +22 -0
  199. data/lib/gooddata/lcm/types/scalar/string.rb +22 -0
  200. data/lib/gooddata/lcm/types/scalar/types.rb +12 -0
  201. data/lib/gooddata/lcm/types/special/array.rb +33 -0
  202. data/lib/gooddata/lcm/types/special/enum.rb +15 -0
  203. data/lib/gooddata/lcm/types/special/types.rb +12 -0
  204. data/lib/gooddata/lcm/types/types.rb +12 -0
  205. data/lib/gooddata/lcm/user_bricks_helper.rb +32 -0
  206. data/lib/gooddata/mixins/author.rb +26 -0
  207. data/lib/gooddata/mixins/content_getter.rb +15 -0
  208. data/lib/gooddata/mixins/content_property_reader.rb +17 -0
  209. data/lib/gooddata/mixins/content_property_writer.rb +17 -0
  210. data/lib/gooddata/mixins/contributor.rb +20 -0
  211. data/lib/gooddata/mixins/data_getter.rb +15 -0
  212. data/lib/gooddata/mixins/data_property_reader.rb +19 -0
  213. data/lib/gooddata/mixins/data_property_writer.rb +19 -0
  214. data/lib/gooddata/mixins/inspector.rb +53 -0
  215. data/lib/gooddata/mixins/is_attribute.rb +17 -0
  216. data/lib/gooddata/mixins/is_dimension.rb +17 -0
  217. data/lib/gooddata/mixins/is_fact.rb +17 -0
  218. data/lib/gooddata/mixins/is_folder.rb +11 -0
  219. data/lib/gooddata/mixins/is_label.rb +19 -0
  220. data/lib/gooddata/mixins/links.rb +15 -0
  221. data/lib/gooddata/mixins/md_finders.rb +79 -0
  222. data/lib/gooddata/mixins/md_grantees.rb +42 -0
  223. data/lib/gooddata/mixins/md_id_to_uri.rb +39 -0
  224. data/lib/gooddata/mixins/md_json.rb +15 -0
  225. data/lib/gooddata/mixins/md_lock.rb +87 -0
  226. data/lib/gooddata/mixins/md_object_id.rb +15 -0
  227. data/lib/gooddata/mixins/md_object_indexer.rb +74 -0
  228. data/lib/gooddata/mixins/md_object_query.rb +134 -0
  229. data/lib/gooddata/mixins/md_relations.rb +43 -0
  230. data/lib/gooddata/mixins/meta_getter.rb +17 -0
  231. data/lib/gooddata/mixins/meta_property_reader.rb +19 -0
  232. data/lib/gooddata/mixins/meta_property_writer.rb +19 -0
  233. data/lib/gooddata/mixins/mixins.rb +19 -0
  234. data/lib/gooddata/mixins/not_attribute.rb +17 -0
  235. data/lib/gooddata/mixins/not_exportable.rb +15 -0
  236. data/lib/gooddata/mixins/not_fact.rb +17 -0
  237. data/lib/gooddata/mixins/not_group.rb +17 -0
  238. data/lib/gooddata/mixins/not_label.rb +19 -0
  239. data/lib/gooddata/mixins/not_metric.rb +19 -0
  240. data/lib/gooddata/mixins/obj_id.rb +15 -0
  241. data/lib/gooddata/mixins/rest_getters.rb +17 -0
  242. data/lib/gooddata/mixins/rest_resource.rb +47 -0
  243. data/lib/gooddata/mixins/root_key_getter.rb +15 -0
  244. data/lib/gooddata/mixins/root_key_setter.rb +15 -0
  245. data/lib/gooddata/mixins/timestamps.rb +19 -0
  246. data/lib/gooddata/mixins/to_json.rb +11 -0
  247. data/lib/gooddata/mixins/uri_getter.rb +9 -0
  248. data/lib/gooddata/models/ads_output_stage.rb +85 -0
  249. data/lib/gooddata/models/automated_data_distribution.rb +36 -0
  250. data/lib/gooddata/models/blueprint/anchor_field.rb +65 -0
  251. data/lib/gooddata/models/blueprint/attribute_field.rb +45 -0
  252. data/lib/gooddata/models/blueprint/blueprint.rb +11 -0
  253. data/lib/gooddata/models/blueprint/blueprint_field.rb +70 -0
  254. data/lib/gooddata/models/blueprint/dashboard_builder.rb +30 -0
  255. data/lib/gooddata/models/blueprint/dataset_blueprint.rb +455 -0
  256. data/lib/gooddata/models/blueprint/date_dimension.rb +20 -0
  257. data/lib/gooddata/models/blueprint/fact_field.rb +20 -0
  258. data/lib/gooddata/models/blueprint/label_field.rb +47 -0
  259. data/lib/gooddata/models/blueprint/project_blueprint.rb +791 -0
  260. data/lib/gooddata/models/blueprint/project_builder.rb +103 -0
  261. data/lib/gooddata/models/blueprint/reference_field.rb +43 -0
  262. data/lib/gooddata/models/blueprint/schema_blueprint.rb +160 -0
  263. data/lib/gooddata/models/blueprint/schema_builder.rb +89 -0
  264. data/lib/gooddata/models/blueprint/to_manifest.rb +185 -0
  265. data/lib/gooddata/models/blueprint/to_wire.rb +173 -0
  266. data/lib/gooddata/models/channel_configuration.rb +112 -0
  267. data/lib/gooddata/models/client.rb +236 -0
  268. data/lib/gooddata/models/client_synchronization_result.rb +31 -0
  269. data/lib/gooddata/models/client_synchronization_result_details.rb +41 -0
  270. data/lib/gooddata/models/data_product.rb +149 -0
  271. data/lib/gooddata/models/datawarehouse.rb +114 -0
  272. data/lib/gooddata/models/domain.rb +505 -0
  273. data/lib/gooddata/models/execution.rb +115 -0
  274. data/lib/gooddata/models/execution_detail.rb +81 -0
  275. data/lib/gooddata/models/from_wire.rb +173 -0
  276. data/lib/gooddata/models/invitation.rb +75 -0
  277. data/lib/gooddata/models/links.rb +50 -0
  278. data/lib/gooddata/models/membership.rb +441 -0
  279. data/lib/gooddata/models/metadata.rb +324 -0
  280. data/lib/gooddata/models/metadata/attribute.rb +155 -0
  281. data/lib/gooddata/models/metadata/dashboard.rb +120 -0
  282. data/lib/gooddata/models/metadata/dashboard/dashboard_item.rb +76 -0
  283. data/lib/gooddata/models/metadata/dashboard/filter_apply_item.rb +37 -0
  284. data/lib/gooddata/models/metadata/dashboard/filter_item.rb +64 -0
  285. data/lib/gooddata/models/metadata/dashboard/geo_chart_item.rb +56 -0
  286. data/lib/gooddata/models/metadata/dashboard/headline_item.rb +56 -0
  287. data/lib/gooddata/models/metadata/dashboard/iframe_item.rb +46 -0
  288. data/lib/gooddata/models/metadata/dashboard/report_item.rb +92 -0
  289. data/lib/gooddata/models/metadata/dashboard/text_item.rb +55 -0
  290. data/lib/gooddata/models/metadata/dashboard_tab.rb +141 -0
  291. data/lib/gooddata/models/metadata/dataset.rb +67 -0
  292. data/lib/gooddata/models/metadata/dimension.rb +57 -0
  293. data/lib/gooddata/models/metadata/fact.rb +51 -0
  294. data/lib/gooddata/models/metadata/folder.rb +49 -0
  295. data/lib/gooddata/models/metadata/label.rb +128 -0
  296. data/lib/gooddata/models/metadata/metadata.rb +12 -0
  297. data/lib/gooddata/models/metadata/metric.rb +206 -0
  298. data/lib/gooddata/models/metadata/report.rb +268 -0
  299. data/lib/gooddata/models/metadata/report_definition.rb +272 -0
  300. data/lib/gooddata/models/metadata/scheduled_mail.rb +277 -0
  301. data/lib/gooddata/models/metadata/scheduled_mail/dashboard_attachment.rb +62 -0
  302. data/lib/gooddata/models/metadata/scheduled_mail/report_attachment.rb +64 -0
  303. data/lib/gooddata/models/metadata/variable.rb +96 -0
  304. data/lib/gooddata/models/model.rb +293 -0
  305. data/lib/gooddata/models/models.rb +12 -0
  306. data/lib/gooddata/models/module_constants.rb +31 -0
  307. data/lib/gooddata/models/notification_rule.rb +113 -0
  308. data/lib/gooddata/models/process.rb +371 -0
  309. data/lib/gooddata/models/profile.rb +451 -0
  310. data/lib/gooddata/models/project.rb +2030 -0
  311. data/lib/gooddata/models/project_creator.rb +209 -0
  312. data/lib/gooddata/models/project_log_formatter.rb +204 -0
  313. data/lib/gooddata/models/project_metadata.rb +67 -0
  314. data/lib/gooddata/models/project_role.rb +79 -0
  315. data/lib/gooddata/models/report_data_result.rb +270 -0
  316. data/lib/gooddata/models/schedule.rb +538 -0
  317. data/lib/gooddata/models/segment.rb +274 -0
  318. data/lib/gooddata/models/style_setting.rb +62 -0
  319. data/lib/gooddata/models/subscription.rb +188 -0
  320. data/lib/gooddata/models/tab_builder.rb +27 -0
  321. data/lib/gooddata/models/user_filters/mandatory_user_filter.rb +76 -0
  322. data/lib/gooddata/models/user_filters/user_filter.rb +101 -0
  323. data/lib/gooddata/models/user_filters/user_filter_builder.rb +553 -0
  324. data/lib/gooddata/models/user_filters/user_filters.rb +13 -0
  325. data/lib/gooddata/models/user_filters/variable_user_filter.rb +33 -0
  326. data/lib/gooddata/models/user_group.rb +250 -0
  327. data/lib/gooddata/rest/README.md +37 -0
  328. data/lib/gooddata/rest/client.rb +396 -0
  329. data/lib/gooddata/rest/connection.rb +776 -0
  330. data/lib/gooddata/rest/object.rb +69 -0
  331. data/lib/gooddata/rest/object_factory.rb +51 -0
  332. data/lib/gooddata/rest/resource.rb +27 -0
  333. data/lib/gooddata/rest/rest.rb +24 -0
  334. data/lib/gooddata/version.rb +23 -0
  335. data/lib/templates/bricks/brick.rb.erb +7 -0
  336. data/lib/templates/bricks/main.rb.erb +5 -0
  337. data/lib/templates/project/Goodfile.erb +4 -0
  338. data/lib/templates/project/data/commits.csv +4 -0
  339. data/lib/templates/project/data/devs.csv +4 -0
  340. data/lib/templates/project/data/repos.csv +3 -0
  341. data/lib/templates/project/model/model.rb.erb +20 -0
  342. data/spec/.rubocop.yml +16 -0
  343. data/spec/bricks/bricks_spec.rb +110 -0
  344. data/spec/bricks/default-config.json +8 -0
  345. data/spec/data/.gooddata +4 -0
  346. data/spec/data/blueprints/additional_dataset_module.json +32 -0
  347. data/spec/data/blueprints/attribute_sort_order_blueprint.json +72 -0
  348. data/spec/data/blueprints/big_blueprint_not_pruned.json +2079 -0
  349. data/spec/data/blueprints/invalid_blueprint.json +103 -0
  350. data/spec/data/blueprints/m_n_model.json +104 -0
  351. data/spec/data/blueprints/model_module.json +25 -0
  352. data/spec/data/blueprints/test_blueprint.json +39 -0
  353. data/spec/data/blueprints/test_project_model_spec.json +106 -0
  354. data/spec/data/cc/data/source/commits.csv +4 -0
  355. data/spec/data/cc/data/source/devs.csv +4 -0
  356. data/spec/data/cc/data/source/repos.csv +3 -0
  357. data/spec/data/cc/devel.prm +0 -0
  358. data/spec/data/cc/graph/graph.grf +11 -0
  359. data/spec/data/cc/workspace.prm +19 -0
  360. data/spec/data/column_based_permissions.csv +7 -0
  361. data/spec/data/column_based_permissions2.csv +6 -0
  362. data/spec/data/dynamic_schedule_params_table.csv +7 -0
  363. data/spec/data/gd_gse_data_blueprint.json +1371 -0
  364. data/spec/data/gd_gse_data_manifest.json +1424 -0
  365. data/spec/data/gd_gse_data_model.json +1772 -0
  366. data/spec/data/gooddata_version_process/gooddata_version.rb +9 -0
  367. data/spec/data/gooddata_version_process/gooddata_version.zip +0 -0
  368. data/spec/data/hello_world_process/hello_world.rb +9 -0
  369. data/spec/data/hello_world_process/hello_world.zip +0 -0
  370. data/spec/data/line_based_permissions.csv +3 -0
  371. data/spec/data/manifests/test_blueprint.json +32 -0
  372. data/spec/data/manifests/test_project.json +107 -0
  373. data/spec/data/reports/left_attr_report.json +108 -0
  374. data/spec/data/reports/metric_only_one_line.json +83 -0
  375. data/spec/data/reports/report_1.json +197 -0
  376. data/spec/data/reports/top_attr_report.json +108 -0
  377. data/spec/data/ruby_params_process/ruby_params.rb +9 -0
  378. data/spec/data/ruby_process/deep_files/deep_stuff.txt +1 -0
  379. data/spec/data/ruby_process/process.rb +8 -0
  380. data/spec/data/ruby_process/stuff.txt +1 -0
  381. data/spec/data/superfluous_titles_view.json +81 -0
  382. data/spec/data/test-ci-data.csv +2 -0
  383. data/spec/data/users.csv +12 -0
  384. data/spec/data/wire_models/attribute_sort_by_model.json +73 -0
  385. data/spec/data/wire_models/model_view.json +1775 -0
  386. data/spec/data/wire_models/nu_model.json +3046 -0
  387. data/spec/data/wire_models/test_blueprint.json +66 -0
  388. data/spec/data/wire_test_project.json +150 -0
  389. data/spec/data/workspace_table.csv +3 -0
  390. data/spec/environment/default.rb +43 -0
  391. data/spec/environment/development.rb +32 -0
  392. data/spec/environment/environment.rb +38 -0
  393. data/spec/environment/production.rb +27 -0
  394. data/spec/environment/staging.rb +33 -0
  395. data/spec/environment/testing.rb +32 -0
  396. data/spec/helpers/blueprint_helper.rb +27 -0
  397. data/spec/helpers/cli_helper.rb +38 -0
  398. data/spec/helpers/connection_helper.rb +43 -0
  399. data/spec/helpers/crypto_helper.rb +19 -0
  400. data/spec/helpers/csv_helper.rb +20 -0
  401. data/spec/helpers/process_helper.rb +35 -0
  402. data/spec/helpers/project_helper.rb +74 -0
  403. data/spec/helpers/schedule_helper.rb +33 -0
  404. data/spec/helpers/spec_helper.rb +17 -0
  405. data/spec/integration/ads_output_stage_spec.rb +45 -0
  406. data/spec/integration/blueprint_updates_spec.rb +107 -0
  407. data/spec/integration/blueprint_with_ca_spec.rb +56 -0
  408. data/spec/integration/blueprint_with_grain_spec.rb +74 -0
  409. data/spec/integration/channel_configuration_spec.rb +67 -0
  410. data/spec/integration/clients_spec.rb +164 -0
  411. data/spec/integration/command_datawarehouse_spec.rb +45 -0
  412. data/spec/integration/command_projects_spec.rb +32 -0
  413. data/spec/integration/commands/command_projects_spec.rb +22 -0
  414. data/spec/integration/core/connection_spec.rb +56 -0
  415. data/spec/integration/core/logging_spec.rb +130 -0
  416. data/spec/integration/core/project_spec.rb +54 -0
  417. data/spec/integration/create_from_template_spec.rb +29 -0
  418. data/spec/integration/create_project_spec.rb +27 -0
  419. data/spec/integration/date_dim_switch_spec.rb +150 -0
  420. data/spec/integration/deprecated_load_spec.rb +60 -0
  421. data/spec/integration/full_process_schedule_spec.rb +367 -0
  422. data/spec/integration/full_project_spec.rb +592 -0
  423. data/spec/integration/helpers_spec.rb +16 -0
  424. data/spec/integration/lcm_spec.rb +54 -0
  425. data/spec/integration/mixins/id_to_uri_spec.rb +44 -0
  426. data/spec/integration/models/data_product_spec.rb +71 -0
  427. data/spec/integration/models/domain_spec.rb +162 -0
  428. data/spec/integration/models/invitation_spec.rb +17 -0
  429. data/spec/integration/models/membership_spec.rb +127 -0
  430. data/spec/integration/models/metadata/report_spec.rb +54 -0
  431. data/spec/integration/models/params_spec.rb +118 -0
  432. data/spec/integration/models/profile_spec.rb +210 -0
  433. data/spec/integration/models/project_role_spec.rb +94 -0
  434. data/spec/integration/models/project_spec.rb +225 -0
  435. data/spec/integration/models/schedule_spec.rb +485 -0
  436. data/spec/integration/models/unit_project_spec.rb +130 -0
  437. data/spec/integration/over_to_user_filters_spec.rb +98 -0
  438. data/spec/integration/partial_md_export_import_spec.rb +41 -0
  439. data/spec/integration/project_spec.rb +381 -0
  440. data/spec/integration/rest_spec.rb +214 -0
  441. data/spec/integration/schedule_spec.rb +613 -0
  442. data/spec/integration/segments_spec.rb +100 -0
  443. data/spec/integration/subscription_spec.rb +88 -0
  444. data/spec/integration/urn_date_dim_spec.rb +53 -0
  445. data/spec/integration/user_filters_spec.rb +306 -0
  446. data/spec/integration/user_group_spec.rb +147 -0
  447. data/spec/integration/variables_spec.rb +189 -0
  448. data/spec/logging_in_logging_out_spec.rb +91 -0
  449. data/spec/spec_helper.rb +66 -0
  450. data/spec/unit/actions/associate_clients_spec.rb +47 -0
  451. data/spec/unit/actions/collect_client_projects_spec.rb +47 -0
  452. data/spec/unit/actions/collect_clients_spec.rb +65 -0
  453. data/spec/unit/actions/collect_data_product_spec.rb +56 -0
  454. data/spec/unit/actions/collect_dynamic_schedule_params_spec.rb +56 -0
  455. data/spec/unit/actions/collect_meta_spec.rb +88 -0
  456. data/spec/unit/actions/collect_segment_clients_spec.rb +81 -0
  457. data/spec/unit/actions/collect_tagged_objects_spec.rb +126 -0
  458. data/spec/unit/actions/collect_users_brick_users_spec.rb +36 -0
  459. data/spec/unit/actions/create_segment_masters_spec.rb +64 -0
  460. data/spec/unit/actions/ensure_data_product_spec.rb +38 -0
  461. data/spec/unit/actions/ensure_technical_users_domain_spec.rb +51 -0
  462. data/spec/unit/actions/ensure_technical_users_project_spec.rb +72 -0
  463. data/spec/unit/actions/execute_schedules_spec.rb +94 -0
  464. data/spec/unit/actions/provision_clients_spec.rb +45 -0
  465. data/spec/unit/actions/purge_clients_spec.rb +47 -0
  466. data/spec/unit/actions/rename_existing_client_projects_spec.rb +54 -0
  467. data/spec/unit/actions/segments_filter_spec.rb +46 -0
  468. data/spec/unit/actions/shared_examples_for_user_actions.rb +26 -0
  469. data/spec/unit/actions/synchronize_cas_spec.rb +58 -0
  470. data/spec/unit/actions/synchronize_etls_in_segment_spec.rb +212 -0
  471. data/spec/unit/actions/synchronize_ldm_spec.rb +57 -0
  472. data/spec/unit/actions/synchronize_user_filters_spec.rb +146 -0
  473. data/spec/unit/actions/synchronize_user_groups_spec.rb +49 -0
  474. data/spec/unit/actions/synchronize_users_spec.rb +134 -0
  475. data/spec/unit/bricks/bricks_spec.rb +34 -0
  476. data/spec/unit/bricks/middleware/aws_middelware_spec.rb +98 -0
  477. data/spec/unit/bricks/middleware/bench_middleware_spec.rb +15 -0
  478. data/spec/unit/bricks/middleware/bulk_salesforce_middleware_spec.rb +15 -0
  479. data/spec/unit/bricks/middleware/gooddata_middleware_spec.rb +15 -0
  480. data/spec/unit/bricks/middleware/logger_middleware_spec.rb +30 -0
  481. data/spec/unit/bricks/middleware/restforce_middleware_spec.rb +15 -0
  482. data/spec/unit/bricks/middleware/stdout_middleware_spec.rb +15 -0
  483. data/spec/unit/bricks/middleware/twitter_middleware_spec.rb +15 -0
  484. data/spec/unit/cli/cli_spec.rb +17 -0
  485. data/spec/unit/cli/commands/cmd_auth_spec.rb +17 -0
  486. data/spec/unit/core/nil_logger_spec.rb +13 -0
  487. data/spec/unit/extensions/hash_spec.rb +22 -0
  488. data/spec/unit/godzilla/goodzilla_spec.rb +74 -0
  489. data/spec/unit/helpers/csv_helper_spec.rb +22 -0
  490. data/spec/unit/helpers/data_helper_spec.rb +67 -0
  491. data/spec/unit/helpers/global_helpers_spec.rb +264 -0
  492. data/spec/unit/helpers_spec.rb +254 -0
  493. data/spec/unit/lcm/user_bricks_helper_spec.rb +58 -0
  494. data/spec/unit/models/blueprint/attribute_sort_by_spec.rb +20 -0
  495. data/spec/unit/models/blueprint/attributes_spec.rb +28 -0
  496. data/spec/unit/models/blueprint/dataset_spec.rb +120 -0
  497. data/spec/unit/models/blueprint/labels_spec.rb +43 -0
  498. data/spec/unit/models/blueprint/project_blueprint_spec.rb +642 -0
  499. data/spec/unit/models/blueprint/reference_spec.rb +28 -0
  500. data/spec/unit/models/blueprint/schema_builder_spec.rb +36 -0
  501. data/spec/unit/models/blueprint/to_wire_spec.rb +195 -0
  502. data/spec/unit/models/execution_spec.rb +109 -0
  503. data/spec/unit/models/from_wire_spec.rb +301 -0
  504. data/spec/unit/models/metadata_spec.rb +140 -0
  505. data/spec/unit/models/metric_spec.rb +129 -0
  506. data/spec/unit/models/model_spec.rb +77 -0
  507. data/spec/unit/models/project_creator_spec.rb +90 -0
  508. data/spec/unit/models/project_spec.rb +94 -0
  509. data/spec/unit/models/report_result_data_spec.rb +194 -0
  510. data/spec/unit/models/to_manifest_spec.rb +136 -0
  511. data/spec/unit/models/user_filters/user_filter_builder_spec.rb +110 -0
  512. data/spec/unit/models/user_filters_spec.rb +95 -0
  513. data/spec/unit/models/variable_spec.rb +280 -0
  514. data/spec/unit/rest/polling_spec.rb +101 -0
  515. data/spec/unit/rest/resource_spec.rb +10 -0
  516. data/yard-server.sh +3 -0
  517. metadata +1207 -0
@@ -0,0 +1,31 @@
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
+ require_relative './client_synchronization_result_details'
8
+
9
+ require_relative '../mixins/data_property_reader'
10
+ require_relative '../mixins/links'
11
+
12
+ require_relative '../rest/resource'
13
+
14
+ module GoodData
15
+ class ClientSynchronizationResult < Rest::Resource
16
+ include Mixin::Links
17
+
18
+ # Initializes object instance from raw wire JSON
19
+ #
20
+ # @param json Json used for initialization
21
+ def initialize(json, opts = {})
22
+ super(opts)
23
+ @json = json
24
+ end
25
+
26
+ def details
27
+ res = client.get(links['details'])
28
+ client.create(GoodData::ClientSynchronizationResultDetails, res) if res
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,41 @@
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
+ require_relative './client'
8
+
9
+ require_relative '../mixins/data_property_reader'
10
+ require_relative '../mixins/links'
11
+
12
+ require_relative '../rest/resource'
13
+
14
+ module GoodData
15
+ class ClientSynchronizationResultDetails < Rest::Resource
16
+ include Mixin::Links
17
+
18
+ attr_accessor :synchronization_result
19
+
20
+ # Initializes object instance from raw wire JSON
21
+ #
22
+ # @param json Json used for initialization
23
+ def initialize(json, opts = { :synchronization_result => nil })
24
+ super(opts)
25
+ @json = json
26
+ @synchronization_result = opts[:synchronization_result]
27
+ end
28
+
29
+ def items
30
+ data['items']
31
+ end
32
+
33
+ def next
34
+ paging && paging['next']
35
+ end
36
+
37
+ def paging
38
+ data['paging']
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,149 @@
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
+ require_relative '../rest/resource'
8
+
9
+ module GoodData
10
+ class DataProduct < Rest::Resource
11
+ include Mixin::UriGetter
12
+
13
+ attr_accessor :domain
14
+
15
+ ALL_DATA_PRODUCTS_PATH = '/gdc/domains/%{domain_name}/dataproducts'
16
+ ONE_DATA_PRODUCT_PATH = '/gdc/domains/%{domain_name}/dataproducts/%{id}'
17
+
18
+ class << self
19
+ def [](id, opts)
20
+ domain = opts[:domain]
21
+ fail ArgumentError, 'No :domain specified' if domain.nil?
22
+
23
+ client = domain.client
24
+ fail ArgumentError, 'No client specified' if client.nil?
25
+
26
+ if id == :all
27
+ GoodData::DataProduct.all(opts)
28
+ else
29
+ data_products_uri = ONE_DATA_PRODUCT_PATH % { domain_name: domain.name, id: id }
30
+
31
+ result = client.get(data_products_uri)
32
+ client.create(GoodData::DataProduct, result.merge('domain' => domain))
33
+ end
34
+ end
35
+
36
+ def all(opts = {})
37
+ domain = opts[:domain]
38
+ fail ArgumentError, 'No :domain specified' if domain.nil?
39
+
40
+ client = domain.client
41
+ fail ArgumentError, 'No client specified' if client.nil?
42
+
43
+ data_products_uri = ALL_DATA_PRODUCTS_PATH % { domain_name: domain.name }
44
+
45
+ GoodData::Helpers.get_path(client.get(data_products_uri), %w(dataProducts items)).map do |i|
46
+ client.create(GoodData::DataProduct, i, domain: domain)
47
+ end
48
+ end
49
+
50
+ def create(data = {}, options = {})
51
+ fail 'id for data_product has to be provided' if data[:id].blank?
52
+ client = options[:client]
53
+ client.create(GoodData::DataProduct, GoodData::Helpers.stringify_keys(dataProduct: data), domain: options[:domain])
54
+ end
55
+ end
56
+
57
+ def initialize(json)
58
+ super
59
+ @json = json
60
+ @domain = json.delete('domain')
61
+ end
62
+
63
+ def clients
64
+ json = client.get(data['links']['clients'])
65
+
66
+ json['clients']['items'].map do |val|
67
+ client.create(GoodData::Client, val, domain: domain)
68
+ end
69
+ end
70
+
71
+ def segments
72
+ json = client.get(data['links']['segments'])
73
+
74
+ json['segments']['items'].map do |val|
75
+ client.create(GoodData::Segment, val, domain: domain, data_product: self)
76
+ end
77
+ end
78
+
79
+ def save
80
+ if @json[:uri]
81
+ client.put(uri, json)
82
+ else
83
+ data_products_uri = ALL_DATA_PRODUCTS_PATH % { domain_name: domain.name }
84
+ res = client.post(data_products_uri, json)
85
+ @json = res
86
+ end
87
+ self
88
+ end
89
+
90
+ def delete(options = {})
91
+ segments.peach { |s| s.delete(options) }
92
+ client.delete(uri) if uri
93
+ self
94
+ end
95
+
96
+ def update_clients(data, options = {})
97
+ if options[:delete_extra] && options[:delete_extra_in_segments]
98
+ fail 'Options delete_extra and delete_extra_in_segments are mutually exclusive.'
99
+ end
100
+
101
+ data_products_uri = ONE_DATA_PRODUCT_PATH % { domain_name: domain.name, id: data_product_id }
102
+
103
+ payload = data.map do |datum|
104
+ {
105
+ :client => {
106
+ :id => datum[:id],
107
+ :segment => data_products_uri + '/segments/' + datum[:segment]
108
+ }
109
+ }.tap do |h|
110
+ h[:client][:project] = datum[:project] if datum.key?(:project)
111
+ end
112
+ end
113
+
114
+ if options[:delete_extra]
115
+ res = client.post(data_products_uri + '/updateClients?deleteExtra=true', updateClients: { items: payload })
116
+ elsif options[:delete_extra_in_segments]
117
+ segments_to_delete_in = options[:delete_extra_in_segments]
118
+ .map { |segment| CGI.escape(segment) }
119
+ .join(',')
120
+ uri = data_products_uri + "/updateClients?deleteExtraInSegments=#{segments_to_delete_in}"
121
+ res = client.post(uri, updateClients: { items: payload })
122
+ else
123
+ res = client.post(data_products_uri + '/updateClients', updateClients: { items: payload })
124
+ end
125
+ data = GoodData::Helpers.get_path(res, ['updateClientsResponse'])
126
+ if data
127
+ result = data.flat_map { |k, v| v.map { |h| GoodData::Helpers.symbolize_keys(h.merge('type' => k)) } }
128
+ result.select { |r| r[:status] == 'DELETED' }.peach { |r| r[:originalProject] && client.delete(r[:originalProject]) } if options[:delete_projects]
129
+ result
130
+ else
131
+ []
132
+ end
133
+ end
134
+
135
+ def data_product_id
136
+ data['id']
137
+ end
138
+
139
+ def data_product_id=(new_id)
140
+ data['id'] = new_id
141
+ end
142
+
143
+ def create_segment(data)
144
+ segment = GoodData::Segment.create(data, domain: domain, client: domain.client)
145
+ segment.data_product = self
146
+ segment.save
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,114 @@
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
+ require_relative '../rest/resource'
8
+
9
+ module GoodData
10
+ class DataWarehouse < Rest::Resource
11
+ class << self
12
+ CREATE_URL = '/gdc/datawarehouse/instances'
13
+
14
+ def [](id = :all, options = { client: GoodData.client })
15
+ c = GoodData.get_client(options)
16
+
17
+ if id == :all
18
+ data = c.get(CREATE_URL)
19
+ data['instances']['items'].map do |ads_data|
20
+ c.create(DataWarehouse, ads_data)
21
+ end
22
+ else
23
+ c.create(DataWarehouse, c.get("#{CREATE_URL}/#{id}"))
24
+ end
25
+ end
26
+
27
+ def all(options = { client: GoodData.client })
28
+ DataWarehouse[:all, options]
29
+ end
30
+
31
+ # Create a data warehouse from given attributes
32
+ # Expected keys:
33
+ # - :title (mandatory)
34
+ # - :auth_token (mandatory)
35
+ # - :summary
36
+ def create(opts)
37
+ GoodData.logger.info "Creating warehouse #{opts[:title]}"
38
+
39
+ c = GoodData.get_client(opts)
40
+
41
+ opts = { :auth_token => Helpers::AuthHelper.read_token }.merge(opts)
42
+ auth_token = opts[:auth_token] || opts[:token]
43
+ fail ArgumentError, 'You have to provide your token for creating projects as :auth_token parameter' if auth_token.nil? || auth_token.empty?
44
+
45
+ title = opts[:title]
46
+ fail ArgumentError, 'You have to provide a title for creating warehouse as :title parameter' if title.nil? || title.empty?
47
+
48
+ json = {
49
+ 'instance' => {
50
+ 'title' => title,
51
+ 'description' => opts[:description] || opts[:summary] || 'No summary',
52
+ 'authorizationToken' => auth_token
53
+ }
54
+ }
55
+ json['instance']['environment'] = opts[:environment] if opts[:environment]
56
+
57
+ # do the first post
58
+ res = c.post(CREATE_URL, json)
59
+
60
+ # wait until the instance is created
61
+ final_res = c.poll_on_response(res['asyncTask']['links']['poll'], opts.merge(sleep_interval: 3)) do |r|
62
+ r['asyncTask']['links']['instance'].nil?
63
+ end
64
+
65
+ # get the json of the created instance
66
+ final_json = c.get(final_res['asyncTask']['links']['instance'])
67
+
68
+ # create the public facing object
69
+ c.create(DataWarehouse, final_json)
70
+ end
71
+ end
72
+
73
+ def initialize(json)
74
+ super
75
+ @json = json
76
+ end
77
+
78
+ def title
79
+ json['instance']['title']
80
+ end
81
+
82
+ def summary
83
+ json['instance']['description']
84
+ end
85
+
86
+ def status
87
+ json['instance']['status']
88
+ end
89
+
90
+ def uri
91
+ json['instance']['links']['self']
92
+ end
93
+
94
+ def id
95
+ uri.split('/')[-1]
96
+ end
97
+
98
+ def delete
99
+ if state == 'DELETED'
100
+ fail "Warehouse '#{title}' with id #{uri} is already deleted"
101
+ end
102
+ client.delete(uri)
103
+ end
104
+
105
+ # alias methods to prevent confusion and support the same keys
106
+ # project has.
107
+ alias_method :state, :status
108
+ alias_method :description, :summary
109
+
110
+ def schemas
111
+ json['instance']['links']['schemas']
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,505 @@
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
+ require 'cgi'
8
+
9
+ require_relative 'profile'
10
+ require_relative '../extensions/enumerable'
11
+ require_relative '../rest/object'
12
+
13
+ module GoodData
14
+ class Domain < Rest::Resource
15
+ attr_reader :name
16
+
17
+ USER_LANGUAGES = {
18
+ 'en-US' => 'English',
19
+ 'nl-NL' => 'Dutch',
20
+ 'es-ES' => 'Spanish',
21
+ 'pt-BR' => 'Portuguese/Brazil',
22
+ 'pt-PT' => 'Portuguese/Portugal',
23
+ 'fr-FR' => 'French',
24
+ 'de-DE' => 'German',
25
+ 'ja-JP' => 'Japanese'
26
+ }
27
+
28
+ class << self
29
+ # Looks for domain
30
+ #
31
+ # @param domain_name [String] Domain name
32
+ # @return [String] Domain object instance
33
+ def [](domain_name, options = { :client => GoodData.connection })
34
+ return domain_name if domain_name.is_a?(Domain)
35
+ c = client(options)
36
+ fail "Using pseudo-id 'all' is not supported by GoodData::Domain" if domain_name.to_s == 'all'
37
+ c.create(GoodData::Domain, domain_name)
38
+ end
39
+
40
+ # Adds user to domain
41
+ #
42
+ # @param domain [String] Domain name
43
+ # @param login [String] Login of user to be invited
44
+ # @param password [String] Default preset password
45
+ # @return [Object] Raw response
46
+ def add_user(user_data, name = nil, opts = { :client => GoodData.connection })
47
+ generated_pass = rand(10E10).to_s
48
+ domain_name = name || user_data[:domain]
49
+ user_data = user_data.to_hash
50
+ data = {
51
+ :login => user_data[:login] || user_data[:email],
52
+ :firstName => user_data[:first_name] || 'FirstName',
53
+ :lastName => user_data[:last_name] || 'LastName',
54
+ :password => user_data[:password] || generated_pass,
55
+ :verifyPassword => user_data[:password] || generated_pass,
56
+ :email => user_data[:email] || user_data[:login],
57
+ :language => ensure_user_language(user_data)
58
+ }
59
+
60
+ # Optional authentication modes
61
+ tmp = user_data[:authentication_modes]
62
+ if tmp
63
+ if tmp.is_a? Array
64
+ data[:authenticationModes] = tmp
65
+ elsif tmp.is_a? String
66
+ data[:authenticationModes] = [tmp]
67
+ end
68
+ end
69
+
70
+ # Optional company
71
+ tmp = user_data[:company_name]
72
+ tmp = user_data[:company] if tmp.nil? || tmp.empty?
73
+ data[:companyName] = tmp if tmp && !tmp.empty?
74
+
75
+ # Optional country
76
+ tmp = user_data[:country]
77
+ data[:country] = tmp if tmp && !tmp.empty?
78
+
79
+ # Optional phone number
80
+ tmp = user_data[:phone]
81
+ tmp = user_data[:phone_number] if tmp.nil? || tmp.empty?
82
+ data[:phoneNumber] = tmp if tmp && !tmp.empty?
83
+
84
+ # Optional position
85
+ tmp = user_data[:position]
86
+ data[:position] = tmp if tmp && !tmp.empty?
87
+
88
+ # Optional sso provider
89
+ tmp = user_data[:sso_provider]
90
+ data['ssoProvider'] = tmp if tmp && !tmp.empty?
91
+
92
+ # Optional timezone
93
+ tmp = user_data[:timezone]
94
+ data[:timezone] = tmp if tmp && !tmp.empty?
95
+
96
+ # Optional ip whitelist
97
+ tmp = user_data[:ip_whitelist]
98
+ data[:ipWhitelist] = tmp if tmp
99
+
100
+ c = client(opts)
101
+
102
+ # TODO: It will be nice if the API will return us user just newly created
103
+ begin
104
+ url = "/gdc/account/domains/#{domain_name}/users"
105
+ response = c.post(url, :accountSetting => data)
106
+ rescue RestClient::BadRequest => e
107
+ error = MultiJson.load(e.response)
108
+ error_type = GoodData::Helpers.get_path(error, %w(error errorClass))
109
+ case error_type
110
+ when 'com.gooddata.webapp.service.userprovisioning.LoginNameAlreadyRegisteredException'
111
+ u = Domain.find_user_by_login(domain_name, data[:login])
112
+ if u
113
+ response = { 'uri' => u.uri }
114
+ else
115
+ raise GoodData::UserInDifferentDomainError, "User #{data[:login]} is already in different domain"
116
+ end
117
+ when 'com.gooddata.json.validator.exception.MalformedMessageException'
118
+ raise GoodData::MalformedUserError, "User #{data[:login]} is malformed. The message from API is #{GoodData::Helpers.interpolate_error_message(error)}"
119
+ else
120
+ raise GoodData::Helpers.interpolate_error_message(error)
121
+ end
122
+ end
123
+
124
+ url = response['uri']
125
+ raw = c.get url
126
+
127
+ # TODO: Remove this hack when POST /gdc/account/domains/{domain-name}/users returns full profile
128
+ raw['accountSetting']['links'] = {} unless raw['accountSetting']['links']
129
+ raw['accountSetting']['links']['self'] = response['uri'] unless raw['accountSetting']['links']['self']
130
+ c.create(GoodData::Profile, raw)
131
+ end
132
+
133
+ def update_user(user_data, options = { client: GoodData.connection })
134
+ user_data = user_data.to_hash if user_data.is_a?(GoodData::Profile)
135
+ client = client(options)
136
+ user_data = user_data.to_hash
137
+ # generated_pass = rand(10E10).to_s
138
+ data = {
139
+ :firstName => user_data[:first_name] || 'FirstName',
140
+ :lastName => user_data[:last_name] || 'LastName',
141
+ :email => user_data[:email],
142
+ :language => ensure_user_language(user_data)
143
+ }
144
+
145
+ # Optional authentication modes
146
+ tmp = user_data[:authentication_modes]
147
+ if tmp
148
+ if tmp.is_a? Array
149
+ data[:authenticationModes] = tmp
150
+ elsif tmp.is_a? String
151
+ data[:authenticationModes] = [tmp]
152
+ end
153
+ end
154
+
155
+ # Optional company
156
+ tmp = user_data[:company_name]
157
+ tmp = user_data[:company] if tmp.nil? || tmp.empty?
158
+ data[:companyName] = tmp if tmp && !tmp.empty?
159
+
160
+ # Optional pass
161
+ tmp = user_data[:password]
162
+ tmp = user_data[:password] if tmp.nil? || tmp.empty?
163
+ data[:password] = tmp if tmp && !tmp.empty?
164
+ data[:verifyPassword] = tmp if tmp && !tmp.empty?
165
+
166
+ # Optional country
167
+ tmp = user_data[:country]
168
+ data[:country] = tmp if tmp && !tmp.empty?
169
+
170
+ # Optional phone number
171
+ tmp = user_data[:phone]
172
+ tmp = user_data[:phone_number] if tmp.nil? || tmp.empty?
173
+ data[:phoneNumber] = tmp if tmp && !tmp.empty?
174
+
175
+ # Optional position
176
+ tmp = user_data[:position]
177
+ data[:position] = tmp if tmp && !tmp.empty?
178
+
179
+ # Optional sso provider
180
+ tmp = user_data[:sso_provider]
181
+ data['ssoProvider'] = tmp if tmp
182
+
183
+ # Optional timezone
184
+ tmp = user_data[:timezone]
185
+ data[:timezone] = tmp if tmp && !tmp.empty?
186
+
187
+ # TODO: It will be nice if the API will return us user just newly created
188
+ url = user_data.delete(:uri)
189
+ data.delete(:password) if client.user.uri == url
190
+ response = client.put(url, :accountSetting => data)
191
+
192
+ # TODO: Remove this hack when POST /gdc/account/domains/{domain-name}/users returns full profile
193
+ response['accountSetting']['links'] = {} unless response['accountSetting']['links']
194
+ response['accountSetting']['links']['self'] = url unless response['accountSetting']['links']['self']
195
+ client.create(GoodData::Profile, response)
196
+ end
197
+
198
+ # Finds user in domain by login
199
+ #
200
+ # @param domain [String] Domain name
201
+ # @param login [String] User login
202
+ # @return [GoodData::Profile] User profile
203
+ def find_user_by_login(domain, login, opts = { :client => GoodData.connection, :project => GoodData.project })
204
+ c = client(opts)
205
+ escaped_login = CGI.escape(login)
206
+ domain = c.domain(domain)
207
+ GoodData.logger.warn("Retrieving particular user \"#{login.inspect}\" from domain #{domain.name}")
208
+ url = "#{domain.uri}/users?login=#{escaped_login}"
209
+ tmp = c.get url
210
+ items = tmp['accountSettings']['items'] if tmp['accountSettings']
211
+ items && !items.empty? ? c.factory.create(GoodData::Profile, items.first) : nil
212
+ end
213
+
214
+ # Returns list of users for domain specified
215
+ # @param [String] domain Domain to list the users for
216
+ # @param [Hash] opts Options.
217
+ # @option opts [Number] :offset The subject
218
+ # @option opts [Number] :limit From address
219
+ # TODO: Review opts[:limit] functionality
220
+ def users(domain, id = :all, opts = {})
221
+ client = client(opts)
222
+ domain = client.domain(domain)
223
+ if id == :all
224
+ GoodData.logger.warn("Retrieving all users from domain #{domain.name}")
225
+ Enumerator.new do |y|
226
+ page_limit = opts[:page_limit] || 1000
227
+ offset = opts[:offset] || 0
228
+ loop do
229
+ begin
230
+ tmp = client(opts).get("#{domain.uri}/users", params: { offset: offset, limit: page_limit })
231
+ end
232
+
233
+ tmp['accountSettings']['items'].each do |user_data|
234
+ user = client.create(GoodData::Profile, user_data)
235
+ y << user if user
236
+ end
237
+ break if tmp['accountSettings']['items'].count < page_limit
238
+ offset += page_limit
239
+ end
240
+ end
241
+ else
242
+ find_user_by_login(domain, id)
243
+ end
244
+ end
245
+
246
+ # Create users specified in list
247
+ # @param [Array<GoodData::Membership>] list List of users
248
+ # @param [String] default_domain_name Default domain name used when no specified in user
249
+ # @return [Array<GoodData::User>] List of users created
250
+ def create_users(list, default_domain = nil, opts = { :client => GoodData.connection, :project => GoodData.project })
251
+ default_domain_name = default_domain.respond_to?(:name) ? default_domain.name : default_domain
252
+ domain = client.domain(default_domain_name)
253
+
254
+ # Prepare cache for domain users
255
+ domain_users_cache = Hash[domain.users.map { |u| [u.login.downcase, u] }]
256
+
257
+ list.pmapcat do |user|
258
+ begin
259
+ user_data = user.to_hash.tap { |uh| uh[:login].downcase! }
260
+ domain_user = domain_users_cache[user_data[:login]]
261
+ user_login = user_data[:login]
262
+ if !domain_user
263
+ added_user = domain.add_user(user_data, opts)
264
+ GoodData.logger.info("Added new user=#{user_login} to domain=#{default_domain_name}.")
265
+ [{ type: :successful, :action => :user_added_to_domain, user: added_user }]
266
+ else
267
+ domain_user_data = domain_user.to_hash
268
+ fields_to_check = opts[:fields_to_check] || user_data.keys
269
+ diff = GoodData::Helpers.diff([domain_user.to_hash], [user_data], key: :login, fields: fields_to_check)
270
+ next [] if diff[:changed].empty?
271
+ updated_user = domain.update_user(domain_user.to_hash.merge(user_data.compact), opts)
272
+ GoodData.logger.debug "Updated user=#{user_login} from old properties \
273
+ (email=#{domain_user_data[:email]}, sso_provider=#{domain_user_data[:sso_provider]}) \
274
+ to new properties (email=#{user_data[:email]}, sso_provider=#{user_data[:sso_provider]}) in domain=#{default_domain_name}."
275
+ [{ type: :successful, :action => :user_changed_in_domain, user: updated_user }]
276
+ end
277
+ rescue RuntimeError => e
278
+ if !domain_user
279
+ GoodData.logger.error("Failed to add user=#{user_login} to domain=#{default_domain_name}. Error: #{e.message}")
280
+ else
281
+ GoodData.logger.error("Failed to update user=#{user_login} in domain=#{default_domain_name}. Error: #{e.message}")
282
+ end
283
+ [{ type: :failed, :user => user, message: e }]
284
+ end
285
+ end
286
+ end
287
+
288
+ private
289
+
290
+ def ensure_user_language(user_data)
291
+ language = user_data[:language] || 'en-US'
292
+ unless USER_LANGUAGES.keys.include?(language)
293
+ available_languages = USER_LANGUAGES.map { |k, v| "#{k} (#{v})" }.join(', ')
294
+ GoodData.logger.warn "The language for user '#{user_data[:login]}' will be English because '#{language}' is an invalid value. \
295
+ Available values for setting language are: #{available_languages}."
296
+ language = 'en-US'
297
+ end
298
+ language
299
+ end
300
+ end
301
+
302
+ def initialize(domain_name)
303
+ @name = domain_name
304
+ end
305
+
306
+ # Adds user to domain
307
+ #
308
+ # @param login [String] Login of user to be invited
309
+ # @param password [String] Default preset password
310
+ # @return [Object] Raw response
311
+ #
312
+ # Example
313
+ #
314
+ # GoodData.connect 'tomas.korcak@gooddata.com' 'your-password'
315
+ # domain = project.domain('domain-name')
316
+ # domain.add_user 'joe.doe@example', 'sup3rS3cr3tP4ssW0rtH'
317
+ #
318
+ def add_user(data, opts = {})
319
+ # data[:domain] = name
320
+ GoodData::Domain.add_user(data, name, { client: client }.merge(opts))
321
+ end
322
+
323
+ # Returns all the clients defined in all segments defined in domain. Alternatively
324
+ # id of a client can be provided in which case it returns just that client
325
+ # if it exists.
326
+ #
327
+ # @param id [String] Id of client that you are looking for
328
+ # @param data_product [DataProduct] data product object in which the clients are located
329
+ # @return [Object] Raw response
330
+ #
331
+ def clients(id = :all, data_product = nil)
332
+ GoodData::Client[id, data_product: data_product, domain: self]
333
+ end
334
+
335
+ alias_method :create_user, :add_user
336
+
337
+ def create_users(list, options = {})
338
+ GoodData::Domain.create_users(list, name, { client: client }.merge(options))
339
+ end
340
+
341
+ def data_products(id = :all)
342
+ GoodData::DataProduct[id, domain: self]
343
+ end
344
+
345
+ def create_data_product(data)
346
+ data_product = GoodData::DataProduct.create(data, domain: self, client: client)
347
+ data_product.save
348
+ end
349
+
350
+ def segments(id = :all, data_product = nil)
351
+ GoodData::Segment[id, data_product: data_product, domain: self]
352
+ end
353
+
354
+ # Creates new segment in current domain from parameters passed
355
+ #
356
+ # @param data [Hash] Data for segment namely :segment_id and :master_project is accepted. Master_project can be given as either a PID or a Project instance
357
+ # @return [GoodData::Segment] New Segment instance
358
+ def create_segment(data)
359
+ segment = GoodData::Segment.create(data, domain: self, client: client)
360
+ segment.save
361
+ end
362
+
363
+ # Gets user by its login or uri in various shapes
364
+ # It does not find by other information because that is not unique. If you want to search by name or email please
365
+ # use fuzzy_get_user.
366
+ #
367
+ # @param [String] name Name to look for
368
+ # @param [Array<GoodData::User>]user_list Optional cached list of users used for look-ups
369
+ # @return [GoodDta::Membership] User
370
+ def get_user(name, user_list = users)
371
+ return member(name, user_list) if name.instance_of?(GoodData::Membership)
372
+ return member(name, user_list) if name.instance_of?(GoodData::Profile)
373
+ name = name.is_a?(Hash) ? name[:login] || name[:uri] : name
374
+ return nil unless name
375
+ name.downcase!
376
+ user_list.find do |user|
377
+ user.uri && user.uri.downcase == name ||
378
+ user.login && user.login.downcase == name
379
+ end
380
+ end
381
+
382
+ # Finds user in domain by login
383
+ #
384
+ # @param login [String] User login
385
+ # @return [GoodData::Profile] User account settings
386
+ def find_user_by_login(login)
387
+ GoodData::Domain.find_user_by_login(self, login, client: client)
388
+ end
389
+
390
+ # Gets membership for profile specified
391
+ #
392
+ # @param [GoodData::Profile] profile - Profile to be checked
393
+ # @param [Array<GoodData::Profile>] list Optional list of members to check against
394
+ # @return [GoodData::Profile] Profile if found
395
+ def member(profile, list = members)
396
+ if profile.is_a? String
397
+ return list.find do |m|
398
+ m.uri == profile || m.login == profile
399
+ end
400
+ end
401
+ list.find { |m| m.login == profile.login }
402
+ end
403
+
404
+ # Checks if the profile is member of project
405
+ #
406
+ # @param [GoodData::Profile] profile - Profile to be checked
407
+ # @param [Array<GoodData::Membership>] list Optional list of members to check against
408
+ # @return [Boolean] true if is member else false
409
+ def member?(profile, list = members)
410
+ !member(profile, list).nil?
411
+ end
412
+
413
+ def members?(profiles, list = members)
414
+ profiles.map { |p| member?(p, list) }
415
+ end
416
+
417
+ # Returns uri for segments on the domain. This will be removed soon. It is here that for segments the "account" portion of the URI was removed. And not for the rest
418
+ #
419
+ # @return [String] Uri of the segments
420
+ def segments_uri
421
+ "/gdc/domains/#{name}"
422
+ end
423
+
424
+ # Calls Segment#synchronize_clients on all segments and concatenates the results
425
+ #
426
+ # @return [Array] Returns array of results
427
+ def synchronize_clients
428
+ segments.flat_map(&:synchronize_clients)
429
+ end
430
+
431
+ # Runs async process that walks through segments and provisions projects if necessary.
432
+ #
433
+ # @return [Enumerator] Returns Enumerator of results
434
+ def provision_client_projects(segments = nil)
435
+ segments = segments.is_a?(Array) ? segments : [segments]
436
+ segments.each do |segment_id|
437
+ segment = segments(segment_id)
438
+ segment.provision_client_projects
439
+ end
440
+ end
441
+
442
+ def update_clients_settings(data)
443
+ data.each do |datum|
444
+ client_id = datum[:id]
445
+ settings = datum[:settings]
446
+ settings.each do |setting|
447
+ GoodData::Client.update_setting(setting[:name], setting[:value], domain: self, client_id: client_id, data_product_id: datum[:data_product_id])
448
+ end
449
+ end
450
+ nil
451
+ end
452
+ alias_method :add_clients_settings, :update_clients_settings
453
+
454
+ def update_clients(data, options = {})
455
+ data.group_by(&:data_product_id).each do |data_product_id, client_update_data|
456
+ data_product = data_products(data_product_id)
457
+ data_product.update_clients(client_update_data, options)
458
+ end
459
+ end
460
+
461
+ # Update user in domain
462
+ #
463
+ # @param opts [Hash] Data of the user to be updated
464
+ # @return [Object] Raw response
465
+ #
466
+ def update_user(data, options = {})
467
+ GoodData::Domain.update_user(data, { client: client }.merge(options))
468
+ end
469
+
470
+ # List users in domain
471
+ #
472
+ # @param [Hash] opts Additional user listing options.
473
+ # @option opts [Number] :offset Offset to start listing from
474
+ # @option opts [Number] :limit Limit of users to be listed
475
+ # @return [Array<GoodData::Profile>] List of user account settings
476
+ #
477
+ # Example
478
+ #
479
+ # GoodData.connect 'tomas.korcak@gooddata.com' 'your-password'
480
+ # domain = GoodData::Domain['gooddata-tomas-korcak']
481
+ # pp domain.users
482
+ #
483
+ def users(id = :all, opts = {})
484
+ GoodData::Domain.users(name, id, opts.merge(client: client))
485
+ end
486
+
487
+ alias_method :members, :users
488
+
489
+ # Returns uri for the domain.
490
+ #
491
+ # @return [String] Uri of the segments
492
+ def uri
493
+ "/gdc/account/domains/#{name}"
494
+ end
495
+
496
+ private
497
+
498
+ # Private setter of domain name. Used by constructor not available for external users.
499
+ #
500
+ # @param domain_name [String] Domain name to be set.
501
+ def name=(domain_name) # rubocop:disable TrivialAccessors
502
+ @name = domain_name
503
+ end
504
+ end
505
+ end