Class: Fog::Storage::GoogleJSON::Real

Inherits:
Object
  • Object
show all
Includes:
Google::Shared, GetObjectHttpUrl, GetObjectHttpsUrl, Utils
Defined in:
lib/fog/storage/google_json/real.rb,
lib/fog/storage/google_json/requests/get_bucket.rb,
lib/fog/storage/google_json/requests/get_object.rb,
lib/fog/storage/google_json/requests/put_bucket.rb,
lib/fog/storage/google_json/requests/put_object.rb,
lib/fog/storage/google_json/requests/copy_object.rb,
lib/fog/storage/google_json/requests/head_object.rb,
lib/fog/storage/google_json/requests/list_buckets.rb,
lib/fog/storage/google_json/requests/delete_bucket.rb,
lib/fog/storage/google_json/requests/delete_object.rb,
lib/fog/storage/google_json/requests/get_bucket_acl.rb,
lib/fog/storage/google_json/requests/get_object_acl.rb,
lib/fog/storage/google_json/requests/get_object_url.rb,
lib/fog/storage/google_json/requests/put_bucket_acl.rb,
lib/fog/storage/google_json/requests/put_object_acl.rb,
lib/fog/storage/google_json/requests/put_object_url.rb,
lib/fog/storage/google_json/requests/get_object_http_url.rb,
lib/fog/storage/google_json/requests/get_object_https_url.rb

Instance Attribute Summary collapse

Attributes included from Google::Shared

#api_url, #api_version, #project

Instance Method Summary collapse

Methods included from GetObjectHttpsUrl

#get_object_https_url

Methods included from GetObjectHttpUrl

#get_object_http_url

Methods included from Google::Shared

#build_excon_response, #create_signing_key, #initialize_google_client, #new_pk12_google_client, #request, #shared_initialize

Methods included from Utils

#http_url, #https_url, #url

Constructor Details

#initialize(options = {}) ⇒ Real

Returns a new instance of Real.



11
12
13
14
15
16
17
18
# File 'lib/fog/storage/google_json/real.rb', line 11

def initialize(options = {})
  shared_initialize(options[:google_project], GOOGLE_STORAGE_JSON_API_VERSION, GOOGLE_STORAGE_JSON_BASE_URL)
  options[:google_api_scope_url] = GOOGLE_STORAGE_JSON_API_SCOPE_URLS.join(" ")
  @host = options[:host] || "storage.googleapis.com"

  @client = initialize_google_client(options)
  @storage_json = @client.discovered_api("storage", api_version)
end

Instance Attribute Details

#clientObject

Returns the value of attribute client.



8
9
10
# File 'lib/fog/storage/google_json/real.rb', line 8

def client
  @client
end

#storage_jsonObject (readonly)

Returns the value of attribute storage_json.



9
10
11
# File 'lib/fog/storage/google_json/real.rb', line 9

def storage_json
  @storage_json
end

Instance Method Details

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

Copy an object from one Google Storage bucket to another cloud.google.com/storage/docs/json_api/v1/objects/copy

Parameters

  • source_bucket_name<~String> - Name of source bucket

  • source_object_name<~String> - Name of source object

  • target_bucket_name<~String> - Name of bucket to create copy in

  • target_object_name<~String> - Name for new copy of object

  • options<~Hash>:

    • ‘x-goog-metadata-directive’<~String> - Specifies whether to copy metadata from source or replace with data in request. Must be in [‘COPY’, ‘REPLACE’]

    • ‘x-goog-copy_source-if-match’<~String> - Copies object if its etag matches this value

    • ‘x-goog-copy_source-if-modified_since’<~Time> - Copies object it it has been modified since this time

    • ‘x-goog-copy_source-if-none-match’<~String> - Copies object if its etag does not match this value

    • ‘x-goog-copy_source-if-unmodified-since’<~Time> - Copies object it it has not been modified since this time

Returns

  • response<~Excon::Response>:

    • body<~Hash>:

      • ‘ETag’<~String> - etag of new object

      • ‘LastModified’<~Time> - date object was last modified



26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/fog/storage/google_json/requests/copy_object.rb', line 26

def copy_object(source_bucket_name, source_object_name, target_bucket_name, target_object_name, options = {})
  api_method = @storage_json.objects.copy
  parameters = {
    "sourceBucket" => source_bucket_name,
    "sourceObject" => source_object_name,
    "destinationBucket" => target_bucket_name,
    "destinationObject" => target_object_name
  }
  parameters.merge! options

  request(api_method, parameters)
end

#delete_bucket(bucket_name) ⇒ Object

Delete an Google Storage bucket cloud.google.com/storage/docs/json_api/v1/buckets/delete

Parameters

  • bucket_name<~String> - name of bucket to delete

Returns

  • response<~Excon::Response>:

    • status<~Integer> - 204



14
15
16
17
18
19
20
21
# File 'lib/fog/storage/google_json/requests/delete_bucket.rb', line 14

def delete_bucket(bucket_name)
  api_method = @storage_json.buckets.delete
  parameters = {
    "bucket" => bucket_name
  }

  request(api_method, parameters)
end

#delete_object(bucket_name, object_name) ⇒ Object

Delete an object from Google Storage cloud.google.com/storage/docs/json_api/v1/objects/delete

Parameters

  • bucket_name<~String> - Name of bucket containing object to delete

  • object_name<~String> - Name of object to delete

Returns

  • response<~Excon::Response>:

    • status<~Integer> - 204



15
16
17
18
19
20
21
22
23
# File 'lib/fog/storage/google_json/requests/delete_object.rb', line 15

def delete_object(bucket_name, object_name)
  api_method = @storage_json.objects.delete
  parameters = {
    "bucket" => bucket_name,
    "object" => object_name
  }

  request(api_method, parameters)
end

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

List information about objects in an Google Storage bucket

Parameters

  • bucket_name<~String> - name of bucket to list object keys from

  • options<~Hash> - config arguments for list. Defaults to {}.

    • ‘ifMetagenerationMatch’<~Long> - Makes the return of the bucket metadata conditional on whether the bucket’s current metageneration matches the given value.

    • ‘ifMetagenerationNotMatch’<~Long> - Makes the return of the bucket metadata conditional on whether the bucket’s current metageneration does not match the given value.

    • ‘projection’<~String> - Set of properties to return. Defaults to ‘noAcl’, also accepts ‘full’.

Returns

Raises:

  • (ArgumentError)


26
27
28
29
30
31
32
33
34
35
36
# File 'lib/fog/storage/google_json/requests/get_bucket.rb', line 26

def get_bucket(bucket_name, options = {})
  raise ArgumentError.new("bucket_name is required") unless bucket_name

  api_method = @storage_json.buckets.get
  parameters = {
    "bucket" => bucket_name
  }
  parameters.merge! options

  request(api_method, parameters)
end

#get_bucket_acl(bucket_name) ⇒ Object

Get access control list for an Google Storage bucket cloud.google.com/storage/docs/json_api/v1/bucketAccessControls/list

Parameters

  • bucket_name<~String> - name of bucket to get access control list for

Returns

  • response<~Excon::Response>:

    • body<~Hash>:

      • ‘AccessControlPolicy’<~Hash>

        • ‘Owner’<~Hash>:

          • ‘DisplayName’<~String> - Display name of object owner

          • ‘ID’<~String> - Id of object owner

        • ‘AccessControlList’<~Array>:

          • ‘Grant’<~Hash>:

            • ‘Grantee’<~Hash>:

              * 'DisplayName'<~String> - Display name of grantee
              * 'ID'<~String> - Id of grantee
              

              or

              * 'URI'<~String> - URI of group to grant access for
              
            • ‘Permission’<~String> - Permission, in [FULL_CONTROL, WRITE, WRITE_ACP, READ, READ_ACP]

Raises:

  • (ArgumentError)


27
28
29
30
31
32
33
34
35
36
# File 'lib/fog/storage/google_json/requests/get_bucket_acl.rb', line 27

def get_bucket_acl(bucket_name)
  raise ArgumentError.new("bucket_name is required") unless bucket_name

  api_method = @storage_json.bucket_access_controls.list
  parameters = {
    "bucket" => bucket_name
  }

  request(api_method, parameters)
end

#get_object(bucket_name, object_name, _options = {}, &_block) ⇒ Object

Get an object from Google Storage cloud.google.com/storage/docs/json_api/v1/objects/get

Parameters

  • bucket_name<~String> - Name of bucket to read from

  • object_name<~String> - Name of object to read

  • options<~Hash>:

    • ‘If-Match’<~String> - Returns object only if its etag matches this value, otherwise returns 412 (Precondition Failed).

    • ‘If-Modified-Since’<~Time> - Returns object only if it has been modified since this time, otherwise returns 304 (Not Modified).

    • ‘If-None-Match’<~String> - Returns object only if its etag differs from this value, otherwise returns 304 (Not Modified)

    • ‘If-Unmodified-Since’<~Time> - Returns object only if it has not been modified since this time, otherwise returns 412 (Precodition Failed).

    • ‘Range’<~String> - Range of object to download

    • ‘versionId’<~String> - specify a particular version to retrieve

Returns

  • response<~Excon::Response>:

    • body<~String> - Contents of object

    • headers<~Hash>:

      • ‘Content-Length’<~String> - Size of object contents

      • ‘Content-Type’<~String> - MIME type of object

      • ‘ETag’<~String> - Etag of object

      • ‘Last-Modified’<~String> - Last modified timestamp for object

Raises:

  • (ArgumentError)


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/fog/storage/google_json/requests/get_object.rb', line 28

def get_object(bucket_name, object_name, _options = {}, &_block)
  raise ArgumentError.new("bucket_name is required") unless bucket_name
  raise ArgumentError.new("object_name is required") unless object_name

  api_method = @storage_json.objects.get
  parameters = {
    "bucket" => bucket_name,
    "object" => object_name,
    "projection" => "full"
  }

  object = request(api_method, parameters)

  # Get the body of the object (can't use request for this)
  parameters["alt"] = "media"
  client_parms = {
    :api_method => api_method,
    :parameters => parameters
  }

  result = @client.execute(client_parms)
  object.headers = object.body
  object.body = result.body.nil? || result.body.empty? ? nil : result.body
  object
end

#get_object_acl(bucket_name, object_name, _options = {}) ⇒ Object

Get access control list for an Google Storage object cloud.google.com/storage/docs/json_api/v1/objectAccessControls/get

Parameters

  • bucket_name<~String> - name of bucket containing object

  • object_name<~String> - name of object to get access control list for

  • options<~Hash>:

    • ‘versionId’<~String> - specify a particular version to retrieve

Returns

  • response<~Excon::Response>:

    • body<~Hash>:

      • ‘AccessControlPolicy’<~Hash>

        • ‘Owner’<~Hash>:

          • ‘DisplayName’<~String> - Display name of object owner

          • ‘ID’<~String> - Id of object owner

        • ‘AccessControlList’<~Array>:

          • ‘Grant’<~Hash>:

            • ‘Grantee’<~Hash>:

              * 'DisplayName'<~String> - Display name of grantee
              * 'ID'<~String> - Id of grantee
              

              or

              * 'URI'<~String> - URI of group to grant access for
              
            • ‘Permission’<~String> - Permission, in [FULL_CONTROL, WRITE, WRITE_ACP, READ, READ_ACP]

Raises:

  • (ArgumentError)


30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/fog/storage/google_json/requests/get_object_acl.rb', line 30

def get_object_acl(bucket_name, object_name, _options = {})
  raise ArgumentError.new("bucket_name is required") unless bucket_name
  raise ArgumentError.new("object_name is required") unless object_name

  api_method = @storage_json.object_access_controls.list
  parameters = {
    "bucket" => bucket_name,
    "object" => object_name
  }

  request(api_method, parameters)
end

#get_object_url(bucket_name, object_name, expires) ⇒ Object

Get an expiring object url from GCS Deprecated, redirects to get_object_https_url.rb



8
9
10
11
# File 'lib/fog/storage/google_json/requests/get_object_url.rb', line 8

def get_object_url(bucket_name, object_name, expires)
  Fog::Logger.deprecation("Fog::Storage::Google => ##{get_object_url} is deprecated, use ##{get_object_https_url} instead[/] [light_black](#{caller.first})")
  get_object_https_url(bucket_name, object_name, expires)
end

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

Get headers for an object from Google Storage cloud.google.com/storage/docs/json_api/v1/objects/get

Parameters

  • bucket_name<~String> - Name of bucket to read from

  • object_name<~String> - Name of object to read

  • options<~Hash>:

    • ‘If-Match’<~String> - Returns object only if its etag matches this value, otherwise returns 412 (Precondition Failed).

    • ‘If-Modified-Since’<~Time> - Returns object only if it has been modified since this time, otherwise returns 304 (Not Modified).

    • ‘If-None-Match’<~String> - Returns object only if its etag differs from this value, otherwise returns 304 (Not Modified)

    • ‘If-Unmodified-Since’<~Time> - Returns object only if it has not been modified since this time, otherwise returns 412 (Precodition Failed).

    • ‘Range’<~String> - Range of object to download

    • ‘versionId’<~String> - specify a particular version to retrieve

Returns

  • response<~Excon::Response>:

    • body<~String> - Contents of object

    • headers<~Hash>:

      • ‘Content-Length’<~String> - Size of object contents

      • ‘Content-Type’<~String> - MIME type of object

      • ‘ETag’<~String> - Etag of object

      • ‘Last-Modified’<~String> - Last modified timestamp for object

Raises:

  • (ArgumentError)


27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/fog/storage/google_json/requests/head_object.rb', line 27

def head_object(bucket_name, object_name, _options = {})
  raise ArgumentError.new("bucket_name is required") unless bucket_name
  raise ArgumentError.new("object_name is required") unless object_name

  api_method = @storage_json.objects.get
  parameters = {
    "bucket" => bucket_name,
    "object" => object_name,
    "projection" => "full"
  }

  object = request(api_method, parameters)
  object.headers = object.body
  object.body = nil
  object
end

#list_bucketsObject

Retrieves a list of buckets for a given project.

Returns

  • response<~Excon::Response>:

    • body<~Hash> - Hash of bucket items

      • ‘kind’<~String> - The kind of item this is (storage#buckets)

      • ‘items’<~Array> - The array of items.

See Also

cloud.google.com/storage/docs/json_api/v1/buckets/list TODO: check if very large lists require working with nextPageToken



16
17
18
19
20
21
22
23
# File 'lib/fog/storage/google_json/requests/list_buckets.rb', line 16

def list_buckets
  api_method = @storage_json.buckets.list
  parameters = {
    "project" => @project
  }

  request(api_method, parameters)
end

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

Create a Google Storage bucket

Parameters

  • bucket_name<~String> - name of bucket to create

  • options<~Hash> - config arguments for bucket. Defaults to {}.

    • ‘LocationConstraint’<~Symbol> - sets the location for the bucket

    • ‘predefinedAcl’<~String> - Apply a predefined set of access controls to this bucket.

    • ‘predefinedDefaultObjectAcl’<~String> - Apply a predefined set of default object access controls to this bucket.

  • body_options<~Hash> - body arguments for bucket creation. See cloud.google.com/storage/docs/json_api/v1/buckets/insert#request-body

Returns

  • response<~Excon::Response>:

    • status<~Integer> - 200

See also

cloud.google.com/storage/docs/json_api/v1/buckets/insert



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/fog/storage/google_json/requests/put_bucket.rb', line 22

def put_bucket(bucket_name, options = {}, body_options = {})
  location = options["LocationConstraint"] if options["LocationConstraint"]

  api_method = @storage_json.buckets.insert
  parameters = {
    "project" => @project,
    "projection" => "full"
  }
  parameters.merge! options
  body_object = {
    "name" => bucket_name,
    "location" => location
  }
  body_object.merge! body_options

  request(api_method, parameters, body_object = body_object)
end

#put_bucket_acl(bucket_name, acl) ⇒ Object

Change access control list for an Google Storage bucket cloud.google.com/storage/docs/json_api/v1/bucketAccessControls/insert

Parameters

  • bucket_name<~String> - name of bucket to create

  • acl<~Hash> - ACL hash to add to bucket, see GCS documentation above

    * entity
    * role
    

Raises:

  • (ArgumentError)


19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/fog/storage/google_json/requests/put_bucket_acl.rb', line 19

def put_bucket_acl(bucket_name, acl)
  raise ArgumentError.new("bucket_name is required") unless bucket_name
  raise ArgumentError.new("acl is required") unless acl

  api_method = @storage_json.bucket_access_controls.insert
  parameters = {
    "bucket" => bucket_name
  }
  body_object = acl

  request(api_method, parameters, body_object = body_object)
end

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

Create an object in an Google Storage bucket cloud.google.com/storage/docs/json_api/v1/objects/insert

Parameters

  • bucket_name<~String> - Name of bucket to create object in

  • object_name<~String> - Name of object to create

  • data<~File> - File or String to create object from

  • options<~Hash>:

    • ‘Cache-Control’<~String> - Caching behaviour

    • ‘Content-Disposition’<~String> - Presentational information for the object

    • ‘Content-Encoding’<~String> - Encoding of object data

    • ‘Content-Length’<~String> - Size of object in bytes (defaults to object.read.length)

    • ‘Content-MD5’<~String> - Base64 encoded 128-bit MD5 digest of message (defaults to Base64 encoded MD5 of object.read)

    • ‘Content-Type’<~String> - Standard MIME type describing contents (defaults to MIME::Types.of.first)

    • ‘x-goog-acl’<~String> - Permissions, must be in [‘private’, ‘public-read’, ‘public-read-write’, ‘authenticated-read’]

    • “x-goog-meta-#name” - Headers to be returned with object, note total size of request without body must be less than 8 KB.

Returns

  • response<~Excon::Response>:

    • headers<~Hash>:

      • ‘ETag’<~String> - etag of new object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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/storage/google_json/requests/put_object.rb', line 26

def put_object(bucket_name, object_name, data, options = {})
  if options["contentType"]
    mime_type = options["contentType"]
    if data.is_a? String
      data = StringIO.new(data)
    end
  elsif data.is_a? String
    data = StringIO.new(data)
    mime_type = "text/plain"
  elsif data.is_a? ::File
    mime_type = Fog::Storage.parse_data(data)[:headers]["Content-Type"]
  end

  media = ::Google::APIClient::UploadIO.new(data, mime_type, object_name)
  api_method = @storage_json.objects.insert
  parameters = {
    "uploadType" => "multipart",
    "bucket" => bucket_name,
    "name" => object_name
  }

  body_object = {
    :contentType => mime_type,
    :contentEncoding => options["contentEncoding"]
  }
  body_object.merge! options

  acl = []
  case options["predefinedAcl"]
  when "publicRead"
    acl.push({ "entity" => "allUsers", "role" => "READER" })
  when "publicReadWrite"
    acl.push({ "entity" => "allUsers", "role" => "OWNER" })
  when "authenticatedRead"
    acl.push({ "entity" => "allAuthenticatedUsers", "role" => "READER" })
  end

  unless acl.empty?
    body_object[:acl] = acl
  end

  request(api_method, parameters, body_object = body_object, media = media)
end

#put_object_acl(bucket_name, object_name, acl) ⇒ Object

Change access control list for an Google Storage object cloud.google.com/storage/docs/json_api/v1/objectAccessControls/insert

Parameters

  • bucket_name<~String> - name of bucket object is in

  • object_name<~String> - name of object to add ACL to

  • acl<~Hash> - ACL hash to add to bucket, see GCS documentation above

    * entity
    * role
    

Raises:

  • (ArgumentError)


14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/fog/storage/google_json/requests/put_object_acl.rb', line 14

def put_object_acl(bucket_name, object_name, acl)
  raise ArgumentError.new("bucket_name is required") unless bucket_name
  raise ArgumentError.new("object_name is required") unless object_name
  raise ArgumentError.new("acl is required") unless acl

  api_method = @storage_json.object_access_controls.insert
  parameters = {
    "bucket" => bucket_name,
    "object" => object_name
  }
  body_object = acl

  request(api_method, parameters, body_object = body_object)
end

#put_object_url(bucket_name, object_name, expires, headers = {}) ⇒ Object

Get an expiring object url from Google Storage for putting an object

Parameters

  • bucket_name<~String> - Name of bucket containing object

  • object_name<~String> - Name of object to get expiring url for

  • expires<~Time> - An expiry time for this url

  • If you want a file to be public you should to add { ‘x-goog-acl’ => ‘public-read’ } to headers And then call for example: curl -H “x-goog-acl:public-read” “signed url”

Returns

  • response<~Excon::Response>:

    • body<~String> - url for object

See Also

cloud.google.com/storage/docs/access-control#Signed-URLs

Raises:

  • (ArgumentError)


22
23
24
25
26
27
28
29
30
31
# File 'lib/fog/storage/google_json/requests/put_object_url.rb', line 22

def put_object_url(bucket_name, object_name, expires, headers = {})
  raise ArgumentError.new("bucket_name is required") unless bucket_name
  raise ArgumentError.new("object_name is required") unless object_name
  https_url({
              :headers  => headers,
              :host     => @host,
              :method   => "PUT",
              :path     => "#{bucket_name}/#{object_name}"
            }, expires)
end

#signature(params) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/fog/storage/google_json/real.rb', line 20

def signature(params)
  string_to_sign = <<-DATA
#{params[:method]}
#{params[:headers]['Content-MD5']}
#{params[:headers]['Content-Type']}
#{params[:headers]['Date']}
DATA

  google_headers = {}
  canonical_google_headers = ""
  params[:headers].each do |key, value|
    google_headers[key] = value if key[0..6] == "x-goog-"
  end

  google_headers = google_headers.sort { |x, y| x[0] <=> y[0] }
  google_headers.each do |key, value|
    canonical_google_headers << "#{key}:#{value}\n"
  end
  string_to_sign << canonical_google_headers.to_s

  canonical_resource = "/"
  if subdomain = params.delete(:subdomain)
    canonical_resource << "#{CGI.escape(subdomain).downcase}/"
  end
  canonical_resource << params[:path].to_s
  canonical_resource << "?"
  for key in (params[:query] || {}).keys
    if %w(acl cors location logging requestPayment versions versioning).include?(key)
      canonical_resource << "#{key}&"
    end
  end
  canonical_resource.chop!
  string_to_sign << canonical_resource.to_s

  key = OpenSSL::PKey::RSA.new(@client.authorization.signing_key)
  digest = OpenSSL::Digest::SHA256.new
  signed_string = key.sign(digest, string_to_sign)

  Base64.encode64(signed_string).chomp!
end