Commit 1920fb23 authored by Thorsten Buss's avatar Thorsten Buss

* migrate to aws sdk v3

* fix downloadUrl usage in getUrl Repo Handler
parent e8efbeb2
......@@ -6,9 +6,9 @@
"license": "MIT",
"require": {
"php": ">=5.3.8",
"aws/aws-sdk-php": "~2.5",
"aws/aws-sdk-php": "~3",
"symfony/yaml": "<2.3",
"herzult/php-ssh": "@dev",
"herzult/php-ssh": "~1.1",
"knplabs/gaufrette": "~0.1"
},
"require-dev": {
......
This diff is collapsed.
......@@ -10,6 +10,7 @@ bnrepo-test-local-2:
bnrepo-test-s3-DISABLED:
type: s3
aws_region: AWS_REGION
aws_key: AWS_KEY
aws_secret: AWS_SECRET
bucket: bnrepo-test
......
......@@ -3,18 +3,18 @@
namespace BNRepo\Repository\Adapter;
use Aws\CloudFront\Exception\Exception;
use Aws\Common\Enum\Region;
use Aws\S3\Enum\CannedAcl;
use Aws\S3\S3Client;
use Gaufrette\Adapter\AmazonS3;
use Gaufrette\Exception\FileNotFound;
use Gaufrette\Exception\UnexpectedFile;
use Gaufrette\Adapter as GaufretteAdapter;
use Guzzle\Service\Resource\Model;
use Aws\Result;
class AdapterAmazonS3Ver2 extends AmazonS3 implements GaufretteAdapter, UrlAware {
/**
* @var S3Client
*/
protected $service;
protected $bucket;
protected $ensureBucket = false;
......@@ -25,7 +25,7 @@ class AdapterAmazonS3Ver2 extends AmazonS3 implements GaufretteAdapter, UrlAware
$this->service = $service;
$this->bucket = $bucket;
$this->options = array_replace_recursive(
array('directory' => '', 'create' => false, 'region' => Region::EU_WEST_1, 'default_acl' => CannedAcl::BUCKET_OWNER_FULL_CONTROL),
array('directory' => '', 'create' => false, 'default_acl' => 'bucket-owner-full-control'),
$options
);
// Set Directory Explicit, cause validation/correction rules
......@@ -110,29 +110,26 @@ class AdapterAmazonS3Ver2 extends AmazonS3 implements GaufretteAdapter, UrlAware
if (array_key_exists('download_url', $options)) {
return sprintf($options['download_url'], $key);
}
$url = "https://{$this->bucket}.s3.amazonaws.com/{$this->computePath($key)}";
// Public Access, or Signed URL
if (in_array($this->options['default_acl'], array(CannedAcl::PUBLIC_READ, CannedAcl::PUBLIC_READ_WRITE))) {
return $url;
if (in_array($this->options['default_acl'], array('public-read', 'public-read-write'))) {
return $this->service->getObjectUrl($this->bucket, $this->computePath($key));
} else {
// Avialable request_options: response-content-type, response-content-language, response-expires, response-cache-control, response-content-disposition, response-content-encoding
$request_options = array();
if (array_key_exists('filename', $options))
$request_options['response-content-disposition'] = "attachment; filename=\"{$options['filename']}\"";
$request_options['response-content-type'] = @$options['content_type'] ?: $this->getContentType($key);
$url .= "?". http_build_query($request_options);
$request = $this->service->get($url);
$cmd = $this->service->getCommand('GetObject', [
'Bucket' => $this->bucket,
'Key' => $this->computePath($key)
]);
if (empty($validTime))
$validTime = 2147483647; // End of UnixTime
elseif (is_numeric($validTime))
$validTime = '+'.$validTime.' seconds';
$validTime = '+ 1 week'; // max expire time
elseif (is_numeric($validTime))
$validTime = '+' . $validTime . ' seconds';
return $this->service->createPresignedUrl($request, $validTime);
$request = $this->service->createPresignedRequest($cmd, $validTime);
// Get the actual presigned-url
return (string)$request->getUri();
}
}
......@@ -166,10 +163,6 @@ class AdapterAmazonS3Ver2 extends AmazonS3 implements GaufretteAdapter, UrlAware
return;
}
if (isset($this->options['region'])) {
$this->service->setRegion($this->options['region']);
}
if ($this->service->doesBucketExist($this->bucket)) {
$this->ensureBucket = true;
return;
......@@ -183,11 +176,13 @@ class AdapterAmazonS3Ver2 extends AmazonS3 implements GaufretteAdapter, UrlAware
}
try {
/** @var $result Model */
/** @var $result Result */
$result = $this->service->createBucket(array(
'Bucket' => $this->bucket,
'ACL' => $this->options['default_acl'],
'LocationConstraint' => $this->options['region']
'CreateBucketConfiguration' => [
'LocationConstraint' => $this->options['region']
]
));
} catch (\Exception $e) {
throw new \RuntimeException(sprintf(
......@@ -201,7 +196,7 @@ class AdapterAmazonS3Ver2 extends AmazonS3 implements GaufretteAdapter, UrlAware
/**
* {@inheritDoc}
* @return Model
* @return Result
*/
public function getKeyIterator($prefix = null) {
$this->ensureBucketExists();
......@@ -267,9 +262,9 @@ class AdapterAmazonS3Ver2 extends AmazonS3 implements GaufretteAdapter, UrlAware
);
try {
/** @var $response Model */
/** @var $response Result */
$response = $this->service->putObject($options);
} catch (Exception $e) {
} catch (\Exception $e) {
return false;
}
......@@ -306,7 +301,7 @@ class AdapterAmazonS3Ver2 extends AmazonS3 implements GaufretteAdapter, UrlAware
$this->ensureBucketExists();
try {
/** @var $response Model */
/** @var $response Result */
$response = $this->getObject($key);
} catch (\Exception $e) {
return false;
......@@ -322,7 +317,7 @@ class AdapterAmazonS3Ver2 extends AmazonS3 implements GaufretteAdapter, UrlAware
$this->ensureBucketExists();
try {
/** @var $response Model */
/** @var $response Result */
$response = $this->service->copyObject(array(
'Bucket' => $this->bucket,
'Key' => $this->computePath($targetKey),
......@@ -366,7 +361,7 @@ class AdapterAmazonS3Ver2 extends AmazonS3 implements GaufretteAdapter, UrlAware
$this->ensureBucketExists();
try {
/** @var $response Model */
/** @var $response Result */
$response = $this->service->deleteObject(array(
'Bucket' => $this->bucket,
'Key' => $this->computePath($key)
......@@ -393,7 +388,7 @@ class AdapterAmazonS3Ver2 extends AmazonS3 implements GaufretteAdapter, UrlAware
/**
* @param $key
* @param array $options
* @return Model
* @return Result
*/
public function getObject($key, $options=array()) {
$options = array_merge($options, array(
......
......@@ -241,7 +241,7 @@ class Repository extends Filesystem {
*/
public function getUrl($key, $downloadUrl = null, $options = array()) {
if ($this->adapter instanceof UrlAware) {
if (array_key_exists('download_url', $this->config))
if (array_key_exists('download_url', $this->config) && !isset($options['download_url']))
$options['download_url'] = $this->generateDownloadUrl($key, $this->config['download_url']);
$downloadUrl = $this->adapter->getUrl($key,$downloadUrl, $options);
}
......
......@@ -12,6 +12,8 @@ class RepositoryS3 extends Repository {
protected function createAdapter($cfg) {
if (!isset($cfg['aws_key']) || empty($cfg['aws_key']))
throw new ParamNotFoundException('param aws_key in S3-repo not set');
if (!isset($cfg['aws_region']) || empty($cfg['aws_region']))
throw new ParamNotFoundException('param aws_region in S3-repo not set');
if (!isset($cfg['aws_secret']) || empty($cfg['aws_secret']))
throw new ParamNotFoundException('param aws_secret in S3-repo not set');
if (!isset($cfg['bucket']) || empty($cfg['bucket']))
......@@ -19,8 +21,12 @@ class RepositoryS3 extends Repository {
// OPtions für AmazonClient
$aws_options = array(
'key' => $cfg['aws_key'],
'secret' => $cfg['aws_secret']
'credentials' => [
'key' => $cfg['aws_key'],
'secret' => $cfg['aws_secret'],
],
'version' => @$cfg['aws_version'] ?: 'latest',
'region' => $cfg['aws_region'],
);
if (isset($cfg['aws_options']) && is_array($cfg['aws_options']))
$aws_options = array_merge($cfg['aws_options'], $aws_options);
......@@ -35,7 +41,8 @@ class RepositoryS3 extends Repository {
$fs_options['region'] = $cfg['region'];
elseif (isset($cfg['host']) && !empty($cfg['host']))
$fs_options['region'] = $cfg['host'];
if (empty($fs_options['region']))
$fs_options['region'] = $aws_options['region'];
// if new SDK not exists, switch automatically to old one
if (!class_exists('\Aws\S3\S3Client'))
$cfg['use_old_version'] = true;
......@@ -45,7 +52,7 @@ class RepositoryS3 extends Repository {
$service = new \AmazonS3($aws_options);
return new AdapterAmazonS3($service, $cfg['bucket'], $fs_options);
} else {
$service = S3Client::factory($aws_options);
$service = new S3Client($aws_options);
return new AdapterAmazonS3Ver2($service, $cfg['bucket'], $fs_options);
}
}
......
......@@ -3,14 +3,13 @@
namespace BNRepo\Tests\Repository;
use BNRepo\Repository\RepositoryManager;
use BNRepo\Repository\RepositoryS3;
class RepositoryAmazonS3Test extends RepositoryTest {
protected $cfg_id = 'bnrepo-test-s3';
protected function tearDown() {
protected function tearDown() {
parent::tearDown();
if ($this->repo()->has('public.txt'))
$this->repo()->delete('public.txt');
......@@ -81,7 +80,16 @@ class RepositoryAmazonS3Test extends RepositoryTest {
}
public function testGetUrl() {
$this->_testGetUrl($this->repo());
// test repo (public access)
$repo = $this->repo();
$this->_testGetUrl($repo);
// test same repo (private access)
$cfg = $repo->getConfig();
$cfg['options']['default_acl'] = 'private';
$cls = get_class($repo);
$repo_private = new $cls($cfg);
$this->_testGetUrl($repo_private);
}
public function testGetPublicUrl() {
......
......@@ -363,6 +363,9 @@ class RepositoryTest extends \PHPUnit_Framework_TestCase {
protected function _testGetUrl(Repository $repo) {
$key = 'subdir/testFile.txt';
if ($repo->has($key))
$repo->delete($key);
$repo->write($key, $this->test_content);
$this->assertTrue($repo->has($key), 'check file exists');
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment