Skip to content

Commit

Permalink
Add sample for CRUD on GCS.
Browse files Browse the repository at this point in the history
(or at least, CRD)
  • Loading branch information
Jerjou Cheng committed Mar 7, 2016
1 parent 6f3c788 commit 14b3d97
Show file tree
Hide file tree
Showing 2 changed files with 171 additions and 0 deletions.
149 changes: 149 additions & 0 deletions storage/api/crud_object.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
#!/usr/bin/env python

# Copyright (C) 2016 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Application for uploading an object using the Cloud Storage API.
This sample is used on this page:
https://cloud.google.com/storage/docs/json_api/v1/json-api-python-samples
For more information, see the README.md under /storage.
"""

import argparse
import filecmp
import json
import tempfile

from googleapiclient import discovery
from googleapiclient import http

from oauth2client.client import GoogleCredentials


def main(bucket, filename, readers=[], owners=[]):
print('Uploading object..')
resp = upload_object(bucket, filename, readers, owners)
print(json.dumps(resp, indent=2))

print('Fetching object..')
with tempfile.NamedTemporaryFile(mode='w+b') as tmpfile:
get_object(bucket, filename, out_file=tmpfile)
tmpfile.seek(0)

if not filecmp.cmp(filename, tmpfile.name):
raise Exception('Downloaded file != uploaded object')

print('Deleting object..')
resp = delete_object(bucket, filename)
if resp:
print(json.dumps(resp, indent=2))
print 'Done'


def create_service():
# Get the application default credentials. When running locally, these are
# available after running `gcloud init`. When running on compute
# engine, these are available from the environment.
credentials = GoogleCredentials.get_application_default()

# Construct the service object for interacting with the Cloud Storage API -
# the 'storage' service, at version 'v1'.
# You can browse other available api services and versions here:
# https://developers.google.com/api-client-library/python/apis/
return discovery.build('storage', 'v1', credentials=credentials)


def upload_object(bucket, filename, readers, owners):
service = create_service()

# This is the request body as specified:
# https://cloud.google.com/storage/docs/json_api/v1/objects/insert#request
body = {
'name': filename,
}

# If specified, create the access control objects and add them to the
# request body
if readers or owners:
body['acl'] = []
for r in readers:
body['acl'].append({
'entity': 'user-%s' % r,
'role': 'READER',
'email': r
})
for o in owners:
body['acl'].append({
'entity': 'user-%s' % o,
'role': 'OWNER',
'email': o
})

# Now insert them into the specified bucket as a media insertion.
# https://developers.google.com/resources/api-libraries/documentation/storage/v1/python/latest/storage_v1.objects.html#insert
with open(filename, 'rb') as f:
req = service.objects().insert(
bucket=bucket, body=body,
# You can also just set media_body=filename, but # for the sake of
# demonstration, pass in the more generic file handle, which could
# very well be a StringIO or similar.
media_body=http.MediaIoBaseUpload(f, 'application/octet-stream'))
resp = req.execute()

return resp


def get_object(bucket, filename, out_file):
service = create_service()

# Use get_media instead of get to get the actual contents of the object.
# https://developers.google.com/resources/api-libraries/documentation/storage/v1/python/latest/storage_v1.objects.html#get_media
req = service.objects().get_media(bucket=bucket, object=filename)

downloader = http.MediaIoBaseDownload(out_file, req)

done = False
while done is False:
status, done = downloader.next_chunk()
print("Download {}%.".format(int(status.progress() * 100)))

return out_file


def delete_object(bucket, filename):
service = create_service()

req = service.objects().delete(bucket=bucket, object=filename)
resp = req.execute()

return resp


if __name__ == '__main__':
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('filename', help='The name of the file to upload')
parser.add_argument('bucket', help='Your Cloud Storage bucket.')
parser.add_argument('--reader', action='append', default=[],
help='Your Cloud Storage bucket.')
parser.add_argument('--owner', action='append', default=[],
help='Your Cloud Storage bucket.')

args = parser.parse_args()

main(args.bucket, args.filename, args.reader, args.owner)
22 changes: 22 additions & 0 deletions storage/api/crud_object_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright 2016, Google, Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from crud_object import main


def test_main(cloud_config, capsys):
main(cloud_config.storage_bucket, __file__)
out, err = capsys.readouterr()

assert not re.search(r'Downloaded file [!]=', out)
assert re.search(r'Uploading.*Fetching.*Deleting.*Done', out)

0 comments on commit 14b3d97

Please sign in to comment.