Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash when MinIO bucket does not have versioning enabled #545 #546

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/server/lib/FlexServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1121,7 +1121,6 @@ export class FlexServer implements GristServer {
await this.loadConfig();
this.addComm();

await this.create.configure?.();
if (!isSingleUserMode()) {
const externalStorage = appSettings.section('externalStorage');
const haveExternalStorage = Object.values(externalStorage.nested)
Expand All @@ -1132,6 +1131,7 @@ export class FlexServer implements GristServer {
this._disableExternalStorage = true;
externalStorage.flag('active').set(false);
}
await this.create.configure?.();
fflorent marked this conversation as resolved.
Show resolved Hide resolved
const workers = this._docWorkerMap;
const docWorkerId = await this._addSelfAsWorker(workers);

Expand Down
6 changes: 5 additions & 1 deletion app/server/lib/ICreate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export interface ICreateActiveDocOptions {
export interface ICreateStorageOptions {
name: string;
check(): boolean;
checkBackend?(): Promise<void>;
create(purpose: 'doc'|'meta', extraPrefix: string): ExternalStorage|undefined;
}

Expand Down Expand Up @@ -119,7 +120,10 @@ export function makeSimpleCreator(opts: {
},
async configure() {
for (const s of storage || []) {
if (s.check()) { break; }
if (s.check()) {
await s.checkBackend?.();
break;
}
}
},
...(opts.shell && {
Expand Down
5 changes: 5 additions & 0 deletions app/server/lib/MinIOExternalStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@ export class MinIOExternalStorage implements ExternalStorage {
}
}

public async hasVersioning(): Promise<Boolean> {
const versioning = await this._s3.getBucketVersioning(this.bucket);
return versioning && versioning.Status === 'Enabled';
}

public async versions(key: string, options?: { includeDeleteMarkers?: boolean }) {
const results: minio.BucketItem[] = [];
await new Promise((resolve, reject) => {
Expand Down
13 changes: 13 additions & 0 deletions app/server/lib/configureMinIOExternalStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,16 @@ export function checkMinIOExternalStorage() {
region
};
}

export async function checkMinIOBucket() {
const options = checkMinIOExternalStorage();
if (!options) {
throw new Error('Configuration check failed for MinIO backend storage.');
}

const externalStorage = new MinIOExternalStorage(options.bucket, options);
if (!await externalStorage.hasVersioning()) {
await externalStorage.close();
throw new Error(`FATAL: the MinIO bucket "${options.bucket}" does not have versioning enabled`);
}
}
71 changes: 38 additions & 33 deletions app/server/mergedServerMain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,44 +106,49 @@ export async function main(port: number, serverTypes: ServerType[],
server.addApiMiddleware();
await server.addBillingMiddleware();

await server.start();

if (includeHome) {
server.addUsage();
if (!includeDocs) {
server.addDocApiForwarder();
try {
await server.start();

if (includeHome) {
server.addUsage();
if (!includeDocs) {
server.addDocApiForwarder();
}
server.addJsonSupport();
await server.addLandingPages();
// todo: add support for home api to standalone app
server.addHomeApi();
server.addBillingApi();
server.addNotifier();
server.addTelemetry();
await server.addHousekeeper();
await server.addLoginRoutes();
server.addAccountPage();
server.addBillingPages();
server.addWelcomePaths();
server.addLogEndpoint();
server.addGoogleAuthEndpoint();
}
server.addJsonSupport();
await server.addLandingPages();
// todo: add support for home api to standalone app
server.addHomeApi();
server.addBillingApi();
server.addNotifier();
server.addTelemetry();
await server.addHousekeeper();
await server.addLoginRoutes();
server.addAccountPage();
server.addBillingPages();
server.addWelcomePaths();
server.addLogEndpoint();
server.addGoogleAuthEndpoint();
}

if (includeDocs) {
server.addJsonSupport();
server.addTelemetry();
await server.addDoc();
}
if (includeDocs) {
server.addJsonSupport();
server.addTelemetry();
await server.addDoc();
}

if (includeHome) {
server.addClientSecrets();
}
if (includeHome) {
server.addClientSecrets();
}

server.finalize();
server.finalize();

server.checkOptionCombinations();
server.summary();
return server;
server.checkOptionCombinations();
server.summary();
return server;
} catch(e) {
await server.close();
throw e;
}
}


Expand Down
3 changes: 2 additions & 1 deletion stubs/app/server/lib/create.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { checkMinIOExternalStorage,
import { checkMinIOBucket, checkMinIOExternalStorage,
configureMinIOExternalStorage } from 'app/server/lib/configureMinIOExternalStorage';
import { makeSimpleCreator } from 'app/server/lib/ICreate';
import { Telemetry } from 'app/server/lib/Telemetry';
Expand All @@ -12,6 +12,7 @@ export const create = makeSimpleCreator({
{
name: 'minio',
check: () => checkMinIOExternalStorage() !== undefined,
checkBackend: () => checkMinIOBucket(),
create: configureMinIOExternalStorage,
},
],
Expand Down
4 changes: 3 additions & 1 deletion stubs/app/server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,5 +114,7 @@ export async function main() {
}

if (require.main === module) {
main().catch((err) => console.error(err));
main().catch((err) => {
console.error(err);
});
}