diff options
27 files changed, 535 insertions, 333 deletions
@@ -12,11 +12,11 @@ To build it using Maven 3, run: mvn clean install -P docker # Docker image -Maven produces a single docker image containing the policy GUIs. These are exposed on -the same port (8080) using different URLs: -- Apex Policy Editor: http://localhost:8080/apex-editor -- PDP Monitoring UI: http://localhost:8080/pdp-monitoring -- CLAMP Designer UI: http://localhost:8080/clamp +Maven produces a single docker image containing the policy GUIs. +These are exposed on the same port (2443) using different URLs: +- Apex Policy Editor: https://localhost:2443/apex-editor +- PDP Monitoring UI: https://localhost:2443/pdp-monitoring +- CLAMP Designer UI: https://localhost:2443/clamp ## Building You can use the following command to build the policy-gui docker image: @@ -25,21 +25,20 @@ mvn clean install -P docker ``` ## Deployment -Currently, the policy-gui docker image can be deployed with minimal configuration. As -the clamp backend is required to use the clamp GUI, you can use the CLAMP_REST_URL -environment variable to set its location. +Currently, the policy-gui docker image can be deployed without configuration. +For the GUI container to start correctly, the CLAMP backend +`policy-clamp-backend` should be started first. -By default, CLAMP_REST_URL is set to an invalid address (0.0.0.0), meaning the CLAMP GUI -will not work without specifying CLAMP_REST_URL. - -If running clamp as part of a docker network, where `policy-clamp-backend` is the CLAMP -backend, then CLAMP_REST_URL should be set to `https://policy-clamp-backend:8443`. - -If running clamp backend on localhost port 8443, the policy-gui docker image would be -started like this: +For local testing, if the CLAMP backend is running on localhost port 8443, +the policy-gui docker container can be started with: ``` -docker run -p 8080:8080 \ - --add-host host.docker.internal:host-gateway \ - --env CLAMP_REST_URL=https://host.docker.internal:8443 \ - onap/policy-gui +docker run -p 2443:2443 --add-host policy-clamp-backend:host-gateway onap/policy-gui ``` + +## Client Credentials +A certificate must be added in the browser and is required to log in properly: + +[org.onap.clamp.p12 (from clamp master)](URL "https://gerrit.onap.org/r/gitweb?p=clamp.git;a=blob_plain;f=src/main/resources/clds/aaf/org.onap.clamp.p12;hb=refs/heads/master") +(Password: "China in the Spring") + +See onap/clamp repo README for details. diff --git a/gui-clamp/ui-react-lib/libIndex.js b/gui-clamp/ui-react-lib/libIndex.js index 779e363..24e3072 100644 --- a/gui-clamp/ui-react-lib/libIndex.js +++ b/gui-clamp/ui-react-lib/libIndex.js @@ -59,8 +59,9 @@ export { default as MonitorInstantiation } from '../ui-react/src/components/dial export { default as InstantiationItem } from '../ui-react/src/components/dialogs/ControlLoop/InstantiationItem'; export { default as InstantiationElements } from '../ui-react/src/components/dialogs/ControlLoop/InstantiationElements'; export { default as InstantiationElementItem } from '../ui-react/src/components/dialogs/ControlLoop/InstantiationElementItem'; -export { default as InstanceModal } from '../ui-react/src/components/dialogs/ControlLoop/InstanceModal'; +export { default as InstancePropertiesModal } from '../ui-react/src/components/dialogs/ControlLoop/InstancePropertiesModal'; export { default as InstantiationManagementModal } from '../ui-react/src/components/dialogs/ControlLoop/InstantiationManagementModal'; +export { default as ChangeOrderStateModal } from '../ui-react/src/components/dialogs/ControlLoop/ChangeOrderStateModal'; export { default as InstantiationOrderStateChangeItem } from '../ui-react/src/components/dialogs/ControlLoop/InstantiationOrderStateChangeItem'; export { default as ControlLoopService } from '../ui-react/src/api/ControlLoopService'; export { default as GetLocalToscaFileForUpload } from '../ui-react/src/components/dialogs/ControlLoop/GetLocalToscaFileForUpload'; diff --git a/gui-clamp/ui-react/package.json b/gui-clamp/ui-react/package.json index 68199e6..732a6b3 100644 --- a/gui-clamp/ui-react/package.json +++ b/gui-clamp/ui-react/package.json @@ -8,6 +8,7 @@ "registry": "${npm.publish.url}" }, "main": "index.js", + "homepage": ".", "proxy": "https://localhost:8443", "scripts": { "start": "HTTPS=true react-scripts start", diff --git a/gui-clamp/ui-react/src/LoopUI.js b/gui-clamp/ui-react/src/LoopUI.js index 79943bf..e593a08 100644 --- a/gui-clamp/ui-react/src/LoopUI.js +++ b/gui-clamp/ui-react/src/LoopUI.js @@ -55,7 +55,8 @@ import ReadAndConvertYaml from "./components/dialogs/ControlLoop/ReadAndConvertY import MonitorInstantiation from "./components/dialogs/ControlLoop/MonitorInstantiation"; import GetLocalToscaFileForUpload from "./components/dialogs/ControlLoop/GetLocalToscaFileForUpload"; import CommissioningModal from "./components/dialogs/ControlLoop/CommissioningModal"; -import InstanceModal from "./components/dialogs/ControlLoop/InstanceModal"; +import InstancePropertiesModal from "./components/dialogs/ControlLoop/InstancePropertiesModal"; +import ChangeOrderStateModal from "./components/dialogs/ControlLoop/ChangeOrderStateModal"; import InstantiationManagementModal from "./components/dialogs/ControlLoop/InstantiationManagementModal"; const StyledMainDiv = styled.div` @@ -387,8 +388,9 @@ export default class LoopUI extends React.Component { showFailAlert={ this.showFailAlert }/>) } /> <Route path="/monitorInstantiation" render={ (routeProps) => (<MonitorInstantiation { ...routeProps } />) }/> - <Route path="/manageInstantiation" render={ (routeProps) => (<InstantiationManagementModal { ...routeProps } />) }/> - <Route path="/editControlLoopInstanceProperties" render={ (routeProps) => (<InstanceModal { ...routeProps } />) }/> + <Route path="/instantiationManagement" render={ (routeProps) => (<InstantiationManagementModal { ...routeProps } />) }/> + <Route path="/editControlLoopInstanceProperties" render={ (routeProps) => (<InstancePropertiesModal { ...routeProps } />) }/> + <Route path="/changeOrderState" render={ (routeProps) => (<ChangeOrderStateModal { ...routeProps } />) }/> </React.Fragment> ); } diff --git a/gui-clamp/ui-react/src/__snapshots__/LoopUI.test.js.snap b/gui-clamp/ui-react/src/__snapshots__/LoopUI.test.js.snap index abfcb8d..222b2a7 100644 --- a/gui-clamp/ui-react/src/__snapshots__/LoopUI.test.js.snap +++ b/gui-clamp/ui-react/src/__snapshots__/LoopUI.test.js.snap @@ -90,13 +90,17 @@ exports[`Verify LoopUI Test the render method 1`] = ` render={[Function]} /> <Route - path="/manageInstantiation" + path="/instantiationManagement" render={[Function]} /> <Route path="/editControlLoopInstanceProperties" render={[Function]} /> + <Route + path="/changeOrderState" + render={[Function]} + /> <div /> <div> <Alert diff --git a/gui-clamp/ui-react/src/__snapshots__/OnapClamp.test.js.snap b/gui-clamp/ui-react/src/__snapshots__/OnapClamp.test.js.snap index a87127e..cc5541b 100644 --- a/gui-clamp/ui-react/src/__snapshots__/OnapClamp.test.js.snap +++ b/gui-clamp/ui-react/src/__snapshots__/OnapClamp.test.js.snap @@ -119,13 +119,17 @@ exports[`Verify OnapClamp Test the render method 1`] = ` render={[Function]} /> <Route - path="/manageInstantiation" + path="/instantiationManagement" render={[Function]} /> <Route path="/editControlLoopInstanceProperties" render={[Function]} /> + <Route + path="/changeOrderState" + render={[Function]} + /> <div /> <div> <Alert diff --git a/gui-clamp/ui-react/src/api/ControlLoopService.js b/gui-clamp/ui-react/src/api/ControlLoopService.js index 0d6e11c..b3d987c 100644 --- a/gui-clamp/ui-react/src/api/ControlLoopService.js +++ b/gui-clamp/ui-react/src/api/ControlLoopService.js @@ -19,17 +19,18 @@ export default class ControlLoopService { - static async getControlLoopInstantiation(windowLocationPathname) { + static async getControlLoopInstantiation() { - const response = await fetch(windowLocationPathname + '/restservices/clds/v2/toscaControlLoop/getToscaInstantiation'); + const response = await fetch(window.location.pathname + + 'restservices/clds/v2/toscaControlLoop/getToscaInstantiation'); return response } - static async createInstanceProperties(instancePropertiesTemplate, windowLocationPathname) { + static async createInstanceProperties(instanceName, instancePropertiesTemplate) { - const response = await fetch(windowLocationPathname + - '/restservices/clds/v2/toscaControlLoop/postToscaInstanceProperties', { + const response = await fetch(window.location.pathname + + 'restservices/clds/v2/toscaControlLoop/postToscaInstanceProperties', { method: 'POST', headers: { "Content-Type": "application/json" @@ -41,16 +42,39 @@ export default class ControlLoopService { return response } - static async getInstanceOrderState(windowLocationPathName) { - const response = await fetch(windowLocationPathName + '/restservices/clds/v2/toscaControlLoop/getInstantiationOrderState'); + static async deleteInstantiation(name, version) { + const params = { + name: name, + version: version + } + + const response = await fetch(window.location.pathname + + 'restservices/clds/v2/toscaControlLoop/deleteToscaInstanceProperties?' + (new URLSearchParams(params)), { + method: 'DELETE', + credentials: 'same-origin', + }); + + const data = await response; + + return data; + } + + static async getInstanceOrderState(name, version) { + const params = { + name: name, + version: version + } + const response = await fetch(window.location.pathname + + 'restservices/clds/v2/toscaControlLoop/getInstantiationOrderState'+ '?' + (new URLSearchParams(params))); const data = await response; return data; } - static async changeInstanceOrderState(toscaObject, windowLocationPathName) { - const response = await fetch(windowLocationPathName + '/restservices/clds/v2/toscaControlLoop/putToscaInstantiationStateChange', { + static async changeInstanceOrderState(toscaObject) { + const response = await fetch(window.location.pathname + + 'restservices/clds/v2/toscaControlLoop/putToscaInstantiationStateChange', { method: 'PUT', headers: { "Content-Type": "application/json" @@ -62,23 +86,23 @@ export default class ControlLoopService { return response } - static async getToscaTemplate(name, version, windowLocationPathname) { + static async getToscaTemplate(name, version) { const params = { name: name, version: version } - const response = await fetch(windowLocationPathname + - '/restservices/clds/v2/toscaControlLoop/getToscaTemplate' + '?' + (new URLSearchParams(params))); + const response = await fetch(window.location.pathname + + 'restservices/clds/v2/toscaControlLoop/getToscaTemplate' + '?' + (new URLSearchParams(params))); const data = await response; return data; } - static async uploadToscaFile(toscaObject, windowLocationPathName) { - const response = await fetch(windowLocationPathName + - '/restservices/clds/v2/toscaControlLoop/commissionToscaTemplate', { + static async uploadToscaFile(toscaObject) { + const response = await fetch(window.location.pathname + + 'restservices/clds/v2/toscaControlLoop/commissionToscaTemplate', { method: 'POST', headers: { "Content-Type": "application/json" @@ -91,14 +115,14 @@ export default class ControlLoopService { } - static async deleteToscaTemplate(name, version, windowLocationPathname) { + static async deleteToscaTemplate(name, version) { const params = { name: name, version: version } - const response = await fetch(windowLocationPathname + - '/restservices/clds/v2/toscaControlLoop/decommissionToscaTemplate' + '?' + (new URLSearchParams(params)), + const response = await fetch(window.location.pathname + + 'restservices/clds/v2/toscaControlLoop/decommissionToscaTemplate' + '?' + (new URLSearchParams(params)), { method: 'DELETE' }); @@ -108,10 +132,10 @@ export default class ControlLoopService { return data; } - static async getToscaControlLoopDefinitions(windowLocationPathname) { + static async getToscaControlLoopDefinitions() { - const response = await fetch(windowLocationPathname + - '/restservices/clds/v2/toscaControlLoop/getElementDefinitions'); + const response = await fetch(window.location.pathname + + 'restservices/clds/v2/toscaControlLoop/getElementDefinitions'); this.checkResponseForError(response); @@ -120,27 +144,27 @@ export default class ControlLoopService { return data; } - static async getCommonOrInstanceProperties(name, version, windowLocationPathName, isCommon) { + static async getCommonOrInstanceProperties(name, version, isCommon) { const params = { name: name, version: version, common: isCommon } - const response = await fetch(windowLocationPathName + - '/restservices/clds/v2/toscaControlLoop/getCommonOrInstanceProperties' + '?' + (new URLSearchParams(params))); + const response = await fetch(window.location.pathname + + 'restservices/clds/v2/toscaControlLoop/getCommonOrInstanceProperties' + '?' + (new URLSearchParams(params))); return response; } - static async getToscaServiceTemplateSchema(section, windowLocationPathName) { + static async getToscaServiceTemplateSchema(section) { const params = { section: section } - const response = await fetch(windowLocationPathName + - '/restservices/clds/v2/toscaControlLoop/getJsonSchema' + '?' + (new URLSearchParams(params))); + const response = await fetch(window.location.pathname + + 'restservices/clds/v2/toscaControlLoop/getJsonSchema' + '?' + (new URLSearchParams(params))); this.checkResponseForError(response); diff --git a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/ChangeOrderStateModal.js b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/ChangeOrderStateModal.js new file mode 100644 index 0000000..d8efd3a --- /dev/null +++ b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/ChangeOrderStateModal.js @@ -0,0 +1,171 @@ +/* + * ============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========================================================= + */ + +import styled from "styled-components"; +import Modal from "react-bootstrap/Modal"; +import Button from "react-bootstrap/Button"; +import React, { useContext, useEffect, useRef, useState } from "react"; +import InstantiationOrderStateChangeItem from "./InstantiationOrderStateChangeItem"; +import ControlLoopService from "../../../api/ControlLoopService"; +import { Alert, Container, Dropdown } from "react-bootstrap"; + +const ModalStyled = styled(Modal)` + @media (min-width: 800px) { + .modal-xl { + max-width: 96%; + } + } + background-color: transparent; +` + +const DivWhiteSpaceStyled = styled.div` + overflow: auto; + min-width: 100%; + max-height: 300px; + padding: 5px 5px 0px 5px; + text-align: center; +` + +const AlertStyled = styled(Alert)` + margin-top: 10px; +` + +const ChangeOrderStateModal = (props) => { + const [show, setShow] = useState(true); + const [controlLoopIdentifierList, setControlLoopIdentifierList] = useState([]); + const [orderedState, setOrderedState] = useState(''); + const [toscaOrderStateObject, setToscaOrderStateObject] = useState({}); + const [instantiationOrderStateError, setInstantiationOrderStateError] = useState(false); + const [instantiationOrderStateMsgError, setInstantiationOrderStateMsgError] = useState({}); + const [alertMessage, setAlertMessage] = useState(null); + + useEffect(async () => { + + const instantiationOrderState = await ControlLoopService.getInstanceOrderState( + props.location.instantiationName, + props.location.instantiationVersion) + .catch(error => error.message); + + const orderStateJson = await instantiationOrderState.json(); + + console.log(orderStateJson); + + if (!instantiationOrderState.ok || orderStateJson['controlLoopIdentifierList'].length === 0) { + setInstantiationOrderStateError(true); + setInstantiationOrderStateMsgError(orderStateJson); + } else { + setControlLoopIdentifierList(orderStateJson['controlLoopIdentifierList']); + setOrderedState(orderStateJson['orderedState']); + } + }, []); + + const handleDropSelect = (event) => { + console.log("handleDropDownChange called"); + + const stateChangeObject = { + orderedState: event, + controlLoopIdentifierList: controlLoopIdentifierList + } + setToscaOrderStateObject(stateChangeObject); + setOrderedState(event); + } + + const handleSave = async () => { + console.log("handleSave called"); + + const response = await ControlLoopService.changeInstanceOrderState(toscaOrderStateObject) + .catch(error => error.message); + + if (response.ok) { + successAlert(); + } else { + await errorAlert(response); + } + } + + const handleClose = () => { + console.log('handleClose called'); + setShow(false); + props.history.push('/'); + } + + const successAlert = () => { + console.log("successAlert called"); + setAlertMessage(<Alert variant="success"> + <Alert.Heading>Order State Changed Success</Alert.Heading> + <p>Order State Changed was successfully changed</p> + <hr/> + </Alert>); + } + + const errorAlert = async (response) => { + console.log("errorAlert called"); + setAlertMessage(<Alert variant="danger"> + <Alert.Heading>Order State Changed Failure</Alert.Heading> + <p>An error occurred while trying to change order state</p> + <p>Status code: { await response.status } : { response.statusText }</p> + <p>Status Text: { await response.text() }</p> + <hr/> + </Alert>); + } + + return ( + <ModalStyled size="sm" + show={ show } + onHide={ handleClose } + backdrop="static" + keyboard={ false }> + <Modal.Header closeButton> + <Modal.Title>Manage Instantiation</Modal.Title> + </Modal.Header> + <div style={ { padding: '5px 5px 0 5px' } }> + <Modal.Body> + <Container> + <Dropdown onSelect={ handleDropSelect }> + <Dropdown.Toggle variant="dark" id="dropdown-basic"> + Select Order State + </Dropdown.Toggle> + <Dropdown.Menu> + <Dropdown.Item eventKey="UNINITIALISED">UNINITIALISED</Dropdown.Item> + <Dropdown.Item eventKey="PASSIVE">PASSIVE</Dropdown.Item> + <Dropdown.Item eventKey="RUNNING">RUNNING</Dropdown.Item> + </Dropdown.Menu> + </Dropdown> + { + controlLoopIdentifierList.map((clIdList, index) => ( + <InstantiationOrderStateChangeItem title={ clIdList.name } orderState={ orderedState } index={ index } key={ index }/> + )) + } + </Container> + <AlertStyled show={ instantiationOrderStateError } + variant="danger">Can't get instantiation ordered state:<br/>{ JSON.stringify(instantiationOrderStateMsgError, null, 2) }</AlertStyled> + </Modal.Body> + <DivWhiteSpaceStyled> + { alertMessage } + </DivWhiteSpaceStyled> + </div> + <Modal.Footer> + <Button variant="primary" onClick={ handleSave }>Save</Button> + <Button variant="secondary" onClick={ handleClose }>Close</Button> + </Modal.Footer> + </ModalStyled> + ); +} + +export default ChangeOrderStateModal; diff --git a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/CommissioningModal.js b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/CommissioningModal.js index 9a615d0..fc150ef 100644 --- a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/CommissioningModal.js +++ b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/CommissioningModal.js @@ -47,7 +47,6 @@ const AlertStyled = styled(Alert)` ` const CommissioningModal = (props) => { - const [windowLocationPathName, setWindowLocationPathName] = useState(''); const [fullToscaTemplate, setFullToscaTemplate] = useState({}); const [toscaInitialValues, setToscaInitialValues] = useState({}); const [commonProperties, setCommonProperties] = useState({}) @@ -62,9 +61,9 @@ const CommissioningModal = (props) => { let editorTemp = null useEffect(async () => { - const toscaTemplateResponse = await ControlLoopService.getToscaTemplate(name, version, windowLocationPathName) + const toscaTemplateResponse = await ControlLoopService.getToscaTemplate(name, version) .catch(error => error.message); - const toscaCommonProperties = await ControlLoopService.getCommonOrInstanceProperties(name, version, windowLocationPathName, true) + const toscaCommonProperties = await ControlLoopService.getCommonOrInstanceProperties(name, version, true) .catch(error => error.message); if (!toscaCommonProperties.ok) { @@ -100,12 +99,11 @@ const CommissioningModal = (props) => { const handleCommission = async () => { - setWindowLocationPathName(window.location.pathname); - await ControlLoopService.deleteToscaTemplate('ToscaServiceTemplateSimple', "1.0.0", windowLocationPathName) + await ControlLoopService.deleteToscaTemplate('ToscaServiceTemplateSimple', "1.0.0") .catch(error => error.message) - const recommissioningResponse = await ControlLoopService.uploadToscaFile(fullToscaTemplate, windowLocationPathName) + const recommissioningResponse = await ControlLoopService.uploadToscaFile(fullToscaTemplate) .catch(error => error.message) await receiveResponseFromCommissioning(recommissioningResponse) diff --git a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/DeleteToscaTemplate.js b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/DeleteToscaTemplate.js index c641272..7968fe2 100644 --- a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/DeleteToscaTemplate.js +++ b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/DeleteToscaTemplate.js @@ -24,13 +24,10 @@ import ControlLoopService from "../../../api/ControlLoopService"; const DeleteToscaTemplate = props => { - const [windowLocationPathName, setWindowLocationPathname] = useState(''); - const deleteTemplateHandler = async () => { console.log('deleteTemplateHandler called'); - setWindowLocationPathname(window.location.pathname); - const response = await ControlLoopService.deleteToscaTemplate(props.templateName, props.templateVersion, windowLocationPathName) + const response = await ControlLoopService.deleteToscaTemplate(props.templateName, props.templateVersion) .catch(error => error.message); console.log('Response is ok: ' + response.ok); diff --git a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/GetToscaTemplate.js b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/GetToscaTemplate.js index 273957f..ba78b80 100644 --- a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/GetToscaTemplate.js +++ b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/GetToscaTemplate.js @@ -23,13 +23,10 @@ import ControlLoopService from "../../../api/ControlLoopService"; const GetToscaTemplate = (props) => { - const [windowLocationPathName, setWindowLocationPathname] = useState(''); - const getTemplateHandler = async () => { console.log('getTemplateHandler called') - setWindowLocationPathname(window.location.pathname); - const response = await ControlLoopService.getToscaTemplate(props.templateName, props.templateVersion, windowLocationPathName) + const response = await ControlLoopService.getToscaTemplate(props.templateName, props.templateVersion) .catch(error => error.message); props.onGetToscaServiceTemplate(response); diff --git a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/InstanceModal.js b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/InstancePropertiesModal.js index 0380fa6..8ad855e 100644 --- a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/InstanceModal.js +++ b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/InstancePropertiesModal.js @@ -24,6 +24,9 @@ import Button from "react-bootstrap/Button"; import ControlLoopService from "../../../api/ControlLoopService"; import { JSONEditor } from "@json-editor/json-editor"; import Alert from "react-bootstrap/Alert"; +import * as PropTypes from "prop-types"; +import Form from "react-bootstrap/Form"; +import Spinner from "react-bootstrap/Spinner"; const ModalStyled = styled(Modal)` @media (min-width: 800px) { @@ -50,22 +53,28 @@ const templateName = "ToscaServiceTemplateSimple"; const templateVersion = "1.0.0"; let tempJsonEditor = null; -const InstanceModal = (props) => { +function Fragment(props) { + return null; +} + +Fragment.propTypes = { children: PropTypes.node }; +const InstancePropertiesModal = (props) => { const [show, setShow] = useState(true); - const [windowLocationPathname, setWindowLocationPathname] = useState(''); const [toscaFullTemplate, setToscaFullTemplate] = useState({}); - const [toscaFilteredInitialValues, setToscaFilteredInitialValues] = useState({}); - const [toscaJsonSchema, setToscaJsonSchema] = useState({}); const [jsonEditor, setJsonEditor] = useState(null); const [alertMessage, setAlertMessage] = useState(null); const [instancePropertiesGlobal, setInstancePropertiesGlobal] = useState({}); const [serviceTemplateResponseOk, setServiceTemplateResponseOk] = useState(true); const [instancePropertiesResponseOk, setInstancePropertiesResponseOk] = useState(true); + const [instanceName, setInstanceName] = useState('') + const [isLoading, setIsLoading] = useState(true); useEffect(async () => { - const toscaInstanceProperties = await ControlLoopService.getCommonOrInstanceProperties(templateName, templateVersion, windowLocationPathname, false).catch(error => error.message); + const toscaInstanceProperties = await ControlLoopService.getCommonOrInstanceProperties(templateName, templateVersion, false) + .catch(error => error.message); - const toscaTemplateResponse = await ControlLoopService.getToscaTemplate(templateName, templateVersion, windowLocationPathname).catch(error => error.message); + const toscaTemplateResponse = await ControlLoopService.getToscaTemplate(templateName, templateVersion) + .catch(error => error.message); if (!toscaInstanceProperties.ok) { const errorResponse = await toscaInstanceProperties.json() @@ -92,6 +101,8 @@ const InstanceModal = (props) => { const fullJsonSchemaTemplate = await fullTemplate.json(); setToscaFullTemplate(fullJsonSchemaTemplate); + console.log(fullJsonSchemaTemplate); + const filteredInitialStartValues = {}; const instanceProperties = await initialProperties.json().then(properties => { @@ -115,13 +126,10 @@ const InstanceModal = (props) => { filteredInitialStartValues[key] = propValues; }); - setToscaFilteredInitialValues(filteredInitialStartValues); - return filteredTemplateObj; }); const propertySchema = makeSchemaForInstanceProperties(instanceProperties); - setToscaJsonSchema(propertySchema); tempJsonEditor = createJsonEditor(propertySchema, filteredInitialStartValues); setJsonEditor(tempJsonEditor); @@ -159,6 +167,8 @@ const InstanceModal = (props) => { const getType = (pType) => { switch (pType) { + case "map": + return "string"; case "string": return "string"; case "integer": @@ -174,6 +184,8 @@ const InstanceModal = (props) => { } const createJsonEditor = (fullSchema, instanceProperties) => { + console.log(props.location.instanceName) + setIsLoading(false) JSONEditor.defaults.options.collapse = true; return new JSONEditor(document.getElementById("editor"), @@ -225,11 +237,12 @@ const InstanceModal = (props) => { const handleSave = async () => { console.log("handleSave called") - setWindowLocationPathname(window.location.pathname); + console.log("instanceName to be saved is: " + instanceName) updateTemplate(jsonEditor.getValue()); - const response = await ControlLoopService.createInstanceProperties(toscaFullTemplate, windowLocationPathname).catch(error => error.message); + const response = await ControlLoopService.createInstanceProperties(instanceName, toscaFullTemplate) + .catch(error => error.message); if (response.ok) { successAlert(); @@ -238,6 +251,10 @@ const InstanceModal = (props) => { } } + const handleNameChange = (e) => { + setInstanceName(e.target.value) + } + const successAlert = () => { console.log("successAlert called"); setAlertMessage(<Alert variant="success"> @@ -265,7 +282,7 @@ const InstanceModal = (props) => { backdrop="static" keyboard={ false }> <Modal.Header closeButton> - <Modal.Title>Change Tosca Instance Properties</Modal.Title> + <Modal.Title>Create Tosca Instance Properties</Modal.Title> </Modal.Header> <div style={ { padding: '5px 5px 0 5px' } }> <Modal.Body> @@ -287,4 +304,4 @@ const InstanceModal = (props) => { ); } -export default InstanceModal; +export default InstancePropertiesModal; diff --git a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/InstanceModal.test.js b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/InstancePropertiesModal.test.js index 36a77d7..141999c 100644 --- a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/InstanceModal.test.js +++ b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/InstancePropertiesModal.test.js @@ -19,36 +19,35 @@ import { mount, shallow } from "enzyme"; import React from "react"; -import InstanceModal from "./InstanceModal"; +import InstancePropertiesModal from "./InstancePropertiesModal"; import toJson from "enzyme-to-json"; import { createMemoryHistory } from "history"; -import MonitorInstantiation from "./MonitorInstantiation"; import { act } from "react-dom/test-utils"; describe('Verify MonitoringInstantiation', () => { it("renders without crashing", () => { - shallow(<InstanceModal />); + shallow(<InstancePropertiesModal />); }); it("renders correctly", () => { - const tree = shallow(<InstanceModal />); + const tree = shallow(<InstancePropertiesModal />); expect(toJson(tree)).toMatchSnapshot(); }); it('should have submit button element', () => { - const container = shallow(<InstanceModal/>) + const container = shallow(<InstancePropertiesModal/>) expect(container.find('[variant="primary"]').length).toEqual(1); }); it('should have close button element', () => { - const container = shallow(<InstanceModal/>) + const container = shallow(<InstancePropertiesModal/>) expect(container.find('[variant="secondary"]').length).toEqual(1); }); it('handleCreateUpdateToscaInstanceProperties called when submit button clicked', () => { const history = createMemoryHistory(); - const component = mount(<InstanceModal />) + const component = mount(<InstancePropertiesModal />) const logSpy = jest.spyOn(console, 'log'); act(() => { @@ -59,7 +58,7 @@ describe('Verify MonitoringInstantiation', () => { it('handleClose called when close button clicked', () => { const history = createMemoryHistory(); - const component = mount(<InstanceModal history={ history }/>) + const component = mount(<InstancePropertiesModal history={ history }/>) const logSpy = jest.spyOn(console, 'log'); act(() => { diff --git a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/InstantiationManagementModal.js b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/InstantiationManagementModal.js index c6c1eb9..6a435e4 100644 --- a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/InstantiationManagementModal.js +++ b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/InstantiationManagementModal.js @@ -15,25 +15,28 @@ * * SPDX-License-Identifier: Apache-2.0 * ============LICENSE_END========================================================= + * + * */ -import styled from "styled-components"; import Modal from "react-bootstrap/Modal"; +import { Alert, Container, Dropdown, Table } from "react-bootstrap"; import Button from "react-bootstrap/Button"; -import React, { useContext, useEffect, useRef, useState } from "react"; -import InstantiationOrderStateChangeItem from "./InstantiationOrderStateChangeItem"; +import React, { useEffect, useState } from "react"; +import styled from "styled-components"; +import { Link } from "react-router-dom"; import ControlLoopService from "../../../api/ControlLoopService"; -import { Alert, Container, Dropdown } from "react-bootstrap"; +import Row from "react-bootstrap/Row"; const ModalStyled = styled(Modal)` - @media (min-width: 800px) { - .modal-xl { - max-width: 96%; - } - } background-color: transparent; ` +const HorizontalSpace = styled.div` + padding-right: 2px; + padding-left: 2px; +`; + const DivWhiteSpaceStyled = styled.div` overflow: auto; min-width: 100%; @@ -41,55 +44,48 @@ const DivWhiteSpaceStyled = styled.div` padding: 5px 5px 0px 5px; text-align: center; ` - -const AlertStyled = styled(Alert)` - margin-top: 10px; -` - const InstantiationManagementModal = (props) => { const [show, setShow] = useState(true); - const [windowLocationPathnameGet, setWindowLocationPathnameGet] = useState(''); - const [windowLocationPathNameSave, setWindowLocationPathNameSave] = useState(''); - const [controlLoopIdentifierList, setControlLoopIdentifierList] = useState([]); - const [orderedState, setOrderedState] = useState(''); - const [toscaOrderStateObject, setToscaOrderStateObject] = useState({}); - const [instantiationOrderStateOk, setInstantiationOrderStateOk] = useState(true); - const [instantiationOrderStateError, setInstantiationOrderStateError] = useState({}); + const [instantiationList, setInstantiationList] = useState([]); const [alertMessage, setAlertMessage] = useState(null); useEffect(async () => { - setWindowLocationPathnameGet(window.location.pathname); - const instantiationOrderState = await ControlLoopService.getInstanceOrderState(windowLocationPathnameGet) - .catch(error => error.message); + const response = await ControlLoopService.getControlLoopInstantiation(); - const orderStateJson = await instantiationOrderState.json(); + const instantiationListJson = await response.json(); - if (!instantiationOrderState.ok || orderStateJson['controlLoopIdentifierList'].length === 0) { - setInstantiationOrderStateOk(true); - setInstantiationOrderStateError(orderStateJson); - } else { - setControlLoopIdentifierList(orderStateJson['controlLoopIdentifierList']); - setOrderedState(orderStateJson['orderedState']); - } - }, []); + const parsedInstantiationList = instantiationListJson['controlLoopList'].map((instance, index) => { + return { + index: index, + name: instance['name'], + version: instance['version'], + orderedState: instance['orderedState'], + currentState: instance['state'], + disableDelete: instance['state'] !== 'UNINITIALISED' + } + }); - const handleDropSelect = (event) => { - console.log("handleDropDownChange called"); + setInstantiationList(parsedInstantiationList); + }, []); - const stateChangeObject = { - orderedState: event, - controlLoopIdentifierList: controlLoopIdentifierList + const getBackgroundColor = (index) => { + if (index % 2 === 0) { + return 'Silver'; } - setToscaOrderStateObject(stateChangeObject); - orderStateContext.orderState = stateChangeObject; + + return 'White'; } - const handleSave = async () => { - console.log("handleSave called"); - setWindowLocationPathNameSave(window.location.pathname); + const deleteInstantiationHandler = async (instantiation, index) => { + console.log("deleteInstantiationHandler called"); + + const name = instantiation.name; + const version = instantiation.version; - const response = await ControlLoopService.changeInstanceOrderState(toscaOrderStateObject, windowLocationPathNameSave).catch(error => error.message); + const response = await ControlLoopService.deleteInstantiation(name, version); + + updateList(index); if (response.ok) { successAlert(); @@ -98,8 +94,34 @@ const InstantiationManagementModal = (props) => { } } + const updateList = (index) => { + console.log("updateList called") + console.log(instantiationList) + + const updatedList = [...instantiationList]; + updatedList.splice(index, 1); + + setInstantiationList(updatedList); + } + + const renderDeleteButton = (instantiation, index) => { + if (instantiation.disableDelete) { + return ( + <Button variant="outline-danger" type="null" + disabled={ true } + style={ { cursor: "not-allowed" } }>Delete</Button> + ); + + } else { + return ( + <Button variant="danger" type="null" + onClick={ async () => deleteInstantiationHandler(instantiation, index) }>Delete</Button> + ); + } + } + const handleClose = () => { - console.log('handleClose called'); + console.log("handleClose called"); setShow(false); props.history.push('/'); } @@ -107,8 +129,8 @@ const InstantiationManagementModal = (props) => { const successAlert = () => { console.log("successAlert called"); setAlertMessage(<Alert variant="success"> - <Alert.Heading>Order State Changed Success</Alert.Heading> - <p>Order State Changed was successfully changed</p> + <Alert.Heading>Deletion of Instantiation Success</Alert.Heading> + <p>Deletion of Instantiation was successful!</p> <hr/> </Alert>); } @@ -116,52 +138,93 @@ const InstantiationManagementModal = (props) => { const errorAlert = async (response) => { console.log("errorAlert called"); setAlertMessage(<Alert variant="danger"> - <Alert.Heading>Order State Changed Failure</Alert.Heading> - <p>An error occurred while trying to change order state</p> + <Alert.Heading>Deletion of Instantiation Failure</Alert.Heading> + <p>An error occurred while trying to delete instantiation</p> <p>Status code: { await response.status } : { response.statusText }</p> <p>Status Text: { await response.text() }</p> <hr/> </Alert>); } + const clearErrors = () => { + console.log("clearErrors called"); + setAlertMessage(null); + } + return ( - <ModalStyled size="sm" + <ModalStyled size="xl" show={ show } onHide={ handleClose } backdrop="static" keyboard={ false }> <Modal.Header closeButton> - <Modal.Title>Manage Instantiation</Modal.Title> + <Modal.Title>Manage Instances</Modal.Title> </Modal.Header> - <div style={ { padding: '5px 5px 0 5px' } }> - <Modal.Body> - <Container> - <Dropdown onSelect={ handleDropSelect }> - <Dropdown.Toggle variant="dark" id="dropdown-basic"> - Select Order State - </Dropdown.Toggle> - <Dropdown.Menu> - <Dropdown.Item eventKey="UNINITIALISED">UNINITIALISED</Dropdown.Item> - <Dropdown.Item eventKey="PASSIVE">PASSIVE</Dropdown.Item> - <Dropdown.Item eventKey="RUNNING">RUNNING</Dropdown.Item> - </Dropdown.Menu> - </Dropdown> - { - controlLoopIdentifierList.map((clIdList, index) => ( - <InstantiationOrderStateChangeItem title={ clIdList.name } index={ index } key={ index } /> - )) - } - </Container> - <AlertStyled show={ !instantiationOrderStateOk } - variant="danger">Can't get instantiation ordered state:<br/>{ JSON.stringify(instantiationOrderStateError, null, 2) }</AlertStyled> - </Modal.Body> + <Modal.Body> + <Container> + <Row> + <Link to={ { pathname: "/editControlLoopInstanceProperties" } }> + <Button variant="primary" type="null">Create Instance</Button> + </Link> + <HorizontalSpace/> + <Link to={ { pathname: "/monitorInstantiation" } }> + <Button variant="secondary" type="null">Monitor Instantiations</Button> + </Link> + </Row> + </Container> + <Table bordered style={ { marginTop: '10px' } }> + <thead> + <tr> + <th>#</th> + <th style={ { textAlign: "center" } }>Instantiation Name</th> + <th style={ { textAlign: "center" } }>Edit Instantiation</th> + <th style={ { textAlign: "center" } }>Delete Instantiation</th> + <th style={ { textAlign: "center" } }>Change Order State</th> + <th style={ { textAlign: "center" } }>Instantiation Order State</th> + <th style={ { textAlign: "center" } }>Instantiation Current State</th> + </tr> + </thead> + <tbody> + { instantiationList.map((instantiation, index) => { + return ( + <tr style={ { backgroundColor: getBackgroundColor(index) } } key={ index } className="instantiationList"> + <td>{ index + 1 }</td> + <td>{ instantiation.name }</td> + <td style={ { textAlign: "center" } }> + <Link to={ { + pathname: "editControlLoopInstanceProperties", + } } state={ instantiation.name }> + <Button variant="outline-success" type="null" + disabled={ true } + style={ { cursor: "not-allowed" } }>Edit</Button> + </Link> + </td> + <td style={ { textAlign: "center" } }> + { renderDeleteButton(instantiation, index) } + </td> + <td style={ { textAlign: "center" } }> + <Link to={ { + pathname: "changeOrderState", + instantiationName: instantiation.name, + instantiationVersion: instantiation.version + } }> + <Button variant="secondary" type="null">Change</Button> + </Link> + </td> + <td>{ instantiation.orderedState }</td> + <td>{ instantiation.currentState }</td> + </tr> + ) + }) } + </tbody> + </Table> <DivWhiteSpaceStyled> { alertMessage } </DivWhiteSpaceStyled> - </div> + </Modal.Body> <Modal.Footer> - <Button variant="primary" onClick={ handleSave }>Save</Button> - <Button variant="secondary" onClick={ handleClose }>Close</Button> + <Button variant="secondary" type="null" onClick={ clearErrors }>Clear Error Message</Button> + <Button variant="secondary" type="null" onClick={ handleClose }>Close</Button> </Modal.Footer> </ModalStyled> ); diff --git a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/MonitorInstantiation.js b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/MonitorInstantiation.js index 6c589b8..dad4185 100644 --- a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/MonitorInstantiation.js +++ b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/MonitorInstantiation.js @@ -36,14 +36,11 @@ const AlertStyled = styled(Alert)` const MonitorInstantiation = (props) => { const [show, setShow] = useState(true); const [controlLoopList, setControlLoopList] = useState([]); - const [windowLocationPathname, setWindowLocationPathname] = useState(''); const [controlLoopInstantiationOk, setControlLoopInstantiationOk] = useState(true); const [controlLoopInstantiationError, setControlLoopInstantiationError] = useState({}); useEffect(async () => { - setWindowLocationPathname(window.location.pathname); - - const controlLoopInstantiation = await ControlLoopService.getControlLoopInstantiation(windowLocationPathname) + const controlLoopInstantiation = await ControlLoopService.getControlLoopInstantiation() .catch(error => error.message); const controlLoopInstantiationJson = await controlLoopInstantiation.json() diff --git a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/UploadToscaFile.js b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/UploadToscaFile.js index 6ee6a43..380838e 100644 --- a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/UploadToscaFile.js +++ b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/UploadToscaFile.js @@ -22,14 +22,12 @@ import React, { useState } from "react"; import ControlLoopService from "../../../api/ControlLoopService"; const UploadToscaFile = (props) => { - const [windowLocationPathName, setWindowLocationPathname] = useState(''); const postServiceTemplateHandler = async (event) => { event.preventDefault(); console.log('postServiceTemplateHandler called'); - setWindowLocationPathname(window.location.pathname); - const response = await ControlLoopService.uploadToscaFile(props.toscaObject, windowLocationPathName) + const response = await ControlLoopService.uploadToscaFile(props.toscaObject) .catch(error => error.message); // const responseMessage = await response.text(); diff --git a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/__snapshots__/InstanceModal.test.js.snap b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/__snapshots__/InstancePropertiesModal.test.js.snap index ba7caf9..96b500e 100644 --- a/gui-clamp/ui-react/src/components/dialogs/ControlLoop/__snapshots__/InstanceModal.test.js.snap +++ b/gui-clamp/ui-react/src/components/dialogs/ControlLoop/__snapshots__/InstancePropertiesModal.test.js.snap @@ -13,7 +13,7 @@ exports[`Verify MonitoringInstantiation renders correctly 1`] = ` closeLabel="Close" > <ModalTitle> - Change Tosca Instance Properties + Create Tosca Instance Properties </ModalTitle> </ModalHeader> <div diff --git a/gui-clamp/ui-react/src/components/dialogs/InstantiationManagementModal.test.js b/gui-clamp/ui-react/src/components/dialogs/InstantiationManagementModal.test.js index 61f8c1a..25292d0 100644 --- a/gui-clamp/ui-react/src/components/dialogs/InstantiationManagementModal.test.js +++ b/gui-clamp/ui-react/src/components/dialogs/InstantiationManagementModal.test.js @@ -22,27 +22,27 @@ import React from "react"; import toJson from "enzyme-to-json"; import { createMemoryHistory } from "history"; import { act } from "react-dom/test-utils"; -import InstantiationManagementModal from "./ControlLoop/InstantiationManagementModal"; +import ChangeOrderStateModal from "./ControlLoop/ChangeOrderStateModal"; describe('Verify InstantiationManagementModal', () => { it("renders without crashing", () => { - shallow(<InstantiationManagementModal />); + shallow(<ChangeOrderStateModal />); }); it("renders correctly", () => { - const tree = shallow(<InstantiationManagementModal />); + const tree = shallow(<ChangeOrderStateModal />); expect(toJson(tree)).toMatchSnapshot(); }); it('should have save button element', () => { - const container = shallow(<InstantiationManagementModal/>) + const container = shallow(<ChangeOrderStateModal/>) expect(container.find('[variant="primary"]').length).toEqual(1); }); it('handleSave called when save button clicked', () => { const history = createMemoryHistory(); - const component = mount(<InstantiationManagementModal history={ history }/>) + const component = mount(<ChangeOrderStateModal history={ history }/>) const logSpy = jest.spyOn(console, 'log'); act(() => { @@ -52,13 +52,13 @@ describe('Verify InstantiationManagementModal', () => { }); it('should have close button element', () => { - const container = shallow(<InstantiationManagementModal/>) + const container = shallow(<ChangeOrderStateModal/>) expect(container.find('[variant="secondary"]').length).toEqual(1); }); it('handleClose called when close button clicked', () => { const history = createMemoryHistory(); - const component = mount(<InstantiationManagementModal history={ history }/>) + const component = mount(<ChangeOrderStateModal history={ history }/>) const logSpy = jest.spyOn(console, 'log'); act(() => { diff --git a/gui-clamp/ui-react/src/components/menu/MenuBar.js b/gui-clamp/ui-react/src/components/menu/MenuBar.js index 99480a9..59cff22 100644 --- a/gui-clamp/ui-react/src/components/menu/MenuBar.js +++ b/gui-clamp/ui-react/src/components/menu/MenuBar.js @@ -115,9 +115,7 @@ export default class MenuBar extends React.Component { </StyledNavDropdown> <StyledNavDropdown title="TOSCA Control Loop"> <NavDropdown.Header>Instantiation</NavDropdown.Header> - <NavDropdown.Item as={ StyledLink } to="/monitorInstantiation">Monitor Instantiation</NavDropdown.Item> - <NavDropdown.Item as={ StyledLink } to="/manageInstantiation">Manage Instantiation</NavDropdown.Item> - <NavDropdown.Item as={ StyledLink } to="/editControlLoopInstanceProperties">Edit Control Loop Instance Properties</NavDropdown.Item> + <NavDropdown.Item as={ StyledLink } to="/instantiationManagement">Instantiation Management</NavDropdown.Item> <NavDropdown.Divider/> <NavDropdown.Header>Commissioning</NavDropdown.Header> <NavDropdown.Item as={ StyledLink } to="/readToscaTemplate">Manage Commissioned Tosca Template</NavDropdown.Item> diff --git a/gui-clamp/ui-react/src/components/menu/__snapshots__/MenuBar.test.js.snap b/gui-clamp/ui-react/src/components/menu/__snapshots__/MenuBar.test.js.snap index 36132ff..dbae793 100644 --- a/gui-clamp/ui-react/src/components/menu/__snapshots__/MenuBar.test.js.snap +++ b/gui-clamp/ui-react/src/components/menu/__snapshots__/MenuBar.test.js.snap @@ -1071,139 +1071,9 @@ exports[`Verify MenuBar Test the render method 1`] = ` } } disabled={false} - to="/monitorInstantiation" + to="/instantiationManagement" > - Monitor Instantiation - </DropdownItem> - <DropdownItem - as={ - Object { - "$$typeof": Symbol(react.forward_ref), - "attrs": Array [], - "componentStyle": e { - "baseHash": -715527839, - "baseStyle": undefined, - "componentId": "sc-bdnxRM", - "isStatic": false, - "rules": Array [ - " - color: ", - [Function], - "; - background-color: ", - [Function], - "; - font-weight: normal; - display: block; - width: 100%; - padding: .25rem 1.5rem; - clear: both; - text-align: inherit; - white-space: nowrap; - border: 0; - - :hover { - text-decoration: none; - background-color: ", - [Function], - "; - color: ", - [Function], - "; - } -", - ], - "staticRulesId": "", - }, - "foldedComponentIds": Array [], - "render": [Function], - "shouldForwardProp": undefined, - "styledComponentId": "sc-bdnxRM", - "target": Object { - "$$typeof": Symbol(react.forward_ref), - "propTypes": Object { - "innerRef": [Function], - "onClick": [Function], - "replace": [Function], - "target": [Function], - "to": [Function], - }, - "render": [Function], - }, - "toString": [Function], - "warnTooManyClasses": [Function], - "withComponent": [Function], - } - } - disabled={false} - to="/manageInstantiation" - > - Manage Instantiation - </DropdownItem> - <DropdownItem - as={ - Object { - "$$typeof": Symbol(react.forward_ref), - "attrs": Array [], - "componentStyle": e { - "baseHash": -715527839, - "baseStyle": undefined, - "componentId": "sc-bdnxRM", - "isStatic": false, - "rules": Array [ - " - color: ", - [Function], - "; - background-color: ", - [Function], - "; - font-weight: normal; - display: block; - width: 100%; - padding: .25rem 1.5rem; - clear: both; - text-align: inherit; - white-space: nowrap; - border: 0; - - :hover { - text-decoration: none; - background-color: ", - [Function], - "; - color: ", - [Function], - "; - } -", - ], - "staticRulesId": "", - }, - "foldedComponentIds": Array [], - "render": [Function], - "shouldForwardProp": undefined, - "styledComponentId": "sc-bdnxRM", - "target": Object { - "$$typeof": Symbol(react.forward_ref), - "propTypes": Object { - "innerRef": [Function], - "onClick": [Function], - "replace": [Function], - "target": [Function], - "to": [Function], - }, - "render": [Function], - }, - "toString": [Function], - "warnTooManyClasses": [Function], - "withComponent": [Function], - } - } - disabled={false} - to="/editControlLoopInstanceProperties" - > - Edit Control Loop Instance Properties + Instantiation Management </DropdownItem> <DropdownDivider role="separator" diff --git a/packages/policy-gui-docker/src/main/docker/Dockerfile b/packages/policy-gui-docker/src/main/docker/Dockerfile index 8820139..0e8bcc2 100644 --- a/packages/policy-gui-docker/src/main/docker/Dockerfile +++ b/packages/policy-gui-docker/src/main/docker/Dockerfile @@ -26,30 +26,23 @@ ARG POLICY_LOGS=/var/log/onap/policy/gui ENV POLICY_LOGS=$POLICY_LOGS ENV POLICY_HOME=$POLICY_HOME/gui -ENV CLAMP_REST_URL=http://0.0.0.0 RUN mkdir -p $POLICY_HOME $POLICY_LOGS $POLICY_HOME/bin $POLICY_HOME/lib && \ chown -R policy:policy $POLICY_HOME $POLICY_LOGS && \ apk update && \ - apk add --no-cache gettext nginx + apk add --no-cache nginx -WORKDIR $POLICY_HOME -COPY policy-gui.sh ./bin/ -COPY /maven/gui-editor-apex-uber.jar ./lib/ -COPY /maven/gui-pdp-monitoring-uber.jar ./lib/ -COPY nginx/nginx.conf /etc/nginx/nginx.conf -COPY nginx/default.conf.template /etc/nginx/templates/default.conf.template -COPY nginx/index.html /usr/share/nginx/html/ -ADD /maven/gui-clamp-html.tar.gz /usr/share/nginx/html/ -ADD /maven/gui-pdp-monitoring-html.tar.gz /usr/share/nginx/html/ -RUN rm /etc/nginx/conf.d/default.conf && \ - ln -sf /dev/stdout /var/log/nginx/access.log && \ +COPY --chown=policy:policy etc/ /etc/ +COPY --chown=policy:policy policy-gui.sh $POLICY_HOME/bin/ +COPY --chown=policy:policy /maven/*.jar $POLICY_HOME/lib/ +ADD --chown=policy:policy index.html /maven/*-html.tar.gz /usr/share/nginx/html/ +RUN ln -sf /dev/stdout /var/log/nginx/access.log && \ ln -sf /dev/stderr /var/log/nginx/error.log && \ touch /var/run/nginx.pid && \ - chown -R policy:policy . /etc/nginx /usr/share/nginx /var/lib/nginx /var/log/nginx /var/run/nginx.pid && \ - chmod 755 bin/*.sh + chown -R policy:policy /etc/nginx /usr/share/nginx /var/lib/nginx /var/log/nginx /var/run/nginx.pid && \ + chmod 755 $POLICY_HOME/bin/*.sh USER policy WORKDIR $POLICY_HOME/bin ENTRYPOINT [ "./policy-gui.sh" ] -EXPOSE 8080 +EXPOSE 2443 diff --git a/packages/policy-gui-docker/src/main/docker/nginx/default.conf.template b/packages/policy-gui-docker/src/main/docker/etc/nginx/http.d/default.conf index d407827..2c589c4 100644 --- a/packages/policy-gui-docker/src/main/docker/nginx/default.conf.template +++ b/packages/policy-gui-docker/src/main/docker/etc/nginx/http.d/default.conf @@ -1,5 +1,9 @@ server { - listen 8080; + listen 2443 default ssl; + ssl_protocols TLSv1.2; + ssl_certificate /etc/ssl/clamp.pem; + ssl_certificate_key /etc/ssl/clamp.key; + ssl_verify_client optional_no_ca; location / { root /usr/share/nginx/html; @@ -8,7 +12,8 @@ server { } location /clamp/restservices/clds/ { - proxy_pass ${CLAMP_REST_URL}/restservices/clds/; + proxy_pass https://policy-clamp-backend:8443/restservices/clds/; + proxy_set_header X-SSL-Cert $ssl_client_escaped_cert; } location /pdp-monitoring/papservices/monitoring/ { diff --git a/packages/policy-gui-docker/src/main/docker/nginx/nginx.conf b/packages/policy-gui-docker/src/main/docker/etc/nginx/nginx.conf index aac9bb6..aac9bb6 100644 --- a/packages/policy-gui-docker/src/main/docker/nginx/nginx.conf +++ b/packages/policy-gui-docker/src/main/docker/etc/nginx/nginx.conf diff --git a/packages/policy-gui-docker/src/main/docker/etc/ssl/clamp.key b/packages/policy-gui-docker/src/main/docker/etc/ssl/clamp.key new file mode 100644 index 0000000..bcbb9f1 --- /dev/null +++ b/packages/policy-gui-docker/src/main/docker/etc/ssl/clamp.key @@ -0,0 +1,32 @@ +Bag Attributes + friendlyName: clamp@clamp.onap.org + localKeyID: 54 69 6D 65 20 31 35 38 30 38 32 39 30 36 35 34 37 39 +Key Attributes: <No Attributes> +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCTB30nMh0hczIk +vWJo7Omg7cAHhz50NBhLB7u+60oXRGCya4SqssqqxNnNqNQQP9MmflW2q/bZepWn +8Rk23X6CLmoIUlrj8BMPkUCRqzgvlaWPSNAK5QcOp6GUvXTuX4EsaWxJhbs9Ujz2 ++qi137iNOqfAx1sUygah1kjALrqHkXDqJGvIfxU5ES0akBi/lB7A3WpE52KTioSF +JS5Kbnpj1ogffGNKyAiNqU61LcF1FjWmINat2z3ZMk/3Xm+HCDg/GLPnbh4E1KoE +10O22AMys6YGEyPvgRfrTF13DsDX52PmmUHbkSB6kwS/CeV5Uu++8b6T2IWpPyZ2 ++5ptmL+tAgMBAAECggEBAIUplzRUswWEq7mSvPqC9+YE7pLi7rGYLRhnXKdBuszv +5RQzROjFHcEkoI8fhVFiPP70FPVpMh0uZTTBrDCA0v9cwjPfQuqGmPzUdUJ5bF3M +jzICpEn5vDaNpE5ueOUcIoXyxVyhfj+/p++YfgybHy7qHN0AsYFWqEMTLLjCmbYF +pZozbAcGQoAR8PSfwuvgusuEezrhYertHsdFwlfZhDtJvnm/4YKRUVEBzuaaA7B9 +sUhnQFS8ScqiUbkAGdjfY9wOYRHnQgjtqiP8poIzLkqCNSoVctgh5Pdv4jp4HO90 +J5QC+f7m7rOoWUw8EYbRo/4C4Mckh0GQQ+oP4xzrtZECgYEA3DYALFgOEY+0RR1K +61HAKqdNy1YbeuidpCBEJEwmIbzdgO1DcJdNznbfdRlmS7VB9orwRfNbf7Hxm2w/ +/xn9USENXWx7fvDoISqSDegvEsBSq5hSEMVl3f7CfQZrYl1f6gxfe7L/jtmbn0eQ +avsr9RaUCWP794DEXKuA9pC8hVsCgYEAquy5I4hO4jNBQ6v5+omjsEgk4513/RNs +f47Md8bsDHKJMbCMKCdqM1D3J1xbgV3DgSv0yNlKdU2wenWdgQAyBtz18NBgno85 +YNanFhp1CymgLFHdLJHSOqAkzutSuCNnGTT6AKspOQvy+cuj7XsnbsxtYK3Cgw5h +Mom3RnUy9ZcCgYAnForHVEYDBgAYuI9g39z9dT8Q1dMA6SN6S6Ps0Xt/R5gF15e9 +941/FYiqr3yB+cWgrp7hu8XFD9/0F63waTuW2AgYSjZNnROHN5g/UbRxXqQOA3al +tXRUiHEbYjVTe4GX+ORF/8rvH19JUZmn87ekxII4fH/wOfIhBOxaV+yuuwKBgHtz +5Tizz/3y9TWSdkgtt6uwP+yipLKGn/v1wNrWM1G+PDdGg8TQyxTrasfkHjdu6LFY +dUHIJ85X4ZphbvRolrl8SKq5Zr+/RLsb7qy5SUZZt1Wrfysc25H6bvuA3ksfTuzW +5acr+Oc6KTGgkvMI229cebe1aONNtIhTDav3JGpbAoGAX5DQvNreqnP8qSAvUN2I +TAHXIzawR3f6vgGgVIdkHkiS2eKzs/fgP3VAK80TbrGSR8HvBcPEcR/icOn1u/e6 +tDp0j6mGt5aPKK9VQkBn94bW35T12FUbdB+L8FWWTUrfiVWJtEW8tEsKil5ac8U4 +Bn3vC5WUeKhW6v6kD4AigqE= +-----END PRIVATE KEY----- diff --git a/packages/policy-gui-docker/src/main/docker/etc/ssl/clamp.pem b/packages/policy-gui-docker/src/main/docker/etc/ssl/clamp.pem new file mode 100644 index 0000000..a01b587 --- /dev/null +++ b/packages/policy-gui-docker/src/main/docker/etc/ssl/clamp.pem @@ -0,0 +1,33 @@ +Bag Attributes + friendlyName: clamp@clamp.onap.org + localKeyID: 54 69 6D 65 20 31 35 38 30 38 32 39 30 36 35 34 37 39 +subject=CN = clamp, emailAddress = mark.d.manager@people.osaaf.com, OU = clamp@clamp.onap.org:DEV, OU = OSAAF, O = ONAP, C = US + +issuer=C = US, O = ONAP, OU = OSAAF, CN = intermediateCA_9 + +-----BEGIN CERTIFICATE----- +MIIEWDCCA0CgAwIBAgIILw1zyDGqB5IwDQYJKoZIhvcNAQELBQAwRzELMAkGA1UE +BhMCVVMxDTALBgNVBAoMBE9OQVAxDjAMBgNVBAsMBU9TQUFGMRkwFwYDVQQDDBBp +bnRlcm1lZGlhdGVDQV85MB4XDTIwMDIwNDEyMjM1MloXDTIxMDIwNDEyMjM1Mlow +gY8xDjAMBgNVBAMMBWNsYW1wMS4wLAYJKoZIhvcNAQkBFh9tYXJrLmQubWFuYWdl +ckBwZW9wbGUub3NhYWYuY29tMSEwHwYDVQQLDBhjbGFtcEBjbGFtcC5vbmFwLm9y +ZzpERVYxDjAMBgNVBAsMBU9TQUFGMQ0wCwYDVQQKDARPTkFQMQswCQYDVQQGEwJV +UzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJMHfScyHSFzMiS9Ymjs +6aDtwAeHPnQ0GEsHu77rShdEYLJrhKqyyqrE2c2o1BA/0yZ+Vbar9tl6lafxGTbd +foIuaghSWuPwEw+RQJGrOC+VpY9I0ArlBw6noZS9dO5fgSxpbEmFuz1SPPb6qLXf +uI06p8DHWxTKBqHWSMAuuoeRcOoka8h/FTkRLRqQGL+UHsDdakTnYpOKhIUlLkpu +emPWiB98Y0rICI2pTrUtwXUWNaYg1q3bPdkyT/deb4cIOD8Ys+duHgTUqgTXQ7bY +AzKzpgYTI++BF+tMXXcOwNfnY+aZQduRIHqTBL8J5XlS777xvpPYhak/Jnb7mm2Y +v60CAwEAAaOB/jCB+zAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIF4DAgBgNVHSUB +Af8EFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwVAYDVR0jBE0wS4AUgfeZWxC5yIze +81Je6k5poEM+rN2hMKQuMCwxDjAMBgNVBAsMBU9TQUFGMQ0wCwYDVQQKDARPTkFQ +MQswCQYDVQQGEwJVU4IBBzAdBgNVHQ4EFgQUzfIed+18wgFs7E6q0b6BbMICtfsw +RwYDVR0RBEAwPoIFY2xhbXCCCmNsYW1wLW9uYXCCHWNsYW1wLmFwaS5zaW1wbGVk +ZW1vLm9uYXAub3JnggpjbGFtcC5vbmFwMA0GCSqGSIb3DQEBCwUAA4IBAQBizhsW +XrJ9wQy3PrBxgh90sOF15tayXPRZSFYPoQb5LhRh3IY/PvXLaSHlkgPHlCLLx36S +0/DiVf86/83ABvyaq9gJIyg/m4ntNae23OKH1AkA1aN+JCKA8yhsAzDBcRF6Aj7E +VJ+vQlSzz5oh+efP1e/8DUMd1/WwbTXvRd0Iqv/fyZunbjb82qNMrsK1mQ2q+87A +0jx9u1EdeMihP6vWiuKzlwy4mKoNT573SPpvaOkjX3yDlmf2CTQZ9vdAvjmFmVsH +1wyrNZOIgW4VjluiZfAk3mOEskrZiP/7aUXnxmNnYTpgZMbhiouLbRrTc4lLEyhx +G7A61/KGTsLZlvxb +-----END CERTIFICATE----- diff --git a/packages/policy-gui-docker/src/main/docker/nginx/index.html b/packages/policy-gui-docker/src/main/docker/index.html index 98742ae..98742ae 100644 --- a/packages/policy-gui-docker/src/main/docker/nginx/index.html +++ b/packages/policy-gui-docker/src/main/docker/index.html diff --git a/packages/policy-gui-docker/src/main/docker/policy-gui.sh b/packages/policy-gui-docker/src/main/docker/policy-gui.sh index bb2d9c9..050cbb7 100644 --- a/packages/policy-gui-docker/src/main/docker/policy-gui.sh +++ b/packages/policy-gui-docker/src/main/docker/policy-gui.sh @@ -30,7 +30,6 @@ echo "Starting gui-pdp-monitoring" $JAVA_HOME/bin/java -jar "$POLICY_HOME/lib/gui-pdp-monitoring-uber.jar" -p 17999 & echo "Starting nginx" -envsubst '${CLAMP_REST_URL}' < /etc/nginx/templates/default.conf.template > /etc/nginx/conf.d/default.conf nginx -g "daemon on;" wait |