Class: Fog::AWS::S3::Mock

Inherits:
Object
  • Object
show all
Defined in:
lib/fog/aws/s3.rb,
lib/fog/aws/models/s3/directories.rb,
lib/fog/aws/requests/s3/get_bucket.rb,
lib/fog/aws/requests/s3/get_object.rb,
lib/fog/aws/requests/s3/put_bucket.rb,
lib/fog/aws/requests/s3/put_object.rb,
lib/fog/aws/requests/s3/copy_object.rb,
lib/fog/aws/requests/s3/get_service.rb,
lib/fog/aws/requests/s3/head_object.rb,
lib/fog/aws/requests/s3/delete_bucket.rb,
lib/fog/aws/requests/s3/delete_object.rb,
lib/fog/aws/requests/s3/get_bucket_location.rb,
lib/fog/aws/requests/s3/get_request_payment.rb,
lib/fog/aws/requests/s3/put_request_payment.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Mock

Returns a new instance of Mock.


72
73
74
75
# File 'lib/fog/aws/s3.rb', line 72

def initialize(options={})
  @aws_access_key_id = options[:aws_access_key_id]
  @data = self.class.data[@aws_access_key_id]
end

Class Method Details

.dataObject


58
59
60
61
62
63
64
# File 'lib/fog/aws/s3.rb', line 58

def self.data
  @data ||= Hash.new do |hash, key|
    hash[key] = {
      :buckets => {}
    }
  end
end

.reset_data(keys = data.keys) ⇒ Object


66
67
68
69
70
# File 'lib/fog/aws/s3.rb', line 66

def self.reset_data(keys=data.keys)
  for key in [*keys]
    data.delete(key)
  end
end

Instance Method Details

#copy_object(source_bucket_name, source_object_name, target_bucket_name, target_object_name, options = {}) ⇒ Object


45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/fog/aws/requests/s3/copy_object.rb', line 45

def copy_object(source_bucket_name, source_object_name, target_bucket_name, target_object_name, options = {})
  response = Excon::Response.new
  source_bucket = @data[:buckets][source_bucket_name]
  source_object = source_bucket && source_bucket[:objects][source_object_name]
  target_bucket = @data[:buckets][target_bucket_name]

  if source_object && target_bucket
    response.status = 200
    target_object = source_object.dup
    target_object.merge!({
      'Name' => target_object_name
    })
    target_bucket[:objects][target_object_name] = target_object
    response.body = {
      'ETag'          => target_object['ETag'],
      'LastModified'  => Time.parse(target_object['LastModified'])
    }
  else
    response.status = 404
    raise(Excon::Errors.status_error({:expects => 200}, response))
  end

  response
end

#delete_bucket(bucket_name) ⇒ Object


27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/fog/aws/requests/s3/delete_bucket.rb', line 27

def delete_bucket(bucket_name)
  response = Excon::Response.new
  if @data[:buckets][bucket_name].nil?
    response.status = 404
    raise(Excon::Errors.status_error({:expects => 204}, response))
  elsif @data[:buckets][bucket_name] && !@data[:buckets][bucket_name][:objects].empty?
    response.status = 409
    raise(Excon::Errors.status_error({:expects => 204}, response))
  else
    @data[:buckets].delete(bucket_name)
    response.status = 204
  end
  response
end

#delete_object(bucket_name, object_name) ⇒ Object


30
31
32
33
34
35
36
37
38
39
40
# File 'lib/fog/aws/requests/s3/delete_object.rb', line 30

def delete_object(bucket_name, object_name)
  response = Excon::Response.new
  if bucket = @data[:buckets][bucket_name]
    response.status = 204
    bucket[:objects].delete(object_name)
  else
    response.status = 404
    raise(Excon::Errors.status_error({:expects => 204}, response))
  end
  response
end

#directoriesObject


15
16
17
# File 'lib/fog/aws/models/s3/directories.rb', line 15

def directories
  Fog::AWS::S3::Directories.new(:connection => self)
end

#get_bucket(bucket_name, options = {}) ⇒ Object

FIXME: implement delimiter


63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/fog/aws/requests/s3/get_bucket.rb', line 63

def get_bucket(bucket_name, options = {})
  unless bucket_name
    raise ArgumentError.new('bucket_name is required')
  end
  response = Excon::Response.new
  if bucket = @data[:buckets][bucket_name]
    response.status = 200
    response.body = {
      'Contents' => bucket[:objects].values.sort {|x,y| x['Key'] <=> y['Key']}.reject do |object|
          (options['prefix'] && object['Key'][0...options['prefix'].length] != options['prefix']) ||
          (options['marker'] && object['Key'] <= options['marker'])
        end.map do |object|
          data = object.reject {|key, value| !['ETag', 'Key', 'LastModified', 'Size', 'StorageClass'].include?(key)}
          data.merge!({
            'LastModified' => Time.parse(data['LastModified']),
            'Owner'        => bucket['Owner'],
            'Size'         => data['Size'].to_i
          })
        data
      end,
      'IsTruncated' => false,
      'Marker'      => options['marker'] || '',
      'MaxKeys'     => options['max-keys'] || 1000,
      'Name'        => bucket['Name'],
      'Prefix'      => options['prefix'] || ''
    }
    if options['max-keys'] && options['max-keys'] < response.body['Contents'].length
        response.body['IsTruncated'] = true
        response.body['Contents'] = response.body['Contents'][0...options['max-keys']]
    end
  else
    response.status = 404
    raise(Excon::Errors.status_error({:expects => 200}, response))
  end
  response
end

#get_bucket_location(bucket_name) ⇒ Object


33
34
35
36
37
38
39
40
41
42
43
# File 'lib/fog/aws/requests/s3/get_bucket_location.rb', line 33

def get_bucket_location(bucket_name)
  response = Excon::Response.new
  if bucket = @data[:buckets][bucket_name]
    response.status = 200
    response.body = {'LocationConstraint' => bucket['LocationConstraint'] }
  else
    response.status = 404
    raise(Excon::Errors.status_error({:expects => 200}, response))
  end
  response
end

#get_object(bucket_name, object_name, options = {}, &block) ⇒ Object


66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/fog/aws/requests/s3/get_object.rb', line 66

def get_object(bucket_name, object_name, options = {}, &block)
  unless bucket_name
    raise ArgumentError.new('bucket_name is required')
  end
  unless object_name
    raise ArgumentError.new('object_name is required')
  end
  response = Excon::Response.new
  if (bucket = @data[:buckets][bucket_name]) && (object = bucket[:objects][object_name])
    if options['If-Match'] && options['If-Match'] != object['ETag']
      response.status = 412
    elsif options['If-Modified-Since'] && options['If-Modified-Since'] > Time.parse(object['LastModified'])
      response.status = 304
    elsif options['If-None-Match'] && options['If-None-Match'] == object['ETag']
      response.status = 304
    elsif options['If-Unmodified-Since'] && options['If-Unmodified-Since'] < Time.parse(object['LastModified'])
      response.status = 412
    else
      response.status = 200
      response.headers = {
        'Content-Length'  => object['Size'],
        'Content-Type'    => object['Content-Type'],
        'ETag'            => object['ETag'],
        'Last-Modified'   => object['LastModified']
      }
      unless block_given?
        response.body = object[:body]
      else
        data = StringIO.new(object[:body])
        remaining = data.length
        while remaining > 0
          chunk = data.read([remaining, Excon::CHUNK_SIZE].min)
          block.call(chunk)
          remaining -= Excon::CHUNK_SIZE
        end
      end
    end
  else
    response.status = 404
    raise(Excon::Errors.status_error({:expects => 200}, response))
  end
  response
end

#get_object_url(bucket_name, object_name, expires) ⇒ Object

Raises:


110
111
112
# File 'lib/fog/aws/requests/s3/get_object.rb', line 110

def get_object_url(bucket_name, object_name, expires)
  raise MockNotImplemented.new("Contributions welcome!")
end

#get_request_payment(bucket_name) ⇒ Object


33
34
35
36
37
38
39
40
41
42
43
# File 'lib/fog/aws/requests/s3/get_request_payment.rb', line 33

def get_request_payment(bucket_name)
  response = Excon::Response.new
  if bucket = @data[:buckets][bucket_name]
    response.status = 200
    response.body = { 'Payer' => bucket['Payer'] }
  else
    response.status = 404
    raise(Excon::Errors.status_error({:expects => 200}, response))
  end
  response
end

#get_serviceObject


35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/fog/aws/requests/s3/get_service.rb', line 35

def get_service
  response = Excon::Response.new
  response.headers['Status'] = 200
  buckets = @data[:buckets].values.map do |bucket|
    bucket.reject do |key, value|
      !['CreationDate', 'Name'].include?(key)
    end
  end
  response.body = {
    'Buckets' => buckets,
    'Owner'   => { 'DisplayName' => 'owner', 'ID' => 'some_id'}
  }
  response
end

#head_object(bucket_name, object_name, options = {}) ⇒ Object


44
45
46
47
48
# File 'lib/fog/aws/requests/s3/head_object.rb', line 44

def head_object(bucket_name, object_name, options = {})
  response = get_object(bucket_name, object_name, options)
  response.body = nil
  response
end

#put_bucket(bucket_name, options = {}) ⇒ Object


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/fog/aws/requests/s3/put_bucket.rb', line 41

def put_bucket(bucket_name, options = {})
  response = Excon::Response.new
  response.status = 200
  bucket = {
    :objects        => {},
    'Name'          => bucket_name,
    'CreationDate'  => Time.now,
    'Owner'         => { 'DisplayName' => 'owner', 'ID' => 'some_id'},
    'Payer'         => 'BucketOwner'
  }
  if options['LocationConstraint']
    bucket['LocationConstraint'] = options['LocationConstraint']
  else
    bucket['LocationConstraint'] = ''
  end
  unless @data[:buckets][bucket_name]
    @data[:buckets][bucket_name] = bucket
  end
  response
end

#put_object(bucket_name, object_name, data, options = {}) ⇒ Object


44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/fog/aws/requests/s3/put_object.rb', line 44

def put_object(bucket_name, object_name, data, options = {})
  data = Fog::AWS::S3.parse_data(data)
  response = Excon::Response.new
  if (bucket = @data[:buckets][bucket_name])
    response.status = 200
    bucket[:objects][object_name] = {
      :body           => data[:body],
      'ETag'          => Fog::AWS::Mock.etag,
      'Key'           => object_name,
      'LastModified'  => Time.now.utc.strftime("%a, %d %b %Y %H:%M:%S +0000"),
      'Size'          => data[:headers]['Content-Length'],
      'StorageClass'  => 'STANDARD'
    }
    bucket[:objects][object_name]['Content-Type'] = data[:headers]['Content-Type']
  else
    response.status = 404
    raise(Excon::Errors.status_error({:expects => 200}, response))
  end
  response
end

#put_request_payment(bucket_name, payer) ⇒ Object


32
33
34
35
36
37
38
39
40
41
42
# File 'lib/fog/aws/requests/s3/put_request_payment.rb', line 32

def put_request_payment(bucket_name, payer)
  response = Excon::Response.new
  if bucket = @data[:buckets][bucket_name]
    response.status = 200
    bucket['Payer'] = payer
  else
    response.status = 404
    raise(Excon::Errors.status_error({:expects => 200}, response))
  end
  response
end