power-bi 1.7.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +18 -1
- data/lib/power-bi/array.rb +3 -2
- data/lib/power-bi/capacity.rb +35 -0
- data/lib/power-bi/dataset.rb +25 -19
- data/lib/power-bi/datasource.rb +15 -9
- data/lib/power-bi/gateway.rb +21 -8
- data/lib/power-bi/gateway_datasource.rb +25 -16
- data/lib/power-bi/object.rb +59 -0
- data/lib/power-bi/page.rb +16 -11
- data/lib/power-bi/parameter.rb +15 -8
- data/lib/power-bi/refresh.rb +19 -12
- data/lib/power-bi/report.rb +24 -16
- data/lib/power-bi/tenant.rb +27 -8
- data/lib/power-bi/user.rb +18 -14
- data/lib/power-bi/workspace.rb +62 -9
- data/lib/power-bi.rb +4 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 349bd7851001e6e16d1d14f50f6abdbd473038ed3ec9665d5cd009a74db365f2
|
4
|
+
data.tar.gz: fe96607cd040b4fd034336865e7f78ceb35b297526242c4bc1f8ea3419dc95a3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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(
|
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:
|
data/lib/power-bi/array.rb
CHANGED
@@ -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.
|
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
|
data/lib/power-bi/dataset.rb
CHANGED
@@ -1,26 +1,33 @@
|
|
1
1
|
module PowerBI
|
2
|
-
class Dataset
|
3
|
-
attr_reader :
|
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,
|
8
|
-
|
9
|
-
@
|
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
|
-
|
79
|
-
data.each { |d| d[:workspace] = @workspace }
|
85
|
+
@tenant.get("/groups/#{@workspace.id}/datasets")[:value]
|
80
86
|
end
|
81
87
|
end
|
82
88
|
end
|
data/lib/power-bi/datasource.rb
CHANGED
@@ -1,13 +1,19 @@
|
|
1
1
|
module PowerBI
|
2
|
-
class Datasource
|
3
|
-
attr_reader :
|
2
|
+
class Datasource < Object
|
3
|
+
attr_reader :dataset
|
4
4
|
|
5
|
-
def initialize(tenant,
|
6
|
-
|
7
|
-
@
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
|
data/lib/power-bi/gateway.rb
CHANGED
@@ -1,16 +1,29 @@
|
|
1
1
|
module PowerBI
|
2
|
-
class Gateway
|
3
|
-
attr_reader :
|
2
|
+
class Gateway < Object
|
3
|
+
attr_reader :gateway_datasources
|
4
4
|
|
5
|
-
def initialize(tenant,
|
6
|
-
|
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 :
|
2
|
+
class GatewayDatasource < Object
|
3
|
+
attr_reader :gateway
|
4
4
|
|
5
|
-
def initialize(tenant,
|
6
|
-
|
7
|
-
@
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
@
|
12
|
-
|
13
|
-
|
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
|
-
|
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.
|
81
|
+
GatewayDatasource.instantiate_from_data(@tenant, @gateway, data)
|
72
82
|
end
|
73
83
|
|
74
84
|
def get_data
|
75
|
-
|
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 :
|
2
|
+
class Page < Object
|
3
|
+
attr_reader :report
|
4
4
|
|
5
|
-
def initialize(tenant,
|
6
|
-
|
7
|
-
@
|
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
|
-
|
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
|
data/lib/power-bi/parameter.rb
CHANGED
@@ -1,12 +1,19 @@
|
|
1
1
|
module PowerBI
|
2
|
-
class Parameter
|
3
|
-
attr_reader :
|
2
|
+
class Parameter < Object
|
3
|
+
attr_reader :dataset
|
4
4
|
|
5
|
-
def initialize(tenant,
|
6
|
-
|
7
|
-
@
|
8
|
-
|
9
|
-
|
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
|
|
data/lib/power-bi/refresh.rb
CHANGED
@@ -1,15 +1,22 @@
|
|
1
1
|
module PowerBI
|
2
|
-
class Refresh
|
3
|
-
attr_reader :
|
2
|
+
class Refresh < Object
|
3
|
+
attr_reader :dataset
|
4
4
|
|
5
|
-
def initialize(tenant,
|
6
|
-
|
7
|
-
@
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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': '
|
36
|
+
@tenant.get("/groups/#{@dataset.workspace.id}/datasets/#{@dataset.id}/refreshes", {'$top': '1'})[:value]
|
30
37
|
end
|
31
38
|
end
|
32
39
|
end
|
data/lib/power-bi/report.rb
CHANGED
@@ -1,23 +1,32 @@
|
|
1
1
|
module PowerBI
|
2
|
-
class Report
|
3
|
-
attr_reader :
|
2
|
+
class Report < Object
|
3
|
+
attr_reader :workspace, :pages
|
4
4
|
|
5
5
|
class ExportToFileError < PowerBI::Error ; end
|
6
6
|
|
7
|
-
def initialize(tenant,
|
8
|
-
|
9
|
-
@
|
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
|
-
|
88
|
-
data.each { |d| d[:workspace] = @workspace }
|
96
|
+
@tenant.get("/groups/#{@workspace.id}/reports")[:value]
|
89
97
|
end
|
90
98
|
end
|
91
99
|
end
|
data/lib/power-bi/tenant.rb
CHANGED
@@ -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)
|
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 :
|
4
|
-
|
5
|
-
def initialize(tenant,
|
6
|
-
|
7
|
-
@
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
-
|
45
|
-
data.each { |d| d[:workspace] = @workspace }
|
49
|
+
@tenant.get("/groups/#{@workspace.id}/users")[:value]
|
46
50
|
end
|
47
51
|
end
|
48
52
|
end
|
data/lib/power-bi/workspace.rb
CHANGED
@@ -1,20 +1,30 @@
|
|
1
1
|
module PowerBI
|
2
|
-
class Workspace
|
3
|
-
attr_reader :
|
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,
|
8
|
-
|
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.
|
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.
|
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.
|
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
|