fluent-plugin-azurestorage-gen2 0.2.6 → 0.3.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 +26 -0
- data/VERSION +1 -1
- data/fluent-plugin-azurestorage-gen2.gemspec +1 -0
- data/lib/fluent/plugin/out_azurestorage_gen2.rb +131 -45
- metadata +22 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: f2ae08b739ba4ac4992427d2f87e8c5dc923d39b
         | 
| 4 | 
            +
              data.tar.gz: 658ff0d35909232a1741d43bfa95bfd00cef3957
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 5a122fb0024c716cfbe9a6aa45f733ec938a28a0059bbb66f2d49ae885533ddb529247b757927abcc4784bfc9b78ab5f3593146cad5fbd562ac972cff15503bc
         | 
| 7 | 
            +
              data.tar.gz: 99103e68b7c4995a7c495069eb302cfd006378c5477642bb03d76d5b9ea2462e3820a11ebc21a38c5383dc26ba5d5f3a4151f24ebf1788ddccf5f93eb3ef52e4
         | 
    
        data/README.md
    CHANGED
    
    | @@ -140,6 +140,10 @@ If that setting is disabled, the worker won't fail on initialization (getting fi | |
| 140 140 |  | 
| 141 141 | 
             
            The defaultt `url_domain_suffix` is `.dfs.core.windows.net`, you can override this in case of private endpoints.
         | 
| 142 142 |  | 
| 143 | 
            +
            ### url_storage_resource
         | 
| 144 | 
            +
             | 
| 145 | 
            +
            The url that is used during accessing a resource. Default value: `https://storage.azure.com/`
         | 
| 146 | 
            +
             | 
| 143 147 | 
             
            ### azure_object_key_format
         | 
| 144 148 |  | 
| 145 149 | 
             
            The format of Azure Storage object keys. You can use several built-in variables:
         | 
| @@ -148,6 +152,7 @@ The format of Azure Storage object keys. You can use several built-in variables: | |
| 148 152 | 
             
            - %{time_slice}
         | 
| 149 153 | 
             
            - %{index}
         | 
| 150 154 | 
             
            - %{file_extension}
         | 
| 155 | 
            +
            - %{upload_timestamp}
         | 
| 151 156 |  | 
| 152 157 | 
             
            to decide keys dynamically.
         | 
| 153 158 |  | 
| @@ -155,6 +160,7 @@ to decide keys dynamically. | |
| 155 160 | 
             
            %{time_slice} is the time-slice in text that are formatted with *time_slice_format*.
         | 
| 156 161 | 
             
            %{index} is the sequential number starts from 0, increments when multiple files are uploaded to Azure Storage in the same time slice.
         | 
| 157 162 | 
             
            %{file_extention} is always "gz" for now.
         | 
| 163 | 
            +
            %{upload_timestamp} is an upload timestamp in text that are formatted with *upload_timestamp_format*. Difference between time_slice and upload_timestamp is that the second one is the actual system timestamp (other one is from the metadata)
         | 
| 158 164 |  | 
| 159 165 | 
             
            The default format is "%{path}%{time_slice}_%{index}.%{file_extension}".
         | 
| 160 166 |  | 
| @@ -279,10 +285,30 @@ Format of the time used as the file name. Default is '%Y%m%d'. Use '%Y%m%d%H' to | |
| 279 285 |  | 
| 280 286 | 
             
            The time to wait old logs. Default is 10 minutes.
         | 
| 281 287 |  | 
| 288 | 
            +
            ### upload_timestamp_format
         | 
| 289 | 
            +
             | 
| 290 | 
            +
            Format of the upload timestamp used as the file name. Can be used instead of index in case of `write_only` option is enabled. Default value is '%H%M%S%L'.
         | 
| 291 | 
            +
             | 
| 282 292 | 
             
            ### utc
         | 
| 283 293 |  | 
| 284 294 | 
             
            Use UTC instead of local time.
         | 
| 285 295 |  | 
| 296 | 
            +
            ### write_only
         | 
| 297 | 
            +
             | 
| 298 | 
            +
            If that option is enabled, HEAD calls are skipped during blob operations. (so make sure to set the chunk limit to 4MB in order to avoid HEAD operation because of the append operation needs the last position of the uploaded blobs).
         | 
| 299 | 
            +
             | 
| 300 | 
            +
            ### proxy_url
         | 
| 301 | 
            +
             | 
| 302 | 
            +
            Proxy URL for Azure endpoint.
         | 
| 303 | 
            +
             | 
| 304 | 
            +
            ### proxy_username
         | 
| 305 | 
            +
             | 
| 306 | 
            +
            Proxy username for Azure proxy endpoint (used only if `proxy_url` is filled)
         | 
| 307 | 
            +
             | 
| 308 | 
            +
            ### proxy_password
         | 
| 309 | 
            +
             | 
| 310 | 
            +
            Proxy password for Azure `proxy_username` (used only if `proxy_url` is filled)
         | 
| 311 | 
            +
             | 
| 286 312 | 
             
            ## TODOs
         | 
| 287 313 |  | 
| 288 314 | 
             
            - add storage key support
         | 
    
        data/VERSION
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            0. | 
| 1 | 
            +
            0.3.0
         | 
| @@ -21,6 +21,7 @@ Gem::Specification.new do |gem| | |
| 21 21 | 
             
              gem.add_runtime_dependency 'typhoeus', '~> 1.0', '>= 1.0.1'
         | 
| 22 22 | 
             
              gem.add_runtime_dependency 'json', '~> 2.1', '>= 2.1.0'
         | 
| 23 23 | 
             
              gem.add_runtime_dependency "yajl-ruby", '~> 1.4'
         | 
| 24 | 
            +
              gem.add_runtime_dependency 'concurrent-ruby', '~> 1.1', '>= 1.1.5'
         | 
| 24 25 | 
             
              gem.add_development_dependency 'rake', '~> 12.3', '>= 12.3.1'
         | 
| 25 26 | 
             
              gem.add_development_dependency 'test-unit', '~> 3.3', '>= 3.3.3'
         | 
| 26 27 | 
             
              gem.add_development_dependency 'test-unit-rr', '~> 1.0', '>= 1.0.5'
         | 
| @@ -6,6 +6,7 @@ require 'tempfile' | |
| 6 6 | 
             
            require 'time'
         | 
| 7 7 | 
             
            require 'typhoeus'
         | 
| 8 8 | 
             
            require 'fluent/plugin/output'
         | 
| 9 | 
            +
            require 'concurrent'
         | 
| 9 10 | 
             
            require 'zlib'
         | 
| 10 11 |  | 
| 11 12 | 
             
            module Fluent::Plugin
         | 
| @@ -38,9 +39,16 @@ module Fluent::Plugin | |
| 38 39 | 
             
                    config_param :enable_retry, :bool, :default => false
         | 
| 39 40 | 
             
                    config_param :startup_fail_on_error, :bool, :default => true
         | 
| 40 41 | 
             
                    config_param :url_domain_suffix, :string, :default => '.dfs.core.windows.net'
         | 
| 42 | 
            +
                    config_param :url_storage_resource, :string, :default => 'https://storage.azure.com/'
         | 
| 41 43 | 
             
                    config_param :format, :string, :default => "out_file"
         | 
| 42 44 | 
             
                    config_param :time_slice_format, :string, :default => '%Y%m%d'
         | 
| 45 | 
            +
                    config_param :hex_random_length, :integer, default: 4
         | 
| 43 46 | 
             
                    config_param :command_parameter, :string, :default => nil
         | 
| 47 | 
            +
                    config_param :proxy_url, :string, :default => nil
         | 
| 48 | 
            +
                    config_param :proxy_username, :string, :default => nil
         | 
| 49 | 
            +
                    config_param :proxy_password, :string, :default => nil, :secret => true
         | 
| 50 | 
            +
                    config_param :write_only, :bool, :default => false
         | 
| 51 | 
            +
                    config_param :upload_timestamp_format, :string, :default => '%H%M%S%L'
         | 
| 44 52 |  | 
| 45 53 | 
             
                    DEFAULT_FORMAT_TYPE = "out_file"
         | 
| 46 54 | 
             
                    ACCESS_TOKEN_API_VERSION = "2018-02-01"
         | 
| @@ -74,16 +82,6 @@ module Fluent::Plugin | |
| 74 82 |  | 
| 75 83 | 
             
                        @formatter = formatter_create
         | 
| 76 84 |  | 
| 77 | 
            -
                        if @localtime
         | 
| 78 | 
            -
                          @path_slicer = Proc.new {|path|
         | 
| 79 | 
            -
                            Time.now.strftime(path)
         | 
| 80 | 
            -
                          }
         | 
| 81 | 
            -
                        else
         | 
| 82 | 
            -
                          @path_slicer = Proc.new {|path|
         | 
| 83 | 
            -
                            Time.now.utc.strftime(path)
         | 
| 84 | 
            -
                          }
         | 
| 85 | 
            -
                        end
         | 
| 86 | 
            -
                  
         | 
| 87 85 | 
             
                        if @azure_container.nil?
         | 
| 88 86 | 
             
                          raise Fluent::ConfigError, "azure_container is needed"
         | 
| 89 87 | 
             
                        end
         | 
| @@ -97,7 +95,7 @@ module Fluent::Plugin | |
| 97 95 | 
             
                        else
         | 
| 98 96 | 
             
                            @final_file_extension = @compressor.ext
         | 
| 99 97 | 
             
                        end
         | 
| 100 | 
            -
             | 
| 98 | 
            +
                        @values_for_object_chunk = {}
         | 
| 101 99 | 
             
                    end
         | 
| 102 100 |  | 
| 103 101 | 
             
                    def multi_workers_ready?
         | 
| @@ -126,17 +124,16 @@ module Fluent::Plugin | |
| 126 124 | 
             
                    end
         | 
| 127 125 |  | 
| 128 126 | 
             
                    def write(chunk)
         | 
| 129 | 
            -
                        metadata = chunk.metadata
         | 
| 130 127 | 
             
                        if @store_as.nil? || @store_as == "none"
         | 
| 131 | 
            -
                            generate_log_name( | 
| 128 | 
            +
                            generate_log_name(chunk, @current_index)
         | 
| 132 129 | 
             
                            if @last_azure_storage_path != @azure_storage_path
         | 
| 133 130 | 
             
                                @current_index = 0
         | 
| 134 | 
            -
                                generate_log_name( | 
| 131 | 
            +
                                generate_log_name(chunk, @current_index)
         | 
| 135 132 | 
             
                            end
         | 
| 136 133 | 
             
                            raw_data = chunk.read
         | 
| 137 134 | 
             
                            unless raw_data.empty?
         | 
| 138 135 | 
             
                                log.debug "azurestorage_gen2: processing raw data", chunk_id: dump_unique_id_hex(chunk.unique_id)
         | 
| 139 | 
            -
                                upload_blob(raw_data,  | 
| 136 | 
            +
                                upload_blob(raw_data, chunk)
         | 
| 140 137 | 
             
                            end
         | 
| 141 138 | 
             
                            chunk.close rescue nil
         | 
| 142 139 | 
             
                            @last_azure_storage_path = @azure_storage_path
         | 
| @@ -146,51 +143,76 @@ module Fluent::Plugin | |
| 146 143 | 
             
                            begin
         | 
| 147 144 | 
             
                                @compressor.compress(chunk, tmp)
         | 
| 148 145 | 
             
                                tmp.rewind
         | 
| 149 | 
            -
                                generate_log_name( | 
| 146 | 
            +
                                generate_log_name(chunk, @current_index)
         | 
| 150 147 | 
             
                                if @last_azure_storage_path != @azure_storage_path
         | 
| 151 148 | 
             
                                    @current_index = 0
         | 
| 152 | 
            -
                                    generate_log_name( | 
| 149 | 
            +
                                    generate_log_name(chunk, @current_index)
         | 
| 153 150 | 
             
                                end
         | 
| 154 151 | 
             
                                log.debug "azurestorage_gen2: Start uploading temp file: #{tmp.path}"
         | 
| 155 152 | 
             
                                content = File.open(tmp.path, 'rb') { |file| file.read }
         | 
| 156 | 
            -
                                upload_blob(content,  | 
| 153 | 
            +
                                upload_blob(content, chunk)
         | 
| 157 154 | 
             
                                @last_azure_storage_path = @azure_storage_path
         | 
| 158 155 | 
             
                            ensure
         | 
| 159 156 | 
             
                                tmp.close(true) rescue nil
         | 
| 160 157 | 
             
                            end
         | 
| 158 | 
            +
                            @values_for_object_chunk.delete(chunk.unique_id)
         | 
| 161 159 | 
             
                        end
         | 
| 162 160 |  | 
| 163 161 | 
             
                    end
         | 
| 164 162 |  | 
| 165 163 | 
             
                    private
         | 
| 166 | 
            -
                    def upload_blob(content,  | 
| 164 | 
            +
                    def upload_blob(content, chunk)
         | 
| 167 165 | 
             
                        log.debug "azurestorage_gen2: Uploading blob: #{@azure_storage_path}"
         | 
| 168 | 
            -
                         | 
| 169 | 
            -
                        if existing_content_length == 0
         | 
| 166 | 
            +
                        if @write_only
         | 
| 170 167 | 
             
                            create_blob(@azure_storage_path)
         | 
| 168 | 
            +
                            append_blob(content, chunk, 0)
         | 
| 169 | 
            +
                        else
         | 
| 170 | 
            +
                            existing_content_length = get_blob_properties(@azure_storage_path)
         | 
| 171 | 
            +
                            if existing_content_length == 0
         | 
| 172 | 
            +
                                create_blob(@azure_storage_path)
         | 
| 173 | 
            +
                            end
         | 
| 174 | 
            +
                            append_blob(content, chunk, existing_content_length)
         | 
| 171 175 | 
             
                        end
         | 
| 172 | 
            -
                        append_blob(content, metadata, existing_content_length)
         | 
| 173 176 | 
             
                    end
         | 
| 174 177 |  | 
| 175 178 | 
             
                    private
         | 
| 176 | 
            -
                    def generate_log_name( | 
| 179 | 
            +
                    def generate_log_name(chunk, index)
         | 
| 180 | 
            +
                        metadata = chunk.metadata
         | 
| 177 181 | 
             
                        time_slice = if metadata.timekey.nil?
         | 
| 178 182 | 
             
                                   ''.freeze
         | 
| 179 183 | 
             
                                 else
         | 
| 180 184 | 
             
                                   Time.at(metadata.timekey).utc.strftime(@time_slice_format)
         | 
| 181 185 | 
             
                                 end
         | 
| 182 | 
            -
                         | 
| 183 | 
            -
             | 
| 184 | 
            -
                             | 
| 185 | 
            -
             | 
| 186 | 
            +
                        if @localtime
         | 
| 187 | 
            +
                            hms_slicer = Time.now.strftime("%H%M%S")
         | 
| 188 | 
            +
                            upload_timestamp = Time.now.strftime(@upload_timestamp_format)
         | 
| 189 | 
            +
                        else
         | 
| 190 | 
            +
                            hms_slicer = Time.now.utc.strftime("%H%M%S")
         | 
| 191 | 
            +
                            upload_timestamp = Time.now.utc.strftime(@upload_timestamp_format)
         | 
| 192 | 
            +
                        end
         | 
| 193 | 
            +
             | 
| 194 | 
            +
                        @values_for_object_chunk[chunk.unique_id] ||= {
         | 
| 195 | 
            +
                            "%{hex_random}" => hex_random(chunk),
         | 
| 196 | 
            +
                        }
         | 
| 197 | 
            +
                        values_for_object_key_pre = {
         | 
| 198 | 
            +
                            "%{path}" => @path,
         | 
| 186 199 | 
             
                            "%{index}" => index,
         | 
| 187 200 | 
             
                            "%{uuid_flush}" => uuid_random,
         | 
| 188 | 
            -
                            "%{file_extension}" => @final_file_extension
         | 
| 201 | 
            +
                            "%{file_extension}" => @final_file_extension,
         | 
| 202 | 
            +
                            "%{upload_timestamp}" => upload_timestamp,
         | 
| 189 203 | 
             
                        }
         | 
| 190 | 
            -
                         | 
| 191 | 
            -
             | 
| 192 | 
            -
             | 
| 193 | 
            -
             | 
| 204 | 
            +
                        values_for_object_key_post = {
         | 
| 205 | 
            +
                            "%{date_slice}" => time_slice,
         | 
| 206 | 
            +
                            "%{time_slice}" => time_slice,
         | 
| 207 | 
            +
                            "%{hms_slice}" => hms_slicer,
         | 
| 208 | 
            +
                        }.merge!(@values_for_object_chunk[chunk.unique_id])
         | 
| 209 | 
            +
                        storage_path = @azure_object_key_format.gsub(%r(%{[^}]+})) do |matched_key|
         | 
| 210 | 
            +
                            values_for_object_key_pre.fetch(matched_key, matched_key)
         | 
| 211 | 
            +
                        end
         | 
| 212 | 
            +
                        storage_path = extract_placeholders(storage_path, chunk)
         | 
| 213 | 
            +
                        storage_path = storage_path.gsub(%r(%{[^}]+}), values_for_object_key_post)
         | 
| 214 | 
            +
                        storage_path = "/" + storage_path unless storage_path.start_with?("/")
         | 
| 215 | 
            +
                        @azure_storage_path = storage_path
         | 
| 194 216 | 
             
                    end
         | 
| 195 217 |  | 
| 196 218 | 
             
                    def setup_access_token
         | 
| @@ -242,11 +264,16 @@ module Fluent::Plugin | |
| 242 264 | 
             
                    # https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/tutorial-linux-vm-access-storage#get-an-access-token-and-use-it-to-call-azure-storage
         | 
| 243 265 | 
             
                    private
         | 
| 244 266 | 
             
                    def acquire_access_token_msi
         | 
| 245 | 
            -
                        params = { :"api-version" => ACCESS_TOKEN_API_VERSION, :resource => " | 
| 267 | 
            +
                        params = { :"api-version" => ACCESS_TOKEN_API_VERSION, :resource => "#{@url_storage_resource}" }
         | 
| 246 268 | 
             
                        unless @azure_instance_msi.nil?
         | 
| 247 269 | 
             
                            params[:msi_res_id] = @azure_instance_msi
         | 
| 248 270 | 
             
                        end
         | 
| 249 | 
            -
                         | 
| 271 | 
            +
                        req_opts = {
         | 
| 272 | 
            +
                            :params => params,
         | 
| 273 | 
            +
                            :headers => { Metadata: "true" }
         | 
| 274 | 
            +
                        }
         | 
| 275 | 
            +
                        add_proxy_options(req_opts)
         | 
| 276 | 
            +
                        request = Typhoeus::Request.new("http://169.254.169.254/metadata/identity/oauth2/token", req_opts)
         | 
| 250 277 | 
             
                        request.on_complete do |response|
         | 
| 251 278 | 
             
                            if response.success?
         | 
| 252 279 | 
             
                              data = JSON.parse(response.body)
         | 
| @@ -261,10 +288,16 @@ module Fluent::Plugin | |
| 261 288 |  | 
| 262 289 | 
             
                    private
         | 
| 263 290 | 
             
                    def acquire_access_token_oauth_app
         | 
| 264 | 
            -
                        params = { :"api-version" => ACCESS_TOKEN_API_VERSION, :resource => " | 
| 291 | 
            +
                        params = { :"api-version" => ACCESS_TOKEN_API_VERSION, :resource => "#{@url_storage_resource}"}
         | 
| 265 292 | 
             
                        headers = {:"Content-Type" => "application/x-www-form-urlencoded"}
         | 
| 266 | 
            -
                        content = "grant_type=client_credentials&client_id=#{@azure_oauth_app_id}&client_secret=#{@azure_oauth_secret}&resource | 
| 267 | 
            -
                         | 
| 293 | 
            +
                        content = "grant_type=client_credentials&client_id=#{@azure_oauth_app_id}&client_secret=#{@azure_oauth_secret}&resource=#{@url_storage_resource}"
         | 
| 294 | 
            +
                        req_opts = {
         | 
| 295 | 
            +
                            :params => params,
         | 
| 296 | 
            +
                            :body => content, 
         | 
| 297 | 
            +
                            :headers => headers
         | 
| 298 | 
            +
                        }
         | 
| 299 | 
            +
                        add_proxy_options(req_opts)
         | 
| 300 | 
            +
                        request = Typhoeus::Request.new("https://login.microsoftonline.com/#{@azure_oauth_tenant_id}/oauth2/token", req_opts)
         | 
| 268 301 | 
             
                        request.on_complete do |response|
         | 
| 269 302 | 
             
                            if response.success?
         | 
| 270 303 | 
             
                              data = JSON.parse(response.body)
         | 
| @@ -279,7 +312,7 @@ module Fluent::Plugin | |
| 279 312 |  | 
| 280 313 | 
             
                    private
         | 
| 281 314 | 
             
                    def acquire_access_token_by_az
         | 
| 282 | 
            -
                        access_token=`az account get-access-token --resource  | 
| 315 | 
            +
                        access_token=`az account get-access-token --resource #{@url_storage_resource} --query accessToken -o tsv`
         | 
| 283 316 | 
             
                        log.debug "azurestorage_gen2: Token response: #{access_token}"
         | 
| 284 317 | 
             
                        @azure_access_token = access_token.chomp
         | 
| 285 318 | 
             
                    end
         | 
| @@ -291,7 +324,13 @@ module Fluent::Plugin | |
| 291 324 | 
             
                        params = {:resource => "filesystem" }
         | 
| 292 325 | 
             
                        auth_header = create_auth_header("head", datestamp, "#{@azure_container}", headers, params)
         | 
| 293 326 | 
             
                        headers[:Authorization] = auth_header
         | 
| 294 | 
            -
                         | 
| 327 | 
            +
                        req_opts = {
         | 
| 328 | 
            +
                            :method => :head,
         | 
| 329 | 
            +
                            :params => params,
         | 
| 330 | 
            +
                            :headers => headers
         | 
| 331 | 
            +
                        }
         | 
| 332 | 
            +
                        add_proxy_options(req_opts)
         | 
| 333 | 
            +
                        request = Typhoeus::Request.new("https://#{azure_storage_account}#{@url_domain_suffix}/#{@azure_container}", req_opts)
         | 
| 295 334 | 
             
                        request.on_complete do |response|
         | 
| 296 335 | 
             
                            if response.success?
         | 
| 297 336 | 
             
                              log.info "azurestorage_gen2: Container '#{@azure_container}' exists."
         | 
| @@ -318,7 +357,13 @@ module Fluent::Plugin | |
| 318 357 | 
             
                        params = {:resource => "filesystem" }
         | 
| 319 358 | 
             
                        auth_header = create_auth_header("put", datestamp, "#{@azure_container}", headers, params)
         | 
| 320 359 | 
             
                        headers[:Authorization] = auth_header
         | 
| 321 | 
            -
                         | 
| 360 | 
            +
                        req_opts = {
         | 
| 361 | 
            +
                            :method => :put,
         | 
| 362 | 
            +
                            :params => params,
         | 
| 363 | 
            +
                            :headers => headers
         | 
| 364 | 
            +
                        }
         | 
| 365 | 
            +
                        add_proxy_options(req_opts)
         | 
| 366 | 
            +
                        request = Typhoeus::Request.new("https://#{azure_storage_account}#{@url_domain_suffix}/#{@azure_container}", req_opts)
         | 
| 322 367 | 
             
                        request.on_complete do |response|
         | 
| 323 368 | 
             
                            if response.success?
         | 
| 324 369 | 
             
                                log.debug "azurestorage_gen2: Container '#{@azure_container}' created, response code: #{response.code}"
         | 
| @@ -338,7 +383,13 @@ module Fluent::Plugin | |
| 338 383 | 
             
                        params = {:resource => "file", :recursive => "false"}
         | 
| 339 384 | 
             
                        auth_header = create_auth_header("put", datestamp, "#{@azure_container}#{blob_path}", headers, params)
         | 
| 340 385 | 
             
                        headers[:Authorization] = auth_header
         | 
| 341 | 
            -
                         | 
| 386 | 
            +
                        req_opts = {
         | 
| 387 | 
            +
                            :method => :put,
         | 
| 388 | 
            +
                            :params => params,
         | 
| 389 | 
            +
                            :headers => headers
         | 
| 390 | 
            +
                        }
         | 
| 391 | 
            +
                        add_proxy_options(req_opts)
         | 
| 392 | 
            +
                        request = Typhoeus::Request.new("https://#{azure_storage_account}#{@url_domain_suffix}/#{@azure_container}#{blob_path}", req_opts)
         | 
| 342 393 | 
             
                        request.on_complete do |response|
         | 
| 343 394 | 
             
                            if response.success?
         | 
| 344 395 | 
             
                                log.debug "azurestorage_gen2: Blob '#{blob_path}' has been created, response code: #{response.code}"
         | 
| @@ -361,7 +412,14 @@ module Fluent::Plugin | |
| 361 412 | 
             
                        params = {:action => "append", :position => "#{position}"}
         | 
| 362 413 | 
             
                        auth_header = create_auth_header("patch", datestamp, "#{@azure_container}#{blob_path}", headers, params)
         | 
| 363 414 | 
             
                        headers[:Authorization] = auth_header
         | 
| 364 | 
            -
                         | 
| 415 | 
            +
                        req_opts = {
         | 
| 416 | 
            +
                            :method => :patch,
         | 
| 417 | 
            +
                            :params => params,
         | 
| 418 | 
            +
                            :headers => headers,
         | 
| 419 | 
            +
                            :body => content
         | 
| 420 | 
            +
                        }
         | 
| 421 | 
            +
                        add_proxy_options(req_opts)
         | 
| 422 | 
            +
                        request = Typhoeus::Request.new("https://#{azure_storage_account}#{@url_domain_suffix}/#{@azure_container}#{blob_path}", req_opts)
         | 
| 365 423 | 
             
                        request.on_complete do |response|
         | 
| 366 424 | 
             
                            if response.success?
         | 
| 367 425 | 
             
                                log.debug "azurestorage_gen2: Blob '#{blob_path}' has been appended, response code: #{response.code}"
         | 
| @@ -386,7 +444,13 @@ module Fluent::Plugin | |
| 386 444 | 
             
                        params = {:action => "flush", :position => "#{position}"}
         | 
| 387 445 | 
             
                        auth_header = create_auth_header("patch", datestamp, "#{@azure_container}#{blob_path}",headers, params)
         | 
| 388 446 | 
             
                        headers[:Authorization] = auth_header
         | 
| 389 | 
            -
                         | 
| 447 | 
            +
                        req_opts = {
         | 
| 448 | 
            +
                            :method => :patch,
         | 
| 449 | 
            +
                            :params => params,
         | 
| 450 | 
            +
                            :headers => headers
         | 
| 451 | 
            +
                        }
         | 
| 452 | 
            +
                        add_proxy_options(req_opts)
         | 
| 453 | 
            +
                        request = Typhoeus::Request.new("https://#{azure_storage_account}#{@url_domain_suffix}/#{@azure_container}#{blob_path}", req_opts)
         | 
| 390 454 | 
             
                        request.on_complete do |response|
         | 
| 391 455 | 
             
                            if response.success?
         | 
| 392 456 | 
             
                                log.debug "azurestorage_gen2: Blob '#{blob_path}' flush was successful, response code: #{response.code}"
         | 
| @@ -407,7 +471,13 @@ module Fluent::Plugin | |
| 407 471 | 
             
                        content_length = -1
         | 
| 408 472 | 
             
                        auth_header = create_auth_header("head", datestamp, "#{@azure_container}#{blob_path}", headers, params)
         | 
| 409 473 | 
             
                        headers[:Authorization] = auth_header
         | 
| 410 | 
            -
                         | 
| 474 | 
            +
                        req_opts = {
         | 
| 475 | 
            +
                            :method => :head,
         | 
| 476 | 
            +
                            :params => params,
         | 
| 477 | 
            +
                            :headers => headers
         | 
| 478 | 
            +
                        }
         | 
| 479 | 
            +
                        add_proxy_options(req_opts)
         | 
| 480 | 
            +
                        request = Typhoeus::Request.new("https://#{azure_storage_account}#{@url_domain_suffix}/#{@azure_container}#{blob_path}", req_opts)
         | 
| 411 481 | 
             
                        request.on_complete do |response|
         | 
| 412 482 | 
             
                            if response.success?
         | 
| 413 483 | 
             
                              log.debug "azurestorage_gen2: Get blob properties for '#{blob_path}', response headers: #{response.headers}"
         | 
| @@ -426,7 +496,7 @@ module Fluent::Plugin | |
| 426 496 | 
             
                    end
         | 
| 427 497 |  | 
| 428 498 | 
             
                    private
         | 
| 429 | 
            -
                    def append_blob(content,  | 
| 499 | 
            +
                    def append_blob(content, chunk, existing_content_length)
         | 
| 430 500 | 
             
                      position = 0
         | 
| 431 501 | 
             
                      log.debug "azurestorage_gen2: append_blob.start: Content size: #{content.length}"
         | 
| 432 502 | 
             
                      loop do
         | 
| @@ -475,6 +545,16 @@ module Fluent::Plugin | |
| 475 545 | 
             
                            "SharedKey #{@azure_storage_account}:#{signed(method, datestamp, resource, headers, params)}"
         | 
| 476 546 | 
             
                        end
         | 
| 477 547 | 
             
                    end
         | 
| 548 | 
            +
                    
         | 
| 549 | 
            +
                    private
         | 
| 550 | 
            +
                    def add_proxy_options(req_opts = {})
         | 
| 551 | 
            +
                        unless @proxy_url.nil?
         | 
| 552 | 
            +
                            req_opts[:proxy] = @proxy_url
         | 
| 553 | 
            +
                            unless @proxy_username.nil? || @proxy_password.nil?
         | 
| 554 | 
            +
                                req_opts[:proxyuserpwd] = "#{@proxy_username}:#{@proxy_password}"
         | 
| 555 | 
            +
                            end
         | 
| 556 | 
            +
                        end
         | 
| 557 | 
            +
                    end
         | 
| 478 558 |  | 
| 479 559 | 
             
                    private
         | 
| 480 560 | 
             
                    def signed(method, datestamp, resource, headers, params)
         | 
| @@ -544,6 +624,12 @@ module Fluent::Plugin | |
| 544 624 | 
             
                        require 'uuidtools'
         | 
| 545 625 | 
             
                        ::UUIDTools::UUID.random_create.to_s
         | 
| 546 626 | 
             
                    end
         | 
| 627 | 
            +
             | 
| 628 | 
            +
                    def hex_random(chunk)
         | 
| 629 | 
            +
                        unique_hex = Fluent::UniqueId.hex(chunk.unique_id)
         | 
| 630 | 
            +
                        unique_hex.reverse!
         | 
| 631 | 
            +
                        unique_hex[0...@hex_random_length]
         | 
| 632 | 
            +
                    end
         | 
| 547 633 |  | 
| 548 634 | 
             
                    def timekey_to_timeformat(timekey)
         | 
| 549 635 | 
             
                        case timekey
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: fluent-plugin-azurestorage-gen2
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.3.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Oliver Szabo
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2020- | 
| 11 | 
            +
            date: 2020-06-17 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: fluentd
         | 
| @@ -104,6 +104,26 @@ dependencies: | |
| 104 104 | 
             
                - - "~>"
         | 
| 105 105 | 
             
                  - !ruby/object:Gem::Version
         | 
| 106 106 | 
             
                    version: '1.4'
         | 
| 107 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 108 | 
            +
              name: concurrent-ruby
         | 
| 109 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 110 | 
            +
                requirements:
         | 
| 111 | 
            +
                - - "~>"
         | 
| 112 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 113 | 
            +
                    version: '1.1'
         | 
| 114 | 
            +
                - - ">="
         | 
| 115 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 116 | 
            +
                    version: 1.1.5
         | 
| 117 | 
            +
              type: :runtime
         | 
| 118 | 
            +
              prerelease: false
         | 
| 119 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 120 | 
            +
                requirements:
         | 
| 121 | 
            +
                - - "~>"
         | 
| 122 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 123 | 
            +
                    version: '1.1'
         | 
| 124 | 
            +
                - - ">="
         | 
| 125 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 126 | 
            +
                    version: 1.1.5
         | 
| 107 127 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 108 128 | 
             
              name: rake
         | 
| 109 129 | 
             
              requirement: !ruby/object:Gem::Requirement
         |