Skip to content

Commit 5943d0a

Browse files
authored
Merge pull request #37066 from nextcloud/backport/34835/stable26
[stable26] Run WebDAV integration tests against S3
2 parents d29551a + 4ca6c3a commit 5943d0a

File tree

7 files changed

+118
-10
lines changed

7 files changed

+118
-10
lines changed
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
name: S3 primary storage integration tests
2+
on:
3+
pull_request:
4+
push:
5+
branches:
6+
- master
7+
- stable*
8+
9+
jobs:
10+
s3-primary-integration-tests-minio:
11+
runs-on: ubuntu-20.04
12+
13+
strategy:
14+
# do not stop on another job's failure
15+
fail-fast: false
16+
matrix:
17+
php-versions: ['8.0']
18+
key: ['objectstore', 'objectstore_multibucket']
19+
20+
name: php${{ matrix.php-versions }}-${{ matrix.key }}-minio
21+
22+
services:
23+
redis:
24+
image: redis
25+
ports:
26+
- "6379:6379"
27+
minio:
28+
env:
29+
MINIO_ACCESS_KEY: minio
30+
MINIO_SECRET_KEY: minio123
31+
image: bitnami/minio:2021.12.29
32+
ports:
33+
- "9000:9000"
34+
35+
steps:
36+
- name: Checkout server
37+
uses: actions/checkout@v3
38+
with:
39+
submodules: true
40+
41+
- name: Set up php ${{ matrix.php-versions }}
42+
uses: shivammathur/setup-php@v2
43+
with:
44+
php-version: ${{ matrix.php-versions }}
45+
tools: phpunit:9
46+
extensions: mbstring, fileinfo, intl, sqlite, pdo_sqlite, zip, gd, redis
47+
env:
48+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
49+
50+
- name: Wait for S3
51+
run: |
52+
sleep 10
53+
curl -f -m 1 --retry-connrefused --retry 10 --retry-delay 10 http://localhost:9000/minio/health/ready
54+
55+
- name: Set up Nextcloud
56+
run: |
57+
mkdir data
58+
echo '<?php $CONFIG=["${{ matrix.key }}" => ["class" => "OC\Files\ObjectStore\S3", "arguments" => ["bucket" => "nextcloud", "autocreate" => true, "key" => "minio", "secret" => "minio123", "hostname" => "localhost", "port" => 9000, "use_ssl" => false, "use_path_style" => true, "uploadPartSize" => 52428800]]];' > config/config.php
59+
echo '<?php $CONFIG=["redis" => ["host" => "localhost", "port" => 6379], "memcache.local" => "\OC\Memcache\Redis", "memcache.distributed" => "\OC\Memcache\Redis"];' > config/redis.config.php
60+
./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin
61+
php -f index.php
62+
63+
- name: Integration
64+
run: |
65+
cd build/integration
66+
bash run.sh --tags "~@failure-s3" features/webdav-related.feature
67+
68+
- name: S3 logs
69+
if: always()
70+
run: |
71+
cat data/nextcloud.log
72+
docker ps -a
73+
docker ps -aq | while read container ; do IMAGE=$(docker inspect --format='{{.Config.Image}}' $container); echo $IMAGE; docker logs $container; echo "\n\n" ; done
74+
75+
76+
s3-primary-integration-summary:
77+
runs-on: ubuntu-latest
78+
needs: [s3-primary-integration-tests-minio]
79+
80+
if: always()
81+
82+
steps:
83+
- name: Summary status
84+
run: if ${{ needs.s3-primary-integration-tests-minio.result != 'success' }}; then exit 1; fi

apps/dav/lib/Connector/Sabre/Directory.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
use OC\Files\Mount\MoveableMount;
3636
use OC\Files\View;
3737
use OC\Metadata\FileMetadata;
38-
use OC\Metadata\MetadataGroup;
3938
use OCA\DAV\Connector\Sabre\Exception\FileLocked;
4039
use OCA\DAV\Connector\Sabre\Exception\Forbidden;
4140
use OCA\DAV\Connector\Sabre\Exception\InvalidPath;
@@ -57,7 +56,6 @@
5756
use OCP\Share\IManager as IShareManager;
5857

5958
class Directory extends \OCA\DAV\Connector\Sabre\Node implements \Sabre\DAV\ICollection, \Sabre\DAV\IQuota, \Sabre\DAV\IMoveTarget, \Sabre\DAV\ICopyTarget {
60-
6159
/**
6260
* Cached directory content
6361
* @var \OCP\Files\FileInfo[]
@@ -116,7 +114,6 @@ public function createFile($name, $data = null) {
116114
// for chunked upload also updating a existing file is a "createFile"
117115
// because we create all the chunks before re-assemble them to the existing file.
118116
if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
119-
120117
// exit if we can't create a new file and we don't updatable existing file
121118
$chunkInfo = \OC_FileChunking::decodeName($name);
122119
if (!$this->fileView->isCreatable($this->path) &&
@@ -328,8 +325,14 @@ public function getQuotaInfo() {
328325
if ($this->quotaInfo) {
329326
return $this->quotaInfo;
330327
}
328+
$relativePath = $this->fileView->getRelativePath($this->info->getPath());
329+
if ($relativePath === null) {
330+
$logger->warning("error while getting quota as the relative path cannot be found");
331+
return [0, 0];
332+
}
333+
331334
try {
332-
$storageInfo = \OC_Helper::getStorageInfo($this->info->getPath(), $this->info, false);
335+
$storageInfo = \OC_Helper::getStorageInfo($relativePath, $this->info, false);
333336
if ($storageInfo['quota'] === \OCP\Files\FileInfo::SPACE_UNLIMITED) {
334337
$free = \OCP\Files\FileInfo::SPACE_UNLIMITED;
335338
} else {

apps/dav/tests/unit/Connector/Sabre/DirectoryTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,10 @@ public function testGetQuotaInfoUnlimited(): void {
304304
->method('free_space')
305305
->willReturn(800);
306306

307+
$this->info->expects($this->any())
308+
->method('getPath')
309+
->willReturn('/admin/files/foo');
310+
307311
$this->info->expects($this->once())
308312
->method('getSize')
309313
->willReturn(200);
@@ -312,6 +316,10 @@ public function testGetQuotaInfoUnlimited(): void {
312316
->method('getMountPoint')
313317
->willReturn($mountPoint);
314318

319+
$this->view->expects($this->any())
320+
->method('getRelativePath')
321+
->willReturn('/foo');
322+
315323
$mountPoint->method('getMountPoint')
316324
->willReturn('/user/files/mymountpoint');
317325

@@ -359,6 +367,10 @@ public function testGetQuotaInfoSpecific(): void {
359367
$mountPoint->method('getMountPoint')
360368
->willReturn('/user/files/mymountpoint');
361369

370+
$this->view->expects($this->any())
371+
->method('getRelativePath')
372+
->willReturn('/foo');
373+
362374
$dir = new Directory($this->view, $this->info);
363375
$this->assertEquals([200, 800], $dir->getQuotaInfo()); //200 used, 800 free
364376
}

apps/provisioning_api/lib/Controller/UsersController.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@
7777
use Psr\Log\LoggerInterface;
7878

7979
class UsersController extends AUserData {
80-
8180
/** @var IURLGenerator */
8281
protected $urlGenerator;
8382
/** @var LoggerInterface */
@@ -374,7 +373,7 @@ public function addUser(
374373
$group = $this->groupManager->get($groupid);
375374
// Check if group exists
376375
if ($group === null) {
377-
throw new OCSException('Subadmin group does not exist', 102);
376+
throw new OCSException('Subadmin group does not exist', 102);
378377
}
379378
// Check if trying to make subadmin of admin group
380379
if ($group->getGID() === 'admin') {
@@ -1311,7 +1310,7 @@ public function addSubAdmin(string $userId, string $groupid): DataResponse {
13111310
}
13121311
// Check if group exists
13131312
if ($group === null) {
1314-
throw new OCSException('Group does not exist', 102);
1313+
throw new OCSException('Group does not exist', 102);
13151314
}
13161315
// Check if trying to make subadmin of admin group
13171316
if ($group->getGID() === 'admin') {

lib/private/Files/View.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ public function getRoot() {
164164
* get path relative to the root of the view
165165
*
166166
* @param string $path
167-
* @return string
167+
* @return ?string
168168
*/
169169
public function getRelativePath($path) {
170170
$this->assertPathLength($path);
@@ -1241,7 +1241,7 @@ private function basicOperation($operation, $path, $hooks = [], $extraParam = nu
12411241
* get the path relative to the default root for hook usage
12421242
*
12431243
* @param string $path
1244-
* @return string
1244+
* @return ?string
12451245
*/
12461246
private function getHookPath($path) {
12471247
if (!Filesystem::getView()) {

lib/private/User/User.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,7 @@ public function setQuota($quota) {
529529
$this->config->setUserValue($this->uid, 'files', 'quota', $quota);
530530
$this->triggerChange('quota', $quota, $oldQuota);
531531
}
532+
\OC_Helper::clearStorageInfo('/' . $this->uid . '/files');
532533
}
533534

534535
/**

lib/private/legacy/OC_Helper.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ public static function getStorageInfo($path, $rootInfo = null, $includeMountPoin
473473
if (!$view) {
474474
throw new \OCP\Files\NotFoundException();
475475
}
476-
$fullPath = $view->getAbsolutePath($path);
476+
$fullPath = Filesystem::normalizePath($view->getAbsolutePath($path));
477477

478478
$cacheKey = $fullPath. '::' . ($includeMountPoints ? 'include' : 'exclude');
479479
if ($useCache) {
@@ -620,6 +620,15 @@ private static function getGlobalStorageInfo(int|float $quota, IUser $user, IMou
620620
];
621621
}
622622

623+
public static function clearStorageInfo(string $absolutePath): void {
624+
/** @var ICacheFactory $cacheFactory */
625+
$cacheFactory = \OC::$server->get(ICacheFactory::class);
626+
$memcache = $cacheFactory->createLocal('storage_info');
627+
$cacheKeyPrefix = Filesystem::normalizePath($absolutePath) . '::';
628+
$memcache->remove($cacheKeyPrefix . 'include');
629+
$memcache->remove($cacheKeyPrefix . 'exclude');
630+
}
631+
623632
/**
624633
* Returns whether the config file is set manually to read-only
625634
* @return bool

0 commit comments

Comments
 (0)