Upgraded gcloud package to 0.11.0

This commit is contained in:
Francesco Siddi 2016-03-14 14:51:46 +01:00
parent 086284b883
commit f90f25d373
5 changed files with 37 additions and 62 deletions

View File

@ -84,7 +84,7 @@ class ValidateCustomFields(Validator):
field, "Error validating properties") field, "Error validating properties")
# We specify a settings.py file because when running on wsgi we can't detect it # We specify a settings.py file because when running on wsgi we can't detect it
# automatically. The default path (which works in Docker) can be overriden with # automatically. The default path (which works in Docker) can be overridden with
# an env variable. # an env variable.
settings_path = os.environ.get( settings_path = os.environ.get(
'EVE_SETTINGS', '/data/git/pillar/pillar/settings.py') 'EVE_SETTINGS', '/data/git/pillar/pillar/settings.py')
@ -105,6 +105,16 @@ bugsnag.configure(
) )
handle_exceptions(app) handle_exceptions(app)
# Storage backend (GCS)
try:
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = \
app.config['GOOGLE_APPLICATION_CREDENTIALS']
except KeyError:
log.debug("The GOOGLE_APPLICATION_CREDENTIALS configuration value should "
"point to an existing and valid JSON file.")
raise
# Algolia search # Algolia search
if 'ALGOLIA_USER' in app.config: if 'ALGOLIA_USER' in app.config:
client = algoliasearch.Client( client = algoliasearch.Client(
@ -122,14 +132,14 @@ if app.config['ENCODING_BACKEND'] == 'zencoder':
else: else:
encoding_service_client = None encoding_service_client = None
from application.utils.authentication import validate_token from utils.authentication import validate_token
from application.utils.authorization import check_permissions from utils.authorization import check_permissions
from application.utils.gcs import update_file_name from utils.gcs import update_file_name
from application.utils.algolia import algolia_index_user_save from utils.algolia import algolia_index_user_save
from application.utils.algolia import algolia_index_node_save from utils.algolia import algolia_index_node_save
from application.utils.activities import activity_subscribe from utils.activities import activity_subscribe
from application.utils.activities import activity_object_add from utils.activities import activity_object_add
from application.utils.activities import notification_parse from utils.activities import notification_parse
from modules.file_storage import process_file from modules.file_storage import process_file
from modules.file_storage import delete_file from modules.file_storage import delete_file
from modules.file_storage import generate_link from modules.file_storage import generate_link

View File

@ -1,11 +1,9 @@
import logging import logging
import os import os
import json
from multiprocessing import Process from multiprocessing import Process
from bson import ObjectId from bson import ObjectId
from flask import request from flask import request
from flask import Blueprint from flask import Blueprint
from flask import abort
from flask import jsonify from flask import jsonify
from flask import send_from_directory from flask import send_from_directory
from flask import url_for, helpers from flask import url_for, helpers
@ -14,7 +12,6 @@ from application import app
from application.utils.imaging import generate_local_thumbnails from application.utils.imaging import generate_local_thumbnails
from application.utils.imaging import get_video_data from application.utils.imaging import get_video_data
from application.utils.imaging import ffmpeg_encode from application.utils.imaging import ffmpeg_encode
from application.utils.storage import remote_storage_sync
from application.utils.storage import push_to_storage from application.utils.storage import push_to_storage
from application.utils.cdn import hash_file_path from application.utils.cdn import hash_file_path
from application.utils.gcs import GoogleCloudStorageBucket from application.utils.gcs import GoogleCloudStorageBucket
@ -24,8 +21,8 @@ from application.utils.encoding import Encoder
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
file_storage = Blueprint('file_storage', __name__, file_storage = Blueprint('file_storage', __name__,
template_folder='templates', template_folder='templates',
static_folder='../../static/storage',) static_folder='../../static/storage',)
@file_storage.route('/gcs/<bucket_name>/<subdir>/') @file_storage.route('/gcs/<bucket_name>/<subdir>/')
@ -70,13 +67,14 @@ def build_thumbnails(file_path=None, file_id=None):
file_ = files_collection.find_one({"_id": ObjectId(file_id)}) file_ = files_collection.find_one({"_id": ObjectId(file_id)})
file_path = file_['name'] file_path = file_['name']
file_full_path = os.path.join(app.config['SHARED_DIR'], file_path[:2], file_path) file_full_path = os.path.join(app.config['SHARED_DIR'], file_path[:2],
file_path)
# Does the original file exist? # Does the original file exist?
if not os.path.isfile(file_full_path): if not os.path.isfile(file_full_path):
return "", 404 return "", 404
else: else:
thumbnails = generate_local_thumbnails(file_full_path, thumbnails = generate_local_thumbnails(file_full_path,
return_image_stats=True) return_image_stats=True)
file_variations = [] file_variations = []
for size, thumbnail in thumbnails.iteritems(): for size, thumbnail in thumbnails.iteritems():
@ -119,7 +117,8 @@ def index(file_name=None):
# Sanitize the filename; source: http://stackoverflow.com/questions/7406102/ # Sanitize the filename; source: http://stackoverflow.com/questions/7406102/
file_name = request.form['name'] file_name = request.form['name']
keepcharacters = {' ', '.', '_'} keepcharacters = {' ', '.', '_'}
file_name = ''.join(c for c in file_name if c.isalnum() or c in keepcharacters).strip() file_name = ''.join(
c for c in file_name if c.isalnum() or c in keepcharacters).strip()
file_name = file_name.lstrip('.') file_name = file_name.lstrip('.')
# Determine & create storage directory # Determine & create storage directory

View File

@ -5,14 +5,13 @@ import bugsnag
from bson import ObjectId from bson import ObjectId
from gcloud.storage.client import Client from gcloud.storage.client import Client
from gcloud.exceptions import NotFound from gcloud.exceptions import NotFound
from oauth2client.client import SignedJwtAssertionCredentials
from application import app from application import app
class GoogleCloudStorageBucket(object): class GoogleCloudStorageBucket(object):
"""Cloud Storage bucket interface. We create a bucket for every project. In """Cloud Storage bucket interface. We create a bucket for every project. In
the bucket we create first level subdirs as follows: the bucket we create first level subdirs as follows:
- '_' (will contain hashed assets, and stays on top of defaul listing) - '_' (will contain hashed assets, and stays on top of default listing)
- 'svn' (svn checkout mirror) - 'svn' (svn checkout mirror)
- 'shared' (any additional folder of static folder that is accessed via a - 'shared' (any additional folder of static folder that is accessed via a
node of 'storage' node_type) node of 'storage' node_type)
@ -21,31 +20,12 @@ class GoogleCloudStorageBucket(object):
:param bucket_name: Name of the bucket. :param bucket_name: Name of the bucket.
:type subdir: string :type subdir: string
:param subdir: The local entrypoint to browse the bucket. :param subdir: The local entry point to browse the bucket.
""" """
CGS_PROJECT_NAME = app.config['CGS_PROJECT_NAME']
GCS_CLIENT_EMAIL = app.config['GCS_CLIENT_EMAIL']
GCS_PRIVATE_KEY_PEM = app.config['GCS_PRIVATE_KEY_PEM']
GCS_PRIVATE_KEY_P12 = app.config['GCS_PRIVATE_KEY_P12']
# Load private key in pem format (used by the API)
with open(GCS_PRIVATE_KEY_PEM) as f:
private_key_pem = f.read()
credentials_pem = SignedJwtAssertionCredentials(GCS_CLIENT_EMAIL,
private_key_pem,
'https://www.googleapis.com/auth/devstorage.full_control')
# Load private key in p12 format (used by the singed urls generator)
with open(GCS_PRIVATE_KEY_P12) as f:
private_key_pkcs12 = f.read()
credentials_p12 = SignedJwtAssertionCredentials(GCS_CLIENT_EMAIL,
private_key_pkcs12,
'https://www.googleapis.com/auth/devstorage.full_control')
def __init__(self, bucket_name, subdir='_/'): def __init__(self, bucket_name, subdir='_/'):
gcs = Client(project=self.CGS_PROJECT_NAME, credentials=self.credentials_pem) gcs = Client()
self.bucket = gcs.get_bucket(bucket_name) self.bucket = gcs.get_bucket(bucket_name)
self.subdir = subdir self.subdir = subdir
@ -62,7 +42,7 @@ class GoogleCloudStorageBucket(object):
fields_to_return = 'nextPageToken,items(name,size,contentType),prefixes' fields_to_return = 'nextPageToken,items(name,size,contentType),prefixes'
req = self.bucket.list_blobs(fields=fields_to_return, prefix=prefix, req = self.bucket.list_blobs(fields=fields_to_return, prefix=prefix,
delimiter='/') delimiter='/')
files = [] files = []
for f in req: for f in req:
@ -86,12 +66,11 @@ class GoogleCloudStorageBucket(object):
list_dict = dict( list_dict = dict(
name=os.path.basename(os.path.normpath(path)), name=os.path.basename(os.path.normpath(path)),
type='group_storage', type='group_storage',
children = files + directories children=files + directories
) )
return list_dict return list_dict
def blob_to_dict(self, blob): def blob_to_dict(self, blob):
blob.reload() blob.reload()
expiration = datetime.datetime.now() + datetime.timedelta(days=1) expiration = datetime.datetime.now() + datetime.timedelta(days=1)
@ -101,16 +80,16 @@ class GoogleCloudStorageBucket(object):
name=os.path.basename(blob.name), name=os.path.basename(blob.name),
size=blob.size, size=blob.size,
content_type=blob.content_type, content_type=blob.content_type,
signed_url=blob.generate_signed_url( signed_url=blob.generate_signed_url(expiration),
expiration, credentials=self.credentials_p12),
public_url=blob.public_url) public_url=blob.public_url)
def Get(self, path, to_dict=True): def Get(self, path, to_dict=True):
"""Get selected file info if the path matches. """Get selected file info if the path matches.
:type path: string :type path: string
:param path: The relative path to the file. :param path: The relative path to the file.
:type to_dict: bool
:param to_dict: Return the object as a dictionary.
""" """
path = os.path.join(self.subdir, path) path = os.path.join(self.subdir, path)
blob = self.bucket.blob(path) blob = self.bucket.blob(path)
@ -122,7 +101,6 @@ class GoogleCloudStorageBucket(object):
else: else:
return None return None
def Post(self, full_path, path=None): def Post(self, full_path, path=None):
"""Create new blob and upload data to it. """Create new blob and upload data to it.
""" """
@ -134,7 +112,6 @@ class GoogleCloudStorageBucket(object):
return blob return blob
# return self.blob_to_dict(blob) # Has issues with threading # return self.blob_to_dict(blob) # Has issues with threading
def Delete(self, path): def Delete(self, path):
"""Delete blob (when removing an asset or replacing a preview)""" """Delete blob (when removing an asset or replacing a preview)"""
@ -146,7 +123,6 @@ class GoogleCloudStorageBucket(object):
except NotFound: except NotFound:
return None return None
def update_name(self, blob, name): def update_name(self, blob, name):
"""Set the ContentDisposition metadata so that when a file is downloaded """Set the ContentDisposition metadata so that when a file is downloaded
it has a human-readable name. it has a human-readable name.

View File

@ -25,10 +25,8 @@ class Development(object):
# Credentials to access project on the Google Cloud where Google Cloud # Credentials to access project on the Google Cloud where Google Cloud
# Storage is enabled (Pillar will automatically create and manage buckets) # Storage is enabled (Pillar will automatically create and manage buckets)
GCS_CLIENT_EMAIL = '' GOOGLE_APPLICATION_CREDENTIALS = os.environ.get(
GCS_PRIVATE_KEY_P12 = '' 'GOOGLE_APPLICATION_CREDENTIALS', '/data/config/google_app.json')
GCS_PRIVATE_KEY_PEM = ''
CGS_PROJECT_NAME = ''
# Fill in only if we plan to sign our urls using a the CDN # Fill in only if we plan to sign our urls using a the CDN
CDN_USE_URL_SIGNING = False CDN_USE_URL_SIGNING = False

View File

@ -4,29 +4,21 @@ bugsnag==2.3.1
Cerberus==0.9.1 Cerberus==0.9.1
Eve==0.5.3 Eve==0.5.3
Events==0.2.1 Events==0.2.1
Flask==0.10.1
Flask-PyMongo==0.3.1
Flask-Script==2.0.5 Flask-Script==2.0.5
flup==1.0.2 flup==1.0.2
gcloud==0.7.1 gcloud==0.11.0
google-apitools==0.4.11 google-apitools==0.4.11
httplib2==0.9.2 httplib2==0.9.2
idna==2.0 idna==2.0
MarkupSafe==0.23 MarkupSafe==0.23
ndg-httpsclient==0.4.0 ndg-httpsclient==0.4.0
oauth2client==1.5.1
Pillow==2.8.1 Pillow==2.8.1
protobuf==3.0.0a1
protorpc==0.11.1
pycparser==2.14 pycparser==2.14
pycrypto==2.6.1 pycrypto==2.6.1
pymongo==2.9.1
pyOpenSSL==0.15.1 pyOpenSSL==0.15.1
requests==2.9.1 requests==2.9.1
rsa==3.3 rsa==3.3
simplejson==3.8.1 simplejson==3.8.1
six==1.10.0
WebOb==1.5.0 WebOb==1.5.0
Werkzeug==0.10.4
wheel==0.24.0 wheel==0.24.0
zencoder==0.6.5 zencoder==0.6.5