Class: PowerBI::Tenant

Inherits:
Object
  • Object
show all
Defined in:
lib/power-bi/tenant.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(token_generator, retries: 5, logger: nil) ⇒ Tenant

Returns a new instance of Tenant.



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/power-bi/tenant.rb', line 5

def initialize(token_generator, retries: 5, logger: nil)
  @token_generator = token_generator
  @workspaces = WorkspaceArray.new(self)
  @gateways = GatewayArray.new(self)
  @capacities = CapacityArray.new(self)
  @profiles = ProfileArray.new(self)
  @logger = logger
  @profile_id = nil
  @admin = Admin.new(self)

  ## WHY RETRIES? ##
  # 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 :-)
  ##################
  @retry_options = {
    max: retries,
    exceptions: [Errno::ETIMEDOUT, Timeout::Error, Faraday::TimeoutError, Faraday::RetriableResponse, Faraday::ConnectionFailed],
    methods: [:get, :post, :patch, :delete],
    retry_statuses: [500], # internal server error
    interval: 0.2,
    interval_randomness: 0,
    backoff_factor: 4,
    retry_block: -> (env, options, retries, exc) { self.log "retrying...!! exception: #{exc.to_s} ---- #{exc.message}, request URL: #{env.url}" },
  }
end

Instance Attribute Details

#adminObject (readonly)

Returns the value of attribute admin.



3
4
5
# File 'lib/power-bi/tenant.rb', line 3

def admin
  @admin
end

#capacitiesObject (readonly)

Returns the value of attribute capacities.



3
4
5
# File 'lib/power-bi/tenant.rb', line 3

def capacities
  @capacities
end

#gatewaysObject (readonly)

Returns the value of attribute gateways.



3
4
5
# File 'lib/power-bi/tenant.rb', line 3

def gateways
  @gateways
end

#profile_idObject (readonly)

Returns the value of attribute profile_id.



3
4
5
# File 'lib/power-bi/tenant.rb', line 3

def profile_id
  @profile_id
end

#profilesObject (readonly)

Returns the value of attribute profiles.



3
4
5
# File 'lib/power-bi/tenant.rb', line 3

def profiles
  @profiles
end

#workspacesObject (readonly)

Returns the value of attribute workspaces.



3
4
5
# File 'lib/power-bi/tenant.rb', line 3

def workspaces
  @workspaces
end

Instance Method Details

#capacity(id) ⇒ Object



44
45
46
# File 'lib/power-bi/tenant.rb', line 44

def capacity(id)
  Capacity.new(self, nil, id)
end

#delete(url, params = {}, use_profile: true) ⇒ Object



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/power-bi/tenant.rb', line 151

def delete(url, params = {}, use_profile: true)
  t0 = Time.now
  conn = Faraday.new do |f|
    f.request :retry, @retry_options
  end
  response = conn.delete(PowerBI::BASE_URL + url) do |req|
    req.params = params
    req.headers['Accept'] = 'application/json'
    req.headers['authorization'] = "Bearer #{token}"
    if use_profile
      add_spp_header(req)
    end
    yield req if block_given?
  end
  log "Calling (DELETE) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms"
  if [400, 401, 404].include? response.status
    raise NotFoundError
  end
  unless [200, 202].include? response.status
    raise APIError.new("Error calling Power BI API (status #{response.status}): #{response.body}")
  end
  unless response.body.empty?
    JSON.parse(response.body, symbolize_names: true)
  end
end

#gateway(id) ⇒ Object



40
41
42
# File 'lib/power-bi/tenant.rb', line 40

def gateway(id)
  Gateway.new(self, nil, id)
end

#get(url, params = {}, use_profile: true) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/power-bi/tenant.rb', line 57

def get(url, params = {}, use_profile: true)
  t0 = Time.now
  conn = Faraday.new do |f|
    f.request :retry, @retry_options
  end
  response = conn.get(PowerBI::BASE_URL + url) do |req|
    req.params = params
    req.headers['Accept'] = 'application/json'
    req.headers['authorization'] = "Bearer #{token}"
    if use_profile
      add_spp_header(req)
    end
    yield req if block_given?
  end
  if response.status == 400
    raise NotFoundError
  end
  unless [200, 202].include? response.status
    raise APIError.new("Error calling Power BI API (status #{response.status}): #{response.body}")
  end
  log "Calling (GET) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms"
  unless response.body.empty?
    JSON.parse(response.body, symbolize_names: true)
  end
end

#get_raw(url, params = {}, use_profile: true) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/power-bi/tenant.rb', line 83

def get_raw(url, params = {}, use_profile: true)
  t0 = Time.now
  conn = Faraday.new do |f|
    f.request :retry, @retry_options
  end
  response = conn.get(PowerBI::BASE_URL + url) do |req|
    req.params = params
    req.headers['authorization'] = "Bearer #{token}"
    if use_profile
      add_spp_header(req)
    end
    yield req if block_given?
  end
  log "Calling (GET - raw) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms"
  unless [200, 202].include? response.status
    raise APIError.new("Error calling Power BI API (status #{response.status}): #{response.body}")
  end
  response.body
end

#log(message, level: :info) ⇒ Object



30
31
32
33
34
# File 'lib/power-bi/tenant.rb', line 30

def log(message, level: :info)
  if @logger
    @logger.send(level, message) # hence, the logger needs to implement the 'level' methods
  end
end

#patch(url, params = {}, use_profile: true) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/power-bi/tenant.rb', line 127

def patch(url, params = {}, use_profile: true)
  t0 = Time.now
  conn = Faraday.new do |f|
    f.request :retry, @retry_options
  end
  response = conn.patch(PowerBI::BASE_URL + url) do |req|
    req.params = params
    req.headers['Accept'] = 'application/json'
    req.headers['Content-Type'] = 'application/json'
    req.headers['authorization'] = "Bearer #{token}"
    if use_profile
      add_spp_header(req)
    end
    yield req if block_given?
  end
  log "Calling (PATCH) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms"
  unless [200, 202].include? response.status
    raise APIError.new("Error calling Power BI API (status #{response.status}): #{response.body}")
  end
  unless response.body.empty?
    JSON.parse(response.body, symbolize_names: true)
  end
end

#post(url, params = {}, use_profile: true) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/power-bi/tenant.rb', line 103

def post(url, params = {}, use_profile: true)
  t0 = Time.now
  conn = Faraday.new do |f|
    f.request :retry, @retry_options
  end
  response = conn.post(PowerBI::BASE_URL + url) do |req|
    req.params = params
    req.headers['Accept'] = 'application/json'
    req.headers['Content-Type'] = 'application/json'
    req.headers['authorization'] = "Bearer #{token}"
    if use_profile
      add_spp_header(req)
    end
    yield req if block_given?
  end
  log "Calling (POST) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms"
  unless [200, 201, 202].include? response.status
    raise APIError.new("Error calling Power BI API (status #{response.status}): #{response.body}")
  end
  unless response.body.empty?
    JSON.parse(response.body, symbolize_names: true)
  end
end

#post_file(url, file, params = {}, use_profile: true) ⇒ Object



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/power-bi/tenant.rb', line 177

def post_file(url, file, params = {}, use_profile: true)
  t0 = Time.now
  conn = Faraday.new do |f|
    f.request :multipart
    f.request :retry, @retry_options
  end
  response = conn.post(PowerBI::BASE_URL + url) do |req|
    req.params = params
    req.headers['Accept'] = 'application/json'
    req.headers['Content-Type'] = 'multipart/form-data'
    req.headers['authorization'] = "Bearer #{token}"
    if use_profile
      add_spp_header(req)
    end
    req.body = {value: Faraday::UploadIO.new(file, 'application/octet-stream')}
    req.options.timeout = 120  # default is 60 seconds Net::ReadTimeout
  end
  log "Calling (POST - file) #{response.env.url.to_s} - took #{((Time.now - t0) * 1000).to_i} ms"
  if response.status != 202
    raise APIError.new("Error calling Power BI API (status #{response.status}): #{response.body}")
  end
  JSON.parse(response.body, symbolize_names: true)
end

#profile(id) ⇒ Object



48
49
50
# File 'lib/power-bi/tenant.rb', line 48

def profile(id)
  Profile.new(self, nil, id)
end

#profile=(profile) ⇒ Object



52
53
54
55
# File 'lib/power-bi/tenant.rb', line 52

def profile=(profile)
  @profile_id = profile.is_a?(String) ? profile : profile&.id
  @workspaces.reload # we need to reload the workspaces because we look through the eyes of the profile
end

#workspace(id) ⇒ Object



36
37
38
# File 'lib/power-bi/tenant.rb', line 36

def workspace(id)
  Workspace.new(self, nil, id)
end