power-bi 0.6.0 → 1.3.1
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 +85 -0
- data/lib/power-bi.rb +2 -0
- data/lib/power-bi/dataset.rb +11 -0
- data/lib/power-bi/gateway.rb +25 -0
- data/lib/power-bi/gateway_datasource.rb +79 -0
- data/lib/power-bi/report.rb +27 -2
- data/lib/power-bi/tenant.rb +66 -6
- 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: 1d25a34c3688310fb090dccae322ca49f7a48312246f3793b4e59cba25fd75a1
         | 
| 4 | 
            +
              data.tar.gz: 5edb3f13333c5319f44fdac97769d3b5ee2adbb59f03296ceb664bc729017e77
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: db57e4e5fb379b3cab50becc7060d19caf48cbcd366aa2231829c988ff448af01cf40ab9f189c8607b26bfaa8c96a8efd14df3d3337d1bbc257fc41315386637
         | 
| 7 | 
            +
              data.tar.gz: 390c4de1b57462be8817be336b35de6e24e488569cad47936d116efc922e382b804c71b16717bbe31fb38aa486e3a946ad69a9816055832da90507f2cf1a4678
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,3 +1,88 @@ | |
| 1 1 | 
             
            # power-bi
         | 
| 2 2 |  | 
| 3 3 | 
             
            Ruby wrapper around the Power BI API
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            # Initialization
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            The Power BI API does not handle the authorization part. It requires the user to pass a function where it can request tokens.
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            ```
         | 
| 10 | 
            +
            pbi = PowerBI::Tenant.new(->{token = get_token(client, token) ; token.token})
         | 
| 11 | 
            +
            ```
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            # Supported endpoints
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            ## Workspaces (aka Groups)
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            * List workspaces: `pbi.workspaces`
         | 
| 18 | 
            +
            * Create workspace: `pbi.workspaces.create`
         | 
| 19 | 
            +
            * Upload PBIX to workspace: `ws.upload_pbix('./test.pbix', 'new_datasetname_in_the_service')`
         | 
| 20 | 
            +
            * Delete workspace: `workspace.delete`
         | 
| 21 | 
            +
            * Add a user to a wokspace: `workspace.add_user('company_0001@fabrikam.com')`
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            ## Reports
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            * List reports in a workspace: `workspace.reports`
         | 
| 26 | 
            +
            * Clone a report from one workspace to another: `report.clone(src_workspace, new_report_name)`
         | 
| 27 | 
            +
            * Rebind report to another dataset: `report.rebind(dataset)`
         | 
| 28 | 
            +
            * Export report to file: `report.export_to_file(filenam, format: 'PDF')`
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            ## Datasets
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            * List datasets in a workspace: `workspace.datasets`
         | 
| 33 | 
            +
            * Update parameter in a dataset: `dataset.update_parameter(parameter_name, new_value)`
         | 
| 34 | 
            +
            * Get time of last refresh: `dataset.last_refresh`
         | 
| 35 | 
            +
            * Refresh the dataset: `dataset.refresh`
         | 
| 36 | 
            +
            * Delete the dataset: `dataset.delete`
         | 
| 37 | 
            +
            * Bind dataset to a gateway datasource: `dataset.bind_to_gateway(gateway, gateway_datasource)`
         | 
| 38 | 
            +
             | 
| 39 | 
            +
            ## Gateways
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            * List gateways: `pbi.gateways`
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            ## Gateway datasources
         | 
| 44 | 
            +
             | 
| 45 | 
            +
            * List datasources in a gateway: `gateway.gateway_datasources`
         | 
| 46 | 
            +
            * Update credentials of a gateway datasource: `gateway_datasource.update_credentials(new_credentials)`
         | 
| 47 | 
            +
            * Create a new gateway datasource: `gateway.gateway_datasource.create(name, credentials, db_server, db_name)`
         | 
| 48 | 
            +
            * Delete a new gateway datasource: `gateway_datasource.delete`
         | 
| 49 | 
            +
             | 
| 50 | 
            +
            # Note about gateway credentials
         | 
| 51 | 
            +
             | 
| 52 | 
            +
            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:
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            ```
         | 
| 55 | 
            +
            using System;
         | 
| 56 | 
            +
            using Microsoft.PowerBI.Api.Models;
         | 
| 57 | 
            +
            using Microsoft.PowerBI.Api.Models.Credentials;
         | 
| 58 | 
            +
            using Microsoft.PowerBI.Api.Extensions;
         | 
| 59 | 
            +
             | 
| 60 | 
            +
             | 
| 61 | 
            +
            namespace pbi_credentials
         | 
| 62 | 
            +
            {
         | 
| 63 | 
            +
                class Program
         | 
| 64 | 
            +
                {
         | 
| 65 | 
            +
                    static void Main(string[] args)
         | 
| 66 | 
            +
                    {
         | 
| 67 | 
            +
                        Console.WriteLine("Kicking off");
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                        var credentials = new BasicCredentials(username: "cdmuser", password: "cdmuserpw4879515365");
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                        var publicKey = new GatewayPublicKey("AQAB", "ru5gTdHbJ+8eC/uwERTOMz9Yktf/kCDWeRDCY1M5fPCB9+p4c8Uk54/NzT5ZWPQCp958bLcO8nSOSOpz4I8fW/AI4d+JxwW6VCsxzue2mKbJjeuSDXXmIiNUFqvjOIolfSIxJFNlfWkZUFlaD3dXgJkjJxrrc4OrYBDUt0FF14UsvdZymTbOl39sAhD4i9CqkXTqm6+JDxsEkPE3GAZ6ZslCsRUqu7lX73anAHkm889FR9NOMtsLV02JDMKCblJqnoszTzgExEEeoTJKxLiJdC8Mfbl96fKFS8JElJIzfTPzldGx5TxdjRmekQODWr7SNMSVJJQTJaANh9C2FZ85pQ==");
         | 
| 72 | 
            +
                        var credentialsEncryptor = new AsymmetricKeyEncryptor(publicKey);
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                        var credentialDetails = new CredentialDetails(
         | 
| 75 | 
            +
                            credentials,
         | 
| 76 | 
            +
                            PrivacyLevel.Private,
         | 
| 77 | 
            +
                            EncryptedConnection.Encrypted,
         | 
| 78 | 
            +
                            credentialsEncryptor
         | 
| 79 | 
            +
                        );
         | 
| 80 | 
            +
                        Console.WriteLine(credentialDetails.Credentials);
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                        Console.WriteLine("Bye Bye");
         | 
| 83 | 
            +
                    }
         | 
| 84 | 
            +
                }
         | 
| 85 | 
            +
            }
         | 
| 86 | 
            +
            ```
         | 
| 87 | 
            +
             | 
| 88 | 
            +
             | 
    
        data/lib/power-bi.rb
    CHANGED
    
    
    
        data/lib/power-bi/dataset.rb
    CHANGED
    
    | @@ -47,6 +47,17 @@ module PowerBI | |
| 47 47 |  | 
| 48 48 | 
             
                def delete
         | 
| 49 49 | 
             
                  @tenant.delete("/groups/#{workspace.id}/datasets/#{id}")
         | 
| 50 | 
            +
                  @workspace.datasets.reload
         | 
| 51 | 
            +
                  true
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                def bind_to_gateway(gateway, gateway_datasource)
         | 
| 55 | 
            +
                  @tenant.post("/groups/#{workspace.id}/datasets/#{id}/Default.BindToGateway") do |req|
         | 
| 56 | 
            +
                    req.body = {
         | 
| 57 | 
            +
                      gatewayObjectId: gateway.id,
         | 
| 58 | 
            +
                      datasourceObjectIds: [gateway_datasource.id]
         | 
| 59 | 
            +
                    }.to_json
         | 
| 60 | 
            +
                  end
         | 
| 50 61 | 
             
                  true
         | 
| 51 62 | 
             
                end
         | 
| 52 63 |  | 
| @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            module PowerBI
         | 
| 2 | 
            +
              class Gateway
         | 
| 3 | 
            +
                attr_reader :name, :id, :type, :public_key, :gateway_datasources
         | 
| 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
         | 
| 11 | 
            +
                  @gateway_datasources = GatewayDatasourceArray.new(@tenant, self)
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              class GatewayArray < Array
         | 
| 17 | 
            +
                def self.get_class
         | 
| 18 | 
            +
                  Gateway
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def get_data
         | 
| 22 | 
            +
                  @tenant.get("/gateways")[:value]
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
            end
         | 
| @@ -0,0 +1,79 @@ | |
| 1 | 
            +
            module PowerBI
         | 
| 2 | 
            +
              class GatewayDatasource
         | 
| 3 | 
            +
                attr_reader :id, :gateway_id, :datasource_type, :connection_details, :credential_type, :datasource_name, :gateway
         | 
| 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
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                def update_credentials(encrypted_credentials)
         | 
| 17 | 
            +
                  response = @tenant.patch("/gateways/#{gateway.id}/datasources/#{id}") do |req|
         | 
| 18 | 
            +
                    req.body = {
         | 
| 19 | 
            +
                      credentialDetails: {
         | 
| 20 | 
            +
                        credentialType: "Basic",
         | 
| 21 | 
            +
                        credentials: encrypted_credentials,
         | 
| 22 | 
            +
                        encryptedConnection: "Encrypted",
         | 
| 23 | 
            +
                        encryptionAlgorithm: "RSA-OAEP",
         | 
| 24 | 
            +
                        privacyLevel: "Organizational",
         | 
| 25 | 
            +
                        useCallerAADIdentity: false,
         | 
| 26 | 
            +
                        useEndUserOAuth2Credentials: false,
         | 
| 27 | 
            +
                      },
         | 
| 28 | 
            +
                    }.to_json
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
                  true
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                def delete
         | 
| 34 | 
            +
                  @tenant.delete("/gateways/#{gateway.id}/datasources/#{id}")
         | 
| 35 | 
            +
                  @gateway.gateway_datasources.reload
         | 
| 36 | 
            +
                  true
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
              class GatewayDatasourceArray < Array
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                def initialize(tenant, gateway)
         | 
| 44 | 
            +
                  super(tenant)
         | 
| 45 | 
            +
                  @gateway = gateway
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                def self.get_class
         | 
| 49 | 
            +
                  GatewayDatasource
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                # only MySQL type is currently supported
         | 
| 53 | 
            +
                def create(name, encrypted_credentials, db_server, db_name)
         | 
| 54 | 
            +
                  data = @tenant.post("/gateways/#{@gateway.id}/datasources",) do |req|
         | 
| 55 | 
            +
                    req.body = {
         | 
| 56 | 
            +
                      connectionDetails: {server: db_server, database: db_name}.to_json,
         | 
| 57 | 
            +
                      credentialDetails: {
         | 
| 58 | 
            +
                        credentialType: "Basic",
         | 
| 59 | 
            +
                        credentials: encrypted_credentials,
         | 
| 60 | 
            +
                        encryptedConnection: "Encrypted",
         | 
| 61 | 
            +
                        encryptionAlgorithm: "RSA-OAEP",
         | 
| 62 | 
            +
                        privacyLevel: "Organizational",
         | 
| 63 | 
            +
                        useCallerAADIdentity: false,
         | 
| 64 | 
            +
                        useEndUserOAuth2Credentials: false,
         | 
| 65 | 
            +
                      },
         | 
| 66 | 
            +
                      datasourceName: name,
         | 
| 67 | 
            +
                      datasourceType: 'MySql',
         | 
| 68 | 
            +
                    }.to_json
         | 
| 69 | 
            +
                  end
         | 
| 70 | 
            +
                  self.reload
         | 
| 71 | 
            +
                  GatewayDatasource.new(@tenant, data)
         | 
| 72 | 
            +
                end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                def get_data
         | 
| 75 | 
            +
                  data = @tenant.get("/gateways/#{@gateway.id}/datasources")[:value]
         | 
| 76 | 
            +
                  data.each { |d| d[:gateway] = @gateway }
         | 
| 77 | 
            +
                end
         | 
| 78 | 
            +
              end
         | 
| 79 | 
            +
            end
         | 
    
        data/lib/power-bi/report.rb
    CHANGED
    
    | @@ -2,6 +2,8 @@ module PowerBI | |
| 2 2 | 
             
              class Report
         | 
| 3 3 | 
             
                attr_reader :name, :id, :report_type, :web_url, :embed_url, :is_from_pbix, :is_owned_by_me, :dataset_id, :workspace
         | 
| 4 4 |  | 
| 5 | 
            +
                class ExportToFileError < PowerBI::Error ; end
         | 
| 6 | 
            +
             | 
| 5 7 | 
             
                def initialize(tenant, data)
         | 
| 6 8 | 
             
                  @id = data[:id]
         | 
| 7 9 | 
             
                  @report_type = data[:reportType]
         | 
| @@ -36,12 +38,35 @@ module PowerBI | |
| 36 38 | 
             
                  true
         | 
| 37 39 | 
             
                end
         | 
| 38 40 |  | 
| 39 | 
            -
                def export_to_file(format: 'PDF')
         | 
| 40 | 
            -
                   | 
| 41 | 
            +
                def export_to_file(filename, format: 'PDF', timeout: 300)
         | 
| 42 | 
            +
                  # post
         | 
| 43 | 
            +
                  data = @tenant.post("/groups/#{workspace.id}/reports/#{id}/ExportTo") do |req|
         | 
| 41 44 | 
             
                    req.body = {
         | 
| 42 45 | 
             
                      format: format
         | 
| 43 46 | 
             
                    }.to_json
         | 
| 44 47 | 
             
                  end
         | 
| 48 | 
            +
                  export_id = data[:id]
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                  # poll
         | 
| 51 | 
            +
                  success = false
         | 
| 52 | 
            +
                  iterations = 0
         | 
| 53 | 
            +
                  status_history = ''
         | 
| 54 | 
            +
                  old_status = ''
         | 
| 55 | 
            +
                  while !success
         | 
| 56 | 
            +
                    sleep 0.1
         | 
| 57 | 
            +
                    iterations += 1
         | 
| 58 | 
            +
                    raise ExportToFileError.new("Report export to file did not succeed after #{timeout} seconds. Status history:#{status_history}") if iterations > (10 * timeout)
         | 
| 59 | 
            +
                    new_status = @tenant.get("/groups/#{workspace.id}/reports/#{id}/exports/#{export_id}")[:status].to_s
         | 
| 60 | 
            +
                    success = (new_status == "Succeeded")
         | 
| 61 | 
            +
                    if new_status != old_status
         | 
| 62 | 
            +
                      status_history += "\nStatus change after #{iterations/10.0}s: '#{old_status}' --> '#{new_status}'"
         | 
| 63 | 
            +
                      old_status = new_status
         | 
| 64 | 
            +
                    end
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                  # get and write file
         | 
| 68 | 
            +
                  data = @tenant.get_raw("/groups/#{workspace.id}/reports/#{id}/exports/#{export_id}/file")
         | 
| 69 | 
            +
                  File.open(filename, "wb") { |f| f.write(data) }
         | 
| 45 70 | 
             
                end
         | 
| 46 71 |  | 
| 47 72 | 
             
              end
         | 
    
        data/lib/power-bi/tenant.rb
    CHANGED
    
    | @@ -1,20 +1,38 @@ | |
| 1 1 | 
             
            module PowerBI
         | 
| 2 2 | 
             
              class Tenant
         | 
| 3 | 
            -
                attr_reader :workspaces
         | 
| 3 | 
            +
                attr_reader :workspaces, :gateways
         | 
| 4 4 |  | 
| 5 | 
            -
                def initialize(token_generator)
         | 
| 5 | 
            +
                def initialize(token_generator, retries: 5)
         | 
| 6 6 | 
             
                  @token_generator = token_generator
         | 
| 7 7 | 
             
                  @workspaces = WorkspaceArray.new(self)
         | 
| 8 | 
            +
                  @gateways = GatewayArray.new(self)
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  ## WHY RETRIES? ##
         | 
| 11 | 
            +
                  # 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 :-)
         | 
| 12 | 
            +
                  ##################
         | 
| 13 | 
            +
                  @retry_options = {
         | 
| 14 | 
            +
                    max: retries,
         | 
| 15 | 
            +
                    exceptions: [Errno::ETIMEDOUT, Timeout::Error, Faraday::TimeoutError, Faraday::RetriableResponse],
         | 
| 16 | 
            +
                    methods: [:get, :post, :patch, :delete],
         | 
| 17 | 
            +
                    retry_statuses: [500], # internal server error
         | 
| 18 | 
            +
                    interval: 0.2,
         | 
| 19 | 
            +
                    interval_randomness: 0,
         | 
| 20 | 
            +
                    backoff_factor: 4,
         | 
| 21 | 
            +
                    retry_block: -> (env, options, retries, exc) { puts "retrying...!! (@ #{Time.now.to_s}), exception: #{exc.to_s} ---- #{exc.message}" },
         | 
| 22 | 
            +
                  }
         | 
| 8 23 | 
             
                end
         | 
| 9 24 |  | 
| 10 25 | 
             
                def get(url, params = {})
         | 
| 11 | 
            -
                   | 
| 26 | 
            +
                  conn = Faraday.new do |f|
         | 
| 27 | 
            +
                    f.request :retry, @retry_options
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                  response = conn.get(PowerBI::BASE_URL + url) do |req|
         | 
| 12 30 | 
             
                    req.params = params
         | 
| 13 31 | 
             
                    req.headers['Accept'] = 'application/json'
         | 
| 14 32 | 
             
                    req.headers['authorization'] = "Bearer #{token}"
         | 
| 15 33 | 
             
                    yield req if block_given?
         | 
| 16 34 | 
             
                  end
         | 
| 17 | 
            -
                   | 
| 35 | 
            +
                  unless [200, 202].include? response.status
         | 
| 18 36 | 
             
                    raise APIError.new("Error calling Power BI API (status #{response.status}): #{response.body}")
         | 
| 19 37 | 
             
                  end
         | 
| 20 38 | 
             
                  unless response.body.empty?
         | 
| @@ -22,8 +40,45 @@ module PowerBI | |
| 22 40 | 
             
                  end
         | 
| 23 41 | 
             
                end
         | 
| 24 42 |  | 
| 43 | 
            +
                def get_raw(url, params = {})
         | 
| 44 | 
            +
                  conn = Faraday.new do |f|
         | 
| 45 | 
            +
                    f.request :retry, @retry_options
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
                  response = conn.get(PowerBI::BASE_URL + url) do |req|
         | 
| 48 | 
            +
                    req.params = params
         | 
| 49 | 
            +
                    req.headers['authorization'] = "Bearer #{token}"
         | 
| 50 | 
            +
                    yield req if block_given?
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
                  unless [200, 202].include? response.status
         | 
| 53 | 
            +
                    raise APIError.new("Error calling Power BI API (status #{response.status}): #{response.body}")
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
                  response.body
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
             | 
| 25 58 | 
             
                def post(url, params = {})
         | 
| 26 | 
            -
                   | 
| 59 | 
            +
                  conn = Faraday.new do |f|
         | 
| 60 | 
            +
                    f.request :retry, @retry_options
         | 
| 61 | 
            +
                  end
         | 
| 62 | 
            +
                  response = conn.post(PowerBI::BASE_URL + url) do |req|
         | 
| 63 | 
            +
                    req.params = params
         | 
| 64 | 
            +
                    req.headers['Accept'] = 'application/json'
         | 
| 65 | 
            +
                    req.headers['Content-Type'] = 'application/json'
         | 
| 66 | 
            +
                    req.headers['authorization'] = "Bearer #{token}"
         | 
| 67 | 
            +
                    yield req if block_given?
         | 
| 68 | 
            +
                  end
         | 
| 69 | 
            +
                  unless [200, 201, 202].include? response.status
         | 
| 70 | 
            +
                    raise APIError.new("Error calling Power BI API (status #{response.status}): #{response.body}")
         | 
| 71 | 
            +
                  end
         | 
| 72 | 
            +
                  unless response.body.empty?
         | 
| 73 | 
            +
                    JSON.parse(response.body, symbolize_names: true)
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
                end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                def patch(url, params = {})
         | 
| 78 | 
            +
                  conn = Faraday.new do |f|
         | 
| 79 | 
            +
                    f.request :retry, @retry_options
         | 
| 80 | 
            +
                  end
         | 
| 81 | 
            +
                  response = conn.patch(PowerBI::BASE_URL + url) do |req|
         | 
| 27 82 | 
             
                    req.params = params
         | 
| 28 83 | 
             
                    req.headers['Accept'] = 'application/json'
         | 
| 29 84 | 
             
                    req.headers['Content-Type'] = 'application/json'
         | 
| @@ -39,7 +94,10 @@ module PowerBI | |
| 39 94 | 
             
                end
         | 
| 40 95 |  | 
| 41 96 | 
             
                def delete(url, params = {})
         | 
| 42 | 
            -
                   | 
| 97 | 
            +
                  conn = Faraday.new do |f|
         | 
| 98 | 
            +
                    f.request :retry, @retry_options
         | 
| 99 | 
            +
                  end
         | 
| 100 | 
            +
                  response = conn.delete(PowerBI::BASE_URL + url) do |req|
         | 
| 43 101 | 
             
                    req.params = params
         | 
| 44 102 | 
             
                    req.headers['Accept'] = 'application/json'
         | 
| 45 103 | 
             
                    req.headers['authorization'] = "Bearer #{token}"
         | 
| @@ -56,6 +114,7 @@ module PowerBI | |
| 56 114 | 
             
                def post_file(url, file, params = {})
         | 
| 57 115 | 
             
                  conn = Faraday.new do |f|
         | 
| 58 116 | 
             
                    f.request :multipart
         | 
| 117 | 
            +
                    f.request :retry, @retry_options
         | 
| 59 118 | 
             
                  end
         | 
| 60 119 | 
             
                  response = conn.post(PowerBI::BASE_URL + url) do |req|
         | 
| 61 120 | 
             
                    req.params = params
         | 
| @@ -63,6 +122,7 @@ module PowerBI | |
| 63 122 | 
             
                    req.headers['Content-Type'] = 'multipart/form-data'
         | 
| 64 123 | 
             
                    req.headers['authorization'] = "Bearer #{token}"
         | 
| 65 124 | 
             
                    req.body = {value: Faraday::UploadIO.new(file, 'application/octet-stream')}
         | 
| 125 | 
            +
                    req.options.timeout = 120  # default is 60 seconds Net::ReadTimeout
         | 
| 66 126 | 
             
                  end
         | 
| 67 127 | 
             
                  if response.status != 202
         | 
| 68 128 | 
             
                    raise APIError.new("Error calling Power BI API (status #{response.status}): #{response.body}")
         | 
    
        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:  | 
| 4 | 
            +
              version: 1.3.1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Lode Cools
         | 
| @@ -38,7 +38,7 @@ dependencies: | |
| 38 38 | 
             
                - - "~>"
         | 
| 39 39 | 
             
                  - !ruby/object:Gem::Version
         | 
| 40 40 | 
             
                    version: '3.0'
         | 
| 41 | 
            -
            description: Ruby wrapper for the Power BI API | 
| 41 | 
            +
            description: Ruby wrapper for the Power BI API
         | 
| 42 42 | 
             
            email: lode.cools1@gmail.com
         | 
| 43 43 | 
             
            executables: []
         | 
| 44 44 | 
             
            extensions: []
         | 
| @@ -50,6 +50,8 @@ files: | |
| 50 50 | 
             
            - lib/power-bi/array.rb
         | 
| 51 51 | 
             
            - lib/power-bi/dataset.rb
         | 
| 52 52 | 
             
            - lib/power-bi/datasource.rb
         | 
| 53 | 
            +
            - lib/power-bi/gateway.rb
         | 
| 54 | 
            +
            - lib/power-bi/gateway_datasource.rb
         | 
| 53 55 | 
             
            - lib/power-bi/parameter.rb
         | 
| 54 56 | 
             
            - lib/power-bi/refresh.rb
         | 
| 55 57 | 
             
            - lib/power-bi/report.rb
         |