diff options
5 files changed, 219 insertions, 120 deletions
diff --git a/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMerger.java b/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMerger.java index cf3c1656c..44b11119b 100644 --- a/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMerger.java +++ b/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMerger.java @@ -105,9 +105,11 @@ public class PoliciesPdpMerger { /** * This method removes the pdp States added for one policy. * - * @param policyJsonNode The policy node in Json + * @param policyJsonNode The policy node Json as String + * @return The Json with pdp group info removed */ public static JsonObject removePdpStatesOnePolicy(JsonObject policyJsonNode) { + //JsonObject policyJson = JsonUtils.GSON.fromJson(policyJsonNode, JsonObject.class); // Simply remove the nodes we have added. policyJsonNode.remove(PdpGroupsAnalyzer.ASSIGNED_PDP_GROUPS_INFO); policyJsonNode.remove(PdpGroupsAnalyzer.SUPPORTED_PDP_GROUPS_INFO); diff --git a/src/main/resources/clds/camel/rest/clamp-api-v2.xml b/src/main/resources/clds/camel/rest/clamp-api-v2.xml index bcad3ea33..f924a8a24 100644 --- a/src/main/resources/clds/camel/rest/clamp-api-v2.xml +++ b/src/main/resources/clds/camel/rest/clamp-api-v2.xml @@ -803,6 +803,107 @@ </doTry> </route> </post> + <get uri="/v2/templates" + outType="org.onap.policy.clamp.loop.template.LoopTemplate" + produces="application/json"> + <route> + <removeHeaders pattern="*"/> + <doTry> + <to + uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET ALL Templates')"/> + <to + uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'template','','read')"/> + <to + uri="bean:org.onap.policy.clamp.loop.template.LoopTemplatesService?method=getAllLoopTemplates()"/> + <to + uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/> + <log loggingLevel="ERROR" + message="GET ALL templates request failed: ${exception.stacktrace}"/> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>GET ALL templates FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </get> + <get uri="/v2/templates/{templateName}" + outType="org.onap.policy.clamp.loop.template.LoopTemplate" + produces="application/json"> + <route> + <removeHeaders pattern="*" + excludePattern="templateName"/> + <doTry> + <to + uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET a Template by NAME')"/> + <to + uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'template','','read')"/> + <to + uri="bean:org.onap.policy.clamp.loop.template.LoopTemplatesService?method=getLoopTemplate(${header.templateName})"/> + <to + uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/> + <log loggingLevel="ERROR" + message="GET Template request failed for template: ${header.templateName}, ${exception.stacktrace}"/> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>GET Template FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </get> + <get uri="/v2/templates/names" outType="java.lang.String[]" + produces="application/json"> + <route> + <removeHeaders pattern="*"/> + <doTry> + <to + uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET ALL Loop Template Names')"/> + <to + uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'template','','read')"/> + <to + uri="bean:org.onap.policy.clamp.loop.template.LoopTemplatesService?method=getLoopTemplateNames()"/> + <to + uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/> + <doCatch> + <exception>java.lang.Exception</exception> + <handled> + <constant>true</constant> + </handled> + <to + uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/> + <log loggingLevel="ERROR" + message="GET All Template names request failed for template: ${exception.stacktrace}"/> + <setHeader headerName="CamelHttpResponseCode"> + <constant>500</constant> + </setHeader> + <setBody> + <simple>GET All Template names FAILED</simple> + </setBody> + </doCatch> + </doTry> + </route> + </get> + + <!-- NON LOOP related endpoints --> <get uri="/v2/dictionary" outType="org.onap.policy.clamp.tosca.Dictionary" produces="application/json"> <route> @@ -1217,106 +1318,6 @@ </route> </put> - <get uri="/v2/templates" - outType="org.onap.policy.clamp.loop.template.LoopTemplate" - produces="application/json"> - <route> - <removeHeaders pattern="*"/> - <doTry> - <to - uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET ALL Templates')"/> - <to - uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'template','','read')"/> - <to - uri="bean:org.onap.policy.clamp.loop.template.LoopTemplatesService?method=getAllLoopTemplates()"/> - <to - uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/> - <doCatch> - <exception>java.lang.Exception</exception> - <handled> - <constant>true</constant> - </handled> - <to - uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/> - <log loggingLevel="ERROR" - message="GET ALL templates request failed: ${exception.stacktrace}"/> - <setHeader headerName="CamelHttpResponseCode"> - <constant>500</constant> - </setHeader> - <setBody> - <simple>GET ALL templates FAILED</simple> - </setBody> - </doCatch> - </doTry> - </route> - </get> - <get uri="/v2/templates/{templateName}" - outType="org.onap.policy.clamp.loop.template.LoopTemplate" - produces="application/json"> - <route> - <removeHeaders pattern="*" - excludePattern="templateName"/> - <doTry> - <to - uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET a Template by NAME')"/> - <to - uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'template','','read')"/> - <to - uri="bean:org.onap.policy.clamp.loop.template.LoopTemplatesService?method=getLoopTemplate(${header.templateName})"/> - <to - uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/> - <doCatch> - <exception>java.lang.Exception</exception> - <handled> - <constant>true</constant> - </handled> - <to - uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/> - <log loggingLevel="ERROR" - message="GET Template request failed for template: ${header.templateName}, ${exception.stacktrace}"/> - <setHeader headerName="CamelHttpResponseCode"> - <constant>500</constant> - </setHeader> - <setBody> - <simple>GET Template FAILED</simple> - </setBody> - </doCatch> - </doTry> - </route> - </get> - <get uri="/v2/templates/names" outType="java.lang.String[]" - produces="application/json"> - <route> - <removeHeaders pattern="*"/> - <doTry> - <to - uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET ALL Loop Template Names')"/> - <to - uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'template','','read')"/> - <to - uri="bean:org.onap.policy.clamp.loop.template.LoopTemplatesService?method=getLoopTemplateNames()"/> - <to - uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/> - <doCatch> - <exception>java.lang.Exception</exception> - <handled> - <constant>true</constant> - </handled> - <to - uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/> - <log loggingLevel="ERROR" - message="GET All Template names request failed for template: ${exception.stacktrace}"/> - <setHeader headerName="CamelHttpResponseCode"> - <constant>500</constant> - </setHeader> - <setBody> - <simple>GET All Template names FAILED</simple> - </setBody> - </doCatch> - </doTry> - </route> - </get> - <!-- Policy Related endpoints, not related to LOOP --> <get uri="/v2/policies" outType="com.google.gson.JsonObject" produces="application/json"> <route> @@ -1360,11 +1361,13 @@ </doTry> </route> </get> - <!-- Update an existing policy, therefore it removes it from pdp first, delete it and then recreate it --> - <!-- TO BE DONE --> <!-- Create a new policy --> - <post uri="/v2/policies/{policyModelName}/{policyModelVersion}" outType="com.google.gson.JsonObject" produces="application/json"> + <post uri="/v2/policies/{policyModelName}/{policyModelVersion}" + type="com.google.gson.JsonElement" + consumes="application/json" + outType="com.google.gson.JsonObject" + produces="application/json"> <route> <removeHeaders pattern="*" excludePattern="policyModelName|policyModelVersion"/> @@ -1382,6 +1385,9 @@ <setBody> <method ref="org.onap.policy.clamp.policy.pdpgroup.PoliciesPdpMerger" method="removePdpStatesOnePolicy(${body})"/> + </setBody> + <setBody> + <simple>${body.toString()}</simple> </setBody> <to uri="direct:create-policy"/> <to diff --git a/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMergerTest.java b/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMergerTest.java index adb797897..ac05d037f 100644 --- a/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMergerTest.java +++ b/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMergerTest.java @@ -103,9 +103,8 @@ public class PoliciesPdpMergerTest { @Test public void testRemovePdpStatesOnePolicy() throws IOException { - JsonObject policiesList = PoliciesPdpMerger.removePdpStatesOnePolicy(JsonUtils.GSON - .fromJson(ResourceFileUtils.getResourceAsString("example/policy/single-policy-enriched.json"), - JsonObject.class)); + JsonObject policiesList = PoliciesPdpMerger.removePdpStatesOnePolicy(JsonUtils.GSON.fromJson( + ResourceFileUtils.getResourceAsString("example/policy/single-policy-enriched.json"), JsonObject.class)); assertThat(policiesList.get(PdpGroupsAnalyzer.ASSIGNED_PDP_GROUPS_INFO)).isNull(); assertThat(policiesList.get(PdpGroupsAnalyzer.SUPPORTED_PDP_GROUPS_INFO)).isNull(); diff --git a/ui-react/src/api/PolicyService.js b/ui-react/src/api/PolicyService.js index fdbb5d5ea..16cc1f322 100644 --- a/ui-react/src/api/PolicyService.js +++ b/ui-react/src/api/PolicyService.js @@ -40,4 +40,27 @@ export default class PolicyService { return {}; }); } + static createNewPolicy(policyModelType, policyModelVersion, policyJson) { + return fetch(window.location.pathname + 'restservices/clds/v2/policies/' + policyModelType + '/' + policyModelVersion, { + method: 'POST', + credentials: 'same-origin', + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify(policyJson) + }) + .then(function (response) { + console.debug("createNewPolicy response received: ", response.status); + if (response.ok) { + return response.text; + } else { + console.error("createNewPolicy query failed"); + return ""; + } + }) + .catch(function (error) { + console.error("createNewPolicy error received", error); + throw new Error(error) + }); + } } diff --git a/ui-react/src/components/dialogs/Policy/ViewAllPolicies.js b/ui-react/src/components/dialogs/Policy/ViewAllPolicies.js index a1cf9d5c1..dfebc51d8 100644 --- a/ui-react/src/components/dialogs/Policy/ViewAllPolicies.js +++ b/ui-react/src/components/dialogs/Policy/ViewAllPolicies.js @@ -47,6 +47,12 @@ import PolicyService from '../../../api/PolicyService'; import PolicyToscaService from '../../../api/PolicyToscaService'; import Select from 'react-select'; import JSONEditor from '@json-editor/json-editor'; +import OnapUtils from '../../../utils/OnapUtils'; +import Alert from 'react-bootstrap/Alert'; + +const DivWhiteSpaceStyled = styled.div` + white-space: pre; +` const ModalStyled = styled(Modal)` @media (min-width: 1200px) { @@ -76,9 +82,11 @@ export default class ViewAllPolicies extends React.Component { state = { show: true, content: 'Please select a policy to display it', - selectedRow: -1, + selectedRowId: -1, policiesListData: [], prefixGrouping: false, + showSuccessAlert: false, + showFailAlert: false, policyColumnsDefinition: [ { title: "Policy Name", field: "name", @@ -148,7 +156,8 @@ export default class ViewAllPolicies extends React.Component { this.handlePrefixGrouping = this.handlePrefixGrouping.bind(this); this.handleDeletePolicy = this.handleDeletePolicy.bind(this); this.handleUpdatePolicy = this.handleUpdatePolicy.bind(this); - this.handleCreateNewVersion = this.handleCreateNewVersion(this); + this.handleCreateNewVersion = this.handleCreateNewVersion.bind(this); + this.disableAlert = this.disableAlert.bind(this); this.getAllPolicies(); } @@ -159,10 +168,10 @@ export default class ViewAllPolicies extends React.Component { let selectedSubPdpGroup = pdpSplit[1]; if (typeof selectedSubPdpGroup !== "undefined") { let temp = this.state.policiesListData; - temp[this.state.selectedRow]["pdpGroupInfo"] = {"pdpGroup":selectedPdpGroup,"pdpSubGroup":selectedSubPdpGroup}; + temp[this.state.selectedRowId]["pdpGroupInfo"] = {"pdpGroup":selectedPdpGroup,"pdpSubGroup":selectedSubPdpGroup}; this.setState({policiesListData: temp}); } else { - delete this.state.policiesListData[this.state.selectedRow]["pdpGroupInfo"]; + delete this.state.policiesListData[this.state.selectedRowId]["pdpGroupInfo"]; } } @@ -237,9 +246,9 @@ export default class ViewAllPolicies extends React.Component { handleOnRowClick(rowData) { PolicyToscaService.getToscaPolicyModel(rowData["type"], rowData["type_version"]).then(respJsonPolicyTosca => { this.setState({ - selectedRow: rowData.tableData.id, - selectedRowJsonSchema: respJsonPolicyTosca, - selectedRowPolicyProperties: rowData["properties"], + selectedRowId: rowData.tableData.id, + selectedRowIdJsonSchema: respJsonPolicyTosca, + selectedRowIdPolicyProperties: rowData["properties"], jsonEditorForPolicy: this.createJsonEditor(respJsonPolicyTosca, rowData["properties"]) }); }); @@ -253,8 +262,52 @@ export default class ViewAllPolicies extends React.Component { return null; } - handleCreateNewVersion(event,rowData) { - return null; + customValidation(editorData) { + // method for sub-classes to override with customized validation + return []; + } + + handleCreateNewVersion() { + var editorData = this.state.jsonEditorForPolicy.getValue(); + var errors = this.state.jsonEditorForPolicy.validate(); + errors = errors.concat(this.customValidation(editorData)); + + if (errors.length !== 0) { + console.error("Errors detected during policy data validation ", errors); + this.setState({ + showFailAlert: true, + showMessage: 'Errors detected during policy data validation:\n' + OnapUtils.jsonEditorErrorFormatter(errors) + }); + return; + } else { + console.info("NO validation errors found in policy data"); + let newPolicy = JSON.parse(JSON.stringify(this.state.policiesListData[this.state.selectedRowId])); + newPolicy["properties"] = editorData; + let newVersion = this.bumpVersion(newPolicy["version"]); + newPolicy["version"] = newVersion; + newPolicy["metadata"]["policy-version"] = newVersion; + // Remove stuff added by UI + delete newPolicy["tableData"]; + PolicyService.createNewPolicy(newPolicy["type"], newPolicy["type_version"], newPolicy).then(respPolicyCreation => { + if (respPolicyCreation === "") { + //it indicates a failure + this.setState({ + showFailAlert: true, + showMessage: 'Policy Creation Failure' + }); + } else { + this.setState({ + showSuccessAlert: true, + showMessage: 'Policy in version ' + newVersion + ' created successfully' + }); + } + }) + } + } + + bumpVersion(versionToBump) { + let semVer = versionToBump.split("."); + return parseInt(semVer[0])+1 + "." + semVer[1] + "." + semVer[2]; } handleUpdatePolicy() { @@ -262,11 +315,16 @@ export default class ViewAllPolicies extends React.Component { this.props.history.push('/') } + disableAlert() { + this.setState ({ showSuccessAlert: false, showFailAlert: false }); + } + render() { return ( <ModalStyled size="xl" show={this.state.show} onHide={this.handleClose} backdrop="static" keyboard={false}> <Modal.Header closeButton> </Modal.Header> + <Modal.Body> <FormControlLabel control={<Switch checked={this.state.prefixGrouping} onChange={this.handlePrefixGrouping} />} @@ -283,7 +341,7 @@ export default class ViewAllPolicies extends React.Component { exportButton: true, headerStyle:rowHeaderStyle, rowStyle: rowData => ({ - backgroundColor: (this.state.selectedRow !== -1 && this.state.selectedRow === rowData.tableData.id) ? '#EEE' : '#FFF' + backgroundColor: (this.state.selectedRowId !== -1 && this.state.selectedRowId === rowData.tableData.id) ? '#EEE' : '#FFF' }) }} actions={[ @@ -293,14 +351,25 @@ export default class ViewAllPolicies extends React.Component { onClick: (event, rowData) => this.handleDeletePolicy(event, rowData) } ]} - /> <JsonEditorDiv> <h5>Policy Properties Editor</h5> <div id="policy-editor" title="Policy Properties"/> - <Button variant="secondary" title="Create a new policy version from the defined parameters" onClick={this.handleCreateNewVersion}>Create New Version</Button> - <Button variant="secondary" title="Update the current policy version, BE CAREFUL this will undeploy the policy from PDP, delete it and then recreate the policy" onClick={this.handleUpdatePolicy}>Update Current Version</Button> + <Button variant="secondary" title="Create a new policy version from the defined parameters" + onClick={this.handleCreateNewVersion}>Create New Version</Button> + <Button variant="secondary" title="Update the current policy version, BE CAREFUL this will undeploy the policy from PDP, delete it and then recreate the policy" + onClick={this.handleUpdatePolicy}>Update Current Version</Button> </JsonEditorDiv> + <Alert variant="success" show={this.state.showSuccessAlert} onClose={this.disableAlert} dismissible> + <DivWhiteSpaceStyled> + {this.state.showMessage} + </DivWhiteSpaceStyled> + </Alert> + <Alert variant="danger" show={this.state.showFailAlert} onClose={this.disableAlert} dismissible> + <DivWhiteSpaceStyled> + {this.state.showMessage} + </DivWhiteSpaceStyled> + </Alert> </Modal.Body> <Modal.Footer> <Button variant="secondary" onClick={this.handleClose}>Close</Button> |