Skip to content

Commit

Permalink
Merge/index operation reindex (#526)
Browse files Browse the repository at this point in the history
* Feature/common 2.5 (#506)

* feat: split to common change

Signed-off-by: suzhou <[email protected]>

* feat: update

Signed-off-by: suzhou <[email protected]>

Signed-off-by: suzhou <[email protected]>

* enable fullwidth for JSON editor (#479)

* enable fullwidth for JSON editor

Signed-off-by: Hailong Cui <[email protected]>

* update width of import settings & mappings

Signed-off-by: Hailong Cui <[email protected]>

* wording change

Signed-off-by: Hailong Cui <[email protected]>

Signed-off-by: Hailong Cui <[email protected]>

* advanced settings

Signed-off-by: Hailong Cui <[email protected]>

* fix integration test

Signed-off-by: Hailong Cui <[email protected]>

* wording change

Signed-off-by: Hailong Cui <[email protected]>

* filter system index and alias from destination

Signed-off-by: Hailong Cui <[email protected]>

* fix code merge issue

Signed-off-by: Hailong Cui <[email protected]>

Signed-off-by: suzhou <[email protected]>
Signed-off-by: Hailong Cui <[email protected]>
Co-authored-by: suzhou <[email protected]>
  • Loading branch information
Hailong-am and SuZhou-Joe committed Jan 6, 2023
1 parent 3a78419 commit d579e67
Show file tree
Hide file tree
Showing 25 changed files with 4,459 additions and 2 deletions.
225 changes: 225 additions & 0 deletions cypress/integration/reindex_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { PLUGIN_NAME } from "../support/constants";
const REINDEX_DEST = "test-ecomm-rdx";
const REINDEX_DEST_NO_SOURCE = "test-reindex-nosource";
const REINDEX_NEW_CREATED = "test-logs-new";

describe("Reindex", () => {
beforeEach(() => {
// Set welcome screen tracking to false
localStorage.setItem("home:welcome:show", "false");

// Visit ISM OSD
cy.visit(`${Cypress.env("opensearch_dashboards")}/app/${PLUGIN_NAME}#/indices`);

// Common text to wait for to confirm page loaded, give up to 60 seconds for initial load
cy.contains("Rows per page", { timeout: 60000 });
});

describe("Reindex validation error", () => {
before(() => {
cy.deleteAllIndices();
// Load ecommerce data
cy.request({
method: "POST",
url: `${Cypress.env("opensearch_dashboards")}/api/sample_data/ecommerce`,
headers: {
"osd-xsrf": true,
},
}).then((response) => {
expect(response.status).equal(200);
});

cy.createIndex(REINDEX_DEST_NO_SOURCE, null, {
mappings: {
_source: {
enabled: false,
},
properties: {
name: {
type: "keyword",
},
},
},
});
});

it("source validation failed", () => {
// Confirm we have our initial index
cy.contains(REINDEX_DEST_NO_SOURCE);

cy.get(`[data-test-subj="checkboxSelectRow-${REINDEX_DEST_NO_SOURCE}"]`).check({ force: true });

// Click actions button
cy.get('[data-test-subj="moreAction"]').click();
// Reindex should show as activate
cy.get('[data-test-subj="Reindex Action"]').should("exist").should("not.have.class", "euiContextMenuItem-isDisabled").click();

cy.contains(/_sources is not enabled/);
});
});

describe("Reindex successfully", () => {
before(() => {
cy.deleteAllIndices();
// Load ecommerce data
cy.request({
method: "POST",
url: `${Cypress.env("opensearch_dashboards")}/api/sample_data/ecommerce`,
headers: {
"osd-xsrf": true,
},
}).then((response) => {
expect(response.status).equal(200);
});

cy.createIndex(REINDEX_DEST, null, { settings: { "index.number_of_replicas": 0 } });

cy.createPipeline("bumpOrderId", {
description: "sample description",
processors: [
{
set: {
field: "order_id",
value: "200{{order_id}}",
},
},
],
});
});

it("successfully", () => {
// Confirm we have our initial index
cy.contains("opensearch_dashboards_sample_data_ecommerce");

// Click actions button
cy.get('[data-test-subj="moreAction"]').click();
// Reindex should show as activate
cy.get('[data-test-subj="Reindex Action"]').should("exist").should("not.have.class", "euiContextMenuItem-isDisabled").click();

cy.get(`div[data-test-subj="sourceSelector"]`)
.find(`input[data-test-subj="comboBoxSearchInput"]`)
.type(`opensearch_dashboards_sample_data_ecommerce{downArrow}{enter}`);

cy.get(`div[data-test-subj="destinationSelector"]`)
.find(`input[data-test-subj="comboBoxSearchInput"]`)
.type(`${REINDEX_DEST}{downArrow}{enter}`);

// open advance option
cy.get('[data-test-subj="advanceOptionToggle"]').click();

// enable subset query
cy.get('[data-test-subj="subsetOption"] #subset').click({ force: true });

// input query to reindex subset
cy.get('[data-test-subj="queryJsonEditor"] textarea')
.focus()
.clear()
.type('{"query":{"match":{"category":"Men\'s Clothing"}}}', { parseSpecialCharSequences: false });

// set slices to auto
cy.get('[data-test-subj="sliceEnabled"]').click({ force: true });

// input pipeline
cy.get(`div[data-test-subj="pipelineCombobox"]`).find(`input[data-test-subj="comboBoxSearchInput"]`).type("bumpOrderId{enter}");

// click to perform reindex
cy.get('[data-test-subj="reindexConfirmButton"]').click();
cy.wait(10);
cy.contains(/Successfully started reindexing/);

cy.wait(10000);
// Type in REINDEX_DEST in search input
cy.get(`input[type="search"]`).focus().type(REINDEX_DEST);

// Confirm we only see REINDEX_DEST in table
cy.get("tbody > tr").should(($tr) => {
expect($tr, "1 row").to.have.length(1);
expect($tr, "item").to.contain(REINDEX_DEST);
});
});
});

describe("Reindex successfully for newly created index", () => {
before(() => {
cy.deleteAllIndices();
// Load logs data
cy.request({
method: "POST",
url: `${Cypress.env("opensearch_dashboards")}/api/sample_data/logs`,
headers: {
"osd-xsrf": true,
},
}).then((response) => {
expect(response.status).equal(200);
});
});

it("successfully", () => {
// search
cy.get(`input[type="search"]`).focus().type("opensearch_dashboards_sample_data_logs");

cy.wait(1000);

// Confirm we have our initial index
cy.contains("opensearch_dashboards_sample_data_logs");

// select logs index
cy.get("#_selection_column_opensearch_dashboards_sample_data_logs-checkbox").click();

// Click actions button
cy.get('[data-test-subj="moreAction"]').click();
// Reindex should show as activate
cy.get('[data-test-subj="Reindex Action"]').click();

// open advance option
cy.get('[data-test-subj="advanceOptionToggle"]').click();

// enable subset query
cy.get('[data-test-subj="subsetOption"] #subset').click({ force: true });

// input query to reindex subset
cy.get('[data-test-subj="queryJsonEditor"] textarea')
.focus()
.clear()
.type('{"query":{"match":{"ip":"135.201.60.64"}}}', { parseSpecialCharSequences: false });

// create destination
cy.get('[data-test-subj="createIndexButton"]').click();
cy.contains("Create Index");

cy.get('[placeholder="Specify a name for the new index."]').type(REINDEX_NEW_CREATED).blur();
cy.wait(1000);

// import setting and mapping
cy.get('[data-test-subj="importSettingMappingBtn"]').click();
cy.get('[data-test-subj="import-settings-opensearch_dashboards_sample_data_logs"]').click();

cy.wait(10);
cy.contains(/have been import successfully/);

cy.get('[data-test-subj="flyout-footer-action-button"]').click({ force: true });

// click to perform reindex
cy.get('[data-test-subj="reindexConfirmButton"]').click();
cy.wait(10);
cy.contains(/Successfully started reindexing/);

cy.wait(10000);
// Type in REINDEX_DEST in search input
cy.get(`input[type="search"]`).focus().type(REINDEX_NEW_CREATED);

// Confirm we only see REINDEX_DEST in table
cy.get("tbody > tr").should(($tr) => {
expect($tr, "1 row").to.have.length(1);
expect($tr, "item").to.contain(REINDEX_NEW_CREATED);
// subset data number
expect($tr, "item").to.contain(13);
});
});
});
});
9 changes: 9 additions & 0 deletions public/pages/Main/Main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import Templates from "../Templates";
import CreateIndexTemplate from "../CreateIndexTemplate";
import CreateIndex from "../CreateIndex";
import IndexDetail from "../IndexDetail";
import Reindex from "../Reindex/container/Reindex";

enum Navigation {
IndexManagement = "Index Management",
Expand Down Expand Up @@ -471,6 +472,14 @@ export default class Main extends Component<MainProps, object> {
</div>
)}
/>
<Route
path={ROUTES.REINDEX}
render={(props: RouteComponentProps) => (
<div style={ROUTE_STYLE}>
<Reindex {...props} commonService={services.commonService} indexService={services.indexService} />
</div>
)}
/>
<Redirect from="/" to={landingPage} />
</Switch>
</EuiPageBody>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { render, waitFor } from "@testing-library/react";
import React from "react";
import CreateIndexFlyout from "./CreateIndexFlyout";
import { coreServicesMock, browserServicesMock, apiCallerMock } from "../../../../../test/mocks";
import { CoreServicesContext } from "../../../../components/core_services";
import { ServicesContext } from "../../../../services";

describe("<CreateIndexFlyout /> spec", () => {
beforeEach(() => {
apiCallerMock(browserServicesMock);
});
it("renders the component", async () => {
const component = render(
<CoreServicesContext.Provider value={coreServicesMock}>
<ServicesContext.Provider value={browserServicesMock}>
<CreateIndexFlyout sourceIndices={[]} onCloseFlyout={() => {}} />,
</ServicesContext.Provider>
</CoreServicesContext.Provider>
);
await waitFor(
() => expect((document.querySelector("#accordionForCreateIndexSettings") as HTMLDivElement).style.height).toEqual("0px"),
{
timeout: 3000,
}
);
expect(component).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from "react";
import CreateIndex, { IndexFormProps, IndexForm } from "../../../CreateIndex/containers/IndexForm";
import { CoreServicesContext } from "../../../../components/core_services";
import { EuiFlyout, EuiFlyoutBody, EuiFlyoutFooter, EuiFlyoutHeader, EuiTitle } from "@elastic/eui";
import FlyoutFooter from "../../../VisualCreatePolicy/components/FlyoutFooter";

interface CreateIndexFlyoutProps extends IndexFormProps {
sourceIndices: string[];
onCloseFlyout: () => void;
}

export default class CreateIndexFlyout extends React.Component<CreateIndexFlyoutProps> {
static contextType = CoreServicesContext;

createIndexRef: IndexForm | null = null;

render() {
const { onCloseFlyout } = this.props;
return (
<EuiFlyout onClose={() => {}} hideCloseButton>
<EuiFlyoutHeader hasBorder>
<EuiTitle size="m">
<h2 id="flyoutTitle"> Create Index </h2>
</EuiTitle>
</EuiFlyoutHeader>

<EuiFlyoutBody>
<CreateIndex ref={(ref) => (this.createIndexRef = ref)} hideButtons={true} {...this.props} />
</EuiFlyoutBody>

<EuiFlyoutFooter>
<FlyoutFooter
action=""
text="Create"
edit={false}
onClickCancel={onCloseFlyout}
onClickAction={() => this.createIndexRef?.onSubmit()}
/>
</EuiFlyoutFooter>
</EuiFlyout>
);
}
}
Loading

0 comments on commit d579e67

Please sign in to comment.