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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ML] Add functional tests for reauthorizing transforms #156699

Merged
merged 10 commits into from
May 18, 2023
4 changes: 2 additions & 2 deletions .buildkite/ftr_configs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ enabled:
- x-pack/test/functional_basic/apps/ml/data_visualizer/group2/config.ts
- x-pack/test/functional_basic/apps/ml/data_visualizer/group3/config.ts
- x-pack/test/functional_basic/apps/transform/creation/index_pattern/config.ts
- x-pack/test/functional_basic/apps/transform/start_reset_delete/config.ts
- x-pack/test/functional_basic/apps/transform/actions/config.ts
- x-pack/test/functional_basic/apps/transform/edit_clone/config.ts
- x-pack/test/functional_basic/apps/transform/creation/runtime_mappings_saved_search/config.ts
- x-pack/test/functional_basic/apps/transform/permissions/config.ts
Expand Down Expand Up @@ -291,7 +291,7 @@ enabled:
- x-pack/test/functional/apps/status_page/config.ts
- x-pack/test/functional/apps/transform/creation/index_pattern/config.ts
- x-pack/test/functional/apps/transform/creation/runtime_mappings_saved_search/config.ts
- x-pack/test/functional/apps/transform/start_reset_delete/config.ts
- x-pack/test/functional/apps/transform/actions/config.ts
- x-pack/test/functional/apps/transform/edit_clone/config.ts
- x-pack/test/functional/apps/transform/permissions/config.ts
- x-pack/test/functional/apps/transform/feature_controls/config.ts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ export const TransformManagement: FC = () => {
<EuiCallOut
iconType="alert"
color="warning"
data-test-subj="transformPageReauthorizeCallout"
title={`${insufficientPermissionsMsg} ${actionMsg}`}
/>
<EuiSpacer size="s" />
Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/transform/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ With PATH_TO_CONFIG and other options as follows.
edit, clone | `test/functional/apps/transform/edit_clone/config.ts`
feature controls | `test/functional/apps/transform/feature_controls/config.ts`
permissions | `test/functional/apps/transform/permissions/config.ts`
start, reset, delete | `test/functional/apps/transform/start_reset_delete/config.ts`
actions | `test/functional/apps/transform/actions/config.ts`

1. Functional UI tests with `Basic` license:

Expand All @@ -133,7 +133,7 @@ With PATH_TO_CONFIG and other options as follows.
edit, clone | `test/functional_basic/apps/transform/edit_clone/config.ts`
feature controls | `test/functional_basic/apps/transform/feature_controls/config.ts`
permissions | `test/functional_basic/apps/transform/permissions/config.ts`
start, reset, delete | `test/functional_basic/apps/transform/start_reset_delete/config.ts`
actions | `test/functional_basic/apps/transform/actions/config.ts`

1. API integration tests with `Trial` license:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertestWithoutAuth');
const transform = getService('transform');

// If transform was created with sufficient -> should still authorize and start
// If transform was created with insufficient -> should still authorize and start

function getTransformIdByUser(username: USER) {
return `transform-by-${username}`;
}
Expand Down Expand Up @@ -51,6 +48,8 @@ export default ({ getService }: FtrProviderContext) => {
await transform.api.deleteIndices(destinationIndex);
}

// If transform was created with sufficient permissions -> should create and start
// If transform was created with insufficient permissions -> should create but not start
describe('/api/transform/reauthorize_transforms', function () {
const apiKeysForTransformUsers = new Map<USER, SecurityCreateApiKeyResponse>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
...functionalConfig.getAll(),
testFiles: [require.resolve('.')],
junit: {
reportName: 'Chrome X-Pack UI Functional Tests - transform - start reset & delete',
reportName: 'Chrome X-Pack UI Functional Tests - transform - actions',
},
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const transform = getService('transform');

describe('transform - start reset & delete', function () {
describe('transform - actions', function () {
this.tags('transform');

before(async () => {
Expand All @@ -33,6 +33,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) {
});

loadTestFile(require.resolve('./deleting'));
loadTestFile(require.resolve('./reauthorizing'));
loadTestFile(require.resolve('./resetting'));
loadTestFile(require.resolve('./starting'));
});
Expand Down
221 changes: 221 additions & 0 deletions x-pack/test/functional/apps/transform/actions/reauthorizing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { TRANSFORM_HEALTH_LABEL, TRANSFORM_STATE } from '@kbn/transform-plugin/common/constants';
import type {
TransformLatestConfig,
TransformPivotConfig,
} from '@kbn/transform-plugin/common/types/transform';
import type { SecurityCreateApiKeyResponse } from '@elastic/elasticsearch/lib/api/types';
import type { FtrProviderContext } from '../../../ftr_provider_context';
import { getLatestTransformConfig, getPivotTransformConfig } from '../helpers';
import { USER } from '../../../services/transform/security_common';
import { COMMON_REQUEST_HEADERS } from '../../../services/ml/common_api';

interface TestDataPivot {
suiteTitle: string;
originalConfig: TransformPivotConfig;
mode: 'batch' | 'continuous';
type: 'pivot';
expected: {
originalState: object;
reauthorizeEnabled: boolean;
reauthorizedState: object;
};
created_by_user: USER;
current_user: USER;
}

interface TestDataLatest {
suiteTitle: string;
originalConfig: TransformLatestConfig;
mode: 'batch' | 'continuous';
type: 'latest';
expected: {
originalState: object;
reauthorizeEnabled: boolean;
reauthorizedState: object;
};
created_by_user: USER;
current_user: USER;
}

type TestData = TestDataPivot | TestDataLatest;

function generateHeaders(apiKey: SecurityCreateApiKeyResponse) {
return {
...COMMON_REQUEST_HEADERS,
'es-secondary-authorization': `ApiKey ${apiKey.encoded}`,
};
}

export default function ({ getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const transform = getService('transform');

const apiKeysForTransformUsers = new Map<USER, SecurityCreateApiKeyResponse>();

describe('reauthorizing', function () {
const PREFIX = 'reauthorizing';
const testDataList: TestData[] = [
{
suiteTitle: 'continuous pivot transform (created by viewer, viewed by viewer)',
originalConfig: getPivotTransformConfig(`${PREFIX}-${USER.TRANSFORM_VIEWER}-1`, true),
mode: 'continuous',
type: 'pivot',
expected: {
originalState: { status: TRANSFORM_STATE.STOPPED, health: TRANSFORM_HEALTH_LABEL.red },
reauthorizeEnabled: false,
reauthorizedState: {
status: TRANSFORM_STATE.STARTED,
health: TRANSFORM_HEALTH_LABEL.green,
},
},
created_by_user: USER.TRANSFORM_VIEWER,
current_user: USER.TRANSFORM_VIEWER,
},
{
suiteTitle: 'batch pivot transform (created by viewer, viewed by poweruser)',
originalConfig: getPivotTransformConfig(PREFIX, false),
mode: 'batch',
type: 'pivot',
expected: {
originalState: { status: TRANSFORM_STATE.STOPPED, health: TRANSFORM_HEALTH_LABEL.red },
reauthorizeEnabled: true,
reauthorizedState: {
status: TRANSFORM_STATE.STOPPED,
progress: '100',
health: TRANSFORM_HEALTH_LABEL.green,
},
},
created_by_user: USER.TRANSFORM_VIEWER,
current_user: USER.TRANSFORM_POWERUSER,
},
{
suiteTitle: 'continuous pivot transform (created by viewer, authorized by poweruser)',
originalConfig: getPivotTransformConfig(`${PREFIX}-${USER.TRANSFORM_VIEWER}-2`, true),
mode: 'continuous',
type: 'pivot',
expected: {
originalState: { status: TRANSFORM_STATE.STOPPED, health: TRANSFORM_HEALTH_LABEL.red },
reauthorizeEnabled: true,
reauthorizedState: {
status: TRANSFORM_STATE.STARTED,
health: TRANSFORM_HEALTH_LABEL.green,
},
},
created_by_user: USER.TRANSFORM_VIEWER,
current_user: USER.TRANSFORM_POWERUSER,
},
{
suiteTitle: 'continuous latest transform (created by poweruser, viewed by viewer)',
originalConfig: getLatestTransformConfig(`${PREFIX}-${USER.TRANSFORM_POWERUSER}-1`, true),
mode: 'continuous',
type: 'latest',
expected: {
originalState: { status: TRANSFORM_STATE.STARTED, health: TRANSFORM_HEALTH_LABEL.green },
reauthorizeEnabled: false,
reauthorizedState: {
status: TRANSFORM_STATE.STARTED,
health: TRANSFORM_HEALTH_LABEL.green,
},
},
created_by_user: USER.TRANSFORM_POWERUSER,
current_user: USER.TRANSFORM_VIEWER,
},
];

before(async () => {
const apiKeyForTransformUsers =
await transform.securityCommon.createApiKeyForTransformUsers();

apiKeyForTransformUsers.forEach(({ user, apiKey }) =>
apiKeysForTransformUsers.set(user.name as USER, apiKey)
);

await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/ecommerce');
await transform.testResources.createIndexPatternIfNeeded('ft_ecommerce', 'order_date');

for (const testData of testDataList) {
await transform.api.createTransform(testData.originalConfig.id, testData.originalConfig, {
deferValidation: true,
// Create transforms with secondary authorization headers
headers: generateHeaders(apiKeysForTransformUsers.get(testData.created_by_user)!),
});
// For transforms created with insufficient permissions, they can be created but not started
// so we should not assert that the api call is successful here
await transform.api.startTransform(testData.originalConfig.id, false);
}
await transform.testResources.setKibanaTimeZoneToUTC();
});

after(async () => {
await transform.securityCommon.clearAllTransformApiKeys();

for (const testData of testDataList) {
await transform.testResources.deleteIndexPatternByTitle(testData.originalConfig.dest.index);
await transform.api.deleteIndices(testData.originalConfig.dest.index);
}

await transform.api.cleanTransformIndices();
await transform.testResources.deleteIndexPatternByTitle('ft_ecommerce');
});

for (const testData of testDataList) {
const transformId = testData.originalConfig.id;

describe(`${testData.suiteTitle}`, function () {
it('reauthorize transform', async () => {
await transform.securityUI.loginAs(testData.current_user);

await transform.testExecution.logTestStep('should load the home page');
await transform.navigation.navigateTo();
await transform.management.assertTransformListPageExists();

await transform.testExecution.logTestStep('should display the transforms table');
await transform.management.assertTransformsTableExists();

await transform.testExecution.logTestStep(
'should display the transforms reauthorize callout'
);
await transform.management.assertTransformsReauthorizeCalloutExists();

await transform.testExecution.logTestStep(
'should display the original transform in the transform list'
);
await transform.table.filterWithSearchString(transformId, 1);
await transform.table.assertTransformRowFields(
transformId,
testData.expected.originalState
);

if (testData.expected.reauthorizeEnabled) {
qn895 marked this conversation as resolved.
Show resolved Hide resolved
await transform.testExecution.logTestStep('should reauthorize the transform');
await transform.table.assertTransformRowActionEnabled(
transformId,
'Reauthorize',
testData.expected.reauthorizeEnabled
);
await transform.table.clickTransformRowAction(transformId, 'Reauthorize');
await transform.table.confirmReauthorizeTransform();

await transform.table.assertTransformRowFields(
transformId,
testData.expected.reauthorizedState
);
await transform.testExecution.logTestStep('should not show Reauthorize action anymore');
await transform.table.assertTransformRowActionMissing(transformId, 'Reauthorize');
} else {
await transform.testExecution.logTestStep('should show disabled action menu button');
await transform.table.assertTransformRowActionsButtonEnabled(transformId, false);
}
await transform.table.clearSearchString(testDataList.length);
});
});
}
});
}
7 changes: 5 additions & 2 deletions x-pack/test/functional/services/transform/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,10 +272,13 @@ export function TransformAPIProvider({ getService }: FtrProviderContext) {
});
},

async startTransform(transformId: string) {
async startTransform(transformId: string, assertSuccess = true) {
log.debug(`Starting transform '${transformId}' ...`);
const { body, status } = await esSupertest.post(`/_transform/${transformId}/_start`);
this.assertResponseStatusCode(200, status, body);

if (assertSuccess) {
this.assertResponseStatusCode(200, status, body);
}
},

async stopTransform(transformId: string) {
Expand Down
4 changes: 4 additions & 0 deletions x-pack/test/functional/services/transform/management.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ export function TransformManagementProvider({ getService }: FtrProviderContext)
await testSubjects.existOrFail('transformCreateFirstButton');
},

async assertTransformsReauthorizeCalloutExists() {
await testSubjects.existOrFail('transformPageReauthorizeCallout');
},

async assertCreateFirstTransformButtonEnabled(expectedValue: boolean) {
const isEnabled = await testSubjects.isEnabled('transformCreateFirstButton');
expect(isEnabled).to.eql(
Expand Down
Loading
Loading