diff options
7 files changed, 799 insertions, 689 deletions
diff --git a/runtime/src/main/resources/clds/camel/routes/controlloop-flows.xml b/runtime/src/main/resources/clds/camel/routes/controlloop-flows.xml index ac83ffd7a..200eac780 100644 --- a/runtime/src/main/resources/clds/camel/routes/controlloop-flows.xml +++ b/runtime/src/main/resources/clds/camel/routes/controlloop-flows.xml @@ -98,10 +98,16 @@ <setHeader name="Content-Type"> <constant>application/json</constant> </setHeader> + <setProperty name="name"> + <simple>${header.name}</simple> + </setProperty> + <setProperty name="version"> + <simple>${header.version}</simple> + </setProperty> <log loggingLevel="INFO" message="Endpoint to get Tosca Instantiation: {{clamp.config.controlloop.runtime.url}}/onap/controlloop/v2/instantiation"></log> <toD - uri="{{clamp.config.controlloop.runtime.url}}/onap/controlloop/v2/instantiation?bridgeEndpoint=true&useSystemProperties=true&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&authMethod=Basic&authUsername={{clamp.config.controlloop.runtime.userName}}&authPassword={{clamp.config.controlloop.runtime.password}}&authenticationPreemptive=true&connectionClose=true"/> + uri="{{clamp.config.controlloop.runtime.url}}/onap/controlloop/v2/instantiation?name=${exchangeProperty[name]}&version=${exchangeProperty[version]}&bridgeEndpoint=true&useSystemProperties=true&throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&authMethod=Basic&authUsername={{clamp.config.controlloop.runtime.userName}}&authPassword={{clamp.config.controlloop.runtime.password}}&authenticationPreemptive=true&connectionClose=true"/> <convertBodyTo type="java.lang.String"/> <doFinally> <to uri="direct:reset-raise-http-exception-flag"/> diff --git a/runtime/src/test/java/org/onap/policy/clamp/runtime/RuntimeInstantiationResponseItTestCase.java b/runtime/src/test/java/org/onap/policy/clamp/runtime/RuntimeInstantiationResponseItTestCase.java new file mode 100644 index 000000000..ae80d0498 --- /dev/null +++ b/runtime/src/test/java/org/onap/policy/clamp/runtime/RuntimeInstantiationResponseItTestCase.java @@ -0,0 +1,96 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.runtime; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.apache.camel.CamelContext; +import org.apache.camel.Exchange; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.builder.ExchangeBuilder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.policy.clamp.clds.Application; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpStatus; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +public class RuntimeInstantiationResponseItTestCase { + @Autowired + CamelContext camelContext; + + private static final String DIRECT_GET_TOSCA_INSTANTIATION = "direct:get-tosca-instantiation"; + + private static final String SERVICE_TEMPLATE_NAME = "name"; + + private static final String SERVICE_TEMPLATE_VERSION = "version"; + + private static final String RAISE_HTTP_EXCEPTION_FLAG = "raiseHttpExceptionFlag"; + + private static final String SAMPLE_CONTROL_LOOP_LIST = "{\"controlLoopList\": [{\"name\": \"PMSHInstance0\"," + + "\"version\": \"1.0.1\",\"definition\": {},\"state\": \"UNINITIALISED\",\"orderedState\": \"UNINITIALISED\"," + + "\"description\": \"PMSH control loop instance 0\",\"elements\": {}}]}"; + + @Test + public void testToscaServiceTemplateStatus() { + ProducerTemplate prodTemplate = camelContext.createProducerTemplate(); + + Exchange exchangeResponse = + prodTemplate.send(DIRECT_GET_TOSCA_INSTANTIATION, ExchangeBuilder.anExchange(camelContext) + .withProperty(SERVICE_TEMPLATE_NAME, "ToscaServiceTemplate") + .withProperty(SERVICE_TEMPLATE_VERSION, "1.0.0") + .withProperty(RAISE_HTTP_EXCEPTION_FLAG, "true") + .build()); + + assertThat(HttpStatus.valueOf((Integer) exchangeResponse.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE)) + .is2xxSuccessful()).isTrue(); + } + + @Test + public void testToscaInstantiationGetResponseBody() { + ProducerTemplate prodTemplate = camelContext.createProducerTemplate(); + + Exchange exchangeResponse = + prodTemplate.send(DIRECT_GET_TOSCA_INSTANTIATION, ExchangeBuilder.anExchange(camelContext) + .withProperty(SERVICE_TEMPLATE_NAME, "ToscaServiceTemplate") + .withProperty(SERVICE_TEMPLATE_VERSION, "1.0.0") + .withProperty(RAISE_HTTP_EXCEPTION_FLAG, "true") + .build()); + + assertThat(exchangeResponse.getIn().getBody()).hasToString(SAMPLE_CONTROL_LOOP_LIST); + } + + @Test + public void testToscaInstantiationStatus() { + ProducerTemplate prodTemplate = camelContext.createProducerTemplate(); + + Exchange exchangeResponse = + prodTemplate.send(DIRECT_GET_TOSCA_INSTANTIATION, ExchangeBuilder.anExchange(camelContext) + .withBody(SAMPLE_CONTROL_LOOP_LIST) + .withProperty(RAISE_HTTP_EXCEPTION_FLAG, "true") + .build()); + + assertThat(HttpStatus.valueOf((Integer) exchangeResponse.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE)) + .is2xxSuccessful()).isTrue(); + } +} diff --git a/runtime/src/test/resources/http-cache/third_party_proxy.py b/runtime/src/test/resources/http-cache/third_party_proxy.py index d6628535d..5c80cdda4 100644 --- a/runtime/src/test/resources/http-cache/third_party_proxy.py +++ b/runtime/src/test/resources/http-cache/third_party_proxy.py @@ -328,7 +328,7 @@ class Proxy(SimpleHTTPServer.SimpleHTTPRequestHandler): return True elif (self.path.startswith("/onap/controlloop/v2/instantiation")) and http_type == "GET": print("self.path start with /instantiation Retrieving Instantiation, generating response json...") - jsonGenerated = "{\"errorDetails\": null,\"affectedControlLoopDefinitions\": [{ \"name\": \"ToscaServiceTemplateSimple\", \"version\": \"1.0.0\" }]}" + jsonGenerated = "{\"controlLoopList\": [{\"name\": \"PMSHInstance0\",\"version\": \"1.0.1\",\"definition\": {},\"state\": \"UNINITIALISED\",\"orderedState\": \"UNINITIALISED\",\"description\": \"PMSH control loop instance 0\",\"elements\": {}}]}"; self._create_cache(jsonGenerated, cached_file_folder, cached_file_header, cached_file_content) return True else: diff --git a/runtime/ui-react/src/components/dialogs/Policy/PolicyDeploymentEditor.js b/runtime/ui-react/src/components/dialogs/Policy/PolicyDeploymentEditor.js index 57d61600a..de29947fe 100644 --- a/runtime/ui-react/src/components/dialogs/Policy/PolicyDeploymentEditor.js +++ b/runtime/ui-react/src/components/dialogs/Policy/PolicyDeploymentEditor.js @@ -32,145 +32,147 @@ import Checkbox from '@material-ui/core/Checkbox'; import FormControlLabel from '@material-ui/core/FormControlLabel'; const DivWhiteSpaceStyled = styled.div` - white-space: pre; + white-space: pre; ` const PanelDiv = styled.div` - text-align: justify; - font-size: ${props => props.theme.policyEditorFontSize}; - background-color: ${props => props.theme.loopViewerBackgroundColor}; + text-align: justify; + font-size: ${ props => props.theme.policyEditorFontSize }; + background-color: ${ props => props.theme.loopViewerBackgroundColor }; ` export default class PolicyDeploymentEditor extends React.Component { - state = { - policyData: this.props.policyData, - showSuccessAlert: false, - showFailAlert: false, - checkboxesState: this.createPdpStructure(this.props.policyData), - checkboxesInitialState: this.createPdpStructure(this.props.policyData), - }; + state = { + policyData: this.props.policyData, + showSuccessAlert: false, + showFailAlert: false, + checkboxesState: this.createPdpStructure(this.props.policyData), + checkboxesInitialState: this.createPdpStructure(this.props.policyData), + }; - constructor(props, context) { - super(props, context); - this.handleClose = this.handleClose.bind(this); - this.handleUpdatePdpDeployment = this.handleUpdatePdpDeployment.bind(this); - this.disableAlert = this.disableAlert.bind(this); - this.renderPdpDeploymentCheckboxes = this.renderPdpDeploymentCheckboxes.bind(this); - this.createPdpStructure = this.createPdpStructure.bind(this); - this.handleCheckboxChange = this.handleCheckboxChange.bind(this); - this.createPdpGroupOperations = this.createPdpGroupOperations.bind(this); - } + constructor(props, context) { + super(props, context); + this.handleClose = this.handleClose.bind(this); + this.handleUpdatePdpDeployment = this.handleUpdatePdpDeployment.bind(this); + this.disableAlert = this.disableAlert.bind(this); + this.renderPdpDeploymentCheckboxes = this.renderPdpDeploymentCheckboxes.bind(this); + this.createPdpStructure = this.createPdpStructure.bind(this); + this.handleCheckboxChange = this.handleCheckboxChange.bind(this); + this.createPdpGroupOperations = this.createPdpGroupOperations.bind(this); + } - handleClose() { - this.setState({ show: false }); + handleClose() { + this.setState({ show: false }); - } + } - disableAlert() { - this.setState ({ showSuccessAlert: false, showFailAlert: false }); - } + disableAlert() { + this.setState({ showSuccessAlert: false, showFailAlert: false }); + } - createPdpGroupOperations(initialStates, newStates) { - let commandsArray = []; - initialStates.forEach(initElem => { - let newStateFound = newStates.find(newElement => newElement.name === initElem.name); - if (initElem.value !== newStateFound.value) { - let newPdpGroupsArray = newStateFound.name.split("/"); - let operation = "POST/"; - if (initElem.value) { - operation = "DELETE/"; - } - commandsArray.push(operation + newPdpGroupsArray[0] + "/"+newPdpGroupsArray[1] + "/" - +this.state.policyData.name + "/" + this.state.policyData.version); - } - }); - return commandsArray.length > 0 ? {"PdpActions":commandsArray} : undefined; - } + createPdpGroupOperations(initialStates, newStates) { + let commandsArray = []; + initialStates.forEach(initElem => { + let newStateFound = newStates.find(newElement => newElement.name === initElem.name); + if (initElem.value !== newStateFound.value) { + let newPdpGroupsArray = newStateFound.name.split("/"); + let operation = "POST/"; + if (initElem.value) { + operation = "DELETE/"; + } + commandsArray.push(operation + newPdpGroupsArray[0] + "/" + newPdpGroupsArray[1] + "/" + + this.state.policyData.name + "/" + this.state.policyData.version); + } + }); + return commandsArray.length > 0 ? { "PdpActions": commandsArray } : undefined; + } - handleUpdatePdpDeployment() { - let operationsList = this.createPdpGroupOperations(this.state.checkboxesInitialState, - this.state.checkboxesState); - if (typeof(operationsList) !== "undefined") { - PolicyService.updatePdpDeployment(operationsList).then(respPdpDeploymentUpdate => { - if (typeof(respPdpDeploymentUpdate) === "undefined") { - //it indicates a failure - this.setState({ - showFailAlert: true, - showMessage: 'Pdp Deployment update Failure' - }); - } else { - this.setState({ - showSuccessAlert: true, - showMessage: 'Pdp Deployment Update successful' - }); - this.props.policiesTableUpdateFunction(); - } - }) - } else { - this.setState({ - showSuccessAlert: true, - showMessage: 'Pdp Deployment: Nothing to change' - }); - } + handleUpdatePdpDeployment() { + let operationsList = this.createPdpGroupOperations(this.state.checkboxesInitialState, + this.state.checkboxesState); + if (typeof (operationsList) !== "undefined") { + PolicyService.updatePdpDeployment(operationsList).then(respPdpDeploymentUpdate => { + if (typeof (respPdpDeploymentUpdate) === "undefined") { + //it indicates a failure + this.setState({ + showFailAlert: true, + showMessage: 'Pdp Deployment update Failure' + }); + } else { + this.setState({ + showSuccessAlert: true, + showMessage: 'Pdp Deployment Update successful' + }); + this.props.policiesTableUpdateFunction(); + } + }) + } else { + this.setState({ + showSuccessAlert: true, + showMessage: 'Pdp Deployment: Nothing to change' + }); } + } - createPdpStructure(policyData) { - // Create map with data for all group/subgroup where the policy is deployed - let infoPdpMap = new Map(); - if (typeof policyData.pdpGroupInfo !== "undefined") { - policyData["pdpGroupInfo"].forEach(pdpGroupElem => { - let pdpGroupName = Object.keys(pdpGroupElem)[0]; - pdpGroupElem[pdpGroupName]["pdpSubgroups"].forEach(pdpSubGroupElem => { - infoPdpMap.set(pdpGroupName + "/" + pdpSubGroupElem["pdpType"], true); - }); - }); - } - // Create the possible values for pdpgroup/subgroup and tick the ones where policy is deployed - let pdpStates = []; - if (typeof policyData.supportedPdpGroups !== "undefined") { - for (const pdpGroup of policyData["supportedPdpGroups"]) { - let pdpGroupName = Object.keys(pdpGroup)[0]; - for (const pdpSubGroup of Object.values(pdpGroup)[0]) { - let fullName = pdpGroupName + "/" + pdpSubGroup; - pdpStates.push({name: fullName, - value: infoPdpMap.get(fullName) !== undefined}); - } - } - } - return pdpStates; + createPdpStructure(policyData) { + // Create map with data for all group/subgroup where the policy is deployed + let infoPdpMap = new Map(); + if (typeof policyData.pdpGroupInfo !== "undefined") { + policyData["pdpGroupInfo"].forEach(pdpGroupElem => { + let pdpGroupName = Object.keys(pdpGroupElem)[0]; + pdpGroupElem[pdpGroupName]["pdpSubgroups"].forEach(pdpSubGroupElem => { + infoPdpMap.set(pdpGroupName + "/" + pdpSubGroupElem["pdpType"], true); + }); + }); } - - handleCheckboxChange(event) { - const checkboxesArray = this.state.checkboxesState; - checkboxesArray.find(element => element.name === event.target.name).value = event.target.checked; - this.setState({checkboxesState:checkboxesArray}); + // Create the possible values for pdpgroup/subgroup and tick the ones where policy is deployed + let pdpStates = []; + if (typeof policyData.supportedPdpGroups !== "undefined") { + for (const pdpGroup of policyData["supportedPdpGroups"]) { + let pdpGroupName = Object.keys(pdpGroup)[0]; + for (const pdpSubGroup of Object.values(pdpGroup)[0]) { + let fullName = pdpGroupName + "/" + pdpSubGroup; + pdpStates.push({ + name: fullName, + value: infoPdpMap.get(fullName) !== undefined + }); + } + } } + return pdpStates; + } - renderPdpDeploymentCheckboxes() { - return this.state.checkboxesState.map(item => { - return <FormControlLabel control={<Checkbox checked={item.value} onChange={this.handleCheckboxChange} - name={item.name} />} label={item.name} />; - }); - } + handleCheckboxChange(event) { + const checkboxesArray = this.state.checkboxesState; + checkboxesArray.find(element => element.name === event.target.name).value = event.target.checked; + this.setState({ checkboxesState: checkboxesArray }); + } - render() { - return ( - <PanelDiv> - <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> - <Button variant="secondary" title="Update the policy to the specified PDP Groups/Subgroups" - onClick={this.handleUpdatePdpDeployment}>Update PDP</Button> - <FormGroup>{this.renderPdpDeploymentCheckboxes()}</FormGroup> - </PanelDiv> - ); - } - }
\ No newline at end of file + renderPdpDeploymentCheckboxes() { + return this.state.checkboxesState.map(item => { + return <FormControlLabel control={ <Checkbox checked={ item.value } onChange={ this.handleCheckboxChange } + name={ item.name }/> } label={ item.name }/>; + }); + } + + render() { + return ( + <PanelDiv> + <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> + <Button variant="secondary" title="Update the policy to the specified PDP Groups/Subgroups" + onClick={ this.handleUpdatePdpDeployment }>Update PDP</Button> + <FormGroup>{ this.renderPdpDeploymentCheckboxes() }</FormGroup> + </PanelDiv> + ); + } +} diff --git a/runtime/ui-react/src/components/dialogs/Policy/PolicyModal.js b/runtime/ui-react/src/components/dialogs/Policy/PolicyModal.js index 4a883fffa..0c7637c44 100644 --- a/runtime/ui-react/src/components/dialogs/Policy/PolicyModal.js +++ b/runtime/ui-react/src/components/dialogs/Policy/PolicyModal.js @@ -31,315 +31,319 @@ import Modal from 'react-bootstrap/Modal'; import styled from 'styled-components'; import LoopService from '../../../api/LoopService'; import LoopCache from '../../../api/LoopCache'; -import { JSONEditor } from '@json-editor/json-editor/dist/jsoneditor.js'; +import { JSONEditor } from '@json-editor/json-editor/dist/jsoneditor.js'; import "@fortawesome/fontawesome-free/css/all.css" import Alert from 'react-bootstrap/Alert'; import OnapConstant from '../../../utils/OnapConstants'; import OnapUtils from '../../../utils/OnapUtils'; const ModalStyled = styled(Modal)` - background-color: transparent; + background-color: transparent; ` const DivWhiteSpaceStyled = styled.div` - white-space: pre; + white-space: pre; ` export default class PolicyModal extends React.Component { - state = { - show: true, - loopCache: this.props.loopCache, - jsonEditor: null, - policyName: this.props.match.params.policyName, - // This is to indicate whether it's an operational or config policy (in terms of loop instance) - policyInstanceType: this.props.match.params.policyInstanceType, - pdpGroup: null, - pdpGroupList: [], - pdpSubgroupList: [], - chosenPdpGroup: '', - chosenPdpSubgroup: '', - showSucAlert: false, - showFailAlert: false - }; - - constructor(props, context) { - super(props, context); - this.handleClose = this.handleClose.bind(this); - this.handleSave = this.handleSave.bind(this); - this.renderJsonEditor = this.renderJsonEditor.bind(this); - this.handlePdpGroupChange = this.handlePdpGroupChange.bind(this); - this.handlePdpSubgroupChange = this.handlePdpSubgroupChange.bind(this); - this.createJsonEditor = this.createJsonEditor.bind(this); - this.handleRefresh = this.handleRefresh.bind(this); - this.disableAlert = this.disableAlert.bind(this); - this.renderPdpGroupDropDown = this.renderPdpGroupDropDown.bind(this); - this.renderOpenLoopMessage = this.renderOpenLoopMessage.bind(this); - this.renderModalTitle = this.renderModalTitle.bind(this); - this.readOnly = props.readOnly !== undefined ? props.readOnly : false; - } + state = { + show: true, + loopCache: this.props.loopCache, + jsonEditor: null, + policyName: this.props.match.params.policyName, + // This is to indicate whether it's an operational or config policy (in terms of loop instance) + policyInstanceType: this.props.match.params.policyInstanceType, + pdpGroup: null, + pdpGroupList: [], + pdpSubgroupList: [], + chosenPdpGroup: '', + chosenPdpSubgroup: '', + showSucAlert: false, + showFailAlert: false + }; - handleSave() { - var editorData = this.state.jsonEditor.getValue(); - var errors = this.state.jsonEditor.validate(); - errors = errors.concat(this.customValidation(editorData, this.state.loopCache.getTemplateName())); + constructor(props, context) { + super(props, context); + this.handleClose = this.handleClose.bind(this); + this.handleSave = this.handleSave.bind(this); + this.renderJsonEditor = this.renderJsonEditor.bind(this); + this.handlePdpGroupChange = this.handlePdpGroupChange.bind(this); + this.handlePdpSubgroupChange = this.handlePdpSubgroupChange.bind(this); + this.createJsonEditor = this.createJsonEditor.bind(this); + this.handleRefresh = this.handleRefresh.bind(this); + this.disableAlert = this.disableAlert.bind(this); + this.renderPdpGroupDropDown = this.renderPdpGroupDropDown.bind(this); + this.renderOpenLoopMessage = this.renderOpenLoopMessage.bind(this); + this.renderModalTitle = this.renderModalTitle.bind(this); + this.readOnly = props.readOnly !== undefined ? props.readOnly : false; + } - 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"); - if (this.state.policyInstanceType === OnapConstant.microServiceType) { - this.state.loopCache.updateMicroServiceProperties(this.state.policyName, editorData); - this.state.loopCache.updateMicroServicePdpGroup(this.state.policyName, this.state.chosenPdpGroup, this.state.chosenPdpSubgroup); - LoopService.setMicroServiceProperties(this.state.loopCache.getLoopName(), this.state.loopCache.getMicroServiceForName(this.state.policyName)).then(resp => { - this.setState({ show: false }); - this.props.history.push('/'); - this.props.loadLoopFunction(this.state.loopCache.getLoopName()); - }); - } else if (this.state.policyInstanceType === OnapConstant.operationalPolicyType) { - this.state.loopCache.updateOperationalPolicyProperties(this.state.policyName, editorData); - this.state.loopCache.updateOperationalPolicyPdpGroup(this.state.policyName, this.state.chosenPdpGroup, this.state.chosenPdpSubgroup); - LoopService.setOperationalPolicyProperties(this.state.loopCache.getLoopName(), this.state.loopCache.getOperationalPolicies()).then(resp => { - this.setState({ show: false }); - this.props.history.push('/'); - this.props.loadLoopFunction(this.state.loopCache.getLoopName()); - }); - } - } - } + handleSave() { + var editorData = this.state.jsonEditor.getValue(); + var errors = this.state.jsonEditor.validate(); + errors = errors.concat(this.customValidation(editorData, this.state.loopCache.getTemplateName())); - customValidation(editorData, templateName) { - // method for sub-classes to override with customized validation - return []; + 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"); + if (this.state.policyInstanceType === OnapConstant.microServiceType) { + this.state.loopCache.updateMicroServiceProperties(this.state.policyName, editorData); + this.state.loopCache.updateMicroServicePdpGroup(this.state.policyName, this.state.chosenPdpGroup, this.state.chosenPdpSubgroup); + LoopService.setMicroServiceProperties(this.state.loopCache.getLoopName(), this.state.loopCache.getMicroServiceForName(this.state.policyName)).then(resp => { + this.setState({ show: false }); + this.props.history.push('/'); + this.props.loadLoopFunction(this.state.loopCache.getLoopName()); + }); + } else if (this.state.policyInstanceType === OnapConstant.operationalPolicyType) { + this.state.loopCache.updateOperationalPolicyProperties(this.state.policyName, editorData); + this.state.loopCache.updateOperationalPolicyPdpGroup(this.state.policyName, this.state.chosenPdpGroup, this.state.chosenPdpSubgroup); + LoopService.setOperationalPolicyProperties(this.state.loopCache.getLoopName(), this.state.loopCache.getOperationalPolicies()).then(resp => { + this.setState({ show: false }); + this.props.history.push('/'); + this.props.loadLoopFunction(this.state.loopCache.getLoopName()); + }); + } } + } - handleClose() { - this.setState({ show: false }); - this.props.history.push('/'); - } + customValidation(editorData, templateName) { + // method for sub-classes to override with customized validation + return []; + } - componentDidMount() { - this.renderJsonEditor(); - } + handleClose() { + this.setState({ show: false }); + this.props.history.push('/'); + } - componentDidUpdate() { - if (this.state.showSucAlert === true || this.state.showFailAlert === true) { - let modalElement = document.getElementById("policyModal") - if (modalElement) { - modalElement.scrollTo(0, 0); - } - } - } + componentDidMount() { + this.renderJsonEditor(); + } - createJsonEditor(toscaModel, editorData) { - return new JSONEditor(document.getElementById("editor"), - { schema: toscaModel, - startval: editorData, - theme: 'bootstrap4', - iconlib: 'fontawesome5', - object_layout: 'grid', - disable_properties: false, - disable_edit_json: false, - disable_array_reorder: true, - disable_array_delete_last_row: true, - disable_array_delete_all_rows: false, - array_controls_top: true, - keep_oneof_values: false, - collapsed:true, - show_errors: 'always', - display_required_only: false, - show_opt_in: false, - prompt_before_delete: true, - required_by_default: false - }) + componentDidUpdate() { + if (this.state.showSucAlert === true || this.state.showFailAlert === true) { + let modalElement = document.getElementById("policyModal") + if (modalElement) { + modalElement.scrollTo(0, 0); + } } + } - renderJsonEditor() { - console.debug("Rendering PolicyModal ", this.state.policyName); - var toscaModel = {}; - var editorData = {}; - var pdpGroupValues = {}; - var chosenPdpGroupValue, chosenPdpSubgroupValue; - if (this.state.policyInstanceType === OnapConstant.microServiceType) { - toscaModel = this.state.loopCache.getMicroServiceJsonRepresentationForName(this.state.policyName); - editorData = this.state.loopCache.getMicroServicePropertiesForName(this.state.policyName); - pdpGroupValues = this.state.loopCache.getMicroServiceSupportedPdpGroup(this.state.policyName); - chosenPdpGroupValue = this.state.loopCache.getMicroServicePdpGroup(this.state.policyName); - chosenPdpSubgroupValue = this.state.loopCache.getMicroServicePdpSubgroup(this.state.policyName); - } else if (this.state.policyInstanceType === OnapConstant.operationalPolicyType) { - toscaModel = this.state.loopCache.getOperationalPolicyJsonRepresentationForName(this.state.policyName); - editorData = this.state.loopCache.getOperationalPolicyPropertiesForName(this.state.policyName); - pdpGroupValues = this.state.loopCache.getOperationalPolicySupportedPdpGroup(this.state.policyName); - chosenPdpGroupValue = this.state.loopCache.getOperationalPolicyPdpGroup(this.state.policyName); - chosenPdpSubgroupValue = this.state.loopCache.getOperationalPolicyPdpSubgroup(this.state.policyName); - } - - if (toscaModel == null) { - return; - } + createJsonEditor(toscaModel, editorData) { + return new JSONEditor(document.getElementById("editor"), + { + schema: toscaModel, + startval: editorData, + theme: 'bootstrap4', + iconlib: 'fontawesome5', + object_layout: 'grid', + disable_properties: false, + disable_edit_json: false, + disable_array_reorder: true, + disable_array_delete_last_row: true, + disable_array_delete_all_rows: false, + array_controls_top: true, + keep_oneof_values: false, + collapsed: true, + show_errors: 'always', + display_required_only: false, + show_opt_in: false, + prompt_before_delete: true, + required_by_default: false + }) + } - var pdpSubgroupValues = []; - if (typeof(chosenPdpGroupValue) !== "undefined") { - var selectedPdpGroup = pdpGroupValues.filter(entry => (Object.keys(entry)[0] === chosenPdpGroupValue)); - pdpSubgroupValues = selectedPdpGroup[0][chosenPdpGroupValue].map((pdpSubgroup) => { return { label: pdpSubgroup, value: pdpSubgroup } }); - } - this.setState({ - jsonEditor: this.createJsonEditor(toscaModel,editorData), - pdpGroup: pdpGroupValues, - pdpGroupList: pdpGroupValues.map(entry => { - return { label: Object.keys(entry)[0], value: Object.keys(entry)[0] }; - }), - pdpSubgroupList: pdpSubgroupValues, - chosenPdpGroup: chosenPdpGroupValue, - chosenPdpSubgroup: chosenPdpSubgroupValue - }) + renderJsonEditor() { + console.debug("Rendering PolicyModal ", this.state.policyName); + var toscaModel = {}; + var editorData = {}; + var pdpGroupValues = {}; + var chosenPdpGroupValue, chosenPdpSubgroupValue; + if (this.state.policyInstanceType === OnapConstant.microServiceType) { + toscaModel = this.state.loopCache.getMicroServiceJsonRepresentationForName(this.state.policyName); + editorData = this.state.loopCache.getMicroServicePropertiesForName(this.state.policyName); + pdpGroupValues = this.state.loopCache.getMicroServiceSupportedPdpGroup(this.state.policyName); + chosenPdpGroupValue = this.state.loopCache.getMicroServicePdpGroup(this.state.policyName); + chosenPdpSubgroupValue = this.state.loopCache.getMicroServicePdpSubgroup(this.state.policyName); + } else if (this.state.policyInstanceType === OnapConstant.operationalPolicyType) { + toscaModel = this.state.loopCache.getOperationalPolicyJsonRepresentationForName(this.state.policyName); + editorData = this.state.loopCache.getOperationalPolicyPropertiesForName(this.state.policyName); + pdpGroupValues = this.state.loopCache.getOperationalPolicySupportedPdpGroup(this.state.policyName); + chosenPdpGroupValue = this.state.loopCache.getOperationalPolicyPdpGroup(this.state.policyName); + chosenPdpSubgroupValue = this.state.loopCache.getOperationalPolicyPdpSubgroup(this.state.policyName); } - handlePdpGroupChange(e) { - var selectedPdpGroup = this.state.pdpGroup.filter(entry => (Object.keys(entry)[0] === e.value)); - const pdpSubgroupValues = selectedPdpGroup[0][e.value].map((pdpSubgroup) => { return { label: pdpSubgroup, value: pdpSubgroup } }); - if (this.state.chosenPdpGroup !== e.value) { - this.setState({ - chosenPdpGroup: e.value, - chosenPdpSubgroup: '', - pdpSubgroupList: pdpSubgroupValues - }); - } + if (toscaModel == null) { + return; } - handlePdpSubgroupChange(e) { - this.setState({ chosenPdpSubgroup: e.value }); + var pdpSubgroupValues = []; + if (typeof (chosenPdpGroupValue) !== "undefined") { + var selectedPdpGroup = pdpGroupValues.filter(entry => (Object.keys(entry)[0] === chosenPdpGroupValue)); + pdpSubgroupValues = selectedPdpGroup[0][chosenPdpGroupValue].map((pdpSubgroup) => { + return { label: pdpSubgroup, value: pdpSubgroup } + }); } + this.setState({ + jsonEditor: this.createJsonEditor(toscaModel, editorData), + pdpGroup: pdpGroupValues, + pdpGroupList: pdpGroupValues.map(entry => { + return { label: Object.keys(entry)[0], value: Object.keys(entry)[0] }; + }), + pdpSubgroupList: pdpSubgroupValues, + chosenPdpGroup: chosenPdpGroupValue, + chosenPdpSubgroup: chosenPdpSubgroupValue + }) + } - handleRefresh() { - var newLoopCache, toscaModel, editorData; - if (this.state.policyInstanceType === OnapConstant.microServiceType) { - LoopService.refreshMicroServicePolicyJson(this.state.loopCache.getLoopName(),this.state.policyName).then(data => { - newLoopCache = new LoopCache(data); - toscaModel = newLoopCache.getMicroServiceJsonRepresentationForName(this.state.policyName); - editorData = newLoopCache.getMicroServicePropertiesForName(this.state.policyName); - document.getElementById("editor").innerHTML = ""; - this.setState({ - loopCache: newLoopCache, - jsonEditor: this.createJsonEditor(toscaModel,editorData), - showSucAlert: true, - showMessage: "Successfully refreshed" - }); - }) - .catch(error => { - console.error("Error while refreshing the Operational Policy Json Representation"); - this.setState({ - showFailAlert: true, - showMessage: "Refreshing of UI failed" - }); - }); - } else if (this.state.policyInstanceType === OnapConstant.operationalPolicyType) { - LoopService.refreshOperationalPolicyJson(this.state.loopCache.getLoopName(),this.state.policyName).then(data => { - var newLoopCache = new LoopCache(data); - toscaModel = newLoopCache.getOperationalPolicyJsonRepresentationForName(this.state.policyName); - editorData = newLoopCache.getOperationalPolicyPropertiesForName(this.state.policyName); - document.getElementById("editor").innerHTML = ""; - this.setState({ - loopCache: newLoopCache, - jsonEditor: this.createJsonEditor(toscaModel,editorData), - showSucAlert: true, - showMessage: "Successfully refreshed" - }); - }) - .catch(error => { - console.error("Error while refreshing the Operational Policy Json Representation"); - this.setState({ - showFailAlert: true, - showMessage: "Refreshing of UI failed" - }); - }); - } + handlePdpGroupChange(e) { + var selectedPdpGroup = this.state.pdpGroup.filter(entry => (Object.keys(entry)[0] === e.value)); + const pdpSubgroupValues = selectedPdpGroup[0][e.value].map((pdpSubgroup) => { + return { label: pdpSubgroup, value: pdpSubgroup } + }); + if (this.state.chosenPdpGroup !== e.value) { + this.setState({ + chosenPdpGroup: e.value, + chosenPdpSubgroup: '', + pdpSubgroupList: pdpSubgroupValues + }); } + } - disableAlert() { - this.setState ({ showSucAlert: false, showFailAlert: false }); - } + handlePdpSubgroupChange(e) { + this.setState({ chosenPdpSubgroup: e.value }); + } - renderPdpGroupDropDown() { - if(this.state.policyInstanceType !== OnapConstant.operationalPolicyType || !this.state.loopCache.isOpenLoopTemplate()) { - return ( - <Form.Group as={Row} controlId="formPlaintextEmail"> - <Form.Label column sm="2">Pdp Group Info</Form.Label> - <Col sm="3"> - <Select value={{ label: this.state.chosenPdpGroup, value: this.state.chosenPdpGroup }} onChange={this.handlePdpGroupChange} options={this.state.pdpGroupList} /> - </Col> - <Col sm="3"> - <Select value={{ label: this.state.chosenPdpSubgroup, value: this.state.chosenPdpSubgroup }} onChange={this.handlePdpSubgroupChange} options={this.state.pdpSubgroupList} /> - </Col> - </Form.Group> - ); - } + handleRefresh() { + var newLoopCache, toscaModel, editorData; + if (this.state.policyInstanceType === OnapConstant.microServiceType) { + LoopService.refreshMicroServicePolicyJson(this.state.loopCache.getLoopName(), this.state.policyName).then(data => { + newLoopCache = new LoopCache(data); + toscaModel = newLoopCache.getMicroServiceJsonRepresentationForName(this.state.policyName); + editorData = newLoopCache.getMicroServicePropertiesForName(this.state.policyName); + document.getElementById("editor").innerHTML = ""; + this.setState({ + loopCache: newLoopCache, + jsonEditor: this.createJsonEditor(toscaModel, editorData), + showSucAlert: true, + showMessage: "Successfully refreshed" + }); + }) + .catch(error => { + console.error("Error while refreshing the Operational Policy Json Representation"); + this.setState({ + showFailAlert: true, + showMessage: "Refreshing of UI failed" + }); + }); + } else if (this.state.policyInstanceType === OnapConstant.operationalPolicyType) { + LoopService.refreshOperationalPolicyJson(this.state.loopCache.getLoopName(), this.state.policyName).then(data => { + var newLoopCache = new LoopCache(data); + toscaModel = newLoopCache.getOperationalPolicyJsonRepresentationForName(this.state.policyName); + editorData = newLoopCache.getOperationalPolicyPropertiesForName(this.state.policyName); + document.getElementById("editor").innerHTML = ""; + this.setState({ + loopCache: newLoopCache, + jsonEditor: this.createJsonEditor(toscaModel, editorData), + showSucAlert: true, + showMessage: "Successfully refreshed" + }); + }) + .catch(error => { + console.error("Error while refreshing the Operational Policy Json Representation"); + this.setState({ + showFailAlert: true, + showMessage: "Refreshing of UI failed" + }); + }); } + } - renderOpenLoopMessage() { - if(this.state.policyInstanceType === OnapConstant.operationalPolicyType && this.state.loopCache.isOpenLoopTemplate()) { - return ( - "Operational Policy cannot be configured as only Open Loop is supported for this Template!" - ); - } - } + disableAlert() { + this.setState({ showSucAlert: false, showFailAlert: false }); + } - renderModalTitle() { - return ( - <Modal.Title>Edit the policy</Modal.Title> - ); + renderPdpGroupDropDown() { + if (this.state.policyInstanceType !== OnapConstant.operationalPolicyType || !this.state.loopCache.isOpenLoopTemplate()) { + return ( + <Form.Group as={ Row } controlId="formPlaintextEmail"> + <Form.Label column sm="2">Pdp Group Info</Form.Label> + <Col sm="3"> + <Select value={ { label: this.state.chosenPdpGroup, value: this.state.chosenPdpGroup } } onChange={ this.handlePdpGroupChange } options={ this.state.pdpGroupList }/> + </Col> + <Col sm="3"> + <Select value={ { label: this.state.chosenPdpSubgroup, value: this.state.chosenPdpSubgroup } } onChange={ this.handlePdpSubgroupChange } options={ this.state.pdpSubgroupList }/> + </Col> + </Form.Group> + ); } + } - renderButton() { - var allElement = [(<Button key="close" variant="secondary" onClick={this.handleClose}> - Close - </Button>)]; - if(this.state.policyInstanceType !== OnapConstant.operationalPolicyType || !this.state.loopCache.isOpenLoopTemplate()) { - allElement.push(( - <Button key="save" variant="primary" disabled={this.readOnly} onClick={this.handleSave}> - Save Changes - </Button> - )); - allElement.push(( - <Button key="refresh" variant="primary" disabled={this.readOnly} onClick={this.handleRefresh}> - Refresh - </Button> - )); - } - return allElement; + renderOpenLoopMessage() { + if (this.state.policyInstanceType === OnapConstant.operationalPolicyType && this.state.loopCache.isOpenLoopTemplate()) { + return ( + "Operational Policy cannot be configured as only Open Loop is supported for this Template!" + ); } + } - render() { - return ( - <ModalStyled size="xl" backdrop="static" keyboard={false} show={this.state.show} onHide={this.handleClose}> - <Modal.Header closeButton> - {this.renderModalTitle()} - </Modal.Header> - <Alert variant="success" show={this.state.showSucAlert} 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> - {this.renderOpenLoopMessage()} - <div id="editor" /> - {this.renderPdpGroupDropDown()} - </Modal.Body> - <Modal.Footer> - {this.renderButton()} - </Modal.Footer> - </ModalStyled> - ); + renderModalTitle() { + return ( + <Modal.Title>Edit the policy</Modal.Title> + ); + } + + renderButton() { + var allElement = [(<Button key="close" variant="secondary" onClick={ this.handleClose }> + Close + </Button>)]; + if (this.state.policyInstanceType !== OnapConstant.operationalPolicyType || !this.state.loopCache.isOpenLoopTemplate()) { + allElement.push(( + <Button key="save" variant="primary" disabled={ this.readOnly } onClick={ this.handleSave }> + Save Changes + </Button> + )); + allElement.push(( + <Button key="refresh" variant="primary" disabled={ this.readOnly } onClick={ this.handleRefresh }> + Refresh + </Button> + )); } + return allElement; + } + + render() { + return ( + <ModalStyled size="xl" backdrop="static" keyboard={ false } show={ this.state.show } onHide={ this.handleClose }> + <Modal.Header closeButton> + { this.renderModalTitle() } + </Modal.Header> + <Alert variant="success" show={ this.state.showSucAlert } 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> + { this.renderOpenLoopMessage() } + <div id="editor"/> + { this.renderPdpGroupDropDown() } + </Modal.Body> + <Modal.Footer> + { this.renderButton() } + </Modal.Footer> + </ModalStyled> + ); + } } diff --git a/runtime/ui-react/src/components/dialogs/Policy/PolicyModal.test.js b/runtime/ui-react/src/components/dialogs/Policy/PolicyModal.test.js index 1e6fac0a0..658b19e26 100644 --- a/runtime/ui-react/src/components/dialogs/Policy/PolicyModal.test.js +++ b/runtime/ui-react/src/components/dialogs/Policy/PolicyModal.test.js @@ -29,107 +29,107 @@ import OnapConstant from '../../../utils/OnapConstants'; import { shallow } from 'enzyme'; describe('Verify PolicyModal', () => { - beforeEach(() => { - fetch.resetMocks(); - fetch.mockImplementation(() => { - return Promise.resolve({ - ok: true, - status: 200, - text: () => "OK" - }); - }); - }) - const loopCacheStr = { - "name": "LOOP_Jbv1z_v1_0_ResourceInstanceName1_tca", - "operationalPolicies": [{ - "name": "OPERATIONAL_h2NMX_v1_0_ResourceInstanceName1_tca", - "configurationsJson": { - "operational_policy": { - "controlLoop": {}, - "policies": [] - } - }, - "policyModel": {"policyPdpGroup": {"supportedPdpGroups":[{"monitoring": ["xacml"]}]}}, - "jsonRepresentation" : {"schema": {}} - }] - }; - - const loopCache = new LoopCache(loopCacheStr); - const historyMock = { push: jest.fn() }; - const flushPromises = () => new Promise(setImmediate); - const match = {params: {policyName:"OPERATIONAL_h2NMX_v1_0_ResourceInstanceName1_tca", policyInstanceType: OnapConstant.operationalPolicyType}} - - it('Test handleClose', () => { - const handleClose = jest.spyOn(PolicyModal.prototype,'handleClose'); - const component = mount(<PolicyModal history={historyMock} match={match} loopCache={loopCache}/>) - - component.find('[variant="secondary"]').prop('onClick')(); - - expect(handleClose).toHaveBeenCalledTimes(1); - expect(component.state('show')).toEqual(false); - expect(historyMock.push.mock.calls[0]).toEqual([ '/']); + beforeEach(() => { + fetch.resetMocks(); + fetch.mockImplementation(() => { + return Promise.resolve({ + ok: true, + status: 200, + text: () => "OK" + }); }); - - it('Test handleSave', async () => { - const loadLoopFunction = jest.fn(); - const handleSave = jest.spyOn(PolicyModal.prototype,'handleSave'); - const component = mount(<PolicyModal history={historyMock} - loopCache={loopCache} match={match} loadLoopFunction={loadLoopFunction} />) - - component.find('[variant="primary"]').get(0).props.onClick(); - await flushPromises(); - component.update(); - - expect(handleSave).toHaveBeenCalledTimes(1); - expect(component.state('show')).toEqual(false); - expect(historyMock.push.mock.calls[0]).toEqual([ '/']); + }) + const loopCacheStr = { + "name": "LOOP_Jbv1z_v1_0_ResourceInstanceName1_tca", + "operationalPolicies": [{ + "name": "OPERATIONAL_h2NMX_v1_0_ResourceInstanceName1_tca", + "configurationsJson": { + "operational_policy": { + "controlLoop": {}, + "policies": [] + } + }, + "policyModel": { "policyPdpGroup": { "supportedPdpGroups": [{ "monitoring": ["xacml"] }] } }, + "jsonRepresentation": { "schema": {} } + }] + }; + + const loopCache = new LoopCache(loopCacheStr); + const historyMock = { push: jest.fn() }; + const flushPromises = () => new Promise(setImmediate); + const match = { params: { policyName: "OPERATIONAL_h2NMX_v1_0_ResourceInstanceName1_tca", policyInstanceType: OnapConstant.operationalPolicyType } } + + it('Test handleClose', () => { + const handleClose = jest.spyOn(PolicyModal.prototype, 'handleClose'); + const component = mount(<PolicyModal history={ historyMock } match={ match } loopCache={ loopCache }/>) + + component.find('[variant="secondary"]').prop('onClick')(); + + expect(handleClose).toHaveBeenCalledTimes(1); + expect(component.state('show')).toEqual(false); + expect(historyMock.push.mock.calls[0]).toEqual(['/']); + }); + + it('Test handleSave', async () => { + const loadLoopFunction = jest.fn(); + const handleSave = jest.spyOn(PolicyModal.prototype, 'handleSave'); + const component = mount(<PolicyModal history={ historyMock } + loopCache={ loopCache } match={ match } loadLoopFunction={ loadLoopFunction }/>) + + component.find('[variant="primary"]').get(0).props.onClick(); + await flushPromises(); + component.update(); + + expect(handleSave).toHaveBeenCalledTimes(1); + expect(component.state('show')).toEqual(false); + expect(historyMock.push.mock.calls[0]).toEqual(['/']); + }); + + it('Test handleRefresh', async () => { + LoopService.refreshOperationalPolicyJson = jest.fn().mockImplementation(() => { + return Promise.resolve(loopCacheStr); }); - - it('Test handleRefresh', async () => { - LoopService.refreshOperationalPolicyJson = jest.fn().mockImplementation(() => { - return Promise.resolve(loopCacheStr); - }); - const updateLoopFunction = jest.fn(); - const handleRefresh = jest.spyOn(PolicyModal.prototype,'handleRefresh'); - const component = mount(<PolicyModal loopCache={loopCache} match={match} updateLoopFunction={updateLoopFunction} />) - - component.find('[variant="primary"]').get(1).props.onClick(); - await flushPromises(); - component.update(); - - expect(handleRefresh).toHaveBeenCalledTimes(1); - expect(component.state('show')).toEqual(true); - expect(component.state('showSucAlert')).toEqual(true); - expect(component.state('showMessage')).toEqual("Successfully refreshed"); - }); - - it('Test handlePdpGroupChange', () => { - const component = mount(<PolicyModal loopCache={loopCache} match={match} />) - component.setState({ - "pdpGroup": [{"option1":["subPdp1","subPdp2"]}], - "chosenPdpGroup": "option2" - }); - expect(component.state('chosenPdpGroup')).toEqual("option2"); - - const instance = component.instance(); - const event = {label:"option1", value:"option1"} - instance.handlePdpGroupChange(event); - expect(component.state('chosenPdpGroup')).toEqual("option1"); - expect(component.state('chosenPdpSubgroup')).toEqual(""); - expect(component.state('pdpSubgroupList')).toEqual([{label:"subPdp1", value:"subPdp1"}, {label:"subPdp2", value:"subPdp2"}]); - }); - - it('Test handlePdpSubgroupChange', () => { - const component = mount(<PolicyModal loopCache={loopCache} match={match} />) - - const instance = component.instance(); - const event = {label:"option1", value:"option1"} - instance.handlePdpSubgroupChange(event); - expect(component.state('chosenPdpSubgroup')).toEqual("option1"); - }); - - it('Test the render method', () => { - const component = shallow(<PolicyModal loopCache={loopCache} match={match}/>) - expect(component).toMatchSnapshot(); + const updateLoopFunction = jest.fn(); + const handleRefresh = jest.spyOn(PolicyModal.prototype, 'handleRefresh'); + const component = mount(<PolicyModal loopCache={ loopCache } match={ match } updateLoopFunction={ updateLoopFunction }/>) + + component.find('[variant="primary"]').get(1).props.onClick(); + await flushPromises(); + component.update(); + + expect(handleRefresh).toHaveBeenCalledTimes(1); + expect(component.state('show')).toEqual(true); + expect(component.state('showSucAlert')).toEqual(true); + expect(component.state('showMessage')).toEqual("Successfully refreshed"); + }); + + it('Test handlePdpGroupChange', () => { + const component = mount(<PolicyModal loopCache={ loopCache } match={ match }/>) + component.setState({ + "pdpGroup": [{ "option1": ["subPdp1", "subPdp2"] }], + "chosenPdpGroup": "option2" }); -});
\ No newline at end of file + expect(component.state('chosenPdpGroup')).toEqual("option2"); + + const instance = component.instance(); + const event = { label: "option1", value: "option1" } + instance.handlePdpGroupChange(event); + expect(component.state('chosenPdpGroup')).toEqual("option1"); + expect(component.state('chosenPdpSubgroup')).toEqual(""); + expect(component.state('pdpSubgroupList')).toEqual([{ label: "subPdp1", value: "subPdp1" }, { label: "subPdp2", value: "subPdp2" }]); + }); + + it('Test handlePdpSubgroupChange', () => { + const component = mount(<PolicyModal loopCache={ loopCache } match={ match }/>) + + const instance = component.instance(); + const event = { label: "option1", value: "option1" } + instance.handlePdpSubgroupChange(event); + expect(component.state('chosenPdpSubgroup')).toEqual("option1"); + }); + + it('Test the render method', () => { + const component = shallow(<PolicyModal loopCache={ loopCache } match={ match }/>) + expect(component).toMatchSnapshot(); + }); +}); diff --git a/runtime/ui-react/src/components/loop_viewer/svg/SvgGenerator.js b/runtime/ui-react/src/components/loop_viewer/svg/SvgGenerator.js index 6d3cd7a21..2692aefa0 100644 --- a/runtime/ui-react/src/components/loop_viewer/svg/SvgGenerator.js +++ b/runtime/ui-react/src/components/loop_viewer/svg/SvgGenerator.js @@ -27,220 +27,222 @@ import LoopCache from '../../../api/LoopCache'; import OnapConstant from '../../../utils/OnapConstants'; const DivStyled = styled.div` - overflow-x: scroll; - display: flex; - width: 100%; - height: 100%; + overflow-x: scroll; + display: flex; + width: 100%; + height: 100%; ` -const emptySvg = (<svg> <text x="60" y="40">No LOOP (SVG)</text> </svg>); +const emptySvg = (<svg> + <text x="60" y="40">No LOOP (SVG)</text> +</svg>); class SvgGenerator extends React.Component { - boxWidth = 200; - boxHeight = 100; - boxSpace = 50; - - static GENERATED_FROM_INSTANCE = "INSTANCE"; - static GENERATED_FROM_TEMPLATE = "TEMPLATE"; - - state = { - loopCache: new LoopCache({}), - clickable: false, - generatedFrom: SvgGenerator.GENERATED_FROM_INSTANCE, // INSTANCE / TEMPLATE - } - - constructor(props) { - super(props); - this.state.loopCache = props.loopCache; - this.state.clickable = props.clickable; - this.state.generatedFrom = props.generatedFrom; - this.handleSvgClick = this.handleSvgClick.bind(this); - this.renderSvg = this.renderSvg.bind(this); - } - - shouldComponentUpdate(nextProps, nextState) { - return this.state.loopCache !== nextProps.loopCache; - } - - componentDidUpdate(prevProps) { - if (prevProps.loopCache !== this.props.loopCache) { - this.setState({ - loopCache: this.props.loopCache, - }); - } + boxWidth = 200; + boxHeight = 100; + boxSpace = 50; + + static GENERATED_FROM_INSTANCE = "INSTANCE"; + static GENERATED_FROM_TEMPLATE = "TEMPLATE"; + + state = { + loopCache: new LoopCache({}), + clickable: false, + generatedFrom: SvgGenerator.GENERATED_FROM_INSTANCE, // INSTANCE / TEMPLATE + } + + constructor(props) { + super(props); + this.state.loopCache = props.loopCache; + this.state.clickable = props.clickable; + this.state.generatedFrom = props.generatedFrom; + this.handleSvgClick = this.handleSvgClick.bind(this); + this.renderSvg = this.renderSvg.bind(this); + } + + shouldComponentUpdate(nextProps, nextState) { + return this.state.loopCache !== nextProps.loopCache; + } + + componentDidUpdate(prevProps) { + if (prevProps.loopCache !== this.props.loopCache) { + this.setState({ + loopCache: this.props.loopCache, + }); } - - handleSvgClick(event) { - console.debug("svg click event received"); - if (this.state.clickable) { - var elementName = event.target.parentNode.getAttribute('policyId'); - console.info("SVG element clicked", elementName); - // Only allow movement to policy editing IF there busyLoadingCOunt is 0, - // meaning we are not waiting for refreshStatus to complete, for example - if (elementName !== null && !this.props.isBusyLoading()) { - this.props.history.push("/policyModal/"+event.target.parentNode.getAttribute('policyType')+"/"+elementName); - } - } - } - - createVesBox (xPos) { - return this.createOneBox(xPos,null,null,'VES Collector','VES',null); + } + + handleSvgClick(event) { + console.debug("svg click event received"); + if (this.state.clickable) { + var elementName = event.target.parentNode.getAttribute('policyId'); + console.info("SVG element clicked", elementName); + // Only allow movement to policy editing IF there busyLoadingCOunt is 0, + // meaning we are not waiting for refreshStatus to complete, for example + if (elementName !== null && !this.props.isBusyLoading()) { + this.props.history.push("/policyModal/" + event.target.parentNode.getAttribute('policyType') + "/" + elementName); + } } - - createOneArrow(xPos) { - return ( - <svg width={this.boxSpace} height={this.boxHeight} x={xPos}> - <defs> - <marker viewBox="0 0 20 20" markerWidth="20" markerHeight="20" orient="auto" refX="8.5" refY="5" id="arrow"> - <path d="m 1 5 l 0 -3 l 7 3 l -7 3 z" - stroke-width= "1" stroke-linecap= "butt" stroke-dasharray= "10000, 1" - fill="#000000" stroke="#000000" /> - </marker> - </defs> - <line x1="0" y1="50%" x2="100%" y2="50%" stroke-width="2" color="black" stroke="black" marker-end="url(#arrow)"/> - </svg> - ); + } + + createVesBox(xPos) { + return this.createOneBox(xPos, null, null, 'VES Collector', 'VES', null); + } + + createOneArrow(xPos) { + return ( + <svg width={ this.boxSpace } height={ this.boxHeight } x={ xPos }> + <defs> + <marker viewBox="0 0 20 20" markerWidth="20" markerHeight="20" orient="auto" refX="8.5" refY="5" id="arrow"> + <path d="m 1 5 l 0 -3 l 7 3 l -7 3 z" + stroke-width="1" stroke-linecap="butt" stroke-dasharray="10000, 1" + fill="#000000" stroke="#000000"/> + </marker> + </defs> + <line x1="0" y1="50%" x2="100%" y2="50%" stroke-width="2" color="black" stroke="black" marker-end="url(#arrow)"/> + </svg> + ); + } + + createBeginCircle(xPos, text) { + return ( + <svg width={ this.boxWidth } height={ this.boxHeight } x={ xPos }> + <circle cx={ this.boxWidth - 30 } cy="50%" r="30" stroke-width="1" color="black" stroke="black" fill="#27ae60"/> + <text x={ this.boxWidth - 30 } y="50%" text-anchor="middle" dominant-baseline="middle" textLength="20%" lengthAdjust="spacingAndGlyphs">{ text }</text> + </svg> + ); + } + + createEndCircle(xPos, text) { + return ( + <svg width={ this.boxWidth } height={ this.boxHeight } x={ xPos }> + <circle cx={ 30 } cy="50%" r="30" stroke-width="2" color="black" stroke="black" fill="#27ae60"/> + <text x={ 30 } y="50%" text-anchor="middle" dominant-baseline="middle" textLength="20%" lengthAdjust="spacingAndGlyphs">{ text }</text> + </svg> + ); + } + + createOneBox(xPos, policyId, loopElementModelId, name, title, policyType) { + return ( + <svg width={ this.boxWidth } height={ this.boxHeight } x={ xPos } title="test"> + <g policyId={ policyId } loopElementModelId={ loopElementModelId } policyType={ policyType }> + <rect width="100%" height="100%" stroke-width="2" color="black" stroke="black" fill="#1abc9c"/> + <text x="50%" y="15%" color="white" fill="white" dominant-baseline="middle" text-anchor="middle" textLength="50%" lengthAdjust="spacingAndGlyphs">{ title }</text> + <text x="50%" y="50%" text-anchor="middle" dominant-baseline="middle" textLength="80%" lengthAdjust="spacingAndGlyphs">{ name }</text> + <text x="50%" y="80%" text-anchor="middle" dominant-baseline="middle" textLength="110%" lengthAdjust="spacingAndGlyphs">{ policyId }</text> + </g> + </svg> + ); + } + + createSvgFromTemplate() { + const allElements = []; + var xPos = 0; + + allElements.push(this.createBeginCircle(xPos, "Start")) + xPos += (this.boxWidth + this.boxSpace); + + allElements.push(this.createOneArrow(xPos - this.boxSpace)); + + allElements.push(this.createVesBox(xPos)); + xPos += (this.boxWidth + this.boxSpace); + + allElements.push(this.createOneArrow(xPos - this.boxSpace)); + //createOneBox(xPos, policyId, loopElementModelId , name, title, policyType) + for (var loopElement of this.state.loopCache.getAllLoopElementModels()) { + + allElements.push(this.createOneBox(xPos, + loopElement['name'], + loopElement['name'], + loopElement['shortName'], + loopElement['loopElementType'], + loopElement['loopElementType'])) + xPos += (this.boxWidth + this.boxSpace); + allElements.push(this.createOneArrow(xPos - this.boxSpace)); } - createBeginCircle(xPos, text) { - return ( - <svg width={this.boxWidth} height={this.boxHeight} x={xPos}> - <circle cx={this.boxWidth-30} cy="50%" r="30" stroke-width="1" color="black" stroke="black" fill="#27ae60"/> - <text x={this.boxWidth-30} y="50%" text-anchor="middle" dominant-baseline="middle" textLength="20%" lengthAdjust="spacingAndGlyphs" >{text}</text> - </svg> - ); - } + allElements.push(this.createEndCircle(xPos, "End")) + xPos += (this.boxWidth + this.boxSpace); - createEndCircle(xPos, text) { - return ( - <svg width={this.boxWidth} height={this.boxHeight} x={xPos}> - <circle cx={30} cy="50%" r="30" stroke-width="2" color="black" stroke="black" fill="#27ae60"/> - <text x={30} y="50%" text-anchor="middle" dominant-baseline="middle" textLength="20%" lengthAdjust="spacingAndGlyphs" >{text}</text> - </svg> - ); - } - - createOneBox(xPos, policyId, loopElementModelId , name, title, policyType) { - return ( - <svg width={this.boxWidth} height={this.boxHeight} x={xPos} title="test"> - <g policyId={policyId} loopElementModelId={loopElementModelId} policyType={policyType}> - <rect width="100%" height="100%" stroke-width="2" color="black" stroke="black" fill="#1abc9c"/> - <text x="50%" y="15%" color="white" fill="white" dominant-baseline="middle" text-anchor="middle" textLength="50%" lengthAdjust="spacingAndGlyphs">{title}</text> - <text x="50%" y="50%" text-anchor="middle" dominant-baseline="middle" textLength="80%" lengthAdjust="spacingAndGlyphs" >{name}</text> - <text x="50%" y="80%" text-anchor="middle" dominant-baseline="middle" textLength="110%" lengthAdjust="spacingAndGlyphs" >{policyId}</text> - </g> - </svg> - ); - } + return allElements; + } - createSvgFromTemplate() { - const allElements = []; - var xPos = 0; + createSvgFromInstance() { + const allElements = []; + var xPos = 0; - allElements.push(this.createBeginCircle(xPos,"Start")) - xPos+=(this.boxWidth+this.boxSpace); + allElements.push(this.createBeginCircle(xPos, "Start")) + xPos += (this.boxWidth + this.boxSpace); - allElements.push(this.createOneArrow(xPos-this.boxSpace)); + allElements.push(this.createOneArrow(xPos - this.boxSpace)); - allElements.push(this.createVesBox(xPos)); - xPos+=(this.boxWidth+this.boxSpace); + allElements.push(this.createVesBox(xPos)); + xPos += (this.boxWidth + this.boxSpace); - allElements.push(this.createOneArrow(xPos-this.boxSpace)); - //createOneBox(xPos, policyId, loopElementModelId , name, title, policyType) - for (var loopElement of this.state.loopCache.getAllLoopElementModels()) { + allElements.push(this.createOneArrow(xPos - this.boxSpace)); - allElements.push(this.createOneBox(xPos, - loopElement['name'], - loopElement['name'], - loopElement['shortName'], - loopElement['loopElementType'], - loopElement['loopElementType'])) - xPos+=(this.boxWidth+this.boxSpace); - allElements.push(this.createOneArrow(xPos-this.boxSpace)); - } - - allElements.push(this.createEndCircle(xPos, "End")) - xPos+=(this.boxWidth+this.boxSpace); - - return allElements; + for (var msPolicy in this.state.loopCache.getMicroServicePolicies()) { + var loopElementModelName = this.state.loopCache.getMicroServicePolicies()[msPolicy]['loopElementModel']; + if (loopElementModelName !== undefined) { + loopElementModelName = loopElementModelName['name']; + } + allElements.push(this.createOneBox(xPos, + this.state.loopCache.getMicroServicePolicies()[msPolicy]['name'], + loopElementModelName, + this.state.loopCache.getMicroServicePolicies()[msPolicy]['policyModel']['policyAcronym'], + 'microservice', + OnapConstant.microServiceType)) + xPos += (this.boxWidth + this.boxSpace); + allElements.push(this.createOneArrow(xPos - this.boxSpace)); } - createSvgFromInstance() { - const allElements = []; - var xPos = 0; - - allElements.push(this.createBeginCircle(xPos,"Start")) - xPos+=(this.boxWidth+this.boxSpace); - - allElements.push(this.createOneArrow(xPos-this.boxSpace)); - - allElements.push(this.createVesBox(xPos)); - xPos+=(this.boxWidth+this.boxSpace); - - allElements.push(this.createOneArrow(xPos-this.boxSpace)); - - for (var msPolicy in this.state.loopCache.getMicroServicePolicies()) { - var loopElementModelName = this.state.loopCache.getMicroServicePolicies()[msPolicy]['loopElementModel']; - if (loopElementModelName !== undefined) { - loopElementModelName = loopElementModelName['name']; - } - allElements.push(this.createOneBox(xPos, - this.state.loopCache.getMicroServicePolicies()[msPolicy]['name'], - loopElementModelName, - this.state.loopCache.getMicroServicePolicies()[msPolicy]['policyModel']['policyAcronym'], - 'microservice', - OnapConstant.microServiceType)) - xPos+=(this.boxWidth+this.boxSpace); - allElements.push(this.createOneArrow(xPos-this.boxSpace)); - } - - for (var opPolicy in this.state.loopCache.getOperationalPolicies()) { - loopElementModelName = this.state.loopCache.getOperationalPolicies()[opPolicy]['loopElementModel']; - if (loopElementModelName !== undefined) { - loopElementModelName = loopElementModelName['name']; - } - allElements.push(this.createOneBox(xPos, - this.state.loopCache.getOperationalPolicies()[opPolicy]['name'], - loopElementModelName, - this.state.loopCache.getOperationalPolicies()[opPolicy]['policyModel']['policyAcronym'], - 'operational', - OnapConstant.operationalPolicyType)) - xPos+=(this.boxWidth+this.boxSpace); - allElements.push(this.createOneArrow(xPos-this.boxSpace)); - } - - allElements.push(this.createEndCircle(xPos, "End")) - xPos+=(this.boxWidth+this.boxSpace); - - return allElements; + for (var opPolicy in this.state.loopCache.getOperationalPolicies()) { + loopElementModelName = this.state.loopCache.getOperationalPolicies()[opPolicy]['loopElementModel']; + if (loopElementModelName !== undefined) { + loopElementModelName = loopElementModelName['name']; + } + allElements.push(this.createOneBox(xPos, + this.state.loopCache.getOperationalPolicies()[opPolicy]['name'], + loopElementModelName, + this.state.loopCache.getOperationalPolicies()[opPolicy]['policyModel']['policyAcronym'], + 'operational', + OnapConstant.operationalPolicyType)) + xPos += (this.boxWidth + this.boxSpace); + allElements.push(this.createOneArrow(xPos - this.boxSpace)); } - renderSvg() { - if (this.state.loopCache.getLoopName() === undefined) { - return [emptySvg]; - } - if (this.state.generatedFrom === SvgGenerator.GENERATED_FROM_INSTANCE) { - return this.createSvgFromInstance(); - } else if (this.state.generatedFrom === SvgGenerator.GENERATED_FROM_TEMPLATE) { - return this.createSvgFromTemplate(); - } - } + allElements.push(this.createEndCircle(xPos, "End")) + xPos += (this.boxWidth + this.boxSpace); - render() { - var allTheElements = this.renderSvg(); - var svgWidth = this.boxWidth*allTheElements.length; - var svgHeight = this.boxHeight+50; - return ( - - <DivStyled onClick={this.handleSvgClick} > - <svg key="main" height={svgHeight} width={svgWidth} viewBox="0,0,{svgWidth},{svgHeight}" preserveAspectRatio="none"> - <svg key="content" x="-50" y="25"> - {allTheElements} - </svg> - </svg> - </DivStyled> - ); + return allElements; + } + + renderSvg() { + if (this.state.loopCache.getLoopName() === undefined) { + return [emptySvg]; + } + if (this.state.generatedFrom === SvgGenerator.GENERATED_FROM_INSTANCE) { + return this.createSvgFromInstance(); + } else if (this.state.generatedFrom === SvgGenerator.GENERATED_FROM_TEMPLATE) { + return this.createSvgFromTemplate(); } + } + + render() { + var allTheElements = this.renderSvg(); + var svgWidth = this.boxWidth * allTheElements.length; + var svgHeight = this.boxHeight + 50; + return ( + + <DivStyled onClick={ this.handleSvgClick }> + <svg key="main" height={ svgHeight } width={ svgWidth } viewBox="0,0,{svgWidth},{svgHeight}" preserveAspectRatio="none"> + <svg key="content" x="-50" y="25"> + { allTheElements } + </svg> + </svg> + </DivStyled> + ); + } } export default withRouter(SvgGenerator); |