Browse Source

Merge pull request #160 from provokateurin/refactor/docker

Refactor docker setup
pull/161/head
Kate 2 years ago committed by GitHub
parent
commit
b5f33bfdd3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 40
      packages/nextcloud/test/core.dart
  2. 112
      packages/nextcloud/test/helper.dart
  3. 19
      packages/nextcloud/test/main_test.dart
  4. 4
      packages/nextcloud/test/news.dart
  5. 4
      packages/nextcloud/test/notes.dart
  6. 4
      packages/nextcloud/test/notifications.dart
  7. 4
      packages/nextcloud/test/provisioning_api.dart
  8. 4
      packages/nextcloud/test/user_status.dart
  9. 4
      packages/nextcloud/test/webdav.dart
  10. 3
      tool/Dockerfile.dev
  11. 2
      tool/build-dev-container-image.sh
  12. 0
      tool/overlay/.gitkeep
  13. 6
      tool/update.sh

40
packages/nextcloud/test/core_test.dart → packages/nextcloud/test/core.dart

@ -4,13 +4,10 @@ import 'package:test/test.dart';
import 'helper.dart'; import 'helper.dart';
Future main() async { Future main() async {
final image = await getDockerImage( await run(await getDockerImage());
apps: [ }
'news',
'notes',
],
);
Future run(final DockerImage image) async {
group('core', () { group('core', () {
late DockerContainer container; late DockerContainer container;
late TestNextcloudClient client; late TestNextcloudClient client;
@ -27,11 +24,12 @@ Future main() async {
test('Get status', () async { test('Get status', () async {
final status = await client.core.getStatus(); final status = await client.core.getStatus();
print(status.toJson());
expect(status.installed, true); expect(status.installed, true);
expect(status.maintenance, false); expect(status.maintenance, false);
expect(status.needsDbUpgrade, false); expect(status.needsDbUpgrade, false);
expect(status.version, startsWith(nextcloudVersion)); expect(status.version, startsWith('25.0.2'));
expect(status.versionstring, startsWith('${nextcloudVersion.split('.')[0]}.')); expect(status.versionstring, '25.0.2');
expect(status.edition, ''); expect(status.edition, '');
expect(status.productname, 'Nextcloud'); expect(status.productname, 'Nextcloud');
expect(status.extendedSupport, false); expect(status.extendedSupport, false);
@ -39,8 +37,8 @@ Future main() async {
test('Get capabilities', () async { test('Get capabilities', () async {
final capabilities = await client.core.getCapabilities(); final capabilities = await client.core.getCapabilities();
expect(capabilities.ocs.data.version.major.toString(), nextcloudVersion.split('.')[0]); expect(capabilities.ocs.data.version.major.toString(), '25');
expect(capabilities.ocs.data.version.string, nextcloudVersion); expect(capabilities.ocs.data.version.string, '25.0.2');
expect(capabilities.ocs.data.capabilities.theming!.name, 'Nextcloud'); expect(capabilities.ocs.data.capabilities.theming!.name, 'Nextcloud');
expect(capabilities.ocs.data.capabilities.theming!.url, 'https://nextcloud.com'); expect(capabilities.ocs.data.capabilities.theming!.url, 'https://nextcloud.com');
expect(capabilities.ocs.data.capabilities.theming!.slogan, 'a safe home for all your data'); expect(capabilities.ocs.data.capabilities.theming!.slogan, 'a safe home for all your data');
@ -75,7 +73,7 @@ Future main() async {
ShareType.group.code, ShareType.group.code,
], ],
); );
expect(response.ocs.data, hasLength(2)); expect(response.ocs.data, hasLength(3));
expect(response.ocs.data[0].id, 'admin'); expect(response.ocs.data[0].id, 'admin');
expect(response.ocs.data[0].label, 'admin'); expect(response.ocs.data[0].label, 'admin');
@ -85,13 +83,21 @@ Future main() async {
expect(response.ocs.data[0].subline, ''); expect(response.ocs.data[0].subline, '');
expect(response.ocs.data[0].shareWithDisplayNameUnique, 'admin@example.com'); expect(response.ocs.data[0].shareWithDisplayNameUnique, 'admin@example.com');
expect(response.ocs.data[1].id, 'admin'); expect(response.ocs.data[1].id, 'user2');
expect(response.ocs.data[1].label, 'admin'); expect(response.ocs.data[1].label, 'User Two');
expect(response.ocs.data[1].icon, ''); expect(response.ocs.data[1].icon, 'icon-user');
expect(response.ocs.data[1].source, 'groups'); expect(response.ocs.data[1].source, 'users');
expect(response.ocs.data[1].status.string, isEmpty); expect(response.ocs.data[1].status.string, isNull);
expect(response.ocs.data[1].subline, ''); expect(response.ocs.data[1].subline, '');
expect(response.ocs.data[1].shareWithDisplayNameUnique, ''); expect(response.ocs.data[1].shareWithDisplayNameUnique, 'user2');
expect(response.ocs.data[2].id, 'admin');
expect(response.ocs.data[2].label, 'admin');
expect(response.ocs.data[2].icon, '');
expect(response.ocs.data[2].source, 'groups');
expect(response.ocs.data[2].status.string, isEmpty);
expect(response.ocs.data[2].subline, '');
expect(response.ocs.data[2].shareWithDisplayNameUnique, '');
}); });
}); });
} }

112
packages/nextcloud/test/helper.dart

@ -3,23 +3,10 @@ import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:math'; import 'dart:math';
import 'package:crypto/crypto.dart';
import 'package:nextcloud/nextcloud.dart'; import 'package:nextcloud/nextcloud.dart';
import 'package:process_run/cmd_run.dart'; import 'package:process_run/cmd_run.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
const String nextcloudVersion = '25.0.2';
const String defaultUsername = 'user1';
const String defaultPassword = 'user1';
class DockerImage {
DockerImage({
required this.name,
});
final String name;
}
class DockerContainer { class DockerContainer {
DockerContainer({ DockerContainer({
required this.id, required this.id,
@ -98,8 +85,8 @@ class TestNextcloudClient extends NextcloudClient {
Future<TestNextcloudClient> getTestClient( Future<TestNextcloudClient> getTestClient(
final DockerContainer container, { final DockerContainer container, {
final String? username = defaultUsername, final String? username = 'user1',
final String? password = defaultPassword, final String? password = 'user1',
final bool useAppPassword = false, final bool useAppPassword = false,
final AppType appType = AppType.unknown, final AppType appType = AppType.unknown,
final String? userAgentOverride, final String? userAgentOverride,
@ -172,7 +159,7 @@ Future<DockerContainer> getDockerContainer(final DockerImage image) async {
'$port:80', '$port:80',
'--add-host', '--add-host',
'host.docker.internal:host-gateway', 'host.docker.internal:host-gateway',
image.name, image,
], ],
); );
// 125 means the docker run command itself has failed which indicated the port is already used // 125 means the docker run command itself has failed which indicated the port is already used
@ -191,23 +178,10 @@ Future<DockerContainer> getDockerContainer(final DockerImage image) async {
); );
} }
Future<DockerImage> getDockerImage({ typedef DockerImage = String;
final List<TestNextcloudUser>? users,
final List<String>? apps,
}) async {
final hash = sha1
.convert(
utf8.encode(
<String>[
if (users != null)
for (final user in users) user.toString(),
if (apps != null) ...apps,
].join(),
),
)
.toString();
final dockerImageName = 'nextcloud-neon-$hash'; Future<DockerImage> getDockerImage() async {
const dockerImageName = 'nextcloud-neon-dev';
final inputStream = StreamController<List<int>>(); final inputStream = StreamController<List<int>>();
final process = runExecutableArguments( final process = runExecutableArguments(
@ -218,21 +192,13 @@ Future<DockerImage> getDockerImage({
dockerImageName, dockerImageName,
'-f', '-f',
'-', '-',
'./test', '../../tool',
], ],
stdout: stdout, stdout: stdout,
stderr: stderr, stderr: stderr,
stdin: inputStream.stream, stdin: inputStream.stream,
); );
inputStream.add( inputStream.add(utf8.encode(File('../../tool/Dockerfile.dev').readAsStringSync()));
utf8.encode(
TestDockerHelper.generateInstructions(
nextcloudVersion,
users: users,
apps: apps,
),
),
);
await inputStream.close(); await inputStream.close();
final result = await process; final result = await process;
@ -240,9 +206,7 @@ Future<DockerImage> getDockerImage({
throw Exception('Failed to build docker image'); throw Exception('Failed to build docker image');
} }
return DockerImage( return dockerImageName;
name: dockerImageName,
);
} }
class TestNextcloudUser { class TestNextcloudUser {
@ -257,64 +221,6 @@ class TestNextcloudUser {
final String? displayName; final String? displayName;
} }
class TestDockerHelper {
static String generateInstructions(
final String nextcloudVersion, {
final List<TestNextcloudUser>? users,
final List<String>? apps,
}) {
users?.sort((final a, final b) => a.username.compareTo(b.username));
apps?.sort();
final instructions = <String>[
generateFromNextcloudImageInstruction(nextcloudVersion),
'WORKDIR /usr/src/nextcloud',
'RUN chown -R www-data:www-data .',
'USER www-data',
'RUN ./occ maintenance:install --admin-pass admin --admin-email admin@example.com',
'RUN ./occ app:disable password_policy',
'RUN ./occ config:system:set allow_local_remote_servers --value=true',
generateCreateTestUserInstruction(),
if (apps != null) ...[
for (final app in apps) ...[
generateInstallAppInstruction(app),
],
],
if (users != null) ...[
for (final user in users) ...[
generateCreateUserInstruction(user),
],
],
'RUN ./occ app:enable password_policy',
'COPY --chown=www-data:www-data overlay /usr/src/nextcloud/',
'',
];
return instructions.join('\n');
}
static String generateFromNextcloudImageInstruction(
final String nextcloudVersion,
) =>
'FROM nextcloud:$nextcloudVersion';
static String generateCreateTestUserInstruction() => generateCreateUserInstruction(
TestNextcloudUser(
defaultUsername,
defaultPassword,
displayName: 'User One',
),
);
static String generateCreateUserInstruction(final TestNextcloudUser user) =>
'RUN OC_PASS="${user.password}" ./occ user:add --password-from-env ${user.displayName != null ? '--display-name="${user.displayName}"' : ''} ${user.username}';
static String generateInstallAppInstruction(
final String appName,
) =>
'RUN ./occ app:install $appName';
}
int randomPort() => 1024 + Random().nextInt(65535 - 1024); int randomPort() => 1024 + Random().nextInt(65535 - 1024);
void expectDateInReasonableTimeRange(final DateTime actual, final DateTime expected) { void expectDateInReasonableTimeRange(final DateTime actual, final DateTime expected) {

19
packages/nextcloud/test/main_test.dart

@ -0,0 +1,19 @@
import 'core.dart' as core;
import 'helper.dart';
import 'news.dart' as news;
import 'notes.dart' as notes;
import 'notifications.dart' as notifications;
import 'provisioning_api.dart' as provisioning_api;
import 'user_status.dart' as user_status;
import 'webdav.dart' as webdav;
Future main() async {
final image = await getDockerImage();
await core.run(image);
await news.run(image);
await notes.run(image);
await notifications.run(image);
await provisioning_api.run(image);
await user_status.run(image);
await webdav.run(image);
}

4
packages/nextcloud/test/news_test.dart → packages/nextcloud/test/news.dart

@ -7,8 +7,10 @@ const wikipediaFeedURL = 'https://en.wikipedia.org/w/api.php?action=featuredfeed
const nasaFeedURL = 'https://www.nasa.gov/rss/dyn/breaking_news.rss'; const nasaFeedURL = 'https://www.nasa.gov/rss/dyn/breaking_news.rss';
Future main() async { Future main() async {
final image = await getDockerImage(apps: ['news']); await run(await getDockerImage());
}
Future run(final DockerImage image) async {
group('news', () { group('news', () {
late DockerContainer container; late DockerContainer container;
late TestNextcloudClient client; late TestNextcloudClient client;

4
packages/nextcloud/test/notes_test.dart → packages/nextcloud/test/notes.dart

@ -4,8 +4,10 @@ import 'package:test/test.dart';
import 'helper.dart'; import 'helper.dart';
Future main() async { Future main() async {
final image = await getDockerImage(apps: ['notes']); await run(await getDockerImage());
}
Future run(final DockerImage image) async {
group('notes', () { group('notes', () {
late DockerContainer container; late DockerContainer container;
late TestNextcloudClient client; late TestNextcloudClient client;

4
packages/nextcloud/test/notifications_test.dart → packages/nextcloud/test/notifications.dart

@ -8,8 +8,10 @@ import 'package:test/test.dart';
import 'helper.dart'; import 'helper.dart';
Future main() async { Future main() async {
final image = await getDockerImage(); await run(await getDockerImage());
}
Future run(final DockerImage image) async {
group('notifications', () { group('notifications', () {
late DockerContainer container; late DockerContainer container;
late TestNextcloudClient client; late TestNextcloudClient client;

4
packages/nextcloud/test/provisioning_api_test.dart → packages/nextcloud/test/provisioning_api.dart

@ -4,8 +4,10 @@ import 'package:test/test.dart';
import 'helper.dart'; import 'helper.dart';
Future main() async { Future main() async {
final image = await getDockerImage(); await run(await getDockerImage());
}
Future run(final DockerImage image) async {
group('provisioning_api', () { group('provisioning_api', () {
late DockerContainer container; late DockerContainer container;
late TestNextcloudClient client; late TestNextcloudClient client;

4
packages/nextcloud/test/user_status_test.dart → packages/nextcloud/test/user_status.dart

@ -4,8 +4,10 @@ import 'package:test/test.dart';
import 'helper.dart'; import 'helper.dart';
Future main() async { Future main() async {
final image = await getDockerImage(); await run(await getDockerImage());
}
Future run(final DockerImage image) async {
group('user_status', () { group('user_status', () {
late DockerContainer container; late DockerContainer container;
late TestNextcloudClient client; late TestNextcloudClient client;

4
packages/nextcloud/test/webdav_test.dart → packages/nextcloud/test/webdav.dart

@ -8,8 +8,10 @@ import 'package:test/test.dart';
import 'helper.dart'; import 'helper.dart';
Future main() async { Future main() async {
final image = await getDockerImage(); await run(await getDockerImage());
}
Future run(final DockerImage image) async {
group('webdav', () { group('webdav', () {
late DockerContainer container; late DockerContainer container;
late TestNextcloudClient client; late TestNextcloudClient client;

3
tool/Dockerfile.dev

@ -4,9 +4,9 @@ RUN chown -R www-data:www-data .
USER www-data USER www-data
RUN ./occ maintenance:install --admin-pass admin --admin-email admin@example.com RUN ./occ maintenance:install --admin-pass admin --admin-email admin@example.com
RUN ./occ app:disable password_policy
RUN ./occ config:system:set allow_local_remote_servers --value=true RUN ./occ config:system:set allow_local_remote_servers --value=true
RUN ./occ config:system:set trusted_domains 1 --value=10.0.2.2 RUN ./occ config:system:set trusted_domains 1 --value=10.0.2.2
RUN ./occ app:disable password_policy
RUN OC_PASS="user1" ./occ user:add --password-from-env --display-name "User One" user1 RUN OC_PASS="user1" ./occ user:add --password-from-env --display-name "User One" user1
RUN OC_PASS="user2" ./occ user:add --password-from-env --display-name "User Two" user2 RUN OC_PASS="user2" ./occ user:add --password-from-env --display-name "User Two" user2
@ -14,4 +14,5 @@ RUN OC_PASS="user2" ./occ user:add --password-from-env --display-name "User Two"
RUN ./occ app:install news RUN ./occ app:install news
RUN ./occ app:install notes RUN ./occ app:install notes
RUN ./occ app:enable password_policy
COPY --chown=www-data:www-data overlay /usr/src/nextcloud/ COPY --chown=www-data:www-data overlay /usr/src/nextcloud/

2
tool/build-dev-container-image.sh

@ -2,4 +2,4 @@
set -euxo pipefail set -euxo pipefail
cd "$(dirname "$0")/.." cd "$(dirname "$0")/.."
docker build -t nextcloud-neon-dev -f - ./packages/nextcloud/test < tool/Dockerfile.dev docker build -t nextcloud-neon-dev -f - ./tool < tool/Dockerfile.dev

0
packages/nextcloud/test/overlay/.gitkeep → tool/overlay/.gitkeep

6
tool/update.sh

@ -23,6 +23,12 @@ elif [ -d "external/nextcloud-$1" ]; then
latest_tag="$(git tag --sort=v:refname | grep -vi "rc" | grep -vi "alpha" | grep -vi "beta" | tail -n 1)" latest_tag="$(git tag --sort=v:refname | grep -vi "rc" | grep -vi "alpha" | grep -vi "beta" | tail -n 1)"
git reset --hard "$latest_tag" git reset --hard "$latest_tag"
git submodule update git submodule update
if [[ "$1" == "server" ]]; then
# shellcheck disable=SC2001
image_version=$(echo "$latest_tag" | sed "s/^v//")
sed -i "s/FROM nextcloud:.*/FROM nextcloud:$image_version/" ../../tool/Dockerfile.dev
fi
) )
else else
echo "$1 not found" echo "$1 not found"

Loading…
Cancel
Save