test(e2e): Add test for minio storage bucket (#2312)
This commit is contained in:
1 parent
a92701701c
commit
5a7e09c70c
3 files changed
+311
-5
No files matched your search
@@ -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);
|
||||
|
||||
+3
-3
@@ -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');
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user