From 3686fc6329ca2d1a52f9eaa2e58a234e0959d50e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Mon, 6 Nov 2017 10:52:39 +0100 Subject: [PATCH] [stable10] Adding mode of operations - either single-instance or clustered-instance - fixes #29444 --- config/config.sample.php | 9 ++++ lib/private/App/AppManager.php | 12 ++++- lib/private/Config.php | 4 ++ lib/private/Server.php | 3 +- tests/lib/App/ManagerTest.php | 99 ++++++++++++++++++++++------------ tests/lib/AppTest.php | 8 ++- 6 files changed, 96 insertions(+), 39 deletions(-) diff --git a/config/config.sample.php b/config/config.sample.php index 20b7a55d226f..7eeb824c8bc6 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -582,6 +582,15 @@ */ 'config_is_read_only' => false, +/** + * This defines the mode of operations. The default value is 'single-instance' + * which means that ownCloud is running on a single node, which might be the + * most common operations mode. The only other possible value for now is + * 'clustered-instance' which means that ownCloud is running on at least 2 + * nodes. The mode of operations has various impact on the behavior of ownCloud. + */ +'operation.mode' => 'single-instance', + /** * Logging */ diff --git a/lib/private/App/AppManager.php b/lib/private/App/AppManager.php index 0138a51e7aad..98820ed108b0 100644 --- a/lib/private/App/AppManager.php +++ b/lib/private/App/AppManager.php @@ -37,6 +37,7 @@ use OCP\Files; use OCP\IAppConfig; use OCP\ICacheFactory; +use OCP\IConfig; use OCP\IGroupManager; use OCP\IUser; use OCP\IUserSession; @@ -72,6 +73,8 @@ class AppManager implements IAppManager { private $alwaysEnabled; /** @var EventDispatcherInterface */ private $dispatcher; + /** @var IConfig */ + private $config; /** * @param IUserSession $userSession @@ -79,17 +82,20 @@ class AppManager implements IAppManager { * @param IGroupManager $groupManager * @param ICacheFactory $memCacheFactory * @param EventDispatcherInterface $dispatcher + * @param IConfig $config */ public function __construct(IUserSession $userSession = null, IAppConfig $appConfig, IGroupManager $groupManager, ICacheFactory $memCacheFactory, - EventDispatcherInterface $dispatcher) { + EventDispatcherInterface $dispatcher, + IConfig $config) { $this->userSession = $userSession; $this->appConfig = $appConfig; $this->groupManager = $groupManager; $this->memCacheFactory = $memCacheFactory; $this->dispatcher = $dispatcher; + $this->config = $config; } /** @@ -435,6 +441,10 @@ public function readAppPackage($path) { * @since 10.0.3 */ public function canInstall() { + if ($this->config->getSystemValue('operation.mode', 'single-instance') !== 'single-instance') { + return false; + } + $appsFolder = OC_App::getInstallPath(); return $appsFolder !== null && is_writable($appsFolder) && is_readable($appsFolder); } diff --git a/lib/private/Config.php b/lib/private/Config.php index b41531e81791..f79c0baadadb 100644 --- a/lib/private/Config.php +++ b/lib/private/Config.php @@ -286,6 +286,10 @@ public function isReadOnly() { if (!$this->getValue('installed', false)) { return false; } + if ($this->getValue('operation.mode', 'single-instance') !== 'single-instance') { + return false; + } + return $this->getValue('config_is_read_only', false); } } diff --git a/lib/private/Server.php b/lib/private/Server.php index c84edfe31f86..1f08bf1b4a20 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -537,7 +537,8 @@ public function __construct($webRoot, \OC\Config $config) { $c->getAppConfig(), $c->getGroupManager(), $c->getMemCacheFactory(), - $c->getEventDispatcher() + $c->getEventDispatcher(), + $c->getConfig() ); }); $this->registerService('DateTimeZone', function (Server $c) { diff --git a/tests/lib/App/ManagerTest.php b/tests/lib/App/ManagerTest.php index 2c10ba38bb7a..4c42df1fc627 100644 --- a/tests/lib/App/ManagerTest.php +++ b/tests/lib/App/ManagerTest.php @@ -9,8 +9,16 @@ namespace Test\App; +use OC\App\AppManager; use OC\Group\Group; +use OCP\App\IAppManager; +use OCP\IAppConfig; +use OCP\ICache; +use OCP\ICacheFactory; +use OCP\IConfig; +use OCP\IGroupManager; use OCP\IUser; +use OCP\IUserSession; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Test\TestCase; @@ -21,12 +29,30 @@ * @group DB */ class ManagerTest extends TestCase { + + /** @var IUserSession | \PHPUnit_Framework_MockObject_MockObject */ + protected $userSession; + /** @var IGroupManager | \PHPUnit_Framework_MockObject_MockObject */ + protected $groupManager; + /** @var IAppConfig */ + protected $appConfig; + /** @var ICache | \PHPUnit_Framework_MockObject_MockObject */ + protected $cache; + /** @var ICacheFactory | \PHPUnit_Framework_MockObject_MockObject */ + protected $cacheFactory; + /** @var IAppManager */ + protected $manager; + /** @var EventDispatcherInterface | \PHPUnit_Framework_MockObject_MockObject */ + protected $eventDispatcher; + /** @var IConfig | \PHPUnit_Framework_MockObject_MockObject */ + private $config; + /** - * @return \OCP\IAppConfig | \PHPUnit_Framework_MockObject_MockObject + * @return IAppConfig | \PHPUnit_Framework_MockObject_MockObject */ protected function getAppConfig() { $appConfig = []; - $config = $this->getMockBuilder('\OCP\IAppConfig') + $config = $this->getMockBuilder(IAppConfig::class) ->disableOriginalConstructor() ->getMock(); @@ -62,41 +88,23 @@ protected function getAppConfig() { return $config; } - /** @var \OCP\IUserSession | \PHPUnit_Framework_MockObject_MockObject */ - protected $userSession; - - /** @var \OCP\IGroupManager | \PHPUnit_Framework_MockObject_MockObject */ - protected $groupManager; - - /** @var \OCP\IAppConfig */ - protected $appConfig; - - /** @var \OCP\ICache | \PHPUnit_Framework_MockObject_MockObject */ - protected $cache; - - /** @var \OCP\ICacheFactory | \PHPUnit_Framework_MockObject_MockObject */ - protected $cacheFactory; - - /** @var \OCP\App\IAppManager */ - protected $manager; - - /** @var EventDispatcherInterface | \PHPUnit_Framework_MockObject_MockObject */ - protected $eventDispatcher; - protected function setUp() { parent::setUp(); - $this->userSession = $this->createMock('\OCP\IUserSession'); - $this->groupManager = $this->createMock('\OCP\IGroupManager'); + $this->userSession = $this->createMock(IUserSession::class); + $this->config = $this->createMock(IConfig::class); + $this->groupManager = $this->createMock(IGroupManager::class); $this->appConfig = $this->getAppConfig(); - $this->cacheFactory = $this->createMock('\OCP\ICacheFactory'); - $this->cache = $this->createMock('\OCP\ICache'); - $this->eventDispatcher = $this->createMock('\Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $this->cacheFactory = $this->createMock(ICacheFactory::class); + $this->cache = $this->createMock(ICache::class); + $this->eventDispatcher = $this->createMock(EventDispatcherInterface::class); $this->cacheFactory->expects($this->any()) ->method('create') ->with('settings') ->willReturn($this->cache); - $this->manager = new \OC\App\AppManager($this->userSession, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher); + $this->manager = new AppManager($this->userSession, $this->appConfig, + $this->groupManager, $this->cacheFactory, $this->eventDispatcher, + $this->config); } protected function expectClearCache() { @@ -164,10 +172,11 @@ public function testEnableAppForGroupsAllowedTypes(array $appInfo) { ]; $this->expectClearCache(); - /** @var \OC\App\AppManager|\PHPUnit_Framework_MockObject_MockObject $manager */ + /** @var AppManager|\PHPUnit_Framework_MockObject_MockObject $manager */ $manager = $this->getMockBuilder('OC\App\AppManager') ->setConstructorArgs([ - $this->userSession, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher + $this->userSession, $this->appConfig, $this->groupManager, + $this->cacheFactory, $this->eventDispatcher, $this->config ]) ->setMethods([ 'getAppInfo' @@ -207,10 +216,11 @@ public function testEnableAppForGroupsForbiddenTypes($type) { new Group('group2', [], null) ]; - /** @var \OC\App\AppManager|\PHPUnit_Framework_MockObject_MockObject $manager */ + /** @var AppManager|\PHPUnit_Framework_MockObject_MockObject $manager */ $manager = $this->getMockBuilder('OC\App\AppManager') ->setConstructorArgs([ - $this->userSession, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher + $this->userSession, $this->appConfig, $this->groupManager, + $this->cacheFactory, $this->eventDispatcher, $this->config ]) ->setMethods([ 'getAppInfo' @@ -333,7 +343,8 @@ public function testGetAppsForUser() { public function testGetAppsNeedingUpgrade() { $this->manager = $this->getMockBuilder('\OC\App\AppManager') - ->setConstructorArgs([$this->userSession, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher]) + ->setConstructorArgs([$this->userSession, $this->appConfig, + $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->config]) ->setMethods(['getAppInfo']) ->getMock(); @@ -375,7 +386,8 @@ function($appId) use ($appInfos) { public function testGetIncompatibleApps() { $this->manager = $this->getMockBuilder('\OC\App\AppManager') - ->setConstructorArgs([$this->userSession, $this->appConfig, $this->groupManager, $this->cacheFactory, $this->eventDispatcher]) + ->setConstructorArgs([$this->userSession, $this->appConfig, + $this->groupManager, $this->cacheFactory, $this->eventDispatcher, $this->config]) ->setMethods(['getAppInfo']) ->getMock(); @@ -408,4 +420,21 @@ function($appId) use ($appInfos) { $this->assertEquals('test1', $apps[0]['id']); $this->assertEquals('test3', $apps[1]['id']); } + + /** + * @dataProvider providesDataForCanInstall + * @param bool $canInstall + * @param string $opsMode + */ + public function testCanInstall($canInstall, $opsMode) { + $this->config->expects($this->once())->method('getSystemValue')->willReturn($opsMode); + $this->assertEquals($canInstall, $this->manager->canInstall()); + } + + public function providesDataForCanInstall() { + return [ + [true, 'single-instance'], + [false, 'clustered-instance'], + ]; + } } diff --git a/tests/lib/AppTest.php b/tests/lib/AppTest.php index 6c7d70d4a1cc..7ea38ed60ecd 100644 --- a/tests/lib/AppTest.php +++ b/tests/lib/AppTest.php @@ -506,7 +506,9 @@ private function registerAppConfig(IAppConfig $appConfig) { return $appConfig; }); \OC::$server->registerService('AppManager', function (\OC\Server $c) use ($appConfig) { - return new \OC\App\AppManager($c->getUserSession(), $appConfig, $c->getGroupManager(), $c->getMemCacheFactory(), $c->getEventDispatcher()); + return new \OC\App\AppManager($c->getUserSession(), $appConfig, + $c->getGroupManager(), $c->getMemCacheFactory(), + $c->getEventDispatcher(), $c->getConfig()); }); } @@ -518,7 +520,9 @@ private function restoreAppConfig() { return new \OC\AppConfig($c->getDatabaseConnection()); }); \OC::$server->registerService('AppManager', function (\OC\Server $c) { - return new \OC\App\AppManager($c->getUserSession(), $c->getAppConfig(), $c->getGroupManager(), $c->getMemCacheFactory(), $c->getEventDispatcher()); + return new \OC\App\AppManager($c->getUserSession(), $c->getAppConfig(), + $c->getGroupManager(), $c->getMemCacheFactory(), + $c->getEventDispatcher(), $c->getConfig()); }); // Remove the cache of the mocked apps list with a forceRefresh