test: 💍 Add storage policies e2e-test (#2175)
* test: 💍 Add storage policies e2e-test ✅ Closes: ICU-12883 * chore: Adjust required env for e2e-tests ✅ Closes: ICU-12883 * CR: Refactor helper method to pass in env --------- Co-authored-by: Michael Li <michael.li@hashicorp.com>
This commit is contained in:
1 parent
0902e42cb0
commit
f100190ac1
5 files changed
+441
-27
No files matched your search
@@ -25,13 +25,13 @@ exports.authenticateBoundaryCli = async () => {
|
||||
try {
|
||||
execSync(
|
||||
'boundary authenticate password' +
|
||||
' -addr=' +
|
||||
process.env.BOUNDARY_ADDR +
|
||||
' -auth-method-id=' +
|
||||
process.env.E2E_PASSWORD_AUTH_METHOD_ID +
|
||||
' -login-name=' +
|
||||
process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME +
|
||||
' -password=env://E2E_PASSWORD_ADMIN_PASSWORD',
|
||||
' -addr=' +
|
||||
process.env.BOUNDARY_ADDR +
|
||||
' -auth-method-id=' +
|
||||
process.env.E2E_PASSWORD_AUTH_METHOD_ID +
|
||||
' -login-name=' +
|
||||
process.env.E2E_PASSWORD_ADMIN_LOGIN_NAME +
|
||||
' -password=env://E2E_PASSWORD_ADMIN_PASSWORD',
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(`${e.stderr}`);
|
||||
@@ -48,18 +48,18 @@ exports.connectToTarget = async (targetId) => {
|
||||
try {
|
||||
connect = exec(
|
||||
'boundary connect' +
|
||||
' -target-id=' +
|
||||
targetId +
|
||||
' -exec /usr/bin/ssh --' +
|
||||
' -l ' +
|
||||
process.env.E2E_SSH_USER +
|
||||
' -i ' +
|
||||
process.env.E2E_SSH_KEY_PATH +
|
||||
' -o UserKnownHostsFile=/dev/null' +
|
||||
' -o StrictHostKeyChecking=no' +
|
||||
' -o IdentitiesOnly=yes' + // forces the use of the provided key
|
||||
' -p {{boundary.port}}' +
|
||||
' {{boundary.ip}}',
|
||||
' -target-id=' +
|
||||
targetId +
|
||||
' -exec /usr/bin/ssh --' +
|
||||
' -l ' +
|
||||
process.env.E2E_SSH_USER +
|
||||
' -i ' +
|
||||
process.env.E2E_SSH_KEY_PATH +
|
||||
' -o UserKnownHostsFile=/dev/null' +
|
||||
' -o StrictHostKeyChecking=no' +
|
||||
' -o IdentitiesOnly=yes' + // forces the use of the provided key
|
||||
' -p {{boundary.port}}' +
|
||||
' {{boundary.ip}}',
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(`${e.stderr}`);
|
||||
@@ -77,12 +77,12 @@ exports.connectSshToTarget = async (targetId) => {
|
||||
try {
|
||||
connect = exec(
|
||||
'boundary connect ssh' +
|
||||
' -target-id=' +
|
||||
targetId +
|
||||
' --' +
|
||||
' -o UserKnownHostsFile=/dev/null' +
|
||||
' -o StrictHostKeyChecking=no' +
|
||||
' -o IdentitiesOnly=yes', // forces the use of the provided key
|
||||
' -target-id=' +
|
||||
targetId +
|
||||
' --' +
|
||||
' -o UserKnownHostsFile=/dev/null' +
|
||||
' -o StrictHostKeyChecking=no' +
|
||||
' -o IdentitiesOnly=yes', // forces the use of the provided key
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(`${e.stderr}`);
|
||||
@@ -124,6 +124,30 @@ exports.deleteOrgCli = async (orgId) => {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses the boundary CLI to delete the specified storage bucket
|
||||
* @param {string} storageBucketId ID of the storage bucket to be deleted
|
||||
*/
|
||||
exports.deleteStorageBucketCli = async (storageBucketId) => {
|
||||
try {
|
||||
exec('boundary storage-buckets delete -id=' + storageBucketId);
|
||||
} catch (e) {
|
||||
console.log(`${e.stderr}`);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses the boundary CLI to delete the specified policy
|
||||
* @param {string} policyId ID of the policy to be deleted
|
||||
*/
|
||||
exports.deletePolicyCli = async (policyId) => {
|
||||
try {
|
||||
exec('boundary policies delete -id=' + policyId);
|
||||
} catch (e) {
|
||||
console.log(`${e.stderr}`);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses the boundary CLI to create a new project.
|
||||
* @param {string} orgId ID of the organization under which the project will be created.
|
||||
@@ -580,3 +604,29 @@ exports.getSessionCli = async (orgName, projectName, targetName) => {
|
||||
}
|
||||
return session;
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses the boundary CLI to wait for a session recording to be available.
|
||||
* @param {string} storageBucketId ID of storage bucket that the session recording is associated with
|
||||
* @returns An object representing a session recording
|
||||
*/
|
||||
exports.waitForSessionRecordingCli = async (storageBucketId) => {
|
||||
let i = 0;
|
||||
let filteredSessionRecording = [];
|
||||
do {
|
||||
i = i + 1;
|
||||
const sessionRecordings = JSON.parse(
|
||||
execSync('boundary session-recordings list -format json'),
|
||||
);
|
||||
filteredSessionRecording = sessionRecordings.items.filter(
|
||||
(obj) =>
|
||||
obj.storage_bucket_id == storageBucketId && obj.state == 'available',
|
||||
);
|
||||
if (filteredSessionRecording.length > 0) {
|
||||
break;
|
||||
}
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
} while (i < 5);
|
||||
|
||||
return filteredSessionRecording[0];
|
||||
};
|
||||
@@ -443,6 +443,46 @@ exports.createSshTargetWithAddressEnt = async (page) => {
|
||||
return targetName;
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses the UI to create a new SSH target with address in boundary-enterprise
|
||||
* Assumes you have selected the desired project.
|
||||
* @param {Page} page Playwright page object
|
||||
* @param {string} address Address of the target
|
||||
* @param {string} port Port of the target
|
||||
* @param {string} workerFilterEgress Egress worker filter
|
||||
* @returns Name of the target
|
||||
*/
|
||||
exports.createSshTargetWithAddressAndWorkerFilterEnt = async (
|
||||
page,
|
||||
address,
|
||||
port,
|
||||
workerFilterEgress,
|
||||
) => {
|
||||
const targetName = 'Target ' + nanoid();
|
||||
await page
|
||||
.getByRole('navigation', { name: 'Resources' })
|
||||
.getByRole('link', { name: 'Targets' })
|
||||
.click();
|
||||
await page.getByRole('link', { name: 'New', exact: true }).click();
|
||||
await page.getByLabel('Name').fill(targetName);
|
||||
await page.getByLabel('Description').fill('This is an automated test');
|
||||
await page.getByRole('group', { name: 'Type' }).getByLabel('SSH').click();
|
||||
await page.getByLabel('Target Address').fill(address);
|
||||
await page.getByLabel('Default Port').fill(port);
|
||||
await page.getByLabel('Egress worker filter').click();
|
||||
await page.getByRole('textbox', { name: 'Filter' }).fill(workerFilterEgress);
|
||||
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(targetName),
|
||||
).toBeVisible();
|
||||
|
||||
return targetName;
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses the UI to delete a Boundary resource. Assume you have selected the desired resource.
|
||||
* Note: For a resource to be deleted using this method,
|
||||
@@ -498,7 +538,8 @@ exports.addHostSourceToTarget = async (page, hostSourceName) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses the UI to navigate to Sessions and waits for the session to appear.
|
||||
* Uses the UI to navigate to Sessions and waits for the session to appear
|
||||
* and be in Active state.
|
||||
* @param {Page} page Playwright page object
|
||||
* @param {string} targetName Name of the target associated with the session
|
||||
*/
|
||||
@@ -509,12 +550,16 @@ exports.waitForSessionToBeVisible = async (page, targetName) => {
|
||||
.click();
|
||||
let i = 0;
|
||||
let sessionIsVisible = false;
|
||||
let sessionIsActive = false;
|
||||
do {
|
||||
i = i + 1;
|
||||
sessionIsVisible = await page
|
||||
.getByRole('cell', { name: targetName })
|
||||
.isVisible();
|
||||
if (sessionIsVisible) {
|
||||
sessionIsActive = await page
|
||||
.getByRole('cell', { name: 'Active' })
|
||||
.isVisible();
|
||||
if (sessionIsVisible && sessionIsActive) {
|
||||
break;
|
||||
}
|
||||
await page.getByRole('button', { name: 'Refresh' }).click();
|
||||
@@ -858,3 +903,109 @@ exports.addGrantsToGroup = async (page, grants) => {
|
||||
page.getByRole('textbox', { name: 'Grant', exact: true }),
|
||||
).toHaveValue(grants);
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses the UI to create a new Storage Bucket. Assumes you have selected the desired scope.
|
||||
* @param {Page} page Playwright page object
|
||||
* @returns Name of the Storage Bucket
|
||||
*/
|
||||
exports.createStorageBucket = async (page) => {
|
||||
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('Bucket name').fill(process.env.E2E_AWS_BUCKET_NAME);
|
||||
await page.getByLabel('Region').fill(process.env.E2E_AWS_REGION);
|
||||
await page
|
||||
.getByLabel('Access key ID')
|
||||
.fill(process.env.E2E_AWS_ACCESS_KEY_ID);
|
||||
await page
|
||||
.getByLabel('Secret access key')
|
||||
.fill(process.env.E2E_AWS_SECRET_ACCESS_KEY);
|
||||
const workerTag = `"${process.env.E2E_WORKER_TAG_EGRESS}" in "/tags/type"`;
|
||||
await page.getByLabel('Worker filter').fill(workerTag);
|
||||
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 enable session recording for a target. Assumes you have selected the desired target.
|
||||
* @param {Page} page Playwright page object
|
||||
* @param {string} storageBucketName name of the Storage Bucket used for session recording
|
||||
*/
|
||||
exports.enableSessionRecording = async (page, storageBucketName) => {
|
||||
await page.getByText('Enable recording').click();
|
||||
await page.getByLabel('Record sessions for this target').click();
|
||||
await page
|
||||
.getByLabel('AWS storage buckets')
|
||||
.selectOption({ label: storageBucketName });
|
||||
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('listitem').getByText(storageBucketName),
|
||||
).toBeVisible();
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses the UI to create a Storage Policy. Assumes you have selected the desired scope.
|
||||
* @param {Page} page Playwright page object
|
||||
* @returns Name of the Storage Policy
|
||||
*/
|
||||
exports.createStoragePolicy = async (page) => {
|
||||
const storagePolicyName = 'Policy ' + nanoid();
|
||||
await page
|
||||
.getByRole('link', { name: 'Storage Policies', exact: true })
|
||||
.click();
|
||||
await page
|
||||
.getByRole('link', { name: 'Create a new storage policy', exact: true })
|
||||
.click();
|
||||
await page.getByLabel('Name').fill(storagePolicyName);
|
||||
await page.getByLabel('Retention Policy').selectOption({ label: 'Forever' });
|
||||
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(storagePolicyName),
|
||||
).toBeVisible();
|
||||
|
||||
return storagePolicyName;
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses the UI to attach Storage Policy to a scope. Assumes you have selected the desired scope.
|
||||
* @param {Page} page Playwright page object
|
||||
* @param {string} policyName name of the Policy to be attached to the scope
|
||||
*/
|
||||
exports.attachStoragePolicy = async (page, policyName) => {
|
||||
await page
|
||||
.getByRole('link', { name: new RegExp('/*Settings'), exact: true })
|
||||
.click();
|
||||
await page.getByText('Add Storage Policy').click();
|
||||
await page.getByLabel('Storage Policy').selectOption({ label: policyName });
|
||||
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('listitem').getByText(policyName)).toBeVisible();
|
||||
};
|
||||
@@ -0,0 +1,211 @@
|
||||
/**
|
||||
* 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,
|
||||
createStorageBucket,
|
||||
enableSessionRecording,
|
||||
createStoragePolicy,
|
||||
attachStoragePolicy,
|
||||
createNewOrg,
|
||||
createNewProject,
|
||||
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_AWS_BUCKET_NAME',
|
||||
'E2E_AWS_REGION',
|
||||
'E2E_AWS_ACCESS_KEY_ID',
|
||||
'E2E_AWS_SECRET_ACCESS_KEY',
|
||||
'E2E_WORKER_TAG_EGRESS',
|
||||
]);
|
||||
|
||||
await checkBoundaryCli();
|
||||
});
|
||||
|
||||
test('Verify session recording can be deleted @ent @aws', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
let orgId;
|
||||
let storagePolicy;
|
||||
let storageBucket;
|
||||
let connect;
|
||||
try {
|
||||
await authenticateBoundaryCli();
|
||||
// Create org
|
||||
const orgName = await createNewOrg(page);
|
||||
await authenticateBoundaryCli();
|
||||
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 createNewProject(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 createStorageBucket(page);
|
||||
const storageBuckets = JSON.parse(
|
||||
execSync('boundary storage-buckets list -format json'),
|
||||
);
|
||||
storageBucket = storageBuckets.items.filter(
|
||||
(obj) => obj.name == storageBucketName,
|
||||
)[0];
|
||||
|
||||
// Create SSH Target
|
||||
await page.getByRole('link', { name: 'Orgs', exact: true }).click();
|
||||
await page.getByRole('link', { name: orgId }).click();
|
||||
await page.getByRole('link', { name: projectId }).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);
|
||||
await addInjectedCredentialsToTarget(page, targetName, credentialName);
|
||||
|
||||
// Enable session recording for Target
|
||||
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: orgId }).click();
|
||||
const policyName = await createStoragePolicy(page);
|
||||
|
||||
// Attach Storage Policy to org scope
|
||||
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' }).click();
|
||||
|
||||
// Try to delete Session Recording: expect failure
|
||||
await waitForSessionRecordingCli(storageBucket.id);
|
||||
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: 'Delete recording' }).click();
|
||||
await page.getByRole('button', { name: 'OK' }).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: orgId }).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();
|
||||
|
||||
// Re-apply Storage Policy to the Session Recording
|
||||
await page.reload(); // fixes error appearing on re-applying storage policy
|
||||
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');
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -39,6 +39,7 @@ test.beforeAll(async () => {
|
||||
'E2E_TARGET_ADDRESS',
|
||||
'E2E_SSH_USER',
|
||||
'E2E_SSH_KEY_PATH',
|
||||
'E2E_WORKER_TAG_EGRESS',
|
||||
]);
|
||||
|
||||
await checkBoundaryCli();
|
||||
|
||||
@@ -33,6 +33,7 @@ test.beforeAll(async () => {
|
||||
'E2E_SSH_KEY_PATH',
|
||||
'E2E_TARGET_ADDRESS',
|
||||
'E2E_TARGET_PORT',
|
||||
'E2E_WORKER_TAG_EGRESS',
|
||||
]);
|
||||
|
||||
await checkBoundaryCli();
|
||||
|
||||
Reference in new issue
Block a user