Skip to content

Commit

Permalink
Add create SM policy
Browse files Browse the repository at this point in the history
Signed-off-by: bowenlan-amzn <[email protected]>
  • Loading branch information
bowenlan-amzn committed May 31, 2022
1 parent 72e5ce8 commit 7b1e394
Show file tree
Hide file tree
Showing 12 changed files with 252 additions and 33 deletions.
25 changes: 25 additions & 0 deletions models/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

// TODO: Backend has PR out to change this model, this needs to be updated once that goes through

import { CreateIndexMapOptions } from "src/core/server/saved_objects/migrations/core/build_index_map";
import { ActionType } from "../public/pages/VisualCreatePolicy/utils/constants";

export interface ManagedIndexMetaData {
Expand Down Expand Up @@ -78,6 +79,30 @@ export interface Policy {
schema_version?: number;
}

export interface SMPolicy {
description: string;
creation: SMCreation;
deletion: SMDeletion;
snapshot_config: object;
}

export interface SMCreation {
schedule: Cron;
time_limit?: string;
}

export interface SMDeletion {
schedule: Cron;
condition: SMDeleteCondition;
time_limit?: string;
}

export interface SMDeleteCondition {
max_count: number;
max_age?: string;
min_count?: number;
}

export interface ErrorNotification {
destination?: Destination;
channel?: Channel;
Expand Down
7 changes: 6 additions & 1 deletion public/pages/Main/Main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,12 @@ export default class Main extends Component<MainProps, object> {
<Snapshots {...props} snapshotManagementService={services.snapshotManagementService} />
)}
/>
<Route path={ROUTES.CREATE_SM_POLICY} render={(props: RouteComponentProps) => <CreateSMPolicy {...props} />} />
<Route
path={ROUTES.CREATE_SM_POLICY}
render={(props: RouteComponentProps) => (
<CreateSMPolicy {...props} snapshotManagementService={services.snapshotManagementService} />
)}
/>
<Route
path={ROUTES.CHANGE_POLICY}
render={(props: RouteComponentProps) => (
Expand Down
26 changes: 26 additions & 0 deletions public/pages/Snapshots/components/ToggleWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from "react";
import { EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiSpacer, EuiSwitch, EuiSwitchEvent, EuiText } from "@elastic/eui";

interface ToggleWrapperProps {
label: any;
checked: boolean;
onSwitchChange: (event: EuiSwitchEvent) => void;
}

const ToggleWrapper = ({ label, checked, onSwitchChange }: ToggleWrapperProps) => (
<EuiFlexGroup>
<EuiFlexItem grow={1}>{label}</EuiFlexItem>
<EuiFlexItem grow={2}>
<EuiFormRow>
<EuiSwitch label="" checked={checked} onChange={onSwitchChange} />
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
);

export default ToggleWrapper;
99 changes: 71 additions & 28 deletions public/pages/Snapshots/containers/CreateSMPolicy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,26 @@ import {
EuiSwitch,
EuiSwitchEvent,
EuiTitle,
EuiButtonEmpty,
EuiButton,
} from "@elastic/eui";
import React, { ChangeEvent, Component } from "react";
import { RouteComponentProps } from "react-router-dom";
import { ContentPanel } from "../../../components/ContentPanel";
import { DEFAULT_DELETE_CONDITION, DEFAULT_SM_POLICY } from "../utils/constants";
import moment from "moment-timezone";
import CustomLabel from "../components/CustomLabel";
import ToggleWrapper from "../components/ToggleWrapper";
import { ROUTES } from "../../../utils/constants";
import { CoreServicesContext } from "../../../components/core_services";
import { getErrorMessage } from "../../../utils/helpers";
import { SnapshotManagementService } from "../../../services";

const timezones = moment.tz.names().map((tz) => ({ label: tz, text: tz }));

interface CreateSMPolicyProps extends RouteComponentProps {}
interface CreateSMPolicyProps extends RouteComponentProps {
snapshotManagementService: SnapshotManagementService;
}

interface CreateSMPolicyState {
name: string;
Expand All @@ -44,9 +53,13 @@ interface CreateSMPolicyState {
minCount: number;

policyJson: any;

isSubmitting: boolean;
}

export default class CreateSMPolicy extends Component<CreateSMPolicyProps, CreateSMPolicyState> {
static contextType = CoreServicesContext;

constructor(props: CreateSMPolicyProps) {
super(props);

Expand All @@ -69,6 +82,8 @@ export default class CreateSMPolicy extends Component<CreateSMPolicyProps, Creat
minCount: DEFAULT_DELETE_CONDITION.min_count,

policyJson: defaultPolicy,

isSubmitting: false,
};
}

Expand Down Expand Up @@ -162,6 +177,30 @@ export default class CreateSMPolicy extends Component<CreateSMPolicyProps, Creat
this.setState({ minCount: minCount, policyJson: newJSON });
};

onCancel = (): void => {
this.props.history.push(ROUTES.SNAPSHOTS);
};

onCreate = async () => {
const { snapshotManagementService } = this.props;
try {
const { name, policyJson } = this.state;
const response = await snapshotManagementService.createPolicy(name, policyJson);
} catch (err) {
this.context.notifications.toasts.addDanger(
`Failed to create transform: ${getErrorMessage(err, "There was a problem creating the transform job")}`
);
}
};

onSubmit = async () => {
this.setState({ isSubmitting: true });
try {
await this.onCreate();
} catch (err) {}
this.setState({ isSubmitting: false });
};

render() {
console.log(`sm dev state ${JSON.stringify(this.state)}`);

Expand All @@ -179,6 +218,7 @@ export default class CreateSMPolicy extends Component<CreateSMPolicyProps, Creat
maxCount,
maxAge,
minCount,
isSubmitting,
} = this.state;

return (
Expand Down Expand Up @@ -243,46 +283,37 @@ export default class CreateSMPolicy extends Component<CreateSMPolicyProps, Creat

<EuiSpacer size="m" />

<EuiFlexGroup>
<EuiFlexItem style={{ minWidth: 300 }}>
<ToggleWrapper
label={
<CustomLabel title="Include global state" helpText="Whether to include cluster state in the snapshot." isOptional={true} />
</EuiFlexItem>
<EuiFlexItem style={{ minWidth: 300 }}>
<EuiFormRow>
<EuiSwitch label="" checked={includeGlobalState} onChange={this.onIncludeGlobalStateToggle} />
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
}
checked={includeGlobalState}
onSwitchChange={this.onIncludeGlobalStateToggle}
/>

<EuiSpacer size="m" />

<EuiFlexGroup>
<EuiFlexItem style={{ minWidth: 300 }}>
<ToggleWrapper
label={
<CustomLabel
title="Ignore unavailable"
helpText="Whether to ignore unavailable index rather than fail the snapshot."
isOptional={true}
/>
</EuiFlexItem>
<EuiFlexItem style={{ minWidth: 300 }}>
<EuiFormRow>
<EuiSwitch label="" checked={ignoreUnavailable} onChange={this.onIgnoreUnavailableToggle} />
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
}
checked={ignoreUnavailable}
onSwitchChange={this.onIgnoreUnavailableToggle}
/>

<EuiSpacer size="m" />

<EuiFlexGroup>
<EuiFlexItem style={{ minWidth: 300 }}>
<ToggleWrapper
label={
<CustomLabel title="Partial" helpText="Whether to allow partial snapshots rather than fail the snapshot." isOptional={true} />
</EuiFlexItem>
<EuiFlexItem style={{ minWidth: 300 }}>
<EuiFormRow>
<EuiSwitch label="" checked={partial} onChange={this.onPartialToggle} />
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
}
checked={partial}
onSwitchChange={this.onPartialToggle}
/>
</ContentPanel>

<EuiSpacer />
Expand All @@ -307,6 +338,18 @@ export default class CreateSMPolicy extends Component<CreateSMPolicyProps, Creat
<EuiFieldText value={minCount} onChange={this.onChangeMinCount} />
</EuiFormRow>
</ContentPanel>

<EuiFlexGroup justifyContent="flexEnd">
<EuiFlexItem grow={false}>
<EuiButtonEmpty onClick={this.onCancel}>Cancel</EuiButtonEmpty>
</EuiFlexItem>

<EuiFlexItem grow={false}>
<EuiButton fill onClick={this.onSubmit} isLoading={isSubmitting}>
Create
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</div>
);
}
Expand Down
1 change: 0 additions & 1 deletion public/pages/Snapshots/containers/Snapshots.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import { DEFAULT_PAGE_SIZE_OPTIONS, SNAPSHOTS_COLUMNS } from "../utils/constants
import { getErrorMessage } from "../../../utils/helpers";
import { CatSnapshot } from "../../../../server/models/interfaces";
import { ContentPanel } from "../../../components/ContentPanel";
import { SnapshotControls } from "../components/SnapshotControls";

interface SnapshotsProps extends RouteComponentProps {
snapshotManagementService: SnapshotManagementService;
Expand Down
10 changes: 9 additions & 1 deletion public/services/SnapshotManagementService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@

import { HttpFetchQuery, HttpSetup } from "opensearch-dashboards/public";
import { NODE_API } from "../../utils/constants";
import { GetSnapshotsResponse } from "../../server/models/interfaces";
import { CreateSMPolicyResponse, GetSnapshotsResponse } from "../../server/models/interfaces";
import { ServerResponse } from "../../server/models/types";
import { SMPolicy } from "../../models/interfaces";

export default class SnapshotManagementService {
httpClient: HttpSetup;
Expand All @@ -20,4 +21,11 @@ export default class SnapshotManagementService {
const response = (await this.httpClient.get(url, { query: queryObject })) as ServerResponse<GetSnapshotsResponse>;
return response;
};

createPolicy = async (id: string, policy: SMPolicy): Promise<ServerResponse<CreateSMPolicyResponse>> => {
let url = `..${NODE_API.SMPolicies}/${id}`;
const response = (await this.httpClient.post(url, { body: JSON.stringify(policy) })) as ServerResponse<CreateSMPolicyResponse>;
console.log(`sm dev public create sm policy response ${JSON.stringify(response)}`);
return response;
};
}
36 changes: 36 additions & 0 deletions server/clusters/ism/ismPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,42 @@ export default function ismPlugin(Client: any, config: any, components: any) {
method: "PUT",
});

ism.createSMPolicy = ca({
url: {
fmt: `${API.SM_POLICY_BASE}/<%=policyId%>?refresh=wait_for`,
req: {
policyId: {
type: "string",
required: true,
},
},
},
needBody: true,
method: "POST",
});

ism.updateSMPolicy = ca({
url: {
fmt: `${API.SM_POLICY_BASE}/<%=policyId%>?if_seq_no=<%=ifSeqNo%>&if_primary_term=<%=ifPrimaryTerm%>&refresh=wait_for`,
req: {
policyId: {
type: "string",
required: true,
},
ifSeqNo: {
type: "string",
required: true,
},
ifPrimaryTerm: {
type: "string",
required: true,
},
},
},
needBody: true,
method: "PUT",
});

ism.deletePolicy = ca({
url: {
fmt: `${API.POLICY_BASE}/<%=policyId%>?refresh=wait_for`,
Expand Down
10 changes: 9 additions & 1 deletion server/models/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
NotificationService,
SnapshotManagementService,
} from "../services";
import { DocumentPolicy, DocumentRollup, DocumentTransform, ManagedIndexItem, Rollup, Transform } from "../../models/interfaces";
import { DocumentPolicy, DocumentRollup, DocumentTransform, ManagedIndexItem, Rollup, SMPolicy, Transform } from "../../models/interfaces";

export interface NodeServices {
indexService: IndexService;
Expand Down Expand Up @@ -133,6 +133,13 @@ export interface PutTransformResponse {
transform: { transform: Transform };
}

export interface CreateSMPolicyResponse {
_id: string;
_primary_term: string;
_seq_no: string;
policy: SMPolicy;
}

export interface PreviewTransformResponse {
documents: object[];
}
Expand Down Expand Up @@ -274,6 +281,7 @@ export interface IndexManagementApi {
readonly ROLLUP_JOBS_BASE: string;
readonly TRANSFORM_BASE: string;
readonly CHANNELS_BASE: string;
readonly SM_POLICY_BASE: string;
}

export interface DefaultHeaders {
Expand Down
30 changes: 30 additions & 0 deletions server/routes/snapshotManagement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,34 @@ export default function (services: NodeServices, router: IRouter) {
},
snapshotManagementService.catSnapshots
);

router.post(
{
path: `${NODE_API.SMPolicies}/{id}`,
validate: {
params: schema.object({
id: schema.string(),
}),
body: schema.any(),
},
},
snapshotManagementService.createPolicy
);

// router.put(
// {
// path: `${NODE_API.SMPolicies}/{id}`,
// validate: {
// params: schema.object({
// id: schema.string(),
// }),
// query: schema.object({
// seqNo: schema.maybe(schema.number()),
// primaryTerm: schema.maybe(schema.number()),
// }),
// body: schema.any(),
// },
// },
// snapshotManagementService.createPolicy
// );
}
Loading

0 comments on commit 7b1e394

Please sign in to comment.