summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/private/Files/Mount/ObjectStorePreviewCacheMountProvider.php51
-rw-r--r--lib/private/Preview/Storage/Root.php11
-rw-r--r--tests/lib/Files/Mount/ObjectStorePreviewCacheMountProviderTest.php106
3 files changed, 165 insertions, 3 deletions
diff --git a/lib/private/Files/Mount/ObjectStorePreviewCacheMountProvider.php b/lib/private/Files/Mount/ObjectStorePreviewCacheMountProvider.php
index a4acdb6bb0f..9ab0327684b 100644
--- a/lib/private/Files/Mount/ObjectStorePreviewCacheMountProvider.php
+++ b/lib/private/Files/Mount/ObjectStorePreviewCacheMountProvider.php
@@ -26,6 +26,8 @@ declare(strict_types=1);
namespace OC\Files\Mount;
use OC\Files\ObjectStore\AppdataPreviewObjectStoreStorage;
+use OC\Files\ObjectStore\ObjectStoreStorage;
+use OC\Files\Storage\Wrapper\Jail;
use OCP\Files\Config\IRootMountProvider;
use OCP\Files\Storage\IStorageFactory;
use OCP\IConfig;
@@ -45,6 +47,10 @@ class ObjectStorePreviewCacheMountProvider implements IRootMountProvider {
$this->config = $config;
}
+ /**
+ * @return MountPoint[]
+ * @throws \Exception
+ */
public function getRootMounts(IStorageFactory $loader): array {
if (!is_array($this->config->getSystemValue('objectstore_multibucket'))) {
return [];
@@ -65,12 +71,25 @@ class ObjectStorePreviewCacheMountProvider implements IRootMountProvider {
$i++;
}
}
+
+ $rootStorageArguments = $this->getMultiBucketObjectStoreForRoot();
+ $fakeRootStorage = new ObjectStoreStorage($rootStorageArguments);
+ $fakeRootStorageJail = new Jail([
+ 'storage' => $fakeRootStorage,
+ 'root' => '/appdata_' . $instanceId . '/preview',
+ ]);
+
+ // add a fallback location to be able to fetch existing previews from the old bucket
+ $mountPoints[] = new MountPoint(
+ $fakeRootStorageJail,
+ '/appdata_' . $instanceId . '/preview/old-multibucket',
+ null,
+ $loader
+ );
+
return $mountPoints;
}
- /**
- * @return array
- */
protected function getMultiBucketObjectStore(int $number): array {
$config = $this->config->getSystemValue('objectstore_multibucket');
@@ -99,4 +118,30 @@ class ObjectStorePreviewCacheMountProvider implements IRootMountProvider {
return $config['arguments'];
}
+
+ protected function getMultiBucketObjectStoreForRoot(): array {
+ $config = $this->config->getSystemValue('objectstore_multibucket');
+
+ // sanity checks
+ if (empty($config['class'])) {
+ $this->logger->error('No class given for objectstore', ['app' => 'files']);
+ }
+ if (!isset($config['arguments'])) {
+ $config['arguments'] = [];
+ }
+
+ /*
+ * Use any provided bucket argument as prefix
+ * and add the mapping from parent/child => bucket
+ */
+ if (!isset($config['arguments']['bucket'])) {
+ $config['arguments']['bucket'] = '';
+ }
+ $config['arguments']['bucket'] .= '0';
+
+ // instantiate object store implementation
+ $config['arguments']['objectstore'] = new $config['class']($config['arguments']);
+
+ return $config['arguments'];
+ }
}
diff --git a/lib/private/Preview/Storage/Root.php b/lib/private/Preview/Storage/Root.php
index 107d87c6301..37ae1758121 100644
--- a/lib/private/Preview/Storage/Root.php
+++ b/lib/private/Preview/Storage/Root.php
@@ -41,6 +41,17 @@ class Root extends AppData {
$internalFolder = $this->getInternalFolder($name);
try {
+ return parent::getFolder('old-multibucket/' . $internalFolder);
+ } catch (NotFoundException $e) {
+ // not in multibucket fallback #1
+ }
+ try {
+ return parent::getFolder('old-multibucket/' . $name);
+ } catch (NotFoundException $e) {
+ // not in multibucket fallback #2
+ }
+
+ try {
return parent::getFolder($internalFolder);
} catch (NotFoundException $e) {
/*
diff --git a/tests/lib/Files/Mount/ObjectStorePreviewCacheMountProviderTest.php b/tests/lib/Files/Mount/ObjectStorePreviewCacheMountProviderTest.php
new file mode 100644
index 00000000000..2da07393f40
--- /dev/null
+++ b/tests/lib/Files/Mount/ObjectStorePreviewCacheMountProviderTest.php
@@ -0,0 +1,106 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2020, Morris Jobke <hey@morrisjobke.de>
+ *
+ * @author Morris Jobke <hey@morrisjobke.de>
+ *
+ * @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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Test\Files\Mount;
+
+use OC\Files\Mount\ObjectStorePreviewCacheMountProvider;
+use OC\Files\ObjectStore\S3;
+use OC\Files\Storage\StorageFactory;
+use OCP\Files\Storage\IStorageFactory;
+use OCP\IConfig;
+use OCP\ILogger;
+use PHPUnit\Framework\MockObject\MockObject;
+
+/**
+ * @group DB
+ *
+ * The DB permission is needed for the fake root storage initialization
+ */
+class ObjectStorePreviewCacheMountProviderTest extends \Test\TestCase {
+
+ /** @var ObjectStorePreviewCacheMountProvider */
+ protected $provider;
+
+ /** @var ILogger|MockObject */
+ protected $logger;
+ /** @var IConfig|MockObject */
+ protected $config;
+ /** @var IStorageFactory|MockObject */
+ protected $loader;
+
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->logger = $this->createMock(ILogger::class);
+ $this->config = $this->createMock(IConfig::class);
+ $this->loader = $this->createMock(StorageFactory::class);
+
+ $this->provider = new ObjectStorePreviewCacheMountProvider($this->logger, $this->config);
+ }
+
+ public function testNoMultibucketObjectStorage() {
+ $this->config->expects($this->once())
+ ->method('getSystemValue')
+ ->with('objectstore_multibucket')
+ ->willReturn(null);
+
+ $this->assertEquals([], $this->provider->getRootMounts($this->loader));
+ }
+
+ public function testMultibucketObjectStorage() {
+ $this->config->expects($this->any())
+ ->method('getSystemValue')
+ ->with('objectstore_multibucket')
+ ->willReturn([
+ 'class' => S3::class,
+ 'arguments' => [
+ 'bucket' => 'abc',
+ 'num_buckets' => 64,
+ 'key' => 'KEY',
+ 'secret' => 'SECRET',
+ 'hostname' => 'IP',
+ 'port' => 'PORT',
+ 'use_ssl' => false,
+ 'use_path_style' => true,
+ ],
+ ]);
+ $this->config->expects($this->once())
+ ->method('getSystemValueString')
+ ->with('instanceid')
+ ->willReturn('INSTANCEID');
+
+ $mounts = $this->provider->getRootMounts($this->loader);
+
+ // 256 mounts for the subfolders and 1 for the fake root
+ $this->assertCount(257, $mounts);
+
+ // do some sanity checks if they have correct mount point paths
+ $this->assertEquals('/appdata_INSTANCEID/preview/0/0/', $mounts[0]->getMountPoint());
+ $this->assertEquals('/appdata_INSTANCEID/preview/2/5/', $mounts[37]->getMountPoint());
+ // also test the path of the fake bucket
+ $this->assertEquals('/appdata_INSTANCEID/preview/old-multibucket/', $mounts[256]->getMountPoint());
+ }
+}