From 0a246f9852ba87583a3cc36c227e68353bb8346b Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 8 Aug 2016 13:54:46 +0200 Subject: [PATCH] split off s3 connection logic Signed-off-by: Robin Appelman --- .../lib/Lib/Storage/AmazonS3.php | 108 ++------------- .../Files/ObjectStore/S3ConnectionTrait.php | 124 ++++++++++++++++++ 2 files changed, 132 insertions(+), 100 deletions(-) create mode 100644 lib/private/Files/ObjectStore/S3ConnectionTrait.php diff --git a/apps/files_external/lib/Lib/Storage/AmazonS3.php b/apps/files_external/lib/Lib/Storage/AmazonS3.php index 25b8e74b82..e6e26e3547 100644 --- a/apps/files_external/lib/Lib/Storage/AmazonS3.php +++ b/apps/files_external/lib/Lib/Storage/AmazonS3.php @@ -38,45 +38,30 @@ namespace OCA\Files_External\Lib\Storage; set_include_path(get_include_path() . PATH_SEPARATOR . \OC_App::getAppPath('files_external') . '/3rdparty/aws-sdk-php'); -require 'aws-autoloader.php'; +require_once 'aws-autoloader.php'; use Aws\S3\S3Client; use Aws\S3\Exception\S3Exception; use Icewind\Streams\IteratorDirectory; +use OC\Files\ObjectStore\S3ConnectionTrait; class AmazonS3 extends \OC\Files\Storage\Common { + use S3ConnectionTrait; - /** - * @var \Aws\S3\S3Client - */ - private $connection; - /** - * @var string - */ - private $bucket; /** * @var array */ private static $tmpFiles = array(); - /** - * @var array - */ - private $params; - /** - * @var bool - */ - private $test = false; - /** - * @var int - */ - private $timeout = 15; + /** * @var int in seconds */ private $rescanDelay = 10; - /** @var string */ - private $id; + public function __construct($parameters) { + parent::__construct($parameters); + $this->parseParams($parameters); + } /** * @param string $path @@ -92,15 +77,6 @@ class AmazonS3 extends \OC\Files\Storage\Common { return $path; } - /** - * when running the tests wait to let the buckets catch up - */ - private function testTimeout() { - if ($this->test) { - sleep($this->timeout); - } - } - private function isRoot($path) { return $path === '.'; } @@ -112,26 +88,6 @@ class AmazonS3 extends \OC\Files\Storage\Common { return $path; } - public function __construct($params) { - if (empty($params['key']) || empty($params['secret']) || empty($params['bucket'])) { - throw new \Exception("Access Key, Secret and Bucket have to be configured."); - } - - $this->id = 'amazon::' . $params['bucket']; - $this->updateLegacyId($params); - - $this->bucket = $params['bucket']; - $this->test = isset($params['test']); - $this->timeout = (!isset($params['timeout'])) ? 15 : $params['timeout']; - $this->rescanDelay = (!isset($params['rescanDelay'])) ? 10 : $params['rescanDelay']; - $params['region'] = empty($params['region']) ? 'eu-west-1' : $params['region']; - $params['hostname'] = empty($params['hostname']) ? 's3.amazonaws.com' : $params['hostname']; - if (!isset($params['port']) || $params['port'] === '') { - $params['port'] = ($params['use_ssl'] === false) ? 80 : 443; - } - $this->params = $params; - } - /** * Updates old storage ids (v0.2.1 and older) that are based on key and secret to new ones based on the bucket name. * TODO Do this in an update.php. requires iterating over all users and loading the mount.json from their home @@ -558,54 +514,6 @@ class AmazonS3 extends \OC\Files\Storage\Common { return $this->id; } - /** - * Returns the connection - * - * @return S3Client connected client - * @throws \Exception if connection could not be made - */ - public function getConnection() { - if (!is_null($this->connection)) { - return $this->connection; - } - - $scheme = ($this->params['use_ssl'] === false) ? 'http' : 'https'; - $base_url = $scheme . '://' . $this->params['hostname'] . ':' . $this->params['port'] . '/'; - - $this->connection = S3Client::factory(array( - 'key' => $this->params['key'], - 'secret' => $this->params['secret'], - 'base_url' => $base_url, - 'region' => $this->params['region'], - S3Client::COMMAND_PARAMS => [ - 'PathStyle' => $this->params['use_path_style'], - ], - )); - - if (!$this->connection->isValidBucketName($this->bucket)) { - throw new \Exception("The configured bucket name is invalid."); - } - - if (!$this->connection->doesBucketExist($this->bucket)) { - try { - $this->connection->createBucket(array( - 'Bucket' => $this->bucket - )); - $this->connection->waitUntilBucketExists(array( - 'Bucket' => $this->bucket, - 'waiter.interval' => 1, - 'waiter.max_attempts' => 15 - )); - $this->testTimeout(); - } catch (S3Exception $e) { - \OCP\Util::logException('files_external', $e); - throw new \Exception('Creation of bucket failed. '.$e->getMessage()); - } - } - - return $this->connection; - } - public function writeBack($tmpFile) { if (!isset(self::$tmpFiles[$tmpFile])) { return false; diff --git a/lib/private/Files/ObjectStore/S3ConnectionTrait.php b/lib/private/Files/ObjectStore/S3ConnectionTrait.php new file mode 100644 index 0000000000..a8b57cb18d --- /dev/null +++ b/lib/private/Files/ObjectStore/S3ConnectionTrait.php @@ -0,0 +1,124 @@ + + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OC\Files\ObjectStore; + +use Aws\S3\Exception\S3Exception; +use Aws\S3\S3Client; + +trait S3ConnectionTrait { + /** @var array */ + protected $params; + + /** @var S3Client */ + protected $connection; + + /** @var string */ + protected $id; + + /** @var string */ + protected $bucket; + + /** @var int */ + protected $timeout; + + protected $test; + + protected function parseParams($params) { + if (empty($params['key']) || empty($params['secret']) || empty($params['bucket'])) { + throw new \Exception("Access Key, Secret and Bucket have to be configured."); + } + + $this->id = 'amazon::' . $params['bucket']; + + $this->test = isset($params['test']); + $this->bucket = $params['bucket']; + $this->timeout = (!isset($params['timeout'])) ? 15 : $params['timeout']; + $params['region'] = empty($params['region']) ? 'eu-west-1' : $params['region']; + $params['hostname'] = empty($params['hostname']) ? 's3.amazonaws.com' : $params['hostname']; + if (!isset($params['port']) || $params['port'] === '') { + $params['port'] = (isset($params['use_ssl']) && $params['use_ssl'] === false) ? 80 : 443; + } + $this->params = $params; + } + + + /** + * Returns the connection + * + * @return S3Client connected client + * @throws \Exception if connection could not be made + */ + protected function getConnection() { + if (!is_null($this->connection)) { + return $this->connection; + } + + $scheme = (isset($this->params['use_ssl']) && $this->params['use_ssl'] === false) ? 'http' : 'https'; + $base_url = $scheme . '://' . $this->params['hostname'] . ':' . $this->params['port'] . '/'; + + $options = [ + 'key' => $this->params['key'], + 'secret' => $this->params['secret'], + 'base_url' => $base_url, + 'region' => $this->params['region'], + S3Client::COMMAND_PARAMS => [ + 'PathStyle' => isset($this->params['use_path_style']) ? $this->params['use_path_style'] : false, + ] + ]; + if (isset($this->params['proxy'])) { + $options[S3Client::REQUEST_OPTIONS] = ['proxy' => $this->params['proxy']]; + } + $this->connection = S3Client::factory($options); + + if (!$this->connection->isValidBucketName($this->bucket)) { + throw new \Exception("The configured bucket name is invalid."); + } + + if (!$this->connection->doesBucketExist($this->bucket)) { + try { + $this->connection->createBucket(array( + 'Bucket' => $this->bucket + )); + $this->connection->waitUntilBucketExists(array( + 'Bucket' => $this->bucket, + 'waiter.interval' => 1, + 'waiter.max_attempts' => 15 + )); + $this->testTimeout(); + } catch (S3Exception $e) { + \OCP\Util::logException('files_external', $e); + throw new \Exception('Creation of bucket failed. ' . $e->getMessage()); + } + } + + return $this->connection; + } + + /** + * when running the tests wait to let the buckets catch up + */ + private function testTimeout() { + if ($this->test) { + sleep($this->timeout); + } + } +}