mirror of
https://github.com/nextcloud/server.git
synced 2026-02-20 00:12:30 -05:00
Merge pull request #52816 from nextcloud/primary-object-store-settings
feat: move primary object store configuration to a single place
This commit is contained in:
commit
be3cfefc75
10 changed files with 316 additions and 266 deletions
|
|
@ -3885,14 +3885,6 @@
|
|||
<code><![CDATA[wrap]]></code>
|
||||
</UndefinedInterfaceMethod>
|
||||
</file>
|
||||
<file src="lib/private/Files/Mount/ObjectHomeMountProvider.php">
|
||||
<InvalidNullableReturnType>
|
||||
<code><![CDATA[\OCP\Files\Mount\IMountPoint]]></code>
|
||||
</InvalidNullableReturnType>
|
||||
<NullableReturnStatement>
|
||||
<code><![CDATA[null]]></code>
|
||||
</NullableReturnStatement>
|
||||
</file>
|
||||
<file src="lib/private/Files/Node/File.php">
|
||||
<InvalidReturnStatement>
|
||||
<code><![CDATA[$this->view->hash($type, $this->path, $raw)]]></code>
|
||||
|
|
|
|||
|
|
@ -1644,6 +1644,7 @@ return array(
|
|||
'OC\\Files\\ObjectStore\\Mapper' => $baseDir . '/lib/private/Files/ObjectStore/Mapper.php',
|
||||
'OC\\Files\\ObjectStore\\ObjectStoreScanner' => $baseDir . '/lib/private/Files/ObjectStore/ObjectStoreScanner.php',
|
||||
'OC\\Files\\ObjectStore\\ObjectStoreStorage' => $baseDir . '/lib/private/Files/ObjectStore/ObjectStoreStorage.php',
|
||||
'OC\\Files\\ObjectStore\\PrimaryObjectStoreConfig' => $baseDir . '/lib/private/Files/ObjectStore/PrimaryObjectStoreConfig.php',
|
||||
'OC\\Files\\ObjectStore\\S3' => $baseDir . '/lib/private/Files/ObjectStore/S3.php',
|
||||
'OC\\Files\\ObjectStore\\S3ConfigTrait' => $baseDir . '/lib/private/Files/ObjectStore/S3ConfigTrait.php',
|
||||
'OC\\Files\\ObjectStore\\S3ConnectionTrait' => $baseDir . '/lib/private/Files/ObjectStore/S3ConnectionTrait.php',
|
||||
|
|
|
|||
|
|
@ -1685,6 +1685,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
|
|||
'OC\\Files\\ObjectStore\\Mapper' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/Mapper.php',
|
||||
'OC\\Files\\ObjectStore\\ObjectStoreScanner' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/ObjectStoreScanner.php',
|
||||
'OC\\Files\\ObjectStore\\ObjectStoreStorage' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/ObjectStoreStorage.php',
|
||||
'OC\\Files\\ObjectStore\\PrimaryObjectStoreConfig' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/PrimaryObjectStoreConfig.php',
|
||||
'OC\\Files\\ObjectStore\\S3' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/S3.php',
|
||||
'OC\\Files\\ObjectStore\\S3ConfigTrait' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/S3ConfigTrait.php',
|
||||
'OC\\Files\\ObjectStore\\S3ConnectionTrait' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/S3ConnectionTrait.php',
|
||||
|
|
|
|||
|
|
@ -7,117 +7,39 @@
|
|||
*/
|
||||
namespace OC\Files\Mount;
|
||||
|
||||
use OC\Files\ObjectStore\HomeObjectStoreStorage;
|
||||
use OC\Files\ObjectStore\PrimaryObjectStoreConfig;
|
||||
use OCP\Files\Config\IHomeMountProvider;
|
||||
use OCP\Files\Mount\IMountPoint;
|
||||
use OCP\Files\Storage\IStorageFactory;
|
||||
use OCP\IConfig;
|
||||
use OCP\IUser;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Mount provider for object store home storages
|
||||
*/
|
||||
class ObjectHomeMountProvider implements IHomeMountProvider {
|
||||
/**
|
||||
* @var IConfig
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* ObjectStoreHomeMountProvider constructor.
|
||||
*
|
||||
* @param IConfig $config
|
||||
*/
|
||||
public function __construct(IConfig $config) {
|
||||
$this->config = $config;
|
||||
public function __construct(
|
||||
private PrimaryObjectStoreConfig $objectStoreConfig,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cache mount for a user
|
||||
* Get the home mount for a user
|
||||
*
|
||||
* @param IUser $user
|
||||
* @param IStorageFactory $loader
|
||||
* @return \OCP\Files\Mount\IMountPoint
|
||||
* @return ?IMountPoint
|
||||
*/
|
||||
public function getHomeMountForUser(IUser $user, IStorageFactory $loader) {
|
||||
$config = $this->getMultiBucketObjectStoreConfig($user);
|
||||
if ($config === null) {
|
||||
$config = $this->getSingleBucketObjectStoreConfig($user);
|
||||
}
|
||||
|
||||
if ($config === null) {
|
||||
public function getHomeMountForUser(IUser $user, IStorageFactory $loader): ?IMountPoint {
|
||||
$objectStoreConfig = $this->objectStoreConfig->getObjectStoreConfigForUser($user);
|
||||
if ($objectStoreConfig === null) {
|
||||
return null;
|
||||
}
|
||||
$arguments = array_merge($objectStoreConfig['arguments'], [
|
||||
'objectstore' => $this->objectStoreConfig->buildObjectStore($objectStoreConfig),
|
||||
'user' => $user,
|
||||
]);
|
||||
|
||||
return new HomeMountPoint($user, '\OC\Files\ObjectStore\HomeObjectStoreStorage', '/' . $user->getUID(), $config['arguments'], $loader, null, null, self::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IUser $user
|
||||
* @return array|null
|
||||
*/
|
||||
private function getSingleBucketObjectStoreConfig(IUser $user) {
|
||||
$config = $this->config->getSystemValue('objectstore');
|
||||
if (!is_array($config)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// sanity checks
|
||||
if (empty($config['class'])) {
|
||||
\OC::$server->get(LoggerInterface::class)->error('No class given for objectstore', ['app' => 'files']);
|
||||
}
|
||||
if (!isset($config['arguments'])) {
|
||||
$config['arguments'] = [];
|
||||
}
|
||||
// instantiate object store implementation
|
||||
$config['arguments']['objectstore'] = new $config['class']($config['arguments']);
|
||||
|
||||
$config['arguments']['user'] = $user;
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IUser $user
|
||||
* @return array|null
|
||||
*/
|
||||
private function getMultiBucketObjectStoreConfig(IUser $user) {
|
||||
$config = $this->config->getSystemValue('objectstore_multibucket');
|
||||
if (!is_array($config)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// sanity checks
|
||||
if (empty($config['class'])) {
|
||||
\OC::$server->get(LoggerInterface::class)->error('No class given for objectstore', ['app' => 'files']);
|
||||
}
|
||||
if (!isset($config['arguments'])) {
|
||||
$config['arguments'] = [];
|
||||
}
|
||||
|
||||
$bucket = $this->config->getUserValue($user->getUID(), 'homeobjectstore', 'bucket', null);
|
||||
|
||||
if ($bucket === null) {
|
||||
/*
|
||||
* Use any provided bucket argument as prefix
|
||||
* and add the mapping from username => bucket
|
||||
*/
|
||||
if (!isset($config['arguments']['bucket'])) {
|
||||
$config['arguments']['bucket'] = '';
|
||||
}
|
||||
$mapper = new \OC\Files\ObjectStore\Mapper($user, $this->config);
|
||||
$numBuckets = $config['arguments']['num_buckets'] ?? 64;
|
||||
$config['arguments']['bucket'] .= $mapper->getBucket($numBuckets);
|
||||
|
||||
$this->config->setUserValue($user->getUID(), 'homeobjectstore', 'bucket', $config['arguments']['bucket']);
|
||||
} else {
|
||||
$config['arguments']['bucket'] = $bucket;
|
||||
}
|
||||
|
||||
// instantiate object store implementation
|
||||
$config['arguments']['objectstore'] = new $config['class']($config['arguments']);
|
||||
|
||||
$config['arguments']['user'] = $user;
|
||||
|
||||
return $config;
|
||||
return new HomeMountPoint($user, HomeObjectStoreStorage::class, '/' . $user->getUID(), $arguments, $loader, null, null, self::class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,79 +10,41 @@ namespace OC\Files\Mount;
|
|||
|
||||
use OC;
|
||||
use OC\Files\ObjectStore\ObjectStoreStorage;
|
||||
use OC\Files\ObjectStore\PrimaryObjectStoreConfig;
|
||||
use OC\Files\Storage\LocalRootStorage;
|
||||
use OC_App;
|
||||
use OCP\Files\Config\IRootMountProvider;
|
||||
use OCP\Files\Storage\IStorageFactory;
|
||||
use OCP\IConfig;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class RootMountProvider implements IRootMountProvider {
|
||||
private PrimaryObjectStoreConfig $objectStoreConfig;
|
||||
private IConfig $config;
|
||||
private LoggerInterface $logger;
|
||||
|
||||
public function __construct(IConfig $config, LoggerInterface $logger) {
|
||||
public function __construct(PrimaryObjectStoreConfig $objectStoreConfig, IConfig $config) {
|
||||
$this->objectStoreConfig = $objectStoreConfig;
|
||||
$this->config = $config;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
public function getRootMounts(IStorageFactory $loader): array {
|
||||
$objectStore = $this->config->getSystemValue('objectstore', null);
|
||||
$objectStoreMultiBucket = $this->config->getSystemValue('objectstore_multibucket', null);
|
||||
$objectStoreConfig = $this->objectStoreConfig->getObjectStoreConfigForRoot();
|
||||
|
||||
if ($objectStoreMultiBucket) {
|
||||
return [$this->getMultiBucketStoreRootMount($loader, $objectStoreMultiBucket)];
|
||||
} elseif ($objectStore) {
|
||||
return [$this->getObjectStoreRootMount($loader, $objectStore)];
|
||||
if ($objectStoreConfig) {
|
||||
return [$this->getObjectStoreRootMount($loader, $objectStoreConfig)];
|
||||
} else {
|
||||
return [$this->getLocalRootMount($loader)];
|
||||
}
|
||||
}
|
||||
|
||||
private function validateObjectStoreConfig(array &$config) {
|
||||
if (empty($config['class'])) {
|
||||
$this->logger->error('No class given for objectstore', ['app' => 'files']);
|
||||
}
|
||||
if (!isset($config['arguments'])) {
|
||||
$config['arguments'] = [];
|
||||
}
|
||||
|
||||
// instantiate object store implementation
|
||||
$name = $config['class'];
|
||||
if (str_starts_with($name, 'OCA\\') && substr_count($name, '\\') >= 2) {
|
||||
$segments = explode('\\', $name);
|
||||
OC_App::loadApp(strtolower($segments[1]));
|
||||
}
|
||||
}
|
||||
|
||||
private function getLocalRootMount(IStorageFactory $loader): MountPoint {
|
||||
$configDataDirectory = $this->config->getSystemValue('datadirectory', OC::$SERVERROOT . '/data');
|
||||
return new MountPoint(LocalRootStorage::class, '/', ['datadir' => $configDataDirectory], $loader, null, null, self::class);
|
||||
}
|
||||
|
||||
private function getObjectStoreRootMount(IStorageFactory $loader, array $config): MountPoint {
|
||||
$this->validateObjectStoreConfig($config);
|
||||
private function getObjectStoreRootMount(IStorageFactory $loader, array $objectStoreConfig): MountPoint {
|
||||
$arguments = array_merge($objectStoreConfig['arguments'], [
|
||||
'objectstore' => $this->objectStoreConfig->buildObjectStore($objectStoreConfig),
|
||||
]);
|
||||
|
||||
$config['arguments']['objectstore'] = new $config['class']($config['arguments']);
|
||||
// mount with plain / root object store implementation
|
||||
$config['class'] = ObjectStoreStorage::class;
|
||||
|
||||
return new MountPoint($config['class'], '/', $config['arguments'], $loader, null, null, self::class);
|
||||
}
|
||||
|
||||
private function getMultiBucketStoreRootMount(IStorageFactory $loader, array $config): MountPoint {
|
||||
$this->validateObjectStoreConfig($config);
|
||||
|
||||
if (!isset($config['arguments']['bucket'])) {
|
||||
$config['arguments']['bucket'] = '';
|
||||
}
|
||||
// put the root FS always in first bucket for multibucket configuration
|
||||
$config['arguments']['bucket'] .= '0';
|
||||
|
||||
$config['arguments']['objectstore'] = new $config['class']($config['arguments']);
|
||||
// mount with plain / root object store implementation
|
||||
$config['class'] = ObjectStoreStorage::class;
|
||||
|
||||
return new MountPoint($config['class'], '/', $config['arguments'], $loader, null, null, self::class);
|
||||
return new MountPoint(ObjectStoreStorage::class, '/', $arguments, $loader, null, null, self::class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
140
lib/private/Files/ObjectStore/PrimaryObjectStoreConfig.php
Normal file
140
lib/private/Files/ObjectStore/PrimaryObjectStoreConfig.php
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
namespace OC\Files\ObjectStore;
|
||||
|
||||
use OCP\App\IAppManager;
|
||||
use OCP\Files\ObjectStore\IObjectStore;
|
||||
use OCP\IConfig;
|
||||
use OCP\IUser;
|
||||
|
||||
/**
|
||||
* @psalm-type ObjectStoreConfig array{class: class-string<IObjectStore>, arguments: array{multibucket: bool, ...}}
|
||||
*/
|
||||
class PrimaryObjectStoreConfig {
|
||||
public function __construct(
|
||||
private readonly IConfig $config,
|
||||
private readonly IAppManager $appManager,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ObjectStoreConfig $config
|
||||
*/
|
||||
public function buildObjectStore(array $config): IObjectStore {
|
||||
return new $config['class']($config['arguments']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ?ObjectStoreConfig
|
||||
*/
|
||||
public function getObjectStoreConfigForRoot(): ?array {
|
||||
$config = $this->getObjectStoreConfig();
|
||||
|
||||
if ($config && $config['arguments']['multibucket']) {
|
||||
if (!isset($config['arguments']['bucket'])) {
|
||||
$config['arguments']['bucket'] = '';
|
||||
}
|
||||
|
||||
// put the root FS always in first bucket for multibucket configuration
|
||||
$config['arguments']['bucket'] .= '0';
|
||||
}
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ?ObjectStoreConfig
|
||||
*/
|
||||
public function getObjectStoreConfigForUser(IUser $user): ?array {
|
||||
$config = $this->getObjectStoreConfig();
|
||||
|
||||
if ($config && $config['arguments']['multibucket']) {
|
||||
$config['arguments']['bucket'] = $this->getBucketForUser($user, $config);
|
||||
}
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ?ObjectStoreConfig
|
||||
*/
|
||||
private function getObjectStoreConfig(): ?array {
|
||||
$objectStore = $this->config->getSystemValue('objectstore', null);
|
||||
$objectStoreMultiBucket = $this->config->getSystemValue('objectstore_multibucket', null);
|
||||
|
||||
// new-style multibucket config uses the same 'objectstore' key but sets `'multibucket' => true`, transparently upgrade older style config
|
||||
if ($objectStoreMultiBucket) {
|
||||
$objectStoreMultiBucket['arguments']['multibucket'] = true;
|
||||
return $this->validateObjectStoreConfig($objectStoreMultiBucket);
|
||||
} elseif ($objectStore) {
|
||||
return $this->validateObjectStoreConfig($objectStore);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ObjectStoreConfig
|
||||
*/
|
||||
private function validateObjectStoreConfig(array $config) {
|
||||
if (!isset($config['class'])) {
|
||||
throw new \Exception('No class configured for object store');
|
||||
}
|
||||
if (!isset($config['arguments'])) {
|
||||
$config['arguments'] = [];
|
||||
}
|
||||
$class = $config['class'];
|
||||
$arguments = $config['arguments'];
|
||||
if (!is_array($arguments)) {
|
||||
throw new \Exception('Configured object store arguments are not an array');
|
||||
}
|
||||
if (!isset($arguments['multibucket'])) {
|
||||
$arguments['multibucket'] = false;
|
||||
}
|
||||
if (!is_bool($arguments['multibucket'])) {
|
||||
throw new \Exception('arguments.multibucket must be a boolean in object store configuration');
|
||||
}
|
||||
|
||||
if (!is_string($class)) {
|
||||
throw new \Exception('Configured class for object store is not a string');
|
||||
}
|
||||
|
||||
if (str_starts_with($class, 'OCA\\') && substr_count($class, '\\') >= 2) {
|
||||
[$appId] = explode('\\', $class);
|
||||
$this->appManager->loadApp(strtolower($appId));
|
||||
}
|
||||
|
||||
if (!is_a($class, IObjectStore::class, true)) {
|
||||
throw new \Exception('Configured class for object store is not an object store');
|
||||
}
|
||||
return [
|
||||
'class' => $class,
|
||||
'arguments' => $arguments,
|
||||
];
|
||||
}
|
||||
|
||||
private function getBucketForUser(IUser $user, array $config): string {
|
||||
$bucket = $this->config->getUserValue($user->getUID(), 'homeobjectstore', 'bucket', null);
|
||||
|
||||
if ($bucket === null) {
|
||||
/*
|
||||
* Use any provided bucket argument as prefix
|
||||
* and add the mapping from username => bucket
|
||||
*/
|
||||
if (!isset($config['arguments']['bucket'])) {
|
||||
$config['arguments']['bucket'] = '';
|
||||
}
|
||||
$mapper = new Mapper($user, $this->config);
|
||||
$numBuckets = isset($config['arguments']['num_buckets']) ? $config['arguments']['num_buckets'] : 64;
|
||||
$bucket = $config['arguments']['bucket'] . $mapper->getBucket($numBuckets);
|
||||
|
||||
$this->config->setUserValue($user->getUID(), 'homeobjectstore', 'bucket', $bucket);
|
||||
}
|
||||
|
||||
return $bucket;
|
||||
}
|
||||
}
|
||||
|
|
@ -55,6 +55,7 @@ use OC\Files\Mount\RootMountProvider;
|
|||
use OC\Files\Node\HookConnector;
|
||||
use OC\Files\Node\LazyRoot;
|
||||
use OC\Files\Node\Root;
|
||||
use OC\Files\ObjectStore\PrimaryObjectStoreConfig;
|
||||
use OC\Files\SetupManager;
|
||||
use OC\Files\Storage\StorageFactory;
|
||||
use OC\Files\Template\TemplateManager;
|
||||
|
|
@ -819,10 +820,11 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
|
||||
$config = $c->get(\OCP\IConfig::class);
|
||||
$logger = $c->get(LoggerInterface::class);
|
||||
$objectStoreConfig = $c->get(PrimaryObjectStoreConfig::class);
|
||||
$manager->registerProvider(new CacheMountProvider($config));
|
||||
$manager->registerHomeProvider(new LocalHomeMountProvider());
|
||||
$manager->registerHomeProvider(new ObjectHomeMountProvider($config));
|
||||
$manager->registerRootProvider(new RootMountProvider($config, $c->get(LoggerInterface::class)));
|
||||
$manager->registerHomeProvider(new ObjectHomeMountProvider($objectStoreConfig));
|
||||
$manager->registerRootProvider(new RootMountProvider($objectStoreConfig, $config));
|
||||
$manager->registerRootProvider(new ObjectStorePreviewCacheMountProvider($logger, $config));
|
||||
|
||||
return $manager;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@
|
|||
namespace Test\Files\Mount;
|
||||
|
||||
use OC\Files\Mount\ObjectHomeMountProvider;
|
||||
use OC\Files\ObjectStore\PrimaryObjectStoreConfig;
|
||||
use OCP\App\IAppManager;
|
||||
use OCP\Files\ObjectStore\IObjectStore;
|
||||
use OCP\Files\Storage\IStorageFactory;
|
||||
use OCP\IConfig;
|
||||
use OCP\IUser;
|
||||
|
|
@ -31,51 +34,54 @@ class ObjectHomeMountProviderTest extends \Test\TestCase {
|
|||
$this->user = $this->createMock(IUser::class);
|
||||
$this->loader = $this->createMock(IStorageFactory::class);
|
||||
|
||||
$this->provider = new ObjectHomeMountProvider($this->config);
|
||||
$objectStoreConfig = new PrimaryObjectStoreConfig($this->config, $this->createMock(IAppManager::class));
|
||||
$this->provider = new ObjectHomeMountProvider($objectStoreConfig);
|
||||
}
|
||||
|
||||
public function testSingleBucket(): void {
|
||||
$this->config->expects($this->once())
|
||||
->method('getSystemValue')
|
||||
->with($this->equalTo('objectstore'), '')
|
||||
->willReturn([
|
||||
'class' => 'Test\Files\Mount\FakeObjectStore',
|
||||
]);
|
||||
$this->config->method('getSystemValue')
|
||||
->willReturnCallback(function ($key, $default) {
|
||||
if ($key === 'objectstore') {
|
||||
return [
|
||||
'class' => 'Test\Files\Mount\FakeObjectStore',
|
||||
'arguments' => [
|
||||
'foo' => 'bar'
|
||||
],
|
||||
];
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
});
|
||||
|
||||
$this->user->expects($this->never())->method($this->anything());
|
||||
$this->loader->expects($this->never())->method($this->anything());
|
||||
$mount = $this->provider->getHomeMountForUser($this->user, $this->loader);
|
||||
$arguments = $this->invokePrivate($mount, 'arguments');
|
||||
|
||||
$config = $this->invokePrivate($this->provider, 'getSingleBucketObjectStoreConfig', [$this->user, $this->loader]);
|
||||
|
||||
$this->assertArrayHasKey('class', $config);
|
||||
$this->assertEquals($config['class'], 'Test\Files\Mount\FakeObjectStore');
|
||||
$this->assertArrayHasKey('arguments', $config);
|
||||
$this->assertArrayHasKey('user', $config['arguments']);
|
||||
$this->assertSame($this->user, $config['arguments']['user']);
|
||||
$this->assertArrayHasKey('objectstore', $config['arguments']);
|
||||
$this->assertInstanceOf('Test\Files\Mount\FakeObjectStore', $config['arguments']['objectstore']);
|
||||
$objectStore = $arguments['objectstore'];
|
||||
$this->assertInstanceOf(FakeObjectStore::class, $objectStore);
|
||||
$this->assertEquals(['foo' => 'bar', 'multibucket' => false], $objectStore->getArguments());
|
||||
}
|
||||
|
||||
public function testMultiBucket(): void {
|
||||
$this->config->expects($this->exactly(2))
|
||||
->method('getSystemValue')
|
||||
->with($this->equalTo('objectstore_multibucket'), '')
|
||||
->willReturn([
|
||||
'class' => 'Test\Files\Mount\FakeObjectStore',
|
||||
]);
|
||||
$this->config->method('getSystemValue')
|
||||
->willReturnCallback(function ($key, $default) {
|
||||
if ($key === 'objectstore_multibucket') {
|
||||
return [
|
||||
'class' => 'Test\Files\Mount\FakeObjectStore',
|
||||
'arguments' => [
|
||||
'foo' => 'bar'
|
||||
],
|
||||
];
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
});
|
||||
|
||||
$this->user->method('getUID')
|
||||
->willReturn('uid');
|
||||
$this->loader->expects($this->never())->method($this->anything());
|
||||
|
||||
$this->config->expects($this->once())
|
||||
->method('getUserValue')
|
||||
->with(
|
||||
$this->equalTo('uid'),
|
||||
$this->equalTo('homeobjectstore'),
|
||||
$this->equalTo('bucket'),
|
||||
$this->equalTo(null)
|
||||
)->willReturn(null);
|
||||
$this->config->method('getUserValue')
|
||||
->willReturn(null);
|
||||
|
||||
$this->config->expects($this->once())
|
||||
->method('setUserValue')
|
||||
|
|
@ -87,42 +93,37 @@ class ObjectHomeMountProviderTest extends \Test\TestCase {
|
|||
$this->equalTo(null)
|
||||
);
|
||||
|
||||
$config = $this->invokePrivate($this->provider, 'getMultiBucketObjectStoreConfig', [$this->user, $this->loader]);
|
||||
$mount = $this->provider->getHomeMountForUser($this->user, $this->loader);
|
||||
$arguments = $this->invokePrivate($mount, 'arguments');
|
||||
|
||||
$this->assertArrayHasKey('class', $config);
|
||||
$this->assertEquals($config['class'], 'Test\Files\Mount\FakeObjectStore');
|
||||
$this->assertArrayHasKey('arguments', $config);
|
||||
$this->assertArrayHasKey('user', $config['arguments']);
|
||||
$this->assertSame($this->user, $config['arguments']['user']);
|
||||
$this->assertArrayHasKey('objectstore', $config['arguments']);
|
||||
$this->assertInstanceOf('Test\Files\Mount\FakeObjectStore', $config['arguments']['objectstore']);
|
||||
$this->assertArrayHasKey('bucket', $config['arguments']);
|
||||
$this->assertEquals('49', $config['arguments']['bucket']);
|
||||
$objectStore = $arguments['objectstore'];
|
||||
$this->assertInstanceOf(FakeObjectStore::class, $objectStore);
|
||||
$this->assertEquals(['foo' => 'bar', 'bucket' => 49, 'multibucket' => true], $objectStore->getArguments());
|
||||
}
|
||||
|
||||
public function testMultiBucketWithPrefix(): void {
|
||||
$this->config->expects($this->exactly(2))
|
||||
->method('getSystemValue')
|
||||
->with('objectstore_multibucket')
|
||||
->willReturn([
|
||||
'class' => 'Test\Files\Mount\FakeObjectStore',
|
||||
'arguments' => [
|
||||
'bucket' => 'myBucketPrefix',
|
||||
],
|
||||
]);
|
||||
$this->config->method('getSystemValue')
|
||||
->willReturnCallback(function ($key, $default) {
|
||||
if ($key === 'objectstore_multibucket') {
|
||||
return [
|
||||
'class' => 'Test\Files\Mount\FakeObjectStore',
|
||||
'arguments' => [
|
||||
'foo' => 'bar',
|
||||
'bucket' => 'myBucketPrefix',
|
||||
],
|
||||
];
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
});
|
||||
|
||||
$this->user->method('getUID')
|
||||
->willReturn('uid');
|
||||
$this->loader->expects($this->never())->method($this->anything());
|
||||
|
||||
$this->config->expects($this->once())
|
||||
$this->config
|
||||
->method('getUserValue')
|
||||
->with(
|
||||
$this->equalTo('uid'),
|
||||
$this->equalTo('homeobjectstore'),
|
||||
$this->equalTo('bucket'),
|
||||
$this->equalTo(null)
|
||||
)->willReturn(null);
|
||||
->willReturn(null);
|
||||
|
||||
$this->config->expects($this->once())
|
||||
->method('setUserValue')
|
||||
|
|
@ -134,66 +135,70 @@ class ObjectHomeMountProviderTest extends \Test\TestCase {
|
|||
$this->equalTo(null)
|
||||
);
|
||||
|
||||
$config = $this->invokePrivate($this->provider, 'getMultiBucketObjectStoreConfig', [$this->user, $this->loader]);
|
||||
$mount = $this->provider->getHomeMountForUser($this->user, $this->loader);
|
||||
$arguments = $this->invokePrivate($mount, 'arguments');
|
||||
|
||||
$this->assertArrayHasKey('class', $config);
|
||||
$this->assertEquals($config['class'], 'Test\Files\Mount\FakeObjectStore');
|
||||
$this->assertArrayHasKey('arguments', $config);
|
||||
$this->assertArrayHasKey('user', $config['arguments']);
|
||||
$this->assertSame($this->user, $config['arguments']['user']);
|
||||
$this->assertArrayHasKey('objectstore', $config['arguments']);
|
||||
$this->assertInstanceOf('Test\Files\Mount\FakeObjectStore', $config['arguments']['objectstore']);
|
||||
$this->assertArrayHasKey('bucket', $config['arguments']);
|
||||
$this->assertEquals('myBucketPrefix49', $config['arguments']['bucket']);
|
||||
$objectStore = $arguments['objectstore'];
|
||||
$this->assertInstanceOf(FakeObjectStore::class, $objectStore);
|
||||
$this->assertEquals(['foo' => 'bar', 'bucket' => 'myBucketPrefix49', 'multibucket' => true], $objectStore->getArguments());
|
||||
}
|
||||
|
||||
public function testMultiBucketBucketAlreadySet(): void {
|
||||
$this->config->expects($this->once())
|
||||
->method('getSystemValue')
|
||||
->with('objectstore_multibucket')
|
||||
->willReturn([
|
||||
'class' => 'Test\Files\Mount\FakeObjectStore',
|
||||
'arguments' => [
|
||||
'bucket' => 'myBucketPrefix',
|
||||
],
|
||||
]);
|
||||
$this->config->method('getSystemValue')
|
||||
->willReturnCallback(function ($key, $default) {
|
||||
if ($key === 'objectstore_multibucket') {
|
||||
return [
|
||||
'class' => 'Test\Files\Mount\FakeObjectStore',
|
||||
'arguments' => [
|
||||
'foo' => 'bar',
|
||||
'bucket' => 'myBucketPrefix',
|
||||
],
|
||||
];
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
});
|
||||
|
||||
$this->user->method('getUID')
|
||||
->willReturn('uid');
|
||||
$this->loader->expects($this->never())->method($this->anything());
|
||||
|
||||
$this->config->expects($this->once())
|
||||
$this->config
|
||||
->method('getUserValue')
|
||||
->with(
|
||||
$this->equalTo('uid'),
|
||||
$this->equalTo('homeobjectstore'),
|
||||
$this->equalTo('bucket'),
|
||||
$this->equalTo(null)
|
||||
)->willReturn('awesomeBucket1');
|
||||
->willReturnCallback(function ($uid, $app, $key, $default) {
|
||||
if ($uid === 'uid' && $app === 'homeobjectstore' && $key === 'bucket') {
|
||||
return 'awesomeBucket1';
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
});
|
||||
|
||||
$this->config->expects($this->never())
|
||||
->method('setUserValue');
|
||||
|
||||
$config = $this->invokePrivate($this->provider, 'getMultiBucketObjectStoreConfig', [$this->user, $this->loader]);
|
||||
$mount = $this->provider->getHomeMountForUser($this->user, $this->loader);
|
||||
$arguments = $this->invokePrivate($mount, 'arguments');
|
||||
|
||||
$this->assertArrayHasKey('class', $config);
|
||||
$this->assertEquals($config['class'], 'Test\Files\Mount\FakeObjectStore');
|
||||
$this->assertArrayHasKey('arguments', $config);
|
||||
$this->assertArrayHasKey('user', $config['arguments']);
|
||||
$this->assertSame($this->user, $config['arguments']['user']);
|
||||
$this->assertArrayHasKey('objectstore', $config['arguments']);
|
||||
$this->assertInstanceOf('Test\Files\Mount\FakeObjectStore', $config['arguments']['objectstore']);
|
||||
$this->assertArrayHasKey('bucket', $config['arguments']);
|
||||
$this->assertEquals('awesomeBucket1', $config['arguments']['bucket']);
|
||||
$objectStore = $arguments['objectstore'];
|
||||
$this->assertInstanceOf(FakeObjectStore::class, $objectStore);
|
||||
$this->assertEquals(['foo' => 'bar', 'bucket' => 'awesomeBucket1', 'multibucket' => true], $objectStore->getArguments());
|
||||
}
|
||||
|
||||
public function testMultiBucketConfigFirst(): void {
|
||||
$this->config->expects($this->exactly(2))
|
||||
->method('getSystemValue')
|
||||
->with('objectstore_multibucket')
|
||||
->willReturn([
|
||||
'class' => 'Test\Files\Mount\FakeObjectStore',
|
||||
]);
|
||||
$this->config->method('getSystemValue')
|
||||
->willReturnCallback(function ($key, $default) {
|
||||
if ($key === 'objectstore_multibucket') {
|
||||
return [
|
||||
'class' => 'Test\Files\Mount\FakeObjectStore',
|
||||
'arguments' => [
|
||||
'foo' => 'bar',
|
||||
'bucket' => 'myBucketPrefix',
|
||||
],
|
||||
];
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
});
|
||||
|
||||
$this->user->method('getUID')
|
||||
->willReturn('uid');
|
||||
|
|
@ -204,11 +209,15 @@ class ObjectHomeMountProviderTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function testMultiBucketConfigFirstFallBackSingle(): void {
|
||||
$this->config->expects($this->exactly(2))
|
||||
$this->config
|
||||
->method('getSystemValue')->willReturnMap([
|
||||
['objectstore_multibucket', '', ''],
|
||||
['objectstore', '', [
|
||||
['objectstore_multibucket', null, null],
|
||||
['objectstore', null, [
|
||||
'class' => 'Test\Files\Mount\FakeObjectStore',
|
||||
'arguments' => [
|
||||
'foo' => 'bar',
|
||||
'bucket' => 'myBucketPrefix',
|
||||
],
|
||||
]],
|
||||
]);
|
||||
|
||||
|
|
@ -221,16 +230,17 @@ class ObjectHomeMountProviderTest extends \Test\TestCase {
|
|||
}
|
||||
|
||||
public function testNoObjectStore(): void {
|
||||
$this->config->expects($this->exactly(2))
|
||||
->method('getSystemValue')
|
||||
->willReturn('');
|
||||
$this->config->method('getSystemValue')
|
||||
->willReturnCallback(function ($key, $default) {
|
||||
return $default;
|
||||
});
|
||||
|
||||
$mount = $this->provider->getHomeMountForUser($this->user, $this->loader);
|
||||
$this->assertNull($mount);
|
||||
}
|
||||
}
|
||||
|
||||
class FakeObjectStore {
|
||||
class FakeObjectStore implements IObjectStore {
|
||||
private $arguments;
|
||||
|
||||
public function __construct(array $arguments) {
|
||||
|
|
@ -240,4 +250,22 @@ class FakeObjectStore {
|
|||
public function getArguments() {
|
||||
return $this->arguments;
|
||||
}
|
||||
|
||||
public function getStorageId() {
|
||||
}
|
||||
|
||||
public function readObject($urn) {
|
||||
}
|
||||
|
||||
public function writeObject($urn, $stream, ?string $mimetype = null) {
|
||||
}
|
||||
|
||||
public function deleteObject($urn) {
|
||||
}
|
||||
|
||||
public function objectExists($urn) {
|
||||
}
|
||||
|
||||
public function copyObject($from, $to) {
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,11 +10,12 @@ namespace Test\Files\Mount;
|
|||
|
||||
use OC\Files\Mount\RootMountProvider;
|
||||
use OC\Files\ObjectStore\ObjectStoreStorage;
|
||||
use OC\Files\ObjectStore\PrimaryObjectStoreConfig;
|
||||
use OC\Files\ObjectStore\S3;
|
||||
use OC\Files\Storage\LocalRootStorage;
|
||||
use OC\Files\Storage\StorageFactory;
|
||||
use OCP\App\IAppManager;
|
||||
use OCP\IConfig;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Test\TestCase;
|
||||
|
||||
/**
|
||||
|
|
@ -40,8 +41,8 @@ class RootMountProviderTest extends TestCase {
|
|||
|
||||
private function getProvider(array $systemConfig): RootMountProvider {
|
||||
$config = $this->getConfig($systemConfig);
|
||||
$provider = new RootMountProvider($config, $this->createMock(LoggerInterface::class));
|
||||
return $provider;
|
||||
$objectStoreConfig = new PrimaryObjectStoreConfig($config, $this->createMock(IAppManager::class));
|
||||
return new RootMountProvider($objectStoreConfig, $config);
|
||||
}
|
||||
|
||||
public function testLocal(): void {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ use OC\Files\Filesystem;
|
|||
use OC\Files\Mount\CacheMountProvider;
|
||||
use OC\Files\Mount\LocalHomeMountProvider;
|
||||
use OC\Files\Mount\RootMountProvider;
|
||||
use OC\Files\ObjectStore\PrimaryObjectStoreConfig;
|
||||
use OC\Files\SetupManager;
|
||||
use OC\Template\Base;
|
||||
use OCP\Command\IBus;
|
||||
|
|
@ -25,7 +26,6 @@ use OCP\IDBConnection;
|
|||
use OCP\IL10N;
|
||||
use OCP\Lock\ILockingProvider;
|
||||
use OCP\Security\ISecureRandom;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
if (version_compare(\PHPUnit\Runner\Version::id(), 10, '>=')) {
|
||||
trait OnNotSuccessfulTestTrait {
|
||||
|
|
@ -332,7 +332,8 @@ abstract class TestCase extends \PHPUnit\Framework\TestCase {
|
|||
$config = \OC::$server->get(IConfig::class);
|
||||
$mountProviderCollection->registerProvider(new CacheMountProvider($config));
|
||||
$mountProviderCollection->registerHomeProvider(new LocalHomeMountProvider());
|
||||
$mountProviderCollection->registerRootProvider(new RootMountProvider($config, \OC::$server->get(LoggerInterface::class)));
|
||||
$objectStoreConfig = \OC::$server->get(PrimaryObjectStoreConfig::class);
|
||||
$mountProviderCollection->registerRootProvider(new RootMountProvider($objectStoreConfig, $config));
|
||||
|
||||
$setupManager->setupRoot();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue