fog-aliyun 0.3.7 → 0.3.12
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/.gitignore +2 -0
- data/README.md +61 -3
- data/fog-aliyun.gemspec +7 -3
- data/lib/fog/aliyun.rb +6 -9
- data/lib/fog/aliyun/models/storage/directories.rb +34 -13
- data/lib/fog/aliyun/models/storage/directory.rb +16 -7
- data/lib/fog/aliyun/models/storage/file.rb +26 -21
- data/lib/fog/aliyun/models/storage/files.rb +104 -77
- data/lib/fog/aliyun/requests/storage/copy_object.rb +3 -5
- data/lib/fog/aliyun/requests/storage/delete_bucket.rb +3 -5
- data/lib/fog/aliyun/requests/storage/delete_container.rb +3 -5
- data/lib/fog/aliyun/requests/storage/delete_object.rb +5 -10
- data/lib/fog/aliyun/requests/storage/get_bucket.rb +43 -32
- data/lib/fog/aliyun/requests/storage/get_container.rb +2 -2
- data/lib/fog/aliyun/requests/storage/get_containers.rb +8 -3
- data/lib/fog/aliyun/requests/storage/get_object.rb +12 -25
- data/lib/fog/aliyun/requests/storage/get_object_http_url.rb +2 -2
- data/lib/fog/aliyun/requests/storage/get_object_https_url.rb +2 -2
- data/lib/fog/aliyun/requests/storage/head_object.rb +3 -5
- data/lib/fog/aliyun/requests/storage/list_buckets.rb +2 -2
- data/lib/fog/aliyun/requests/storage/list_objects.rb +23 -25
- data/lib/fog/aliyun/requests/storage/put_bucket.rb +2 -2
- data/lib/fog/aliyun/requests/storage/put_container.rb +3 -5
- data/lib/fog/aliyun/requests/storage/put_object.rb +24 -42
- data/lib/fog/aliyun/storage.rb +24 -10
- data/lib/fog/aliyun/version.rb +1 -1
- data/lib/fog/bin/aliyun.rb +1 -1
- metadata +61 -4
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: c47b8a9b6a56d553d1b0161be29b2d2444671f41f083e8af34707bd1eadc1718
         | 
| 4 | 
            +
              data.tar.gz: 17e83f9d11b7ae7b1802941ddb13427346bbd971b563d7ac04436f7d036d7ef7
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 52060f2e1a3881ccb72ccc6e5fbeddd988bd2820416c419a7409e714c6d4f08fb7b37f5f98ff1e8fc66b47c0f2aa5656349da06e939edfb0c78c4adba05bf1ef
         | 
| 7 | 
            +
              data.tar.gz: 30bdcf81e3e78e2983545d391ef2062ebc49975bee90c9d93226f30a631b3eaa7627916b179d15c684b38211bbd2e9e78e84210a2471b8185c5c3d21fbfe3001
         | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -30,9 +30,9 @@ Since it's a bad practice to have your credentials in source code, you should lo | |
| 30 30 |  | 
| 31 31 | 
             
            ```
         | 
| 32 32 | 
             
            default:
         | 
| 33 | 
            -
               | 
| 34 | 
            -
               | 
| 35 | 
            -
               | 
| 33 | 
            +
              aliyun_accesskey_id:     "<YOUR_ACCESS_KEY_ID>"
         | 
| 34 | 
            +
              aliyun_accesskey_secret: "<YOUR_SECRET_ACCESS_KEY>"
         | 
| 35 | 
            +
              aliyun_region_id:        "<YOUR_TARGET_REGION>"
         | 
| 36 36 | 
             
            ```
         | 
| 37 37 |  | 
| 38 38 | 
             
            ### Connecting to OSS
         | 
| @@ -307,6 +307,64 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run | |
| 307 307 |  | 
| 308 308 | 
             
            To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
         | 
| 309 309 |  | 
| 310 | 
            +
            ## Testing
         | 
| 311 | 
            +
             | 
| 312 | 
            +
             | 
| 313 | 
            +
             | 
| 314 | 
            +
            To run test suite use the following command:
         | 
| 315 | 
            +
             | 
| 316 | 
            +
            ```
         | 
| 317 | 
            +
            rake spec
         | 
| 318 | 
            +
            ```
         | 
| 319 | 
            +
             | 
| 320 | 
            +
            ### Code coverage
         | 
| 321 | 
            +
             | 
| 322 | 
            +
            To run test suite with code coverage:
         | 
| 323 | 
            +
             | 
| 324 | 
            +
            ```
         | 
| 325 | 
            +
            export COVERAGE=true
         | 
| 326 | 
            +
            rake spec
         | 
| 327 | 
            +
            ```
         | 
| 328 | 
            +
             | 
| 329 | 
            +
            The result will be generated in `coverage` folder.
         | 
| 330 | 
            +
             | 
| 331 | 
            +
            ### Integration tests
         | 
| 332 | 
            +
             | 
| 333 | 
            +
            To run integration tests please prepare a set of AliCloud credentials to be used by integration tests.
         | 
| 334 | 
            +
             | 
| 335 | 
            +
            Define the credentials and bucket in `~/.fog` file in using following format:
         | 
| 336 | 
            +
             | 
| 337 | 
            +
            ```
         | 
| 338 | 
            +
            default:
         | 
| 339 | 
            +
              aliyun_accesskey_id:     "...access key..." # You can create a set of credentials  
         | 
| 340 | 
            +
              aliyun_accesskey_secret: "...secret..." # using Alicloud console portal
         | 
| 341 | 
            +
              aliyun_region_id:        "...region name..." # Example: cn-shanghai
         | 
| 342 | 
            +
              aliyun_oss_bucket:       "...name of the bucket..." # Example: fog-integration-test-bucket
         | 
| 343 | 
            +
            ```
         | 
| 344 | 
            +
             | 
| 345 | 
            +
            WARNING: Do NOT use any productive account credentials and buckets for the testing, it may be harmful to your data!
         | 
| 346 | 
            +
             | 
| 347 | 
            +
            The tests are using [https://github.com/aliyun/aliyun-cli#installation](Aliyun CLI) to setup integration bucket and content for tests, 
         | 
| 348 | 
            +
            please install it locally before running integration tests.
         | 
| 349 | 
            +
             | 
| 350 | 
            +
            Aliyun CLI will be configured automatically as part of test execution using the credentials provided for fog connection.
         | 
| 351 | 
            +
             | 
| 352 | 
            +
            Then run the test suite with `INTEGRATION` environment variable to activate integration tests:
         | 
| 353 | 
            +
             | 
| 354 | 
            +
            ```
         | 
| 355 | 
            +
            export INTEGRATION=true
         | 
| 356 | 
            +
            rake spec
         | 
| 357 | 
            +
            ```
         | 
| 358 | 
            +
             | 
| 359 | 
            +
            ### Performance test
         | 
| 360 | 
            +
             | 
| 361 | 
            +
            Performance tests are providing memory consumption report for download/upload operations.
         | 
| 362 | 
            +
             | 
| 363 | 
            +
            ```
         | 
| 364 | 
            +
            export PERFORMANCE=true
         | 
| 365 | 
            +
            rake spec
         | 
| 366 | 
            +
            ```
         | 
| 367 | 
            +
             | 
| 310 368 | 
             
            ## License
         | 
| 311 369 |  | 
| 312 370 | 
             
            The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
         | 
    
        data/fog-aliyun.gemspec
    CHANGED
    
    | @@ -7,10 +7,10 @@ require 'fog/aliyun/version' | |
| 7 7 | 
             
            Gem::Specification.new do |spec|
         | 
| 8 8 | 
             
              spec.name = 'fog-aliyun'
         | 
| 9 9 | 
             
              spec.version = Fog::Aliyun::VERSION
         | 
| 10 | 
            -
              spec.authors = ['Qinsi Deng, Jianxun Li, Jane Han']
         | 
| 11 | 
            -
              spec.email = ['dengqinsi@sina.com']
         | 
| 10 | 
            +
              spec.authors = ['Qinsi Deng, Jianxun Li, Jane Han, Guimin He']
         | 
| 11 | 
            +
              spec.email = ['dengqinsi@sina.com', 'guimin.hgm@alibaba-inc.com']
         | 
| 12 12 |  | 
| 13 | 
            -
              spec.summary = 'Fog provider for  | 
| 13 | 
            +
              spec.summary = 'Fog provider for Alibaba Cloud Web Services.'
         | 
| 14 14 | 
             
              spec.description = 'As a FOG provider, fog-aliyun support aliyun OSS/ECS. It will support more aliyun services later.'
         | 
| 15 15 | 
             
              spec.homepage = 'https://github.com/fog/fog-aliyun'
         | 
| 16 16 | 
             
              spec.license = 'MIT'
         | 
| @@ -26,9 +26,13 @@ Gem::Specification.new do |spec| | |
| 26 26 | 
             
              spec.add_development_dependency 'rake'
         | 
| 27 27 | 
             
              spec.add_development_dependency 'rspec'
         | 
| 28 28 | 
             
              spec.add_development_dependency 'rubocop'
         | 
| 29 | 
            +
              spec.add_development_dependency 'simplecov'
         | 
| 30 | 
            +
              spec.add_development_dependency 'memory_profiler'
         | 
| 31 | 
            +
              spec.add_development_dependency 'aliyun-sdk'
         | 
| 29 32 |  | 
| 30 33 | 
             
              spec.add_dependency 'fog-core'
         | 
| 31 34 | 
             
              spec.add_dependency 'fog-json'
         | 
| 32 35 | 
             
              spec.add_dependency 'ipaddress', '~> 0.8'
         | 
| 33 36 | 
             
              spec.add_dependency 'xml-simple', '~> 1.1'
         | 
| 37 | 
            +
              spec.add_dependency 'aliyun-sdk'
         | 
| 34 38 | 
             
            end
         | 
    
        data/lib/fog/aliyun.rb
    CHANGED
    
    | @@ -2,19 +2,16 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            require 'fog/core'
         | 
| 4 4 | 
             
            require 'fog/json'
         | 
| 5 | 
            -
            require ' | 
| 5 | 
            +
            require File.expand_path('../aliyun/version', __FILE__)
         | 
| 6 6 |  | 
| 7 7 | 
             
            module Fog
         | 
| 8 | 
            -
              module Compute
         | 
| 9 | 
            -
                autoload :Aliyun, 'fog/aliyun/compute'
         | 
| 10 | 
            -
              end
         | 
| 11 | 
            -
             | 
| 12 | 
            -
              module Storage
         | 
| 13 | 
            -
                autoload :Aliyun, 'fog/aliyun/storage'
         | 
| 14 | 
            -
              end
         | 
| 15 | 
            -
             | 
| 16 8 | 
             
              module Aliyun
         | 
| 17 9 | 
             
                extend Fog::Provider
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                # Services
         | 
| 12 | 
            +
                autoload :Compute,          File.expand_path('../aliyun/compute', __FILE__)
         | 
| 13 | 
            +
                autoload :Storage,          File.expand_path('../aliyun/storage', __FILE__)
         | 
| 14 | 
            +
             | 
| 18 15 | 
             
                service(:compute, 'Compute')
         | 
| 19 16 | 
             
                service(:storage, 'Storage')
         | 
| 20 17 | 
             
              end
         | 
| @@ -4,10 +4,10 @@ require 'fog/core/collection' | |
| 4 4 | 
             
            require 'fog/aliyun/models/storage/directory'
         | 
| 5 5 |  | 
| 6 6 | 
             
            module Fog
         | 
| 7 | 
            -
              module  | 
| 8 | 
            -
                class  | 
| 7 | 
            +
              module Aliyun
         | 
| 8 | 
            +
                class Storage
         | 
| 9 9 | 
             
                  class Directories < Fog::Collection
         | 
| 10 | 
            -
                    model Fog::Storage:: | 
| 10 | 
            +
                    model Fog::Aliyun::Storage::Directory
         | 
| 11 11 |  | 
| 12 12 | 
             
                    def all
         | 
| 13 13 | 
             
                      containers = service.get_containers
         | 
| @@ -30,6 +30,9 @@ module Fog | |
| 30 30 | 
             
                    # If key is a directory(including /), return an existed or a new one;
         | 
| 31 31 | 
             
                    # If key does not contain /, if bucket, return '', else return an existed or a new one directory;
         | 
| 32 32 | 
             
                    def get(key, options = {})
         | 
| 33 | 
            +
                      if key.is_a? Array
         | 
| 34 | 
            +
                        key = key[0]
         | 
| 35 | 
            +
                      end
         | 
| 33 36 | 
             
                      if !key.nil? && key != '' && key != '.'
         | 
| 34 37 | 
             
                        key = key.chomp('/')
         | 
| 35 38 | 
             
                        if key.include? '/'
         | 
| @@ -37,21 +40,39 @@ module Fog | |
| 37 40 | 
             
                          ret = service.head_object(dir, options)
         | 
| 38 41 | 
             
                          new(key: key) if ret.data[:status] == 200
         | 
| 39 42 | 
             
                        else
         | 
| 40 | 
            -
                           | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
                           | 
| 48 | 
            -
             | 
| 43 | 
            +
                          remap_attributes(options, {
         | 
| 44 | 
            +
                              :delimiter  => 'delimiter',
         | 
| 45 | 
            +
                              :marker     => 'marker',
         | 
| 46 | 
            +
                              :max_keys   => 'max-keys',
         | 
| 47 | 
            +
                              :prefix     => 'prefix'
         | 
| 48 | 
            +
                          })
         | 
| 49 | 
            +
                          data = service.get_bucket(key, options)
         | 
| 50 | 
            +
                          directory = new(:key => data['Name'], :is_persisted => true)
         | 
| 51 | 
            +
                          options = {}
         | 
| 52 | 
            +
                          for k, v in data
         | 
| 53 | 
            +
                            if ['CommonPrefixes', 'Delimiter', 'IsTruncated', 'Marker', 'MaxKeys', 'Prefix'].include?(k)
         | 
| 54 | 
            +
                              # Sometimes, the v will be a Array, like "Name"=>["blobstore-droplet1"], "Prefix"=>[{}], "Marker"=>[{}], "MaxKeys"=>["100"], "Delimiter"=>[{}], "IsTruncated"=>["false"]
         | 
| 55 | 
            +
                              # and there needs to parse them
         | 
| 56 | 
            +
                              if !v.nil? && (v.is_a? Array) && (v.size > 0)
         | 
| 57 | 
            +
                                if v[0].is_a? Hash
         | 
| 58 | 
            +
                                  v = nil
         | 
| 59 | 
            +
                                else
         | 
| 60 | 
            +
                                  v = v[0]
         | 
| 61 | 
            +
                                end
         | 
| 62 | 
            +
                              end
         | 
| 63 | 
            +
                              options[k] = v
         | 
| 64 | 
            +
                            end
         | 
| 65 | 
            +
                          end
         | 
| 66 | 
            +
                          directory.files.merge_attributes(options)
         | 
| 67 | 
            +
                          if data.key?('Contents') && !data['Contents'].nil?
         | 
| 68 | 
            +
                            directory.files.load(data['Contents'])
         | 
| 49 69 | 
             
                          end
         | 
| 70 | 
            +
                          directory
         | 
| 50 71 | 
             
                        end
         | 
| 51 72 | 
             
                      else
         | 
| 52 73 | 
             
                        new(key: '')
         | 
| 53 74 | 
             
                      end
         | 
| 54 | 
            -
                    rescue Fog::Storage:: | 
| 75 | 
            +
                    rescue Fog::Aliyun::Storage::NotFound
         | 
| 55 76 | 
             
                      nil
         | 
| 56 77 | 
             
                    end
         | 
| 57 78 | 
             
                  end
         | 
| @@ -4,10 +4,10 @@ require 'fog/core/model' | |
| 4 4 | 
             
            require 'fog/aliyun/models/storage/files'
         | 
| 5 5 |  | 
| 6 6 | 
             
            module Fog
         | 
| 7 | 
            -
              module  | 
| 8 | 
            -
                class  | 
| 7 | 
            +
              module Aliyun
         | 
| 8 | 
            +
                class Storage
         | 
| 9 9 | 
             
                  class Directory < Fog::Model
         | 
| 10 | 
            -
                    identity :key
         | 
| 10 | 
            +
                    identity :key, :aliases => ['Key', 'Name', 'name']
         | 
| 11 11 |  | 
| 12 12 | 
             
                    def destroy
         | 
| 13 13 | 
             
                      requires :key
         | 
| @@ -15,20 +15,19 @@ module Fog | |
| 15 15 | 
             
                      ret = service.list_objects(prefix: prefix)['Contents']
         | 
| 16 16 |  | 
| 17 17 | 
             
                      if ret.nil?
         | 
| 18 | 
            -
                        puts ' Not found: Direction not exist!'
         | 
| 19 18 | 
             
                        false
         | 
| 20 19 | 
             
                      elsif ret.size == 1
         | 
| 21 20 | 
             
                        service.delete_container(key)
         | 
| 22 21 | 
             
                        true
         | 
| 23 22 | 
             
                      else
         | 
| 24 | 
            -
                        raise Fog::Storage:: | 
| 23 | 
            +
                        raise Fog::Aliyun::Storage::Error, ' Forbidden: Direction not empty!'
         | 
| 25 24 | 
             
                        false
         | 
| 26 25 | 
             
                      end
         | 
| 27 26 | 
             
                    end
         | 
| 28 27 |  | 
| 29 28 | 
             
                    def files
         | 
| 30 29 | 
             
                      @files ||= begin
         | 
| 31 | 
            -
                        Fog::Storage:: | 
| 30 | 
            +
                        Fog::Aliyun::Storage::Files.new(
         | 
| 32 31 | 
             
                          directory: self,
         | 
| 33 32 | 
             
                          service: service
         | 
| 34 33 | 
             
                        )
         | 
| @@ -41,7 +40,17 @@ module Fog | |
| 41 40 |  | 
| 42 41 | 
             
                    def save
         | 
| 43 42 | 
             
                      requires :key
         | 
| 44 | 
            -
             | 
| 43 | 
            +
             | 
| 44 | 
            +
                      # Checking whether the key is a bucket and meet the multi-bucket scenario.
         | 
| 45 | 
            +
                      # If the key is a existing bucket, return it directly.
         | 
| 46 | 
            +
                      key = key.chomp('/')
         | 
| 47 | 
            +
                      if !key.nil? && key != '' && key != '.' && !(key.include? '/')
         | 
| 48 | 
            +
                        data = service.get_bucket(key)
         | 
| 49 | 
            +
                        if data.class == Hash && data.key?('Code') && !data['Code'].nil? && !data['Code'].empty?
         | 
| 50 | 
            +
                          service.put_container(key)
         | 
| 51 | 
            +
                        end
         | 
| 52 | 
            +
                      end
         | 
| 53 | 
            +
             | 
| 45 54 | 
             
                      true
         | 
| 46 55 | 
             
                    end
         | 
| 47 56 | 
             
                  end
         | 
| @@ -3,10 +3,10 @@ | |
| 3 3 | 
             
            require 'fog/core/model'
         | 
| 4 4 |  | 
| 5 5 | 
             
            module Fog
         | 
| 6 | 
            -
              module  | 
| 7 | 
            -
                class  | 
| 6 | 
            +
              module Aliyun
         | 
| 7 | 
            +
                class Storage
         | 
| 8 8 | 
             
                  class File < Fog::Model
         | 
| 9 | 
            -
                    identity :key, aliases: 'name'
         | 
| 9 | 
            +
                    identity :key, aliases: ['Key', 'Name', 'name']
         | 
| 10 10 | 
             
                    attribute :date, aliases: 'Date'
         | 
| 11 11 | 
             
                    attribute :content_length, aliases: 'Content-Length', type: :integer
         | 
| 12 12 | 
             
                    attribute :content_type, aliases: 'Content-Type'
         | 
| @@ -35,29 +35,32 @@ module Fog | |
| 35 35 |  | 
| 36 36 | 
             
                    def copy(target_directory_key, target_file_key, options = {})
         | 
| 37 37 | 
             
                      requires :directory, :key
         | 
| 38 | 
            -
                       | 
| 38 | 
            +
                      source_bucket, directory_key = collection.check_directory_key(directory.key)
         | 
| 39 | 
            +
                      source_object = if directory_key == ''
         | 
| 39 40 | 
             
                                        key
         | 
| 40 41 | 
             
                                      else
         | 
| 41 | 
            -
                                         | 
| 42 | 
            +
                                        directory_key + '/' + key
         | 
| 42 43 | 
             
                                      end
         | 
| 44 | 
            +
                      target_bucket, target_directory_key = collection.check_directory_key(target_directory_key)
         | 
| 43 45 | 
             
                      target_object = if target_directory_key == ''
         | 
| 44 46 | 
             
                                        target_file_key
         | 
| 45 47 | 
             
                                      else
         | 
| 46 48 | 
             
                                        target_directory_key + '/' + target_file_key
         | 
| 47 49 | 
             
                                      end
         | 
| 48 | 
            -
                      service.copy_object( | 
| 50 | 
            +
                      service.copy_object(source_bucket, source_object, target_bucket, target_object, options)
         | 
| 49 51 | 
             
                      target_directory = service.directories.new(key: target_directory_key)
         | 
| 50 52 | 
             
                      target_directory.files.get(target_file_key)
         | 
| 51 53 | 
             
                    end
         | 
| 52 54 |  | 
| 53 55 | 
             
                    def destroy
         | 
| 54 56 | 
             
                      requires :directory, :key
         | 
| 55 | 
            -
                       | 
| 57 | 
            +
                      bucket_name, directory_key = collection.check_directory_key(directory.key)
         | 
| 58 | 
            +
                      object = if directory_key == ''
         | 
| 56 59 | 
             
                                 key
         | 
| 57 60 | 
             
                               else
         | 
| 58 | 
            -
                                  | 
| 61 | 
            +
                                 directory_key + '/' + key
         | 
| 59 62 | 
             
                               end
         | 
| 60 | 
            -
                      service.delete_object(object)
         | 
| 63 | 
            +
                      service.delete_object(object, bucket: bucket_name)
         | 
| 61 64 | 
             
                      true
         | 
| 62 65 | 
             
                    end
         | 
| 63 66 |  | 
| @@ -91,12 +94,13 @@ module Fog | |
| 91 94 | 
             
                      expires = expires.nil? ? 0 : expires.to_i
         | 
| 92 95 |  | 
| 93 96 | 
             
                      requires :directory, :key
         | 
| 94 | 
            -
                       | 
| 97 | 
            +
                      bucket_name, directory_key = collection.check_directory_key(directory.key)
         | 
| 98 | 
            +
                      object = if directory_key == ''
         | 
| 95 99 | 
             
                                 key
         | 
| 96 100 | 
             
                               else
         | 
| 97 | 
            -
                                  | 
| 101 | 
            +
                                 directory_key + '/' + key
         | 
| 98 102 | 
             
                               end
         | 
| 99 | 
            -
                      service.get_object_http_url_public(object, expires, options)
         | 
| 103 | 
            +
                      service.get_object_http_url_public(object, expires, options.merge(bucket: bucket_name))
         | 
| 100 104 | 
             
                    end
         | 
| 101 105 |  | 
| 102 106 | 
             
                    def public_url
         | 
| @@ -109,18 +113,18 @@ module Fog | |
| 109 113 | 
             
                      options['Content-Type'] = content_type if content_type
         | 
| 110 114 | 
             
                      options['Content-Disposition'] = content_disposition if content_disposition
         | 
| 111 115 | 
             
                      options.merge!(metadata_to_headers)
         | 
| 112 | 
            -
             | 
| 113 | 
            -
                      object = if  | 
| 116 | 
            +
                      bucket_name, directory_key = collection.check_directory_key(directory.key)
         | 
| 117 | 
            +
                      object = if directory_key == ''
         | 
| 114 118 | 
             
                                 key
         | 
| 115 119 | 
             
                               else
         | 
| 116 | 
            -
                                  | 
| 120 | 
            +
                                 directory_key + '/' + key
         | 
| 117 121 | 
             
                               end
         | 
| 118 122 | 
             
                      if body.is_a?(::File)
         | 
| 119 | 
            -
                        data = service.put_object(object, body, options).data
         | 
| 123 | 
            +
                        data = service.put_object(object, body, options.merge(bucket: bucket_name)).data
         | 
| 120 124 | 
             
                      elsif body.is_a?(String)
         | 
| 121 | 
            -
                        data = service.put_object_with_body(object, body, options).data
         | 
| 125 | 
            +
                        data = service.put_object_with_body(object, body, options.merge(bucket: bucket_name)).data
         | 
| 122 126 | 
             
                      else
         | 
| 123 | 
            -
                        raise Fog::Storage:: | 
| 127 | 
            +
                        raise Fog::Aliyun::Storage::Error, " Forbidden: Invalid body type: #{body.class}!"
         | 
| 124 128 | 
             
                      end
         | 
| 125 129 | 
             
                      update_attributes_from(data)
         | 
| 126 130 | 
             
                      refresh_metadata
         | 
| @@ -168,13 +172,14 @@ module Fog | |
| 168 172 |  | 
| 169 173 | 
             
                    def metadata_attributes
         | 
| 170 174 | 
             
                      if last_modified
         | 
| 171 | 
            -
                         | 
| 175 | 
            +
                        bucket_name, directory_key = collection.check_directory_key(directory.key)
         | 
| 176 | 
            +
                        object = if directory_key == ''
         | 
| 172 177 | 
             
                                   key
         | 
| 173 178 | 
             
                                 else
         | 
| 174 | 
            -
                                    | 
| 179 | 
            +
                                   directory_key + '/' + key
         | 
| 175 180 | 
             
                                 end
         | 
| 176 181 |  | 
| 177 | 
            -
                        data = service.head_object(object).data
         | 
| 182 | 
            +
                        data = service.head_object(object, bucket: bucket_name).data
         | 
| 178 183 | 
             
                        if data[:status] == 200
         | 
| 179 184 | 
             
                          headers = data[:headers]
         | 
| 180 185 | 
             
                          headers.select! { |k, _v| metadata_attribute?(k) }
         | 
| @@ -2,23 +2,67 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            require 'fog/core/collection'
         | 
| 4 4 | 
             
            require 'fog/aliyun/models/storage/file'
         | 
| 5 | 
            +
            require 'aliyun/oss'
         | 
| 5 6 |  | 
| 6 7 | 
             
            module Fog
         | 
| 7 | 
            -
              module  | 
| 8 | 
            -
                class  | 
| 8 | 
            +
              module Aliyun
         | 
| 9 | 
            +
                class Storage
         | 
| 9 10 | 
             
                  class Files < Fog::Collection
         | 
| 10 11 | 
             
                    attribute :directory
         | 
| 11 12 | 
             
                    attribute :limit
         | 
| 12 | 
            -
                    attribute : | 
| 13 | 
            +
                    attribute :prefix,          :aliases => 'Prefix'
         | 
| 13 14 | 
             
                    attribute :path
         | 
| 14 | 
            -
                    attribute : | 
| 15 | 
            -
             | 
| 16 | 
            -
                     | 
| 15 | 
            +
                    attribute :common_prefixes, :aliases => 'CommonPrefixes'
         | 
| 16 | 
            +
                    attribute :delimiter,       :aliases => 'Delimiter'
         | 
| 17 | 
            +
                    attribute :is_truncated,    :aliases => 'IsTruncated'
         | 
| 18 | 
            +
                    attribute :marker,          :aliases => 'Marker'
         | 
| 19 | 
            +
                    attribute :max_keys,        :aliases => ['MaxKeys', 'max-keys']
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                    model Fog::Aliyun::Storage::File
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                    # check_directory_key have two functions:
         | 
| 24 | 
            +
                    # 1. trim the directory_key suffix '/'
         | 
| 25 | 
            +
                    # 2. checking whether the directory_key is a bucket.
         | 
| 26 | 
            +
                    #    If so, it will return directly to avoid to create a new redundant folder named with directory_key.
         | 
| 27 | 
            +
                    #    This point will be applied to multi-bucket and make bucket as a directory scenario.
         | 
| 28 | 
            +
                    def check_directory_key(directory_key)
         | 
| 29 | 
            +
                      bucket_name = nil
         | 
| 30 | 
            +
                      if directory_key.is_a? Array
         | 
| 31 | 
            +
                        directory_key = directory_key[0]
         | 
| 32 | 
            +
                      end
         | 
| 33 | 
            +
                      if directory_key != ''
         | 
| 34 | 
            +
                        # trim the suffix '/'
         | 
| 35 | 
            +
                        directory_key = directory_key.chomp('/')
         | 
| 36 | 
            +
                        # The bucket name can not contain '/', so if directory_key, return directory.
         | 
| 37 | 
            +
                        if directory_key.include? '/'
         | 
| 38 | 
            +
                          directory_key
         | 
| 39 | 
            +
                        else
         | 
| 40 | 
            +
                          data = service.get_bucket(directory_key)
         | 
| 41 | 
            +
                          if data.class == Hash && data.key?('Code') && !data['Code'].nil? && !data['Code'].empty?
         | 
| 42 | 
            +
                            directory_key
         | 
| 43 | 
            +
                          else
         | 
| 44 | 
            +
                            bucket_name = directory_key
         | 
| 45 | 
            +
                            directory_key = ''
         | 
| 46 | 
            +
                          end
         | 
| 47 | 
            +
                        end
         | 
| 48 | 
            +
                      end
         | 
| 49 | 
            +
                      return bucket_name, directory_key
         | 
| 50 | 
            +
                    end
         | 
| 17 51 |  | 
| 18 | 
            -
                    def all( | 
| 52 | 
            +
                    def all(options = {})
         | 
| 19 53 | 
             
                      requires :directory
         | 
| 20 | 
            -
                       | 
| 21 | 
            -
                       | 
| 54 | 
            +
                      bucket_name, directory_key = check_directory_key(directory.key)
         | 
| 55 | 
            +
                      remap_attributes(options, {
         | 
| 56 | 
            +
                          :delimiter  => 'delimiter',
         | 
| 57 | 
            +
                          :marker     => 'marker',
         | 
| 58 | 
            +
                          :max_keys   => 'max-keys',
         | 
| 59 | 
            +
                          :prefix     => 'prefix'
         | 
| 60 | 
            +
                      })
         | 
| 61 | 
            +
                      prefix_value = options['prefix']
         | 
| 62 | 
            +
                      prefix_value = directory_key + '/' + prefix if directory_key != '' && directory_key != '.' && !directory_key.nil?
         | 
| 63 | 
            +
                      options['prefix'] = prefix_value
         | 
| 64 | 
            +
                      options['bucket'] = bucket_name
         | 
| 65 | 
            +
                      files = service.list_objects(options)['Contents']
         | 
| 22 66 | 
             
                      return if files.nil?
         | 
| 23 67 | 
             
                      data = []
         | 
| 24 68 | 
             
                      i = 0
         | 
| @@ -59,112 +103,88 @@ module Fog | |
| 59 103 |  | 
| 60 104 | 
             
                    def get(key)
         | 
| 61 105 | 
             
                      requires :directory
         | 
| 62 | 
            -
                       | 
| 106 | 
            +
                      bucket_name, directory_key = check_directory_key(directory.key)
         | 
| 107 | 
            +
                      object = if directory_key == ''
         | 
| 63 108 | 
             
                                 key
         | 
| 64 109 | 
             
                               else
         | 
| 65 | 
            -
                                  | 
| 110 | 
            +
                                 directory_key + '/' + key
         | 
| 66 111 | 
             
                               end
         | 
| 67 112 | 
             
                      begin
         | 
| 68 | 
            -
                        data = service.get_object(object)
         | 
| 69 | 
            -
             | 
| 70 | 
            -
                         | 
| 71 | 
            -
             | 
| 113 | 
            +
                        data = service.get_object(object, nil, bucket: bucket_name)
         | 
| 114 | 
            +
                        lastModified = data['headers'][:last_modified]
         | 
| 115 | 
            +
                        last_modified = (Time.parse(lastModified).localtime if !lastModified.nil? && lastModified != '')
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                        date = data['headers'][:date]
         | 
| 118 | 
            +
                        date = (Time.parse(date).localtime if !date.nil? && date != '')
         | 
| 119 | 
            +
                        file_data = {
         | 
| 120 | 
            +
                            body: data[:body],
         | 
| 121 | 
            +
                            content_length: data['headers'][:content_length].to_i,
         | 
| 122 | 
            +
                            key: key,
         | 
| 123 | 
            +
                            last_modified: last_modified,
         | 
| 124 | 
            +
                            content_type: data['headers'][:content_type],
         | 
| 125 | 
            +
                            etag: data['headers'][:etag],
         | 
| 126 | 
            +
                            date: date,
         | 
| 127 | 
            +
                            connection: data['headers'][:connection],
         | 
| 128 | 
            +
                            accept_ranges: data['headers'][:accept_ranges],
         | 
| 129 | 
            +
                            server: data['headers'][:server],
         | 
| 130 | 
            +
                            object_type: data['headers'][:x_oss_object_type]
         | 
| 131 | 
            +
                        }
         | 
| 132 | 
            +
             | 
| 133 | 
            +
                        new(file_data)
         | 
| 134 | 
            +
                      rescue AliyunOssSdk::ServerError => error
         | 
| 135 | 
            +
                        case error.error_code
         | 
| 136 | 
            +
                        when %r{NoSuchKey},%r{SymlinkTargetNotExist}
         | 
| 72 137 | 
             
                          nil
         | 
| 73 138 | 
             
                        else
         | 
| 74 139 | 
             
                          raise(error)
         | 
| 75 140 | 
             
                        end
         | 
| 76 141 | 
             
                      end
         | 
| 77 | 
            -
             | 
| 78 | 
            -
                      contentLen = data[:headers]['Content-Length'].to_i
         | 
| 79 | 
            -
             | 
| 80 | 
            -
                      if block_given?
         | 
| 81 | 
            -
                        pagesNum = (contentLen + Excon::CHUNK_SIZE - 1) / Excon::CHUNK_SIZE
         | 
| 82 | 
            -
             | 
| 83 | 
            -
                        for i in 1..pagesNum
         | 
| 84 | 
            -
                          _start = (i - 1) * Excon::CHUNK_SIZE
         | 
| 85 | 
            -
                          _end = i * Excon::CHUNK_SIZE - 1
         | 
| 86 | 
            -
                          range = "#{_start}-#{_end}"
         | 
| 87 | 
            -
                          begin
         | 
| 88 | 
            -
                            data = service.get_object(object, range)
         | 
| 89 | 
            -
                            chunk = data[:body]
         | 
| 90 | 
            -
                          rescue StandardError => error
         | 
| 91 | 
            -
                            case error.response.body
         | 
| 92 | 
            -
                              when %r{<Code>NoSuchKey</Code>},%r{<Code>SymlinkTargetNotExist</Code>}
         | 
| 93 | 
            -
                                chunk = ''
         | 
| 94 | 
            -
                              else
         | 
| 95 | 
            -
                                raise(error)
         | 
| 96 | 
            -
                            end
         | 
| 97 | 
            -
                          end
         | 
| 98 | 
            -
                          yield(chunk)
         | 
| 99 | 
            -
                          body = nil
         | 
| 100 | 
            -
                        end
         | 
| 101 | 
            -
                      else
         | 
| 102 | 
            -
                        body = data[:body]
         | 
| 103 | 
            -
                      end
         | 
| 104 | 
            -
             | 
| 105 | 
            -
                      lastModified = data[:headers]['Last-Modified']
         | 
| 106 | 
            -
                      last_modified = (Time.parse(lastModified).localtime if !lastModified.nil? && lastModified != '')
         | 
| 107 | 
            -
             | 
| 108 | 
            -
                      date = data[:headers]['Date']
         | 
| 109 | 
            -
                      date = (Time.parse(date).localtime if !date.nil? && date != '')
         | 
| 110 | 
            -
                      file_data = {
         | 
| 111 | 
            -
                        body: body,
         | 
| 112 | 
            -
                        content_length: contentLen,
         | 
| 113 | 
            -
                        key: key,
         | 
| 114 | 
            -
                        last_modified: last_modified,
         | 
| 115 | 
            -
                        content_type: data[:headers]['Content-Type'],
         | 
| 116 | 
            -
                        etag: data[:headers]['ETag'],
         | 
| 117 | 
            -
                        date: date,
         | 
| 118 | 
            -
                        connection: data[:headers]['Connection'],
         | 
| 119 | 
            -
                        accept_ranges: data[:headers]['Accept-Ranges'],
         | 
| 120 | 
            -
                        server: data[:headers]['Server'],
         | 
| 121 | 
            -
                        object_type: data[:headers]['x-oss-object-type'],
         | 
| 122 | 
            -
                        content_disposition: data[:headers]['Content-Disposition']
         | 
| 123 | 
            -
                      }
         | 
| 124 | 
            -
             | 
| 125 | 
            -
                      new(file_data)
         | 
| 126 142 | 
             
                    end
         | 
| 127 143 |  | 
| 128 144 | 
             
                    def get_url(key)
         | 
| 129 145 | 
             
                      requires :directory
         | 
| 130 | 
            -
                       | 
| 146 | 
            +
                      bucket_name, directory_key = check_directory_key(directory.key)
         | 
| 147 | 
            +
                      object = if directory_key == ''
         | 
| 131 148 | 
             
                                 key
         | 
| 132 149 | 
             
                               else
         | 
| 133 | 
            -
                                  | 
| 150 | 
            +
                                 directory_key + '/' + key
         | 
| 134 151 | 
             
                               end
         | 
| 135 | 
            -
                      service.get_object_http_url_public(object, 3600)
         | 
| 152 | 
            +
                      service.get_object_http_url_public(object, 3600, bucket: bucket_name)
         | 
| 136 153 | 
             
                    end
         | 
| 137 154 |  | 
| 138 155 | 
             
                    def get_http_url(key, expires, options = {})
         | 
| 139 156 | 
             
                      requires :directory
         | 
| 140 | 
            -
                       | 
| 157 | 
            +
                      bucket_name, directory_key = check_directory_key(directory.key)
         | 
| 158 | 
            +
                      object = if directory_key == ''
         | 
| 141 159 | 
             
                                 key
         | 
| 142 160 | 
             
                               else
         | 
| 143 | 
            -
                                  | 
| 161 | 
            +
                                 directory_key + '/' + key
         | 
| 144 162 | 
             
                               end
         | 
| 145 163 | 
             
                      expires = expires.nil? ? 0 : expires.to_i
         | 
| 146 | 
            -
                      service.get_object_http_url_public(object, expires, options)
         | 
| 164 | 
            +
                      service.get_object_http_url_public(object, expires, options.merge(bucket: bucket_name))
         | 
| 147 165 | 
             
                    end
         | 
| 148 166 |  | 
| 149 167 | 
             
                    def get_https_url(key, expires, options = {})
         | 
| 150 168 | 
             
                      requires :directory
         | 
| 151 | 
            -
                       | 
| 169 | 
            +
                      bucket_name, directory_key = check_directory_key(directory.key)
         | 
| 170 | 
            +
                      object = if directory_key == ''
         | 
| 152 171 | 
             
                                 key
         | 
| 153 172 | 
             
                               else
         | 
| 154 | 
            -
                                  | 
| 173 | 
            +
                                 directory_key + '/' + key
         | 
| 155 174 | 
             
                               end
         | 
| 156 175 | 
             
                      expires = expires.nil? ? 0 : expires.to_i
         | 
| 157 | 
            -
                      service.get_object_https_url_public(object, expires, options)
         | 
| 176 | 
            +
                      service.get_object_https_url_public(object, expires, options.merge(bucket: bucket_name))
         | 
| 158 177 | 
             
                    end
         | 
| 159 178 |  | 
| 160 179 | 
             
                    def head(key, _options = {})
         | 
| 161 180 | 
             
                      requires :directory
         | 
| 162 | 
            -
                       | 
| 181 | 
            +
                      bucket_name, directory_key = check_directory_key(directory.key)
         | 
| 182 | 
            +
                      object = if directory_key == ''
         | 
| 163 183 | 
             
                                 key
         | 
| 164 184 | 
             
                               else
         | 
| 165 | 
            -
                                  | 
| 185 | 
            +
                                 directory_key + '/' + key
         | 
| 166 186 | 
             
                               end
         | 
| 167 | 
            -
                      data = service.head_object(object).data
         | 
| 187 | 
            +
                      data = service.head_object(object, bucket: bucket_name).data
         | 
| 168 188 | 
             
                      return nil if data[:status] == 404
         | 
| 169 189 | 
             
                      lastModified = data[:headers]['Last-Modified']
         | 
| 170 190 | 
             
                      last_modified = (Time.parse(lastModified).localtime if !lastModified.nil? && lastModified != '')
         | 
| @@ -185,12 +205,19 @@ module Fog | |
| 185 205 | 
             
                        object_type: data[:headers]['x-oss-object-type']
         | 
| 186 206 | 
             
                      }
         | 
| 187 207 | 
             
                      new(file_data)
         | 
| 188 | 
            -
                    rescue Fog::Storage:: | 
| 208 | 
            +
                    rescue Fog::Aliyun::Storage::NotFound
         | 
| 189 209 | 
             
                      nil
         | 
| 190 210 | 
             
                    end
         | 
| 191 211 |  | 
| 192 212 | 
             
                    def new(attributes = {})
         | 
| 193 213 | 
             
                      requires :directory
         | 
| 214 | 
            +
                      # Sometimes, the v will be a Array, like "Prefix"=>[{}], "Marker"=>[xxxx], "MaxKeys"=>["100"], "IsTruncated"=>["false"]
         | 
| 215 | 
            +
                      # and there needs to parse them
         | 
| 216 | 
            +
                      for k, v in attributes
         | 
| 217 | 
            +
                        if !v.nil? && (v.is_a? Array) && (v.size > 0)
         | 
| 218 | 
            +
                          attributes[k] = v[0]
         | 
| 219 | 
            +
                        end
         | 
| 220 | 
            +
                      end
         | 
| 194 221 | 
             
                      super({ directory: directory }.merge!(attributes))
         | 
| 195 222 | 
             
                    end
         | 
| 196 223 | 
             
                  end
         |