Skip to content

Commit

Permalink
Introduce bucket website endpoint tests
Browse files Browse the repository at this point in the history
Issue: ZENKO-4837
  • Loading branch information
williamlardier committed Oct 23, 2024
1 parent 4464479 commit b56188c
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 7 deletions.
2 changes: 1 addition & 1 deletion .github/scripts/end2end/configure-e2e-ctst.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export NOTIF_KAFKA_HOST=${KAFKA_HOST_PORT%:*}
export NOTIF_KAFKA_PORT=${KAFKA_HOST_PORT#*:}

echo "127.0.0.1 iam.zenko.local ui.zenko.local s3-local-file.zenko.local keycloak.zenko.local \
sts.zenko.local management.zenko.local s3.zenko.local" | sudo tee -a /etc/hosts
sts.zenko.local management.zenko.local s3.zenko.local website.mywebsite.com" | sudo tee -a /etc/hosts

# Add bucket notification target
envsubst < ./configs/notification_destinations.yaml | kubectl apply -f -
Expand Down
19 changes: 19 additions & 0 deletions tests/ctst/features/bucketWebsite.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Feature: Bucket Websites

@2.6.0
@PreMerge
@BucketWebsite
Scenario Outline: Bucket Website CRUD
# The scenario should test that we can put a bucket website configuration on a bucket
# send an index.html
# And also use a pensieve API to add the new endpoint to the list
# Then using the local etc hosts, we should be able to load the html page
Given an existing bucket "website" "" versioning, "without" ObjectLock "without" retention mode
And an index html file
When the user puts the bucket website configuration
And the "<domain>" endpoint is added to the overlay
Then the user should be able to load the index.html file from the "<domain>" endpoint

Examples:
| domain |
| mywebsite.com |
10 changes: 5 additions & 5 deletions tests/ctst/steps/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ export async function deleteFile(path: string) {
return fsp.unlink(path);
}

async function uploadSetup(world: Zenko, action: string) {
async function uploadSetup(world: Zenko, action: string, body?: string) {
if (action !== 'PutObject' && action !== 'UploadPart') {
return;
}
const objectSize = world.getSaved<number>('objectSize') || 0;
if (objectSize > 0) {
if (body || objectSize > 0) {
const tempFileName = `${Utils.randomString()}_${world.getSaved<string>('objectName')}`;
world.addToSaved('tempFileName', `/tmp/${tempFileName}`);
const objectBody = 'a'.repeat(objectSize);
const objectBody = body || 'a'.repeat(objectSize);
await saveAsFile(tempFileName, objectBody);
world.addCommandParameter({ body: world.getSaved<string>('tempFileName') });
}
Expand Down Expand Up @@ -199,15 +199,15 @@ async function createBucketWithConfiguration(
}
}

async function putObject(world: Zenko, objectName?: string) {
async function putObject(world: Zenko, objectName?: string, content?: string) {
world.resetCommand();
let finalObjectName = objectName;
if (!finalObjectName) {
finalObjectName = `${Utils.randomString()}`;
}
world.addToSaved('objectName', finalObjectName);
world.logger.debug('Adding object', { objectName: finalObjectName });
await uploadSetup(world, 'PutObject');
await uploadSetup(world, 'PutObject', content);
world.addCommandParameter({ key: finalObjectName });
world.addCommandParameter({ bucket: world.getSaved<string>('bucketName') });
const userMetadata = world.getSaved<string>('userMetadata');
Expand Down
50 changes: 50 additions & 0 deletions tests/ctst/steps/website/website.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import assert from 'assert';
import { Given, When, Then } from '@cucumber/cucumber';
import Zenko from '../../world/Zenko';
import { putObject } from '../utils/utils';
import { S3, Utils } from 'cli-testing';

const pageMessage = Utils.randomString();

Given('an index html file', async function (this: Zenko) {
// push a file with a basic html content named index.html in the bucket
const content = `<html><head><title>Index</title></head><body><h1>${pageMessage}</h1></body></html>`;
this.addToSaved('objectSize', content.length);
await putObject(this, 'index.html', content);
});

When('the user puts the bucket website configuration', async function (this: Zenko) {
const bucketWebSiteConfiguration = JSON.stringify({
IndexDocument: {
Suffix: 'index.html',
},
ErrorDocument: {
Key: 'error.html',
},
});

await S3.putBucketWebsite({
bucket: this.getSaved<string>('bucketName'),
websiteConfiguration: bucketWebSiteConfiguration,
});
});

When('the {string} endpoint is added to the overlay', async function (this: Zenko, endpoint: string) {
await this.addWebsiteEndpoint(endpoint);
});

Then('the user should be able to load the index.html file from the {string} endpoint',
async function (this: Zenko, endpoint: string) {
const uri = `http://${this.getSaved<string>('bucketName')}.${endpoint}`;
try {
const response = await fetch(uri);
const content = await response.text();
assert.strictEqual(content.includes(pageMessage), true);
} catch (err) {
this.logger.error('error when fetching the bucket website', {
err,
uri,
});
throw err;
}
});
28 changes: 27 additions & 1 deletion tests/ctst/world/Zenko.ts
Original file line number Diff line number Diff line change
Expand Up @@ -909,7 +909,7 @@ export default class Zenko extends World<ZenkoWorldParameters> {
method: Method,
path: string,
headers: object = {},
payload: object = {}
payload: object | string = {},
): Promise<{ statusCode: number; data: object } | { statusCode: number; err: unknown }> {
const token = await this.getWebIdentityToken(
this.parameters.KeycloakUsername || 'zenko-end2end',
Expand All @@ -935,9 +935,25 @@ export default class Zenko extends World<ZenkoWorldParameters> {
};
try {
const response: AxiosResponse = await axiosInstance(axiosConfig);
this.logger.debug('Management API request', {
method,
path,
headers,
payload,
response: response.data,
statusCode: response.status,
});
return { statusCode: response.status, data: response.data as object };
/* eslint-disable */
} catch (err: any) {
this.logger.debug('Error when making management API request', {
method,
path,
headers,
payload,
err: err.response.data,
status: err.response.status,
});
return {
statusCode: err.response.status,
err: err.response.data,
Expand All @@ -946,6 +962,16 @@ export default class Zenko extends World<ZenkoWorldParameters> {
}
}

async addWebsiteEndpoint(this: Zenko, endpoint: string) :
Promise<{ statusCode: number; data: object } | { statusCode: number; err: unknown }> {
return await this.managementAPIRequest('POST',
`/config/${this.parameters.InstanceID}/website/endpoint`,
{
'Content-Type': 'application/json',
},
`"${endpoint}"`);
}

async deleteLocation(this: Zenko, locationName: string) :
Promise<{ statusCode: number; data: object } | { statusCode: number; err: unknown }> {
return await this.managementAPIRequest('DELETE',
Expand Down

0 comments on commit b56188c

Please sign in to comment.