Skip to content
This repository was archived by the owner on Dec 10, 2019. It is now read-only.

Include Uploads example notebook #23

Merged
merged 1 commit into from
Sep 7, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 159 additions & 0 deletions examples/Uploads.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Uploading imagery"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from rasterfoundry.api import API\n",
"from rasterfoundry.models.upload import Upload\n",
"refresh_token = '<your refresh token>'\n",
"api = API(refresh_token=refresh_token)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The python client makes it easy to upload imagery to Raster Foundry\n",
"from a variety of sources. There are three ways Raster Foundry can\n",
"import data -- from local files, from S3, or from the Planet Labs API.\n",
"\n",
"This notebook will walk through creating uploads from local files.\n",
"\n",
"You'll need to make sure that Raster Foundry has permission to read from\n",
"the bucket. This is easy using the `aws` module:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from rasterfoundry.aws import s3\n",
"bucket_name = '<your bucket name here>'\n",
"s3.authorize_bucket(bucket_name)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You'll also need a little bit more information about the upload you're planning:\n",
"\n",
"- the path to your data (as a glob string or as a list)\n",
"- the id of the datasource to link the upload to\n",
"- your organization id\n",
"- optionally a project id\n",
"\n",
"For this example, I'll use the UAV 3 Band datasource. You can browse more\n",
"datasources in the Raster Foundry web application under `Imports`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"# id for UAV 3 Band datasource\n",
"datasource_id = 'c14c8e97-ba85-4677-ac9c-069cfef1f0b1'\n",
"source_files = 'path/to/data/*.tif'\n",
"# or:\n",
"# source_files = ['path1', 'path2', 'path3', ...]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Fill in your organization id below and desired S3 bucket and prefix below (you can just reuse `bucket_name` if you used it above):"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"organization_id = ''\n",
"s3_bucket = '' or bucket_name\n",
"s3_prefix = 'raster-foundry-imagery'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you leave `dry_run=True`, this won't actually upload the files to S3. This is useful if they're already there, or if you're just experimenting. If you'd like to upload the files to S3, either remove `dry_run` or set it to `False`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"uc = Upload.upload_create_from_files(\n",
" datasource=datasource_id,\n",
" organization=organization_id,\n",
" paths_to_tifs=source_files,\n",
" dest_bucket=s3_bucket,\n",
" dest_prefix=s3_prefix,\n",
" dry_run=True\n",
")\n",
"uc"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can then `POST` your upload to kick off processing:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Upload.create(api, uc)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.12"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Empty file added rasterfoundry/aws/__init__.py
Empty file.
98 changes: 98 additions & 0 deletions rasterfoundry/aws/s3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import json

import boto3
from botocore.exceptions import ClientError


s3 = boto3.client('s3')


RF_ACCESS_POLICY = {
'Sid': 'RasterFoundryReadWriteAccess',
'Effect': 'Allow',
'Principal': {
'AWS': 'arn:aws:iam::615874746523:root'
},
'Action': [
's3:GetObject',
's3:ListBucket',
's3:PutObject'
],
'Resource': [
'arn:aws:s3:::{}',
'arn:aws:s3:::{}/*'
]
}


def authorize_bucket(bucket_name):
"""Authorize Raster Foundry to read and write from an S3 bucket

Args:
bucket_name (str): the name of the bucket to authorize

Returns:
int: the status code from the attempted policy change
"""

rf_access_policy = RF_ACCESS_POLICY.copy()
rf_access_policy['Resource'] = [
x.format(bucket_name) for x in rf_access_policy['Resource']
]

try:
resp = s3.get_bucket_policy(Bucket=bucket_name)
existing_policy = json.loads(resp['Policy'])
except ClientError:
existing_policy = {
'Version': '2012-10-17',
'Statement': []
}

existing_policy['Statement'].append(rf_access_policy)
new_policy_str = json.dumps(existing_policy)
return s3.put_bucket_policy(
Bucket=bucket_name, Policy=new_policy_str
)['ResponseMetadata']['HTTPStatusCode']


def unauthorize_bucket(bucket_name):
"""Remove Raster Foundry authorization from a bucket

Args:
bucket_name (str): the name of the bucket to unauthorize

Returns:
int: the status code from the attempted policy change
"""
rf_access_policy = RF_ACCESS_POLICY.copy()
rf_access_policy['Resource'] = [
x.format(bucket_name) for x in rf_access_policy['Resource']
]

try:
resp = s3.get_bucket_policy(Bucket=bucket_name)
existing_policy = json.loads(resp['Policy'])
except ClientError:
existing_policy = {
'Version': '2012-10-17',
'Statement': []
}

if rf_access_policy in existing_policy['Statement']:
new_statement = [
x for x in existing_policy['Statement'] if x != rf_access_policy
]
existing_policy['Statement'] = new_statement
if new_statement:
new_policy_str = json.dumps(existing_policy)
resp = s3.put_bucket_policy(
Bucket=bucket_name, Policy=new_policy_str
)['ResponseMetadata']['HTTPStatusCode']
else:
resp = s3.delete_bucket_policy(Bucket=bucket_name)
else:
# No work to do, so just create a mock response
resp = {'ResponseMetadata': {'HTTPStatusCode': 204}}

return resp['ResponseMetadata']['HTTPStatusCode']
14 changes: 14 additions & 0 deletions rasterfoundry/models/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,20 @@ def __init__(self, project, api):
self.name = project.name
self.id = project.id

@classmethod
def create(cls, api, project_create):
"""Post a project to Raster Foundry

Args:
api (API): API to use for requests
project_create (dict): post parameters for /projects. See
project_create

Returns:
Project: created object in Raster Foundry
"""
return api.client.Imagery.post_projects(project_create)

def get_center(self):
"""Get the center of this project's extent"""
coords = self._project.extent.get('coordinates')
Expand Down