-
Notifications
You must be signed in to change notification settings - Fork 79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
S3 #781
S3 #781
Changes from all commits
ac13afc
87c4a93
782fe9f
6ce7bc9
603e665
4061d12
d417b90
74a6325
307bfb2
09817ac
bbe4594
8b8ba18
75def90
a8240fc
bf1970d
40ebb9c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,3 +3,4 @@ container_data | |
.cache | ||
node_modules | ||
OpenOversight/app/static/dist/* | ||
/OpenOversight/tests/resources/.minio.sys/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
from io import BytesIO | ||
|
||
import boto3 | ||
from botocore.client import Config | ||
from botocore.exceptions import ClientError | ||
import botocore | ||
import datetime | ||
|
@@ -29,6 +30,13 @@ | |
SAVED_UMASK = os.umask(0o077) | ||
|
||
|
||
def get_s3_connection(config=None): | ||
if current_app.config['S3_ENDPOINT']: | ||
return boto3.client('s3', config=config, endpoint_url=current_app.config['S3_ENDPOINT']) | ||
else: | ||
return boto3.client('s3', config=config) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use local minio if an env var is set, otherwise use S3 as normal |
||
|
||
|
||
def set_dynamic_default(form_field, value): | ||
# First we ensure no value is set already | ||
if not form_field.data: | ||
|
@@ -226,8 +234,22 @@ def compute_hash(data_to_hash): | |
return hashlib.sha256(data_to_hash).hexdigest() | ||
|
||
|
||
def get_presigned_image_url(s3_path: str): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. pulled code from |
||
unsigned = Config(signature_version=botocore.UNSIGNED) | ||
s3_client_unsigned = get_s3_connection(unsigned) | ||
|
||
url = s3_client_unsigned.generate_presigned_url( | ||
'get_object', | ||
Params={'Bucket': current_app.config['S3_BUCKET_NAME'], 'Key': s3_path} | ||
) | ||
return url | ||
|
||
|
||
def upload_obj_to_s3(file_obj, dest_filename): | ||
s3_client = boto3.client('s3') | ||
if current_app.config['S3_ENDPOINT']: | ||
s3_client = get_s3_connection(Config(signature_version='s3v4')) | ||
else: | ||
s3_client = get_s3_connection() | ||
|
||
# Folder to store files in on S3 is first two chars of dest_filename | ||
s3_folder = dest_filename[0:2] | ||
|
@@ -240,16 +262,7 @@ def upload_obj_to_s3(file_obj, dest_filename): | |
current_app.config['S3_BUCKET_NAME'], | ||
s3_path, | ||
ExtraArgs={'ContentType': s3_content_type, 'ACL': 'public-read'}) | ||
|
||
config = s3_client._client_config | ||
config.signature_version = botocore.UNSIGNED | ||
url = boto3.resource( | ||
's3', config=config).meta.client.generate_presigned_url( | ||
'get_object', | ||
Params={'Bucket': current_app.config['S3_BUCKET_NAME'], | ||
'Key': s3_path}) | ||
|
||
return url | ||
return get_presigned_image_url(s3_path) | ||
|
||
|
||
def filter_by_form(form, officer_query, department_id=None): | ||
|
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -5,7 +5,6 @@ | |||
import random | ||||
from selenium import webdriver | ||||
import time | ||||
import threading | ||||
from xvfbwrapper import Xvfb | ||||
from faker import Faker | ||||
import csv | ||||
|
@@ -14,7 +13,7 @@ | |||
import os | ||||
from PIL import Image as Pimage | ||||
|
||||
from OpenOversight.app import create_app, models | ||||
from OpenOversight.app import create_app, models, utils | ||||
from OpenOversight.app.utils import merge_dicts | ||||
from OpenOversight.app.models import db as _db | ||||
|
||||
|
@@ -131,10 +130,11 @@ def build_salary(officer): | |||
|
||||
def assign_faces(officer, images): | ||||
if random.uniform(0, 1) >= 0.5: | ||||
for num in range(1, len(images)): | ||||
return models.Face(officer_id=officer.id, | ||||
img_id=num, | ||||
original_image_id=random.choice(images).id) | ||||
# for num in range(1, len(images)): # <-- bug here, we always return on the first one, the for-loop is unneeded | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Good catch! |
||||
img_id = random.choice(images).id | ||||
return models.Face(officer_id=officer.id, | ||||
img_id=img_id, | ||||
original_image_id=img_id) | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. found + fixed a bug. We only ever used the one face on the dev data, probably unintentional. |
||||
else: | ||||
return False | ||||
|
||||
|
@@ -251,10 +251,15 @@ def add_mockdata(session): | |||
|
||||
unit1 = models.Unit(descrip="test") | ||||
|
||||
test_images = [models.Image(filepath='/static/images/test_cop{}.png'.format(x + 1), department_id=1) for x in range(5)] + \ | ||||
[models.Image(filepath='/static/images/test_cop{}.png'.format(x + 1), department_id=2) for x in range(5)] | ||||
test_images = [ | ||||
models.Image( | ||||
filepath=utils.get_presigned_image_url('/images/test_cop{}.png'.format(x + 1)), | ||||
department_id=1) for x in range(5)] + \ | ||||
[models.Image( | ||||
filepath=utils.get_presigned_image_url('/images/test_cop{}.png'.format(x + 1)), | ||||
department_id=2) for x in range(5)] | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. updated the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sweet, we're no longer hackily relying on two different routes between testing and production! |
||||
|
||||
officers = [generate_officer() for o in range(NUM_OFFICERS)] | ||||
officers = [generate_officer() for _ in range(NUM_OFFICERS)] | ||||
session.add_all(officers) | ||||
session.add_all(test_images) | ||||
|
||||
|
@@ -549,12 +554,7 @@ def teardown(): | |||
|
||||
|
||||
@pytest.fixture | ||||
def browser(app, request): | ||||
# start server | ||||
threading.Thread(target=app.run).start() | ||||
# give the server a few seconds to ensure it is up | ||||
time.sleep(10) | ||||
|
||||
def browser(): | ||||
# start headless webdriver | ||||
vdisplay = Xvfb() | ||||
vdisplay.start() | ||||
|
@@ -563,10 +563,6 @@ def browser(app, request): | |||
time.sleep(3) | ||||
yield driver | ||||
|
||||
# shutdown server | ||||
driver.get("http://localhost:5000/shutdown") | ||||
time.sleep(3) | ||||
|
||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed the special pytest flask invocation from the |
||||
# shutdown headless webdriver | ||||
driver.quit() | ||||
vdisplay.stop() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The host network change required a change from
run
toexec
, not entirely sure why....