power-bi 1.7.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2cdaf275d6377b0f772985c4e6b616030022652fd88201f7cc79b04cfe009d67
4
- data.tar.gz: 654d2e658ffbc996beb652976094eceecf95256897ad70ff59b461e46810ff82
3
+ metadata.gz: 349bd7851001e6e16d1d14f50f6abdbd473038ed3ec9665d5cd009a74db365f2
4
+ data.tar.gz: fe96607cd040b4fd034336865e7f78ceb35b297526242c4bc1f8ea3419dc95a3
5
5
  SHA512:
6
- metadata.gz: ccf88e40d284bc8e91e0bc683ed077a42a077a810e409346ac6dce508e8803b9313c7ccc1ec3ab0937c43d53169dfdbb04db64c3c73d55b52180a4f2d59a0dc0
7
- data.tar.gz: 221a648dbbc8e35ab2ed75834dfbe756e57f5583282a5f1224194489378c6c17d3c10f5f2578c50f377e1536b14bd9398b7a586ba89ec751bfa89eb15c0ca79e
6
+ metadata.gz: efc0967cf34f597d99b17a25272ba8546c9200d7e7d85ab8ffbf2ff36f99861560799cefa280f2efb787135bb4afd5bd6588fc3d147b867bd97794803d128637
7
+ data.tar.gz: eff9aeb3c7609cd54cf7d9888bb0b6ebc2cddc9cd9996e614d3dffdd8d61f77fc40480fa71baebbfc775044dedc0bd40cf83e36236c512d6808ff8ea3dcb293b
data/README.md CHANGED
@@ -12,20 +12,28 @@ pbi = PowerBI::Tenant.new(->{token = get_token(client, token) ; token.token})
12
12
 
13
13
  # Supported endpoints
14
14
 
15
+ Note: where possible we use _lazy evaluation_: we only call the REST API endpoint when really needed. For examples `pbi.workspaces` won't trigger a call, while `pbi.workspaces.count` will trigger a call. And `pbi.workspace('123')` won't trigger a call, while `pbi.workspace('123').name` will trigger a call.
16
+
17
+ Note 2: to limit the number of API calls, it is best to directly use the _getters_ iso the _lists_.
18
+
15
19
  ## Workspaces (aka Groups)
16
20
 
17
21
  * List workspaces: `pbi.workspaces`
22
+ * Get a specific workspace `pbi.workspace(id)`
18
23
  * Create workspace: `pbi.workspaces.create`
19
24
  * Upload PBIX to workspace: `ws.upload_pbix('./test.pbix', 'new_datasetname_in_the_service')`
20
25
  * Delete workspace: `workspace.delete`
21
26
  * Add a user to a wokspace: `workspace.add_user('company_0001@fabrikam.com')`
27
+ * Assign a workspace to a capacity: `workspace.assign_to_capacity(capacity)`
28
+ * Unassign a workspace from a capacity: `workspace.unassign_from_capacity`
22
29
 
23
30
  ## Reports
24
31
 
25
32
  * List reports in a workspace: `workspace.reports`
33
+ * Get report in a workspace: `workspace.report(id)`
26
34
  * Clone a report from one workspace to another: `report.clone(src_workspace, new_report_name)`
27
35
  * Rebind report to another dataset: `report.rebind(dataset)`
28
- * Export report to file: `report.export_to_file(filenam, format: 'PDF')`
36
+ * Export report to file: `report.export_to_file(filename, format: 'PDF')`
29
37
 
30
38
  ## Pages
31
39
 
@@ -40,6 +48,7 @@ pbi = PowerBI::Tenant.new(->{token = get_token(client, token) ; token.token})
40
48
  ## Datasets
41
49
 
42
50
  * List datasets in a workspace: `workspace.datasets`
51
+ * Get report in a workspace: `workspace.dataset(id)`
43
52
  * Update parameter in a dataset: `dataset.update_parameter(parameter_name, new_value)`
44
53
  * Get time of last refresh: `dataset.last_refresh`
45
54
  * Refresh the dataset: `dataset.refresh`
@@ -49,6 +58,7 @@ pbi = PowerBI::Tenant.new(->{token = get_token(client, token) ; token.token})
49
58
  ## Gateways
50
59
 
51
60
  * List gateways: `pbi.gateways`
61
+ * Get a specific gateway `pbi.gateway(id)`
52
62
 
53
63
  ## Gateway datasources
54
64
 
@@ -57,6 +67,13 @@ pbi = PowerBI::Tenant.new(->{token = get_token(client, token) ; token.token})
57
67
  * Create a new gateway datasource: `gateway.gateway_datasource.create(name, credentials, db_server, db_name)`
58
68
  * Delete a new gateway datasource: `gateway_datasource.delete`
59
69
 
70
+ ## Capacities
71
+
72
+ Note: Capacities are Azure creatures, you can't create them in Power BI.
73
+
74
+ * List capacities: `pbi.capacities`
75
+ * Get a capacity: `pbi.capacity(id)`
76
+
60
77
  # Note about gateway credentials
61
78
 
62
79
  Power BI uses an obscure mechanism to encrypt credential exchange between the service and the gateway. The encryption must be done outside this module on a Windows machine based on th public key of the gateway. This is an example C# script:
@@ -2,10 +2,11 @@ module PowerBI
2
2
 
3
3
  class Array
4
4
 
5
- def initialize(tenant)
5
+ def initialize(tenant, parent = nil)
6
6
  @fulfilled = false
7
7
  @content = nil
8
8
  @tenant = tenant
9
+ @parent = parent
9
10
  end
10
11
 
11
12
  def reload
@@ -19,7 +20,7 @@ module PowerBI
19
20
  def get_content
20
21
  unless @fulfilled
21
22
  klass = self.class.get_class
22
- @content = get_data.map { |d| klass.new(@tenant, d)}
23
+ @content = get_data.map { |d| klass.instantiate_from_data(@tenant, @parent, d) }
23
24
  @fulfilled = true
24
25
  end
25
26
  @content
@@ -0,0 +1,35 @@
1
+ module PowerBI
2
+ class Capacity < Object
3
+
4
+ def initialize(tenant, parent, id = nil)
5
+ super(tenant, id)
6
+ end
7
+
8
+ def get_data(id)
9
+ @tenant.get("/capacities", {'$filter': "id eq #{id}"})[:value].first
10
+ end
11
+
12
+ def data_to_attributes(data)
13
+ {
14
+ id: data[:id],
15
+ display_name: data[:displayName],
16
+ sku: data[:sku],
17
+ state: data[:state],
18
+ region: data[:region],
19
+ capacity_user_access_right: data[:capacityUserAccessRight],
20
+ admins: data[:admins],
21
+ }
22
+ end
23
+
24
+ end
25
+
26
+ class CapacityArray < Array
27
+ def self.get_class
28
+ Capacity
29
+ end
30
+
31
+ def get_data
32
+ @tenant.get("/capacities")[:value]
33
+ end
34
+ end
35
+ end
@@ -1,26 +1,33 @@
1
1
  module PowerBI
2
- class Dataset
3
- attr_reader :id, :name, :add_rows_API_enabled, :configured_by, :is_refreshable, :is_effective_identity_required,
4
- :is_effective_identity_roles_required, :is_on_prem_gateway_required, :target_storage_mode, :workspace, :datasources,
5
- :parameters, :refresh_history
2
+ class Dataset < Object
3
+ attr_reader :workspace, :datasources, :parameters, :refresh_history
6
4
 
7
- def initialize(tenant, data)
8
- @id = data[:id]
9
- @name = data[:name]
10
- @add_rows_API_enabled = data[:addRowsAPIEnabled]
11
- @configured_by = data[:configuredBy]
12
- @is_refreshable = data[:isRefreshable]
13
- @is_effective_identity_required = data[:isEffectiveIdentityRequired]
14
- @is_effective_identity_roles_required = data[:isEffectiveIdentityRolesRequired]
15
- @is_on_prem_gateway_required = data[:isOnPremGatewayRequired]
16
- @target_storage_mode = data[:targetStorageMode]
17
- @workspace = data[:workspace]
18
- @tenant = tenant
5
+ def initialize(tenant, parent, id = nil)
6
+ super(tenant, id)
7
+ @workspace = parent
19
8
  @datasources = DatasourceArray.new(@tenant, self)
20
9
  @parameters = ParameterArray.new(@tenant, self)
21
10
  @refresh_history = RefreshArray.new(@tenant, self)
22
11
  end
23
12
 
13
+ def get_data(id)
14
+ @tenant.get("/groups/#{@workspace.id}/datasets/#{id}")
15
+ end
16
+
17
+ def data_to_attributes(data)
18
+ {
19
+ id: data[:id],
20
+ name: data[:name],
21
+ add_rows_API_enabled: data[:addRowsAPIEnabled],
22
+ configured_by: data[:configuredBy],
23
+ is_refreshable: data[:isRefreshable],
24
+ is_effective_identity_required: data[:isEffectiveIdentityRequired],
25
+ is_effective_identity_roles_required: data[:isEffectiveIdentityRolesRequired],
26
+ is_on_prem_gateway_required: data[:isOnPremGatewayRequired],
27
+ target_storage_mode: data[:targetStorageMode],
28
+ }
29
+ end
30
+
24
31
  def update_parameter(name, value)
25
32
  @tenant.post("/groups/#{workspace.id}/datasets/#{id}/Default.UpdateParameters") do |req|
26
33
  req.body = {
@@ -66,7 +73,7 @@ module PowerBI
66
73
  class DatasetArray < Array
67
74
 
68
75
  def initialize(tenant, workspace)
69
- super(tenant)
76
+ super(tenant, workspace)
70
77
  @workspace = workspace
71
78
  end
72
79
 
@@ -75,8 +82,7 @@ module PowerBI
75
82
  end
76
83
 
77
84
  def get_data
78
- data = @tenant.get("/groups/#{@workspace.id}/datasets")[:value]
79
- data.each { |d| d[:workspace] = @workspace }
85
+ @tenant.get("/groups/#{@workspace.id}/datasets")[:value]
80
86
  end
81
87
  end
82
88
  end
@@ -1,13 +1,19 @@
1
1
  module PowerBI
2
- class Datasource
3
- attr_reader :gateway_id, :datasource_id, :datasource_type, :connection_details
2
+ class Datasource < Object
3
+ attr_reader :dataset
4
4
 
5
- def initialize(tenant, data)
6
- @gateway_id = data[:gatewayId]
7
- @datasource_type = data[:datasourceType]
8
- @connection_details = data[:connectionDetails]
9
- @datasource_id = data[:datasourceId]
10
- @tenant = tenant
5
+ def initialize(tenant, parent, id = nil)
6
+ super(tenant, id)
7
+ @dataset = parent
8
+ end
9
+
10
+ def data_to_attributes(data)
11
+ {
12
+ gateway_id: data[:gatewayId],
13
+ datasource_type: data[:datasourceType],
14
+ connection_details: data[:connectionDetails],
15
+ datasource_id: data[:datasourceId],
16
+ }
11
17
  end
12
18
 
13
19
  end
@@ -15,7 +21,7 @@ module PowerBI
15
21
  class DatasourceArray < Array
16
22
 
17
23
  def initialize(tenant, dataset)
18
- super(tenant)
24
+ super(tenant, dataset)
19
25
  @dataset = dataset
20
26
  end
21
27
 
@@ -1,16 +1,29 @@
1
1
  module PowerBI
2
- class Gateway
3
- attr_reader :name, :id, :type, :public_key, :gateway_datasources
2
+ class Gateway < Object
3
+ attr_reader :gateway_datasources
4
4
 
5
- def initialize(tenant, data)
6
- @id = data[:id]
7
- @name = data[:name]
8
- @type = data[:type]
9
- @public_key = data[:publicKey]
10
- @tenant = tenant
5
+ def initialize(tenant, parent, id = nil)
6
+ super(tenant, id)
11
7
  @gateway_datasources = GatewayDatasourceArray.new(@tenant, self)
12
8
  end
13
9
 
10
+ def get_data(id)
11
+ @tenant.get("/gateways/#{id}")
12
+ end
13
+
14
+ def data_to_attributes(data)
15
+ {
16
+ id: data[:id],
17
+ name: data[:name],
18
+ type: data[:type],
19
+ public_key: data[:publicKey],
20
+ }
21
+ end
22
+
23
+ def gateway_datasource(id)
24
+ GatewayDatasource.new(@tenant, self, id)
25
+ end
26
+
14
27
  end
15
28
 
16
29
  class GatewayArray < Array
@@ -1,20 +1,30 @@
1
1
  module PowerBI
2
- class GatewayDatasource
3
- attr_reader :id, :gateway_id, :datasource_type, :connection_details, :credential_type, :datasource_name, :gateway
2
+ class GatewayDatasource < Object
3
+ attr_reader :gateway
4
4
 
5
- def initialize(tenant, data)
6
- @gateway_id = data[:gatewayId]
7
- @datasource_type = data[:datasourceType]
8
- @datasource_name = data[:datasourceName]
9
- @connection_details = data[:connectionDetails]
10
- @id = data[:id]
11
- @credential_type = data[:credentialType]
12
- @gateway = data[:gateway]
13
- @tenant = tenant
5
+ def initialize(tenant, parent, id = nil)
6
+ super(tenant, id)
7
+ @gateway = parent
8
+ end
9
+
10
+ def get_data(id)
11
+ @tenant.get("/gateways/#{@gateway.id}/datasources/#{id}")
12
+ end
13
+
14
+ def data_to_attributes(data)
15
+ {
16
+ gateway_id: data[:gatewayId],
17
+ datasource_type: data[:datasourceType],
18
+ datasource_name: data[:datasourceName],
19
+ connection_details: data[:connectionDetails],
20
+ id: data[:id],
21
+ credential_type: data[:credentialType],
22
+ gateway: data[:gateway],
23
+ }
14
24
  end
15
25
 
16
26
  def update_credentials(encrypted_credentials)
17
- response = @tenant.patch("/gateways/#{gateway.id}/datasources/#{id}") do |req|
27
+ @tenant.patch("/gateways/#{gateway.id}/datasources/#{id}") do |req|
18
28
  req.body = {
19
29
  credentialDetails: {
20
30
  credentialType: "Basic",
@@ -41,7 +51,7 @@ module PowerBI
41
51
  class GatewayDatasourceArray < Array
42
52
 
43
53
  def initialize(tenant, gateway)
44
- super(tenant)
54
+ super(tenant, gateway)
45
55
  @gateway = gateway
46
56
  end
47
57
 
@@ -68,12 +78,11 @@ module PowerBI
68
78
  }.to_json
69
79
  end
70
80
  self.reload
71
- GatewayDatasource.new(@tenant, data)
81
+ GatewayDatasource.instantiate_from_data(@tenant, @gateway, data)
72
82
  end
73
83
 
74
84
  def get_data
75
- data = @tenant.get("/gateways/#{@gateway.id}/datasources")[:value]
76
- data.each { |d| d[:gateway] = @gateway }
85
+ @tenant.get("/gateways/#{@gateway.id}/datasources")[:value]
77
86
  end
78
87
  end
79
88
  end
@@ -0,0 +1,59 @@
1
+ module PowerBI
2
+
3
+ class Object
4
+ attr_reader :id
5
+
6
+ class UnkownAttributeError < PowerBI::Error ; end
7
+ class UnspecifiedIdError < PowerBI::Error ; end
8
+
9
+ def initialize(tenant, id = nil)
10
+ @id = id
11
+ @fulfilled = false
12
+ @not_found = nil
13
+ @attributes = nil
14
+ @tenant = tenant
15
+ end
16
+
17
+ def set_attributes(data)
18
+ @fulfilled = true
19
+ @not_found = false
20
+ @id = data[:id]
21
+ @attributes = data_to_attributes(data)
22
+ end
23
+
24
+ def reload
25
+ @fulfilled = false
26
+ @attributes = nil
27
+ self
28
+ end
29
+
30
+ def self.instantiate_from_data(tenant, parent, data)
31
+ o = new(tenant, parent)
32
+ o.set_attributes(data)
33
+ o
34
+ end
35
+
36
+ private
37
+
38
+ def get_attributes
39
+ unless @fulfilled
40
+ raise UnspecifiedIdError unless @id
41
+ begin
42
+ set_attributes(get_data(@id))
43
+ rescue PowerBI::NotFoundError
44
+ @not_found = true
45
+ raise PowerBI::NotFoundError
46
+ end
47
+ end
48
+ @attributes
49
+ end
50
+
51
+ def method_missing(method, *args, &block)
52
+ get_attributes.fetch(method.to_sym) do
53
+ raise UnkownAttributeError.new "Unknown attribute #{method}"
54
+ end
55
+ end
56
+
57
+ end
58
+
59
+ end
data/lib/power-bi/page.rb CHANGED
@@ -1,20 +1,26 @@
1
1
  module PowerBI
2
- class Page
3
- attr_reader :display_name, :name, :order, :report
2
+ class Page < Object
3
+ attr_reader :report
4
4
 
5
- def initialize(tenant, data)
6
- @name = data[:name]
7
- @display_name = data[:displayName]
8
- @order = data[:order]
9
- @report = data[:report]
10
- @tenant = tenant
5
+ def initialize(tenant, parent, id = nil)
6
+ super(tenant, id)
7
+ @report = parent
11
8
  end
9
+
10
+ def data_to_attributes(data)
11
+ {
12
+ name: data[:name],
13
+ display_name: data[:displayName],
14
+ order: data[:order],
15
+ }
16
+ end
17
+
12
18
  end
13
19
 
14
20
  class PageArray < Array
15
21
 
16
22
  def initialize(tenant, report)
17
- super(tenant)
23
+ super(tenant, report)
18
24
  @report = report
19
25
  end
20
26
 
@@ -23,8 +29,7 @@ module PowerBI
23
29
  end
24
30
 
25
31
  def get_data
26
- data = @tenant.get("/groups/#{@report.workspace.id}/reports/#{@report.id}/pages")[:value]
27
- data.each { |d| d[:report] = @report }
32
+ @tenant.get("/groups/#{@report.workspace.id}/reports/#{@report.id}/pages")[:value]
28
33
  end
29
34
  end
30
35
  end
@@ -1,12 +1,19 @@
1
1
  module PowerBI
2
- class Parameter
3
- attr_reader :name, :type, :is_required, :current_value
2
+ class Parameter < Object
3
+ attr_reader :dataset
4
4
 
5
- def initialize(tenant, data)
6
- @name = data[:name]
7
- @type = data[:type]
8
- @is_required = data[:isRequired]
9
- @current_value = data[:currentValue]
5
+ def initialize(tenant, parent, id = nil)
6
+ super(tenant, id)
7
+ @dataset = parent
8
+ end
9
+
10
+ def data_to_attributes(data)
11
+ {
12
+ name: data[:name],
13
+ type: data[:type],
14
+ is_required: data[:isRequired],
15
+ current_value: data[:currentValue],
16
+ }
10
17
  end
11
18
 
12
19
  end
@@ -14,7 +21,7 @@ module PowerBI
14
21
  class ParameterArray < Array
15
22
 
16
23
  def initialize(tenant, dataset)
17
- super(tenant)
24
+ super(tenant, dataset)
18
25
  @dataset = dataset
19
26
  end
20
27
 
@@ -1,15 +1,22 @@
1
1
  module PowerBI
2
- class Refresh
3
- attr_reader :refresh_type, :start_time, :end_time, :service_exception_json, :status, :request_id
2
+ class Refresh < Object
3
+ attr_reader :dataset
4
4
 
5
- def initialize(tenant, data)
6
- @id = data[:id]
7
- @refresh_type = data[:refreshType]
8
- @start_time = DateTime.iso8601(data[:startTime])
9
- @end_time = DateTime.iso8601(data[:endTime]) if data[:endTime]
10
- @service_exception_json = data[:serviceExceptionJson]
11
- @status = data[:status]
12
- @request_id = data[:requestId]
5
+ def initialize(tenant, parent, id = nil)
6
+ super(tenant, id)
7
+ @dataset = parent
8
+ end
9
+
10
+ def data_to_attributes(data)
11
+ {
12
+ id: data[:id],
13
+ refresh_type: data[:refreshType],
14
+ start_time: DateTime.iso8601(data[:startTime]),
15
+ end_time: data[:endTime] ? DateTime.iso8601(data[:endTime]) : nil,
16
+ service_exception_json: data[:serviceExceptionJson],
17
+ status: data[:status],
18
+ request_id: data[:requestId],
19
+ }
13
20
  end
14
21
 
15
22
  end
@@ -17,7 +24,7 @@ module PowerBI
17
24
  class RefreshArray < Array
18
25
 
19
26
  def initialize(tenant, dataset)
20
- super(tenant)
27
+ super(tenant, dataset)
21
28
  @dataset = dataset
22
29
  end
23
30
 
@@ -26,7 +33,7 @@ module PowerBI
26
33
  end
27
34
 
28
35
  def get_data
29
- @tenant.get("/groups/#{@dataset.workspace.id}/datasets/#{@dataset.id}/refreshes", {'$top': '3'})[:value]
36
+ @tenant.get("/groups/#{@dataset.workspace.id}/datasets/#{@dataset.id}/refreshes", {'$top': '1'})[:value]
30
37
  end
31
38
  end
32
39
  end
@@ -1,23 +1,32 @@
1
1
  module PowerBI
2
- class Report
3
- attr_reader :name, :id, :report_type, :web_url, :embed_url, :is_from_pbix, :is_owned_by_me, :dataset_id, :workspace, :pages
2
+ class Report < Object
3
+ attr_reader :workspace, :pages
4
4
 
5
5
  class ExportToFileError < PowerBI::Error ; end
6
6
 
7
- def initialize(tenant, data)
8
- @id = data[:id]
9
- @report_type = data[:reportType]
10
- @name = data[:name]
11
- @web_url = data[:webUrl]
12
- @embed_url = data[:embedUrl]
13
- @is_from_pbix = data[:isFromPbix]
14
- @is_owned_by_me = data[:isOwnedByMe]
15
- @dataset_id = data[:datasetId]
16
- @workspace = data[:workspace]
17
- @tenant = tenant
7
+ def initialize(tenant, parent, id = nil)
8
+ super(tenant, id)
9
+ @workspace = parent
18
10
  @pages = PageArray.new(@tenant, self)
19
11
  end
20
12
 
13
+ def get_data(id)
14
+ @tenant.get("/groups/#{@workspace.id}/reports/#{id}")
15
+ end
16
+
17
+ def data_to_attributes(data)
18
+ {
19
+ id: data[:id],
20
+ report_type: data[:reportType],
21
+ name: data[:name],
22
+ web_url: data[:webUrl],
23
+ embed_url: data[:embedUrl],
24
+ is_from_pbix: data[:isFromPbix],
25
+ is_owned_by_me: data[:isOwnedByMe],
26
+ dataset_id: data[:datasetId],
27
+ }
28
+ end
29
+
21
30
  def clone(target_workspace, new_report_name)
22
31
  data = @tenant.post("/reports/#{@id}/Clone") do |req|
23
32
  req.body = {
@@ -75,7 +84,7 @@ module PowerBI
75
84
  class ReportArray < Array
76
85
 
77
86
  def initialize(tenant, workspace)
78
- super(tenant)
87
+ super(tenant, workspace)
79
88
  @workspace = workspace
80
89
  end
81
90
 
@@ -84,8 +93,7 @@ module PowerBI
84
93
  end
85
94
 
86
95
  def get_data
87
- data = @tenant.get("/groups/#{@workspace.id}/reports")[:value]
88
- data.each { |d| d[:workspace] = @workspace }
96
+ @tenant.get("/groups/#{@workspace.id}/reports")[:value]
89
97
  end
90
98
  end
91
99
  end
@@ -1,15 +1,16 @@
1
1
  module PowerBI
2
2
  class Tenant
3
- attr_reader :workspaces, :gateways
3
+ attr_reader :workspaces, :gateways, :capacities
4
4
 
5
5
  def initialize(token_generator, retries: 5, logger: nil)
6
6
  @token_generator = token_generator
7
7
  @workspaces = WorkspaceArray.new(self)
8
8
  @gateways = GatewayArray.new(self)
9
+ @capacities = CapacityArray.new(self)
9
10
  @logger = logger
10
11
 
11
12
  ## WHY RETRIES? ##
12
- # It is noticed that once in a while (~0.1% API calls), the Power BI server returns a 500 (internal server error) withou apparent reason, just retrying works :-)
13
+ # It is noticed that once in a while (~0.1% API calls), the Power BI server returns a 500 (internal server error) without apparent reason, just retrying works :-)
13
14
  ##################
14
15
  @retry_options = {
15
16
  max: retries,
@@ -29,6 +30,18 @@ module PowerBI
29
30
  end
30
31
  end
31
32
 
33
+ def workspace(id)
34
+ Workspace.new(self, nil, id)
35
+ end
36
+
37
+ def gateway(id)
38
+ Gateway.new(self, nil, id)
39
+ end
40
+
41
+ def capacity(id)
42
+ Capacity.new(self, nil, id)
43
+ end
44
+
32
45
  def get(url, params = {})
33
46
  t0 = Time.now
34
47
  conn = Faraday.new do |f|
@@ -40,10 +53,13 @@ module PowerBI
40
53
  req.headers['authorization'] = "Bearer #{token}"
41
54
  yield req if block_given?
42
55
  end
56
+ if response.status == 400
57
+ raise NotFoundError
58
+ end
43
59
  unless [200, 202].include? response.status
44
60
  raise APIError.new("Error calling Power BI API (status #{response.status}): #{response.body}")
45
61
  end
46
- log "Calling (GET) #{url} - took #{((Time.now - t0) * 1000).to_i} ms"
62
+ log "Calling (GET) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms"
47
63
  unless response.body.empty?
48
64
  JSON.parse(response.body, symbolize_names: true)
49
65
  end
@@ -59,7 +75,7 @@ module PowerBI
59
75
  req.headers['authorization'] = "Bearer #{token}"
60
76
  yield req if block_given?
61
77
  end
62
- log "Calling (GET - raw) #{url} - took #{((Time.now - t0) * 1000).to_i} ms"
78
+ log "Calling (GET - raw) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms"
63
79
  unless [200, 202].include? response.status
64
80
  raise APIError.new("Error calling Power BI API (status #{response.status}): #{response.body}")
65
81
  end
@@ -78,7 +94,7 @@ module PowerBI
78
94
  req.headers['authorization'] = "Bearer #{token}"
79
95
  yield req if block_given?
80
96
  end
81
- log "Calling (POST) #{url} - took #{((Time.now - t0) * 1000).to_i} ms"
97
+ log "Calling (POST) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms"
82
98
  unless [200, 201, 202].include? response.status
83
99
  raise APIError.new("Error calling Power BI API (status #{response.status}): #{response.body}")
84
100
  end
@@ -99,7 +115,7 @@ module PowerBI
99
115
  req.headers['authorization'] = "Bearer #{token}"
100
116
  yield req if block_given?
101
117
  end
102
- log "Calling (PATCH) #{url} - took #{((Time.now - t0) * 1000).to_i} ms"
118
+ log "Calling (PATCH) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms"
103
119
  unless [200, 202].include? response.status
104
120
  raise APIError.new("Error calling Power BI API (status #{response.status}): #{response.body}")
105
121
  end
@@ -119,7 +135,10 @@ module PowerBI
119
135
  req.headers['authorization'] = "Bearer #{token}"
120
136
  yield req if block_given?
121
137
  end
122
- log "Calling (DELETE) #{url} - took #{((Time.now - t0) * 1000).to_i} ms"
138
+ log "Calling (DELETE) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms"
139
+ if [400, 401, 404].include? response.status
140
+ raise NotFoundError
141
+ end
123
142
  unless [200, 202].include? response.status
124
143
  raise APIError.new("Error calling Power BI API (status #{response.status}): #{response.body}")
125
144
  end
@@ -142,7 +161,7 @@ module PowerBI
142
161
  req.body = {value: Faraday::UploadIO.new(file, 'application/octet-stream')}
143
162
  req.options.timeout = 120 # default is 60 seconds Net::ReadTimeout
144
163
  end
145
- log "Calling (POST - file) #{url} - took #{((Time.now - t0) * 1000).to_i} ms"
164
+ log "Calling (POST - file) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms"
146
165
  if response.status != 202
147
166
  raise APIError.new("Error calling Power BI API (status #{response.status}): #{response.body}")
148
167
  end
data/lib/power-bi/user.rb CHANGED
@@ -1,15 +1,20 @@
1
1
  module PowerBI
2
- class User
3
- attr_reader :email_address, :group_user_access_right, :display_name, :identifier, :principal_type
4
-
5
- def initialize(tenant, data)
6
- @email_address = data[:emailAddress]
7
- @group_user_access_right = data[:groupUserAccessRight]
8
- @display_name = data[:displayName]
9
- @identifier = data[:identifier]
10
- @principal_type = data[:principalType]
11
- @workspace = data[:workspace]
12
- @tenant = tenant
2
+ class User < Object
3
+ attr_reader :workspace
4
+
5
+ def initialize(tenant, parent, id = nil)
6
+ super(tenant, id)
7
+ @workspace = parent
8
+ end
9
+
10
+ def data_to_attributes(data)
11
+ {
12
+ email_address: data[:emailAddress],
13
+ group_user_access_right: data[:groupUserAccessRight],
14
+ display_name: data[:displayName],
15
+ identifier: data[:identifier],
16
+ principal_type: data[:principalType],
17
+ }
13
18
  end
14
19
 
15
20
  def delete
@@ -22,7 +27,7 @@ module PowerBI
22
27
  class UserArray < Array
23
28
 
24
29
  def initialize(tenant, workspace)
25
- super(tenant)
30
+ super(tenant, workspace)
26
31
  @workspace = workspace
27
32
  end
28
33
 
@@ -41,8 +46,7 @@ module PowerBI
41
46
  end
42
47
 
43
48
  def get_data
44
- data = @tenant.get("/groups/#{@workspace.id}/users")[:value]
45
- data.each { |d| d[:workspace] = @workspace }
49
+ @tenant.get("/groups/#{@workspace.id}/users")[:value]
46
50
  end
47
51
  end
48
52
  end
@@ -1,20 +1,30 @@
1
1
  module PowerBI
2
- class Workspace
3
- attr_reader :name, :is_read_only, :is_on_dedicated_capacity, :id, :reports, :datasets, :users
2
+ class Workspace < Object
3
+ attr_reader :reports, :datasets, :users
4
4
 
5
5
  class UploadError < PowerBI::Error ; end
6
+ class CapacityAssignmentError < PowerBI::Error ; end
6
7
 
7
- def initialize(tenant, data)
8
- @id = data[:id]
9
- @is_read_only = data[:isReadOnly]
10
- @is_on_dedicated_capacity = data[:isOnDedicatedCapacity]
11
- @name = data[:name]
12
- @tenant = tenant
8
+ def initialize(tenant, parent, id = nil)
9
+ super(tenant, id)
13
10
  @reports = ReportArray.new(@tenant, self)
14
11
  @datasets = DatasetArray.new(@tenant, self)
15
12
  @users = UserArray.new(@tenant, self)
16
13
  end
17
14
 
15
+ def get_data(id)
16
+ @tenant.get("/groups", {'$filter': "id eq #{id}"})[:value].first
17
+ end
18
+
19
+ def data_to_attributes(data)
20
+ {
21
+ id: data[:id],
22
+ is_read_only: data[:isReadOnly],
23
+ is_on_dedicated_capacity: data[:isOnDedicatedCapacity],
24
+ name: data[:name],
25
+ }
26
+ end
27
+
18
28
  def upload_pbix(file, dataset_name, timeout: 30)
19
29
  data = @tenant.post_file("/groups/#{@id}/imports", file, {datasetDisplayName: dataset_name})
20
30
  import_id = data[:id]
@@ -44,6 +54,49 @@ module PowerBI
44
54
  true
45
55
  end
46
56
 
57
+ def report(id)
58
+ Report.new(@tenant, self, id)
59
+ end
60
+
61
+ def dataset(id)
62
+ Dataset.new(@tenant, self, id)
63
+ end
64
+
65
+ def assign_to_capacity(capacity, timeout: 30)
66
+ _assign_to_capacity(capacity.id, timeout: timeout)
67
+ end
68
+
69
+ def unassign_from_capacity(timeout: 30)
70
+ _assign_to_capacity('00000000-0000-0000-0000-000000000000', timeout: timeout)
71
+ end
72
+
73
+ private
74
+
75
+ def _assign_to_capacity(capacity_id, timeout: 30)
76
+ @tenant.post("/groups/#{@id}/AssignToCapacity") do |req|
77
+ req.body = {
78
+ capacityId: capacity_id,
79
+ }.to_json
80
+ end
81
+
82
+ success = false
83
+ iterations = 0
84
+ status_history = ''
85
+ old_status = ''
86
+ while !success
87
+ sleep 0.5
88
+ iterations += 1
89
+ raise CapacityAssignmentError.new("(Un)assignment did not succeed after #{timeout} seconds. Status history:#{status_history}") if iterations > (2 * timeout)
90
+ new_status = @tenant.get("/groups/#{@id}/CapacityAssignmentStatus")[:status].to_s
91
+ success = (new_status == "CompletedSuccessfully")
92
+ if new_status != old_status
93
+ status_history += "\nStatus change after #{iterations/2}s: '#{old_status}' --> '#{new_status}'"
94
+ old_status = new_status
95
+ end
96
+ end
97
+ self.reload
98
+ end
99
+
47
100
  end
48
101
 
49
102
  class WorkspaceArray < Array
@@ -56,7 +109,7 @@ module PowerBI
56
109
  req.body = {name: name}.to_json
57
110
  end
58
111
  self.reload
59
- Workspace.new(@tenant, data)
112
+ Workspace.instantiate_from_data(@tenant, nil, data)
60
113
  end
61
114
 
62
115
  def get_data
data/lib/power-bi.rb CHANGED
@@ -8,9 +8,11 @@ module PowerBI
8
8
 
9
9
  class Error < StandardError ; end
10
10
  class APIError < Error ; end
11
+ class NotFoundError < Error; end
11
12
  end
12
13
 
13
14
  require_relative "power-bi/tenant"
15
+ require_relative "power-bi/object"
14
16
  require_relative "power-bi/array"
15
17
  require_relative "power-bi/workspace"
16
18
  require_relative "power-bi/report"
@@ -21,4 +23,5 @@ require_relative "power-bi/refresh"
21
23
  require_relative "power-bi/gateway"
22
24
  require_relative "power-bi/gateway_datasource"
23
25
  require_relative "power-bi/page"
24
- require_relative "power-bi/user"
26
+ require_relative "power-bi/user"
27
+ require_relative "power-bi/capacity"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: power-bi
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lode Cools
@@ -90,10 +90,12 @@ files:
90
90
  - README.md
91
91
  - lib/power-bi.rb
92
92
  - lib/power-bi/array.rb
93
+ - lib/power-bi/capacity.rb
93
94
  - lib/power-bi/dataset.rb
94
95
  - lib/power-bi/datasource.rb
95
96
  - lib/power-bi/gateway.rb
96
97
  - lib/power-bi/gateway_datasource.rb
98
+ - lib/power-bi/object.rb
97
99
  - lib/power-bi/page.rb
98
100
  - lib/power-bi/parameter.rb
99
101
  - lib/power-bi/refresh.rb
@@ -120,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
122
  - !ruby/object:Gem::Version
121
123
  version: '0'
122
124
  requirements: []
123
- rubygems_version: 3.1.6
125
+ rubygems_version: 3.4.6
124
126
  signing_key:
125
127
  specification_version: 4
126
128
  summary: Ruby wrapper for the Power BI API