test(e2e): Add test for minio storage bucket (#2312)

This commit is contained in:
Michael Li authored and GitHub committed 2024-06-06 14:59:13 -04:00
1 parent a92701701c
commit 5a7e09c70c
3 files changed
+311 -5

No files matched your search

+60 -2
View File
@@ -930,7 +930,7 @@ exports.addGrantsToGroup = async (page, grants) => {
};
/**
* Uses the UI to create a new Storage Bucket. Assumes you have selected the desired scope.
* Uses the UI to create a new AWS Storage Bucket.
* @param {Page} page Playwright page object
* @param {string} scope Scope of the Storage Bucket
* @param {string} bucketName Name of the Storage Bucket
@@ -940,7 +940,7 @@ exports.addGrantsToGroup = async (page, grants) => {
* @param {string} workerFilter Worker filter for the Storage Bucket
* @returns Name of the Storage Bucket
*/
exports.createStorageBucket = async (
exports.createStorageBucketAws = async (
page,
scope,
bucketName,
@@ -956,6 +956,64 @@ exports.createStorageBucket = async (
await page.getByRole('link', { name: 'New Storage Bucket' }).click();
await page.getByLabel(new RegExp('Name*')).fill(storageBucketName);
await page.getByLabel('Scope').selectOption({ label: scope });
await page
.getByRole('group', { name: 'Provider' })
.getByLabel('Amazon S3')
.click();
await page.getByLabel('Bucket name').fill(bucketName);
await page.getByLabel('Region').fill(region);
await page.getByLabel('Access key ID').fill(accessKeyId);
await page.getByLabel('Secret access key').fill(secretAccessKey);
await page.getByLabel('Worker filter').fill(workerFilter);
await page.getByLabel('Disable credential rotation').click();
await page.getByRole('button', { name: 'Save' }).click();
await expect(
page.getByRole('alert').getByText('Success', { exact: true }),
).toBeVisible();
await page.getByRole('button', { name: 'Dismiss' }).click();
await expect(
page
.getByRole('navigation', { name: 'breadcrumbs' })
.getByText(storageBucketName),
).toBeVisible();
return storageBucketName;
};
/**
* Uses the UI to create a new MinIO Storage Bucket.
* @param {Page} page Playwright page object
* @param {string} scope Scope of the Storage Bucket
* @param {string} endpointUrl Endpoint URL of the Storage Bucket
* @param {string} bucketName Name of the Storage Bucket
* @param {string} region Region of the Storage Bucket
* @param {string} accessKeyId Access Key ID for the Storage Bucket
* @param {string} secretAccessKey Secret Access Key for the Storage Bucket
* @param {string} workerFilter Worker filter for the Storage Bucket
* @returns Name of the Storage Bucket
*/
exports.createStorageBucketMinio = async (
page,
scope,
endpointUrl,
bucketName,
region,
accessKeyId,
secretAccessKey,
workerFilter,
) => {
const storageBucketName = 'Bucket ' + nanoid();
await page
.getByRole('link', { name: 'Storage Buckets', exact: true })
.click();
await page.getByRole('link', { name: 'New Storage Bucket' }).click();
await page.getByLabel(new RegExp('Name*')).fill(storageBucketName);
await page.getByLabel('Scope').selectOption({ label: scope });
await page
.getByRole('group', { name: 'Provider' })
.getByLabel('MinIO')
.click();
await page.getByLabel('Endpoint URL').fill(endpointUrl);
await page.getByLabel('Bucket name').fill(bucketName);
await page.getByLabel('Region').fill(region);
await page.getByLabel('Access key ID').fill(accessKeyId);
@@ -19,7 +19,7 @@ const {
const {
createSshTargetWithAddressAndWorkerFilterEnt,
waitForSessionToBeVisible,
createStorageBucket,
createStorageBucketAws,
enableSessionRecording,
createStoragePolicy,
attachStoragePolicy,
@@ -48,7 +48,7 @@ test.beforeAll(async () => {
await checkBoundaryCli();
});
test('Verify session recording can be deleted @ent @aws', async ({ page }) => {
test('Session Recording Test (AWS) @ent @aws', async ({ page }) => {
await page.goto('/');
let orgId;
let storagePolicy;
@@ -77,7 +77,7 @@ test('Verify session recording can be deleted @ent @aws', async ({ page }) => {
// Create storage bucket
await page.getByRole('link', { name: 'Orgs', exact: true }).click();
const storageBucketName = await createStorageBucket(
const storageBucketName = await createStorageBucketAws(
page,
orgName,
process.env.E2E_AWS_BUCKET_NAME,
@@ -0,0 +1,248 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/
/* eslint-disable no-undef */
const { test, expect } = require('@playwright/test');
const { execSync } = require('child_process');
const { checkEnv, authenticatedState } = require('../helpers/general');
const {
authenticateBoundaryCli,
checkBoundaryCli,
connectSshToTarget,
deleteOrgCli,
waitForSessionRecordingCli,
deleteStorageBucketCli,
deletePolicyCli,
} = require('../helpers/boundary-cli');
const {
createSshTargetWithAddressAndWorkerFilterEnt,
waitForSessionToBeVisible,
createStorageBucketMinio,
enableSessionRecording,
createStoragePolicy,
attachStoragePolicy,
createOrg,
createProject,
createStaticCredentialStore,
createStaticCredentialKeyPair,
addInjectedCredentialsToTarget,
} = require('../helpers/boundary-ui');
test.use({ storageState: authenticatedState });
test.beforeAll(async () => {
await checkEnv([
'E2E_SSH_USER',
'E2E_SSH_KEY_PATH',
'E2E_TARGET_ADDRESS',
'E2E_TARGET_PORT',
'E2E_BUCKET_NAME',
'E2E_BUCKET_ENDPOINT_URL',
'E2E_BUCKET_ACCESS_KEY_ID',
'E2E_BUCKET_SECRET_ACCESS_KEY',
'E2E_REGION',
]);
await checkBoundaryCli();
});
test('Session Recording Test (MinIO) @ent @docker', async ({ page }) => {
await page.goto('/');
let orgId;
let storagePolicy;
let storageBucket;
let connect;
try {
// Create org
const orgName = await createOrg(page);
await authenticateBoundaryCli(
process.env.BOUNDARY_ADDR,
process.env.E2E_PASSWORD_AUTH_METHOD_ID,
process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME,
process.env.E2E_PASSWORD_ADMIN_PASSWORD,
);
const orgs = JSON.parse(execSync('boundary scopes list -format json'));
const org = orgs.items.filter((obj) => obj.name == orgName)[0];
orgId = org.id;
// Create project
const projectName = await createProject(page);
const projects = JSON.parse(
execSync('boundary scopes list -format json -scope-id ' + org.id),
);
const project = projects.items.filter((obj) => obj.name == projectName)[0];
const projectId = project.id;
// Create storage bucket
await page.getByRole('link', { name: 'Orgs', exact: true }).click();
const storageBucketName = await createStorageBucketMinio(
page,
orgName,
process.env.E2E_BUCKET_ENDPOINT_URL,
process.env.E2E_BUCKET_NAME,
process.env.E2E_REGION,
process.env.E2E_BUCKET_ACCESS_KEY_ID,
process.env.E2E_BUCKET_SECRET_ACCESS_KEY,
`"${process.env.E2E_WORKER_TAG_EGRESS}" in "/tags/type"`,
);
const storageBuckets = JSON.parse(
execSync('boundary storage-buckets list --recursive -format json'),
);
storageBucket = storageBuckets.items.filter(
(obj) => obj.name == storageBucketName,
)[0];
// Create target
await page.getByRole('link', { name: 'Orgs', exact: true }).click();
await page.getByRole('link', { name: orgName }).click();
await page.getByRole('link', { name: projectName }).click();
const targetName = await createSshTargetWithAddressAndWorkerFilterEnt(
page,
process.env.E2E_TARGET_ADDRESS,
process.env.E2E_TARGET_PORT,
`"${process.env.E2E_WORKER_TAG_EGRESS}" in "/tags/type"`,
);
const targets = JSON.parse(
execSync('boundary targets list -format json -scope-id ' + projectId),
);
const target = targets.items.filter((obj) => obj.name == targetName)[0];
await createStaticCredentialStore(page);
const credentialName = await createStaticCredentialKeyPair(
page,
process.env.E2E_SSH_USER,
process.env.E2E_SSH_KEY_PATH,
);
await addInjectedCredentialsToTarget(page, targetName, credentialName);
await page.getByRole('link', { name: targetName }).click();
await enableSessionRecording(page, storageBucketName);
// Create storage policy in org scope: keep session recordings forever
await page.getByRole('link', { name: 'Orgs', exact: true }).click();
await page.getByRole('link', { name: orgName }).click();
const policyName = await createStoragePolicy(page);
await attachStoragePolicy(page, policyName);
// Establish connection to target and cancel it
connect = await connectSshToTarget(target.id);
await page.getByRole('link', { name: 'Projects', exact: true }).click();
await page.getByRole('link', { name: projectName }).click();
await waitForSessionToBeVisible(page, targetName);
await page
.getByRole('cell', { name: targetName })
.locator('..')
.getByRole('button', { name: 'Cancel' })
.click();
await expect(
page.getByRole('alert').getByText('Success', { exact: true }),
).toBeVisible();
await page.getByRole('button', { name: 'Dismiss', exact: true }).click();
await waitForSessionRecordingCli(storageBucket.id);
// Play back session recording
await page.getByRole('link', { name: 'Orgs', exact: true }).click();
await page
.getByRole('navigation', { name: 'General' })
.getByRole('link', { name: 'Session Recordings', exact: true })
.click();
await page
.getByRole('row', { name: targetName })
.getByRole('link', { name: 'View' })
.click();
await page
.getByRole('cell', { name: 'Channel 1' })
.locator('..')
.getByRole('link', { name: 'Play' })
.click();
await page.locator('div.session-recording-player').hover();
await page.locator('.ap-playback-button').click();
// Try to delete session recording: expect failure
await page.getByRole('link', { name: 'Orgs', exact: true }).click();
await page
.getByRole('navigation', { name: 'General' })
.getByRole('link', { name: 'Session Recordings', exact: true })
.click();
await page
.getByRole('row', { name: targetName })
.getByRole('link', { name: 'View' })
.click();
await page.getByText('Manage').click();
await page.getByRole('button', { name: 'Delete recording' }).click();
await page.getByRole('button', { name: 'OK', exact: true }).click();
await expect(
page.getByRole('alert').getByText('Error', { exact: true }),
).toBeVisible();
await page.getByRole('button', { name: 'Dismiss' }).click();
// Edit storage policy: do not protect from deletion
const storagePolicies = JSON.parse(
execSync('boundary policies list -format json -scope-id ' + orgId),
);
storagePolicy = storagePolicies.items.filter(
(obj) => obj.name == policyName,
)[0];
await page.getByRole('link', { name: 'Orgs', exact: true }).click();
await page.getByRole('link', { name: orgName }).click();
await page
.getByRole('link', { name: 'Storage Policies', exact: true })
.click();
await page.getByRole('link', { name: policyName }).click();
await page.getByRole('button', { name: 'Edit form' }).click();
await page
.getByLabel('Retention Policy')
.selectOption({ label: 'Do not protect, allow deletion any time' });
await page.getByLabel('Deletion Policy').selectOption({ label: 'Custom' });
await page.getByRole('button', { name: 'Save' }).click();
await expect(
page.getByRole('alert').getByText('Success', { exact: true }),
).toBeVisible();
await page.getByRole('button', { name: 'Dismiss' }).click();
// BUG? After the error trying to delete the session recording, subsequent
// actions result in an error. Reloading the page fixes the issue. This is a
// temporary workaround.
await page.reload();
// Re-apply storage policy to the session recording
await page.getByRole('link', { name: 'Orgs', exact: true }).click();
await page
.getByRole('link', { name: 'Session Recordings', exact: true })
.click();
await page
.getByRole('row', { name: targetName })
.getByRole('link', { name: 'View' })
.click();
await page.getByText('Manage').click();
await page.getByRole('button', { name: 'Re-apply storage policy' }).click();
await expect(
page.getByRole('alert').getByText('Success', { exact: true }),
).toBeVisible();
await page.getByRole('button', { name: 'Dismiss' }).click();
// Delete session recording
await page.getByText('Manage').click();
await page.getByRole('button', { name: 'Delete recording' }).click();
await page.getByRole('button', { name: 'OK' }).click();
await expect(
page.getByRole('alert').getByText('Success', { exact: true }),
).toBeVisible();
await page.getByRole('button', { name: 'Dismiss' }).click();
} finally {
if (storagePolicy) {
await deletePolicyCli(storagePolicy.id);
}
if (orgId) {
await deleteOrgCli(orgId);
}
if (storageBucket) {
await deleteStorageBucketCli(storageBucket.id);
}
// End `boundary connect` process
if (connect) {
connect.kill('SIGTERM');
}
}
});